2020import static com .google .cloud .pubsublite .internal .ApiExceptionMatcher .assertFutureThrowsCode ;
2121import static com .google .cloud .pubsublite .internal .testing .UnitTestExamples .example ;
2222import static com .google .common .truth .Truth .assertThat ;
23+ import static org .junit .Assert .assertThrows ;
2324import static org .mockito .Mockito .verify ;
2425import static org .mockito .Mockito .when ;
2526import static org .mockito .MockitoAnnotations .initMocks ;
2627
2728import com .google .api .core .ApiFuture ;
2829import com .google .api .core .ApiFutures ;
30+ import com .google .api .gax .longrunning .OperationFuture ;
31+ import com .google .api .gax .rpc .ApiException ;
32+ import com .google .api .gax .rpc .OperationCallable ;
2933import com .google .api .gax .rpc .StatusCode .Code ;
3034import com .google .api .gax .rpc .UnaryCallable ;
3135import com .google .cloud .pubsublite .BacklogLocation ;
3539import com .google .cloud .pubsublite .ProjectNumber ;
3640import com .google .cloud .pubsublite .ReservationName ;
3741import com .google .cloud .pubsublite .ReservationPath ;
42+ import com .google .cloud .pubsublite .SeekTarget ;
3843import com .google .cloud .pubsublite .SubscriptionName ;
3944import com .google .cloud .pubsublite .SubscriptionPath ;
4045import com .google .cloud .pubsublite .TopicName ;
5964import com .google .cloud .pubsublite .proto .ListTopicSubscriptionsResponse ;
6065import com .google .cloud .pubsublite .proto .ListTopicsRequest ;
6166import com .google .cloud .pubsublite .proto .ListTopicsResponse ;
67+ import com .google .cloud .pubsublite .proto .OperationMetadata ;
6268import com .google .cloud .pubsublite .proto .Reservation ;
69+ import com .google .cloud .pubsublite .proto .SeekSubscriptionRequest ;
70+ import com .google .cloud .pubsublite .proto .SeekSubscriptionRequest .NamedTarget ;
71+ import com .google .cloud .pubsublite .proto .SeekSubscriptionResponse ;
6372import com .google .cloud .pubsublite .proto .Subscription ;
6473import com .google .cloud .pubsublite .proto .Subscription .DeliveryConfig ;
74+ import com .google .cloud .pubsublite .proto .TimeTarget ;
6575import com .google .cloud .pubsublite .proto .Topic ;
6676import com .google .cloud .pubsublite .proto .Topic .PartitionConfig ;
6777import com .google .cloud .pubsublite .proto .TopicPartitions ;
7383import com .google .common .collect .ImmutableList ;
7484import com .google .protobuf .Empty ;
7585import com .google .protobuf .FieldMask ;
86+ import com .google .protobuf .Timestamp ;
7687import java .io .IOException ;
7788import org .junit .After ;
7889import org .junit .Before ;
@@ -103,6 +114,8 @@ public class AdminClientImplTest {
103114 .setThroughputCapacity (example (Reservation .class ).getThroughputCapacity () + 1 )
104115 .build ();
105116
117+ private static final String OPERATION_PATH = "/path/for/operation" ;
118+
106119 private static final <T > ApiFuture <T > failedPreconditionFuture () {
107120 return ApiFutures .immediateFailedFuture (
108121 new CheckedApiException (Code .FAILED_PRECONDITION ).underlying );
@@ -128,6 +141,12 @@ private static final <T> ApiFuture<T> failedPreconditionFuture() {
128141 @ Mock UnaryCallable <UpdateSubscriptionRequest , Subscription > updateSubscriptionCallable ;
129142 @ Mock UnaryCallable <DeleteSubscriptionRequest , Empty > deleteSubscriptionCallable ;
130143
144+ @ Mock
145+ OperationCallable <SeekSubscriptionRequest , SeekSubscriptionResponse , OperationMetadata >
146+ seekSubscriptionCallable ;
147+
148+ @ Mock OperationFuture <SeekSubscriptionResponse , OperationMetadata > seekFuture ;
149+
131150 @ Mock UnaryCallable <CreateReservationRequest , Reservation > createReservationCallable ;
132151 @ Mock UnaryCallable <GetReservationRequest , Reservation > getReservationCallable ;
133152 @ Mock UnaryCallable <ListReservationsRequest , ListReservationsResponse > listReservationsCallable ;
@@ -159,6 +178,7 @@ public void setUp() throws IOException {
159178 when (stub .listSubscriptionsCallable ()).thenReturn (listSubscriptionsCallable );
160179 when (stub .updateSubscriptionCallable ()).thenReturn (updateSubscriptionCallable );
161180 when (stub .deleteSubscriptionCallable ()).thenReturn (deleteSubscriptionCallable );
181+ when (stub .seekSubscriptionOperationCallable ()).thenReturn (seekSubscriptionCallable );
162182
163183 when (stub .createReservationCallable ()).thenReturn (createReservationCallable );
164184 when (stub .getReservationCallable ()).thenReturn (getReservationCallable );
@@ -546,6 +566,104 @@ public void listSubscriptions_Error() {
546566 client .listSubscriptions (example (LocationPath .class )), Code .FAILED_PRECONDITION );
547567 }
548568
569+ @ Test
570+ public void seekSubscription_PublishTimeOk () throws Exception {
571+ Timestamp publishTime = Timestamp .newBuilder ().setSeconds (123 ).build ();
572+ SeekSubscriptionRequest request =
573+ SeekSubscriptionRequest .newBuilder ()
574+ .setName (example (SubscriptionPath .class ).toString ())
575+ .setTimeTarget (TimeTarget .newBuilder ().setPublishTime (publishTime ))
576+ .build ();
577+
578+ when (seekFuture .getName ()).thenReturn (OPERATION_PATH );
579+ when (seekSubscriptionCallable .futureCall (request )).thenReturn (seekFuture );
580+
581+ assertThat (
582+ client
583+ .seekSubscription (
584+ example (SubscriptionPath .class ), SeekTarget .ofPublishTime (publishTime ))
585+ .getName ())
586+ .isEqualTo (OPERATION_PATH );
587+ }
588+
589+ @ Test
590+ public void seekSubscription_EventTimeOk () throws Exception {
591+ Timestamp eventTime = Timestamp .newBuilder ().setSeconds (456 ).build ();
592+ SeekSubscriptionRequest request =
593+ SeekSubscriptionRequest .newBuilder ()
594+ .setName (example (SubscriptionPath .class ).toString ())
595+ .setTimeTarget (TimeTarget .newBuilder ().setEventTime (eventTime ))
596+ .build ();
597+
598+ when (seekFuture .getName ()).thenReturn (OPERATION_PATH );
599+ when (seekSubscriptionCallable .futureCall (request )).thenReturn (seekFuture );
600+
601+ assertThat (
602+ client
603+ .seekSubscription (
604+ example (SubscriptionPath .class ), SeekTarget .ofEventTime (eventTime ))
605+ .getName ())
606+ .isEqualTo (OPERATION_PATH );
607+ }
608+
609+ @ Test
610+ public void seekSubscription_BacklogBeginningOk () throws Exception {
611+ SeekSubscriptionRequest request =
612+ SeekSubscriptionRequest .newBuilder ()
613+ .setName (example (SubscriptionPath .class ).toString ())
614+ .setNamedTarget (NamedTarget .TAIL )
615+ .build ();
616+
617+ when (seekFuture .getName ()).thenReturn (OPERATION_PATH );
618+ when (seekSubscriptionCallable .futureCall (request )).thenReturn (seekFuture );
619+
620+ assertThat (
621+ client
622+ .seekSubscription (
623+ example (SubscriptionPath .class ), SeekTarget .of (BacklogLocation .BEGINNING ))
624+ .getName ())
625+ .isEqualTo (OPERATION_PATH );
626+ }
627+
628+ @ Test
629+ public void seekSubscription_BacklogEndOk () throws Exception {
630+ SeekSubscriptionRequest request =
631+ SeekSubscriptionRequest .newBuilder ()
632+ .setName (example (SubscriptionPath .class ).toString ())
633+ .setNamedTarget (NamedTarget .HEAD )
634+ .build ();
635+
636+ when (seekFuture .getName ()).thenReturn (OPERATION_PATH );
637+ when (seekSubscriptionCallable .futureCall (request )).thenReturn (seekFuture );
638+
639+ assertThat (
640+ client
641+ .seekSubscription (
642+ example (SubscriptionPath .class ), SeekTarget .of (BacklogLocation .END ))
643+ .getName ())
644+ .isEqualTo (OPERATION_PATH );
645+ }
646+
647+ @ Test
648+ public void seekSubscription_Error () throws Exception {
649+ SeekSubscriptionRequest request =
650+ SeekSubscriptionRequest .newBuilder ()
651+ .setName (example (SubscriptionPath .class ).toString ())
652+ .setNamedTarget (NamedTarget .HEAD )
653+ .build ();
654+
655+ when (seekFuture .getName ()).thenThrow (new CheckedApiException (Code .NOT_FOUND ).underlying );
656+ when (seekSubscriptionCallable .futureCall (request )).thenReturn (seekFuture );
657+
658+ assertThrows (
659+ ApiException .class ,
660+ () ->
661+ client
662+ .seekSubscription (
663+ example (SubscriptionPath .class ), SeekTarget .of (BacklogLocation .END ))
664+ .getName ());
665+ }
666+
549667 @ Test
550668 public void createReservation_Ok () throws Exception {
551669 CreateReservationRequest request =
0 commit comments