GRPCClientTests.m 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /*
  2. *
  3. * Copyright 2015, Google Inc.
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions are
  8. * met:
  9. *
  10. * * Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * * Redistributions in binary form must reproduce the above
  13. * copyright notice, this list of conditions and the following disclaimer
  14. * in the documentation and/or other materials provided with the
  15. * distribution.
  16. * * Neither the name of Google Inc. nor the names of its
  17. * contributors may be used to endorse or promote products derived from
  18. * this software without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  23. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  24. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  25. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  26. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  27. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  28. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  30. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. *
  32. */
  33. #import <UIKit/UIKit.h>
  34. #import <XCTest/XCTest.h>
  35. #import <GRPCClient/GRPCCall.h>
  36. #import <ProtoRPC/ProtoMethod.h>
  37. #import <RemoteTest/Messages.pbobjc.h>
  38. #import <RxLibrary/GRXWriteable.h>
  39. #import <RxLibrary/GRXWriter+Immediate.h>
  40. // These are a few tests similar to InteropTests, but which use the generic gRPC client (GRPCCall)
  41. // rather than a generated proto library on top of it.
  42. static NSString * const kHostAddress = @"grpc-test.sandbox.google.com";
  43. static NSString * const kPackage = @"grpc.testing";
  44. static NSString * const kService = @"TestService";
  45. static ProtoMethod *kInexistentMethod;
  46. static ProtoMethod *kEmptyCallMethod;
  47. static ProtoMethod *kUnaryCallMethod;
  48. @interface GRPCClientTests : XCTestCase
  49. @end
  50. @implementation GRPCClientTests
  51. - (void)setUp {
  52. // This method isn't implemented by the remote server.
  53. kInexistentMethod = [[ProtoMethod alloc] initWithPackage:kPackage
  54. service:kService
  55. method:@"Inexistent"];
  56. kEmptyCallMethod = [[ProtoMethod alloc] initWithPackage:kPackage
  57. service:kService
  58. method:@"EmptyCall"];
  59. kUnaryCallMethod = [[ProtoMethod alloc] initWithPackage:kPackage
  60. service:kService
  61. method:@"UnaryCall"];
  62. }
  63. - (void)testConnectionToRemoteServer {
  64. __weak XCTestExpectation *expectation = [self expectationWithDescription:@"Server reachable."];
  65. GRPCCall *call = [[GRPCCall alloc] initWithHost:kHostAddress
  66. path:kInexistentMethod.HTTPPath
  67. requestsWriter:[GRXWriter writerWithValue:[NSData data]]];
  68. id<GRXWriteable> responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
  69. XCTFail(@"Received unexpected response: %@", value);
  70. } completionHandler:^(NSError *errorOrNil) {
  71. XCTAssertNotNil(errorOrNil, @"Finished without error!");
  72. // TODO(jcanizales): The server should return code 12 UNIMPLEMENTED, not 5 NOT FOUND.
  73. XCTAssertEqual(errorOrNil.code, 5, @"Finished with unexpected error: %@", errorOrNil);
  74. [expectation fulfill];
  75. }];
  76. [call startWithWriteable:responsesWriteable];
  77. [self waitForExpectationsWithTimeout:4 handler:nil];
  78. }
  79. - (void)testEmptyRPC {
  80. __weak XCTestExpectation *response = [self expectationWithDescription:@"Empty response received."];
  81. __weak XCTestExpectation *completion = [self expectationWithDescription:@"Empty RPC completed."];
  82. GRPCCall *call = [[GRPCCall alloc] initWithHost:kHostAddress
  83. path:kEmptyCallMethod.HTTPPath
  84. requestsWriter:[GRXWriter writerWithValue:[NSData data]]];
  85. id<GRXWriteable> responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
  86. XCTAssertNotNil(value, @"nil value received as response.");
  87. XCTAssertEqual([value length], 0, @"Non-empty response received: %@", value);
  88. [response fulfill];
  89. } completionHandler:^(NSError *errorOrNil) {
  90. XCTAssertNil(errorOrNil, @"Finished with unexpected error: %@", errorOrNil);
  91. [completion fulfill];
  92. }];
  93. [call startWithWriteable:responsesWriteable];
  94. [self waitForExpectationsWithTimeout:4 handler:nil];
  95. }
  96. - (void)testSimpleProtoRPC {
  97. __weak XCTestExpectation *response = [self expectationWithDescription:@"Expected response."];
  98. __weak XCTestExpectation *completion = [self expectationWithDescription:@"RPC completed."];
  99. RMTSimpleRequest *request = [RMTSimpleRequest message];
  100. request.responseSize = 100;
  101. request.fillUsername = YES;
  102. request.fillOauthScope = YES;
  103. GRXWriter *requestsWriter = [GRXWriter writerWithValue:[request data]];
  104. GRPCCall *call = [[GRPCCall alloc] initWithHost:kHostAddress
  105. path:kUnaryCallMethod.HTTPPath
  106. requestsWriter:requestsWriter];
  107. id<GRXWriteable> responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
  108. XCTAssertNotNil(value, @"nil value received as response.");
  109. XCTAssertGreaterThan(value.length, 0, @"Empty response received.");
  110. RMTSimpleResponse *responseProto = [RMTSimpleResponse parseFromData:value error:NULL];
  111. // We expect empty strings, not nil:
  112. XCTAssertNotNil(responseProto.username, @"Response's username is nil.");
  113. XCTAssertNotNil(responseProto.oauthScope, @"Response's OAuth scope is nil.");
  114. [response fulfill];
  115. } completionHandler:^(NSError *errorOrNil) {
  116. XCTAssertNil(errorOrNil, @"Finished with unexpected error: %@", errorOrNil);
  117. [completion fulfill];
  118. }];
  119. [call startWithWriteable:responsesWriteable];
  120. [self waitForExpectationsWithTimeout:4 handler:nil];
  121. }
  122. - (void)testMetadata {
  123. __weak XCTestExpectation *expectation = [self expectationWithDescription:@"RPC unauthorized."];
  124. RMTSimpleRequest *request = [RMTSimpleRequest message];
  125. request.fillUsername = YES;
  126. request.fillOauthScope = YES;
  127. GRXWriter *requestsWriter = [GRXWriter writerWithValue:[request data]];
  128. GRPCCall *call = [[GRPCCall alloc] initWithHost:kHostAddress
  129. path:kUnaryCallMethod.HTTPPath
  130. requestsWriter:requestsWriter];
  131. call.requestMetadata[@"Authorization"] = @"Bearer bogusToken";
  132. id<GRXWriteable> responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
  133. XCTFail(@"Received unexpected response: %@", value);
  134. } completionHandler:^(NSError *errorOrNil) {
  135. XCTAssertNotNil(errorOrNil, @"Finished without error!");
  136. XCTAssertEqual(errorOrNil.code, 16, @"Finished with unexpected error: %@", errorOrNil);
  137. XCTAssertEqualObjects(call.responseMetadata, errorOrNil.userInfo[kGRPCStatusMetadataKey],
  138. @"Metadata in the NSError object and call object differ.");
  139. NSString *challengeHeader = call.responseMetadata[@"www-authenticate"];
  140. XCTAssertGreaterThan(challengeHeader.length, 0,
  141. @"No challenge in response headers %@", call.responseMetadata);
  142. [expectation fulfill];
  143. }];
  144. [call startWithWriteable:responsesWriteable];
  145. [self waitForExpectationsWithTimeout:4 handler:nil];
  146. }
  147. @end