| # |
| # Licensed to the Apache Software Foundation (ASF) under one |
| # or more contributor license agreements. See the NOTICE file |
| # distributed with this work for additional information |
| # regarding copyright ownership. The ASF licenses this file |
| # to you under the Apache License, Version 2.0 (the |
| # "License"); you may not use this file except in compliance |
| # with the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, |
| # software distributed under the License is distributed on an |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| # KIND, either express or implied. See the License for the |
| # specific language governing permissions and limitations |
| # under the License. |
| # |
| import unittest |
| |
| from system_test import TestCase, Qdrouterd, TIMEOUT |
| try: |
| import grpc |
| import friendship_server as fs |
| from friendship_pb2_grpc import FriendshipStub |
| from friendship_pb2 import Person, FriendshipRequest, PersonEmail |
| _GRPC_UNAVAILABLE = False |
| except ImportError: |
| _GRPC_UNAVAILABLE = True |
| |
| |
| def skip_test(): |
| """If grpc cannot be imported, test must be skipped""" |
| return _GRPC_UNAVAILABLE |
| |
| |
| class GrpcServiceMethodsTest(TestCase): |
| |
| """ |
| Data for the grpc service |
| """ |
| NAME_EMAIL = { |
| "One": "one@apache.org", |
| "Two": "two@apache.org", |
| "Three": "three@apache.org", |
| "Four": "four@apache.org", |
| "Five": "five@apache.org", |
| } |
| |
| """ |
| List of how friendships will be defined at the grpc service |
| 1 = 2; 3; 4 |
| 2 = 1; 3; 5 |
| 3 = 1; 2; 4 |
| 4 = 1; 3; 5 |
| 5 = 2; 4 |
| """ |
| FRIENDS = { |
| "one@apache.org": ["two@apache.org", "three@apache.org", "four@apache.org"], |
| "two@apache.org": ["three@apache.org", "five@apache.org"], |
| "three@apache.org": ["four@apache.org"], |
| "four@apache.org": ["five@apache.org"], |
| } |
| EXP_FRIENDS = { |
| "one@apache.org": ["two@apache.org", "three@apache.org", "four@apache.org"], |
| "two@apache.org": ["one@apache.org", "three@apache.org", "five@apache.org"], |
| "three@apache.org": ["one@apache.org", "two@apache.org", "four@apache.org"], |
| "four@apache.org": ["one@apache.org", "three@apache.org", "five@apache.org"], |
| "five@apache.org": ["two@apache.org", "four@apache.org"] |
| } |
| |
| """ |
| List of common friends to request for and the expected |
| result to be returned by the service |
| """ |
| COMMON_FRIENDS_ITER = [ |
| ["one@apache.org", "five@apache.org"], |
| ["two@apache.org", "four@apache.org"], |
| ] |
| COMMON_FRIENDS_EXP = [ |
| ["two@apache.org", "four@apache.org"], |
| ["one@apache.org", "three@apache.org", "five@apache.org"], |
| ] |
| |
| @classmethod |
| def setUpClass(cls): |
| super(GrpcServiceMethodsTest, cls).setUpClass() |
| if skip_test(): |
| return |
| |
| # Define a random port for the gRPC server to bind |
| cls.grpc_server_port = str(cls.tester.get_port()) |
| |
| # Run the gRPC server (see friendship.proto for more info) |
| cls.grpc_server = fs.serve(cls.grpc_server_port) |
| |
| # Prepare router to communicate with the gRPC server |
| cls.connector_props = { |
| 'port': cls.grpc_server_port, |
| 'address': 'examples', |
| 'host': '127.0.0.1', |
| 'protocolVersion': 'HTTP2', |
| 'name': 'grpc-server' |
| } |
| cls.router_http_port = cls.tester.get_port() |
| config = Qdrouterd.Config([ |
| ('router', {'mode': 'standalone', 'id': 'QDR'}), |
| ('listener', {'port': cls.tester.get_port(), 'role': 'normal', 'host': '0.0.0.0'}), |
| |
| ('httpListener', {'port': cls.router_http_port, 'address': 'examples', |
| 'host': '127.0.0.1', 'protocolVersion': 'HTTP2'}), |
| ('httpConnector', cls.connector_props) |
| ]) |
| cls.router_qdr = cls.tester.qdrouterd("grpc-test-router", config, wait=True) |
| |
| # If you wanna try it without the router, set the grpc_channel |
| # directly to the grpc_server_port |
| cls.grpc_channel = grpc.insecure_channel('127.0.0.1:%s' % |
| cls.router_http_port) |
| cls.grpc_stub = FriendshipStub(cls.grpc_channel) |
| |
| @classmethod |
| def tearDownClass(cls): |
| super(GrpcServiceMethodsTest, cls).tearDownClass() |
| if skip_test(): |
| return |
| cls.grpc_server.stop(TIMEOUT) |
| |
| @classmethod |
| def create_person(cls, name, email): |
| p = Person() |
| p.name = name |
| p.email = email |
| res = cls.grpc_stub.Create(p) |
| assert res.success |
| assert res.message == "" |
| return p |
| |
| @classmethod |
| def friendship_generator(cls): |
| for key in cls.FRIENDS: |
| for friend in cls.FRIENDS[key]: |
| fr = FriendshipRequest() |
| fr.email1 = key |
| fr.email2 = friend |
| yield fr |
| |
| @classmethod |
| def common_friends_list(cls, friends): |
| for friend in friends: |
| pe = PersonEmail() |
| pe.email = friend |
| yield pe |
| |
| @unittest.skipIf(skip_test(), "grpcio is needed to run grpc tests") |
| def test_grpc_01_unary(self): |
| """ |
| Validates unary request and response message |
| :return: |
| """ |
| for key in self.NAME_EMAIL: |
| name = key |
| mail = self.NAME_EMAIL[key] |
| p = self.create_person(name, mail) |
| assert p is not None |
| |
| @unittest.skipIf(skip_test(), "grpcio is needed to run grpc tests") |
| def test_grpc_02_bidirectional_stream(self): |
| """ |
| Validates bidirectional streaming request and response messages |
| :return: |
| """ |
| for res in self.grpc_stub.MakeFriends(self.friendship_generator()): |
| assert res.friend1 is not None |
| assert res.friend2 is not None |
| assert not res.error |
| |
| @unittest.skipIf(skip_test(), "grpcio is needed to run grpc tests") |
| def test_grpc_03_server_stream(self): |
| """ |
| Validates server streaming response messages |
| :return: |
| """ |
| for key in self.EXP_FRIENDS: |
| pe = PersonEmail() |
| pe.email = key |
| friends = [] |
| for friend in self.grpc_stub.ListFriends(pe): |
| friends.append(friend.email) |
| assert all(f in self.EXP_FRIENDS[key] for f in friends) |
| assert all(f in friends for f in self.EXP_FRIENDS[key]) |
| |
| @unittest.skipIf(skip_test(), "grpcio is needed to run grpc tests") |
| def test_grpc_04_client_stream(self): |
| """ |
| Validates client streaming request messages |
| :return: |
| """ |
| for i in range(len(self.COMMON_FRIENDS_ITER)): |
| friends = self.COMMON_FRIENDS_ITER[i] |
| exp_friends = self.COMMON_FRIENDS_EXP[i] |
| res = self.grpc_stub.CommonFriendsCount(self.common_friends_list(friends)) |
| assert res.count == len(exp_friends) |
| assert all(f in res.friends for f in exp_friends) |
| assert all(f in exp_friends for f in res.friends) |