• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2017 gRPC authors.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14"""Objects for use in testing gRPC Python-using application code."""
15
16import abc
17import six
18
19from google.protobuf import descriptor
20
21import grpc
22
23
24class UnaryUnaryChannelRpc(six.with_metaclass(abc.ABCMeta)):
25    """Fixture for a unary-unary RPC invoked by a system under test.
26
27    Enables users to "play server" for the RPC.
28    """
29
30    @abc.abstractmethod
31    def send_initial_metadata(self, initial_metadata):
32        """Sends the RPC's initial metadata to the system under test.
33
34        Args:
35          initial_metadata: The RPC's initial metadata to be "sent" to
36            the system under test.
37        """
38        raise NotImplementedError()
39
40    @abc.abstractmethod
41    def cancelled(self):
42        """Blocks until the system under test has cancelled the RPC."""
43        raise NotImplementedError()
44
45    @abc.abstractmethod
46    def terminate(self, response, trailing_metadata, code, details):
47        """Terminates the RPC.
48
49        Args:
50          response: The response for the RPC.
51          trailing_metadata: The RPC's trailing metadata.
52          code: The RPC's status code.
53          details: The RPC's status details.
54        """
55        raise NotImplementedError()
56
57
58class UnaryStreamChannelRpc(six.with_metaclass(abc.ABCMeta)):
59    """Fixture for a unary-stream RPC invoked by a system under test.
60
61    Enables users to "play server" for the RPC.
62    """
63
64    @abc.abstractmethod
65    def send_initial_metadata(self, initial_metadata):
66        """Sends the RPC's initial metadata to the system under test.
67
68        Args:
69          initial_metadata: The RPC's initial metadata to be "sent" to
70            the system under test.
71        """
72        raise NotImplementedError()
73
74    @abc.abstractmethod
75    def send_response(self, response):
76        """Sends a response to the system under test.
77
78        Args:
79          response: A response message to be "sent" to the system under test.
80        """
81        raise NotImplementedError()
82
83    @abc.abstractmethod
84    def cancelled(self):
85        """Blocks until the system under test has cancelled the RPC."""
86        raise NotImplementedError()
87
88    @abc.abstractmethod
89    def terminate(self, trailing_metadata, code, details):
90        """Terminates the RPC.
91
92        Args:
93          trailing_metadata: The RPC's trailing metadata.
94          code: The RPC's status code.
95          details: The RPC's status details.
96        """
97        raise NotImplementedError()
98
99
100class StreamUnaryChannelRpc(six.with_metaclass(abc.ABCMeta)):
101    """Fixture for a stream-unary RPC invoked by a system under test.
102
103    Enables users to "play server" for the RPC.
104    """
105
106    @abc.abstractmethod
107    def send_initial_metadata(self, initial_metadata):
108        """Sends the RPC's initial metadata to the system under test.
109
110        Args:
111          initial_metadata: The RPC's initial metadata to be "sent" to
112            the system under test.
113        """
114        raise NotImplementedError()
115
116    @abc.abstractmethod
117    def take_request(self):
118        """Draws one of the requests added to the RPC by the system under test.
119
120        This method blocks until the system under test has added to the RPC
121        the request to be returned.
122
123        Successive calls to this method return requests in the same order in
124        which the system under test added them to the RPC.
125
126        Returns:
127          A request message added to the RPC by the system under test.
128        """
129        raise NotImplementedError()
130
131    @abc.abstractmethod
132    def requests_closed(self):
133        """Blocks until the system under test has closed the request stream."""
134        raise NotImplementedError()
135
136    @abc.abstractmethod
137    def cancelled(self):
138        """Blocks until the system under test has cancelled the RPC."""
139        raise NotImplementedError()
140
141    @abc.abstractmethod
142    def terminate(self, response, trailing_metadata, code, details):
143        """Terminates the RPC.
144
145        Args:
146          response: The response for the RPC.
147          trailing_metadata: The RPC's trailing metadata.
148          code: The RPC's status code.
149          details: The RPC's status details.
150        """
151        raise NotImplementedError()
152
153
154class StreamStreamChannelRpc(six.with_metaclass(abc.ABCMeta)):
155    """Fixture for a stream-stream RPC invoked by a system under test.
156
157    Enables users to "play server" for the RPC.
158    """
159
160    @abc.abstractmethod
161    def send_initial_metadata(self, initial_metadata):
162        """Sends the RPC's initial metadata to the system under test.
163
164        Args:
165          initial_metadata: The RPC's initial metadata to be "sent" to the
166            system under test.
167        """
168        raise NotImplementedError()
169
170    @abc.abstractmethod
171    def take_request(self):
172        """Draws one of the requests added to the RPC by the system under test.
173
174        This method blocks until the system under test has added to the RPC
175        the request to be returned.
176
177        Successive calls to this method return requests in the same order in
178        which the system under test added them to the RPC.
179
180        Returns:
181          A request message added to the RPC by the system under test.
182        """
183        raise NotImplementedError()
184
185    @abc.abstractmethod
186    def send_response(self, response):
187        """Sends a response to the system under test.
188
189        Args:
190          response: A response messages to be "sent" to the system under test.
191        """
192        raise NotImplementedError()
193
194    @abc.abstractmethod
195    def requests_closed(self):
196        """Blocks until the system under test has closed the request stream."""
197        raise NotImplementedError()
198
199    @abc.abstractmethod
200    def cancelled(self):
201        """Blocks until the system under test has cancelled the RPC."""
202        raise NotImplementedError()
203
204    @abc.abstractmethod
205    def terminate(self, trailing_metadata, code, details):
206        """Terminates the RPC.
207
208        Args:
209          trailing_metadata: The RPC's trailing metadata.
210          code: The RPC's status code.
211          details: The RPC's status details.
212        """
213        raise NotImplementedError()
214
215
216class Channel(six.with_metaclass(abc.ABCMeta, grpc.Channel)):
217    """A grpc.Channel double with which to test a system that invokes RPCs."""
218
219    @abc.abstractmethod
220    def take_unary_unary(self, method_descriptor):
221        """Draws an RPC currently being made by the system under test.
222
223        If the given descriptor does not identify any RPC currently being made
224        by the system under test, this method blocks until the system under
225        test invokes such an RPC.
226
227        Args:
228          method_descriptor: A descriptor.MethodDescriptor describing a
229            unary-unary RPC method.
230
231        Returns:
232          A (invocation_metadata, request, unary_unary_channel_rpc) tuple of
233            the RPC's invocation metadata, its request, and a
234            UnaryUnaryChannelRpc with which to "play server" for the RPC.
235        """
236        raise NotImplementedError()
237
238    @abc.abstractmethod
239    def take_unary_stream(self, method_descriptor):
240        """Draws an RPC currently being made by the system under test.
241
242        If the given descriptor does not identify any RPC currently being made
243        by the system under test, this method blocks until the system under
244        test invokes such an RPC.
245
246        Args:
247          method_descriptor: A descriptor.MethodDescriptor describing a
248            unary-stream RPC method.
249
250        Returns:
251          A (invocation_metadata, request, unary_stream_channel_rpc) tuple of
252            the RPC's invocation metadata, its request, and a
253            UnaryStreamChannelRpc with which to "play server" for the RPC.
254        """
255        raise NotImplementedError()
256
257    @abc.abstractmethod
258    def take_stream_unary(self, method_descriptor):
259        """Draws an RPC currently being made by the system under test.
260
261        If the given descriptor does not identify any RPC currently being made
262        by the system under test, this method blocks until the system under
263        test invokes such an RPC.
264
265        Args:
266          method_descriptor: A descriptor.MethodDescriptor describing a
267            stream-unary RPC method.
268
269        Returns:
270          A (invocation_metadata, stream_unary_channel_rpc) tuple of the RPC's
271            invocation metadata and a StreamUnaryChannelRpc with which to "play
272            server" for the RPC.
273        """
274        raise NotImplementedError()
275
276    @abc.abstractmethod
277    def take_stream_stream(self, method_descriptor):
278        """Draws an RPC currently being made by the system under test.
279
280        If the given descriptor does not identify any RPC currently being made
281        by the system under test, this method blocks until the system under
282        test invokes such an RPC.
283
284        Args:
285          method_descriptor: A descriptor.MethodDescriptor describing a
286            stream-stream RPC method.
287
288        Returns:
289          A (invocation_metadata, stream_stream_channel_rpc) tuple of the RPC's
290            invocation metadata and a StreamStreamChannelRpc with which to
291            "play server" for the RPC.
292        """
293        raise NotImplementedError()
294
295
296class UnaryUnaryServerRpc(six.with_metaclass(abc.ABCMeta)):
297    """Fixture for a unary-unary RPC serviced by a system under test.
298
299    Enables users to "play client" for the RPC.
300    """
301
302    @abc.abstractmethod
303    def initial_metadata(self):
304        """Accesses the initial metadata emitted by the system under test.
305
306        This method blocks until the system under test has added initial
307        metadata to the RPC (or has provided one or more response messages or
308        has terminated the RPC, either of which will cause gRPC Python to
309        synthesize initial metadata for the RPC).
310
311        Returns:
312          The initial metadata for the RPC.
313        """
314        raise NotImplementedError()
315
316    @abc.abstractmethod
317    def cancel(self):
318        """Cancels the RPC."""
319        raise NotImplementedError()
320
321    @abc.abstractmethod
322    def termination(self):
323        """Blocks until the system under test has terminated the RPC.
324
325        Returns:
326          A (response, trailing_metadata, code, details) sequence with the RPC's
327            response, trailing metadata, code, and details.
328        """
329        raise NotImplementedError()
330
331
332class UnaryStreamServerRpc(six.with_metaclass(abc.ABCMeta)):
333    """Fixture for a unary-stream RPC serviced by a system under test.
334
335    Enables users to "play client" for the RPC.
336    """
337
338    @abc.abstractmethod
339    def initial_metadata(self):
340        """Accesses the initial metadata emitted by the system under test.
341
342        This method blocks until the system under test has added initial
343        metadata to the RPC (or has provided one or more response messages or
344        has terminated the RPC, either of which will cause gRPC Python to
345        synthesize initial metadata for the RPC).
346
347        Returns:
348          The initial metadata for the RPC.
349        """
350        raise NotImplementedError()
351
352    @abc.abstractmethod
353    def take_response(self):
354        """Draws one of the responses added to the RPC by the system under test.
355
356        Successive calls to this method return responses in the same order in
357        which the system under test added them to the RPC.
358
359        Returns:
360          A response message added to the RPC by the system under test.
361        """
362        raise NotImplementedError()
363
364    @abc.abstractmethod
365    def cancel(self):
366        """Cancels the RPC."""
367        raise NotImplementedError()
368
369    @abc.abstractmethod
370    def termination(self):
371        """Blocks until the system under test has terminated the RPC.
372
373        Returns:
374          A (trailing_metadata, code, details) sequence with the RPC's trailing
375            metadata, code, and details.
376        """
377        raise NotImplementedError()
378
379
380class StreamUnaryServerRpc(six.with_metaclass(abc.ABCMeta)):
381    """Fixture for a stream-unary RPC serviced by a system under test.
382
383    Enables users to "play client" for the RPC.
384    """
385
386    @abc.abstractmethod
387    def initial_metadata(self):
388        """Accesses the initial metadata emitted by the system under test.
389
390        This method blocks until the system under test has added initial
391        metadata to the RPC (or has provided one or more response messages or
392        has terminated the RPC, either of which will cause gRPC Python to
393        synthesize initial metadata for the RPC).
394
395        Returns:
396          The initial metadata for the RPC.
397        """
398        raise NotImplementedError()
399
400    @abc.abstractmethod
401    def send_request(self, request):
402        """Sends a request to the system under test.
403
404        Args:
405          request: A request message for the RPC to be "sent" to the system
406            under test.
407        """
408        raise NotImplementedError()
409
410    @abc.abstractmethod
411    def requests_closed(self):
412        """Indicates the end of the RPC's request stream."""
413        raise NotImplementedError()
414
415    @abc.abstractmethod
416    def cancel(self):
417        """Cancels the RPC."""
418        raise NotImplementedError()
419
420    @abc.abstractmethod
421    def termination(self):
422        """Blocks until the system under test has terminated the RPC.
423
424        Returns:
425          A (response, trailing_metadata, code, details) sequence with the RPC's
426            response, trailing metadata, code, and details.
427        """
428        raise NotImplementedError()
429
430
431class StreamStreamServerRpc(six.with_metaclass(abc.ABCMeta)):
432    """Fixture for a stream-stream RPC serviced by a system under test.
433
434    Enables users to "play client" for the RPC.
435    """
436
437    @abc.abstractmethod
438    def initial_metadata(self):
439        """Accesses the initial metadata emitted by the system under test.
440
441        This method blocks until the system under test has added initial
442        metadata to the RPC (or has provided one or more response messages or
443        has terminated the RPC, either of which will cause gRPC Python to
444        synthesize initial metadata for the RPC).
445
446        Returns:
447          The initial metadata for the RPC.
448        """
449        raise NotImplementedError()
450
451    @abc.abstractmethod
452    def send_request(self, request):
453        """Sends a request to the system under test.
454
455        Args:
456          request: A request message for the RPC to be "sent" to the system
457            under test.
458        """
459        raise NotImplementedError()
460
461    @abc.abstractmethod
462    def requests_closed(self):
463        """Indicates the end of the RPC's request stream."""
464        raise NotImplementedError()
465
466    @abc.abstractmethod
467    def take_response(self):
468        """Draws one of the responses added to the RPC by the system under test.
469
470        Successive calls to this method return responses in the same order in
471        which the system under test added them to the RPC.
472
473        Returns:
474          A response message added to the RPC by the system under test.
475        """
476        raise NotImplementedError()
477
478    @abc.abstractmethod
479    def cancel(self):
480        """Cancels the RPC."""
481        raise NotImplementedError()
482
483    @abc.abstractmethod
484    def termination(self):
485        """Blocks until the system under test has terminated the RPC.
486
487        Returns:
488          A (trailing_metadata, code, details) sequence with the RPC's trailing
489            metadata, code, and details.
490        """
491        raise NotImplementedError()
492
493
494class Server(six.with_metaclass(abc.ABCMeta)):
495    """A server with which to test a system that services RPCs."""
496
497    @abc.abstractmethod
498    def invoke_unary_unary(self, method_descriptor, invocation_metadata,
499                           request, timeout):
500        """Invokes an RPC to be serviced by the system under test.
501
502        Args:
503          method_descriptor: A descriptor.MethodDescriptor describing a unary-unary
504            RPC method.
505          invocation_metadata: The RPC's invocation metadata.
506          request: The RPC's request.
507          timeout: A duration of time in seconds for the RPC or None to
508            indicate that the RPC has no time limit.
509
510        Returns:
511          A UnaryUnaryServerRpc with which to "play client" for the RPC.
512        """
513        raise NotImplementedError()
514
515    @abc.abstractmethod
516    def invoke_unary_stream(self, method_descriptor, invocation_metadata,
517                            request, timeout):
518        """Invokes an RPC to be serviced by the system under test.
519
520        Args:
521          method_descriptor: A descriptor.MethodDescriptor describing a unary-stream
522            RPC method.
523          invocation_metadata: The RPC's invocation metadata.
524          request: The RPC's request.
525          timeout: A duration of time in seconds for the RPC or None to
526            indicate that the RPC has no time limit.
527
528        Returns:
529          A UnaryStreamServerRpc with which to "play client" for the RPC.
530        """
531        raise NotImplementedError()
532
533    @abc.abstractmethod
534    def invoke_stream_unary(self, method_descriptor, invocation_metadata,
535                            timeout):
536        """Invokes an RPC to be serviced by the system under test.
537
538        Args:
539          method_descriptor: A descriptor.MethodDescriptor describing a stream-unary
540            RPC method.
541          invocation_metadata: The RPC's invocation metadata.
542          timeout: A duration of time in seconds for the RPC or None to
543            indicate that the RPC has no time limit.
544
545        Returns:
546          A StreamUnaryServerRpc with which to "play client" for the RPC.
547        """
548        raise NotImplementedError()
549
550    @abc.abstractmethod
551    def invoke_stream_stream(self, method_descriptor, invocation_metadata,
552                             timeout):
553        """Invokes an RPC to be serviced by the system under test.
554
555        Args:
556          method_descriptor: A descriptor.MethodDescriptor describing a stream-stream
557            RPC method.
558          invocation_metadata: The RPC's invocation metadata.
559          timeout: A duration of time in seconds for the RPC or None to
560            indicate that the RPC has no time limit.
561
562        Returns:
563          A StreamStreamServerRpc with which to "play client" for the RPC.
564        """
565        raise NotImplementedError()
566
567
568class Time(six.with_metaclass(abc.ABCMeta)):
569    """A simulation of time.
570
571    Implementations needn't be connected with real time as provided by the
572    Python interpreter, but as long as systems under test use
573    RpcContext.is_active and RpcContext.time_remaining for querying RPC liveness
574    implementations may be used to change passage of time in tests.
575    """
576
577    @abc.abstractmethod
578    def time(self):
579        """Accesses the current test time.
580
581        Returns:
582          The current test time (over which this object has authority).
583        """
584        raise NotImplementedError()
585
586    @abc.abstractmethod
587    def call_in(self, behavior, delay):
588        """Adds a behavior to be called after some time.
589
590        Args:
591          behavior: A behavior to be called with no arguments.
592          delay: A duration of time in seconds after which to call the behavior.
593
594        Returns:
595          A grpc.Future with which the call of the behavior may be cancelled
596            before it is executed.
597        """
598        raise NotImplementedError()
599
600    @abc.abstractmethod
601    def call_at(self, behavior, time):
602        """Adds a behavior to be called at a specific time.
603
604        Args:
605          behavior: A behavior to be called with no arguments.
606          time: The test time at which to call the behavior.
607
608        Returns:
609          A grpc.Future with which the call of the behavior may be cancelled
610            before it is executed.
611        """
612        raise NotImplementedError()
613
614    @abc.abstractmethod
615    def sleep_for(self, duration):
616        """Blocks for some length of test time.
617
618        Args:
619          duration: A duration of test time in seconds for which to block.
620        """
621        raise NotImplementedError()
622
623    @abc.abstractmethod
624    def sleep_until(self, time):
625        """Blocks until some test time.
626
627        Args:
628          time: The test time until which to block.
629        """
630        raise NotImplementedError()
631
632
633def strict_real_time():
634    """Creates a Time backed by the Python interpreter's time.
635
636    The returned instance will be "strict" with respect to callbacks
637    submitted to it: it will ensure that all callbacks registered to
638    be called at time t have been called before it describes the time
639    as having advanced beyond t.
640
641    Returns:
642      A Time backed by the "system" (Python interpreter's) time.
643    """
644    from grpc_testing import _time
645    return _time.StrictRealTime()
646
647
648def strict_fake_time(now):
649    """Creates a Time that can be manipulated by test code.
650
651    The returned instance maintains an internal representation of time
652    independent of real time. This internal representation only advances
653    when user code calls the instance's sleep_for and sleep_until methods.
654
655    The returned instance will be "strict" with respect to callbacks
656    submitted to it: it will ensure that all callbacks registered to
657    be called at time t have been called before it describes the time
658    as having advanced beyond t.
659
660    Returns:
661      A Time that simulates the passage of time.
662    """
663    from grpc_testing import _time
664    return _time.StrictFakeTime(now)
665
666
667def channel(service_descriptors, time):
668    """Creates a Channel for use in tests of a gRPC Python-using system.
669
670    Args:
671      service_descriptors: An iterable of descriptor.ServiceDescriptors
672        describing the RPCs that will be made on the returned Channel by the
673        system under test.
674      time: A Time to be used for tests.
675
676    Returns:
677      A Channel for use in tests.
678    """
679    from grpc_testing import _channel
680    return _channel.testing_channel(service_descriptors, time)
681
682
683def server_from_dictionary(descriptors_to_servicers, time):
684    """Creates a Server for use in tests of a gRPC Python-using system.
685
686    Args:
687      descriptors_to_servicers: A dictionary from descriptor.ServiceDescriptors
688        defining RPC services to servicer objects (usually instances of classes
689        that implement "Servicer" interfaces defined in generated "_pb2_grpc"
690        modules) implementing those services.
691      time: A Time to be used for tests.
692
693    Returns:
694      A Server for use in tests.
695    """
696    from grpc_testing import _server
697    return _server.server_from_dictionary(descriptors_to_servicers, time)
698