Merge github.com:grpc/grpc into one-pass

pull/1369/head
Craig Tiller 10 years ago
commit 8de0c88b02
  1. 79
      gRPC.podspec
  2. 3
      src/objective-c/GRPCClient/GRPCMethodName.h
  3. 46
      src/objective-c/ProtoRPC/ProtoRPC.h
  4. 91
      src/objective-c/ProtoRPC/ProtoRPC.m
  5. 49
      src/objective-c/ProtoRPC/ProtoService.h
  6. 81
      src/objective-c/ProtoRPC/ProtoService.m
  7. 6
      src/objective-c/RxLibrary/GRXWriteable.h
  8. 24
      src/objective-c/RxLibrary/GRXWriteable.m
  9. 1
      src/objective-c/examples/Sample/RemoteTestClient/RemoteTest.podspec
  10. 86
      src/objective-c/examples/Sample/RemoteTestClient/Test.pb.h
  11. 136
      src/objective-c/examples/Sample/RemoteTestClient/Test.pb.m
  12. 12
      src/objective-c/examples/Sample/Sample.xcodeproj/project.pbxproj
  13. 90
      src/objective-c/examples/Sample/SampleTests/RemoteProtoTests.m

@ -7,15 +7,13 @@ Pod::Spec.new do |s|
s.authors = { 'Jorge Canizales' => 'jcanizales@google.com' } s.authors = { 'Jorge Canizales' => 'jcanizales@google.com' }
# s.source = { :git => 'https://github.com/grpc/grpc.git', :tag => 'release-0_5_0' } # s.source = { :git => 'https://github.com/grpc/grpc.git', :tag => 'release-0_5_0' }
s.source_files = 'src/objective-c/GRPCClient/*.{h,m}', 'src/objective-c/GRPCClient/private/*.{h,m}'
s.private_header_files = 'src/objective-c/GRPCClient/private/*.h'
s.platform = :ios s.platform = :ios
s.ios.deployment_target = '6.0' s.ios.deployment_target = '6.0'
s.requires_arc = true s.requires_arc = true
s.subspec 'RxLibrary' do |rs| s.subspec 'RxLibrary' do |rs|
rs.summary = 'Reactive Extensions library for iOS' rs.summary = 'Reactive Extensions library for iOS.'
rs.authors = { 'Jorge Canizales' => 'jcanizales@google.com' } rs.authors = { 'Jorge Canizales' => 'jcanizales@google.com' }
rs.source_files = 'src/objective-c/RxLibrary/*.{h,m}', 'src/objective-c/RxLibrary/transformations/*.{h,m}', 'src/objective-c/RxLibrary/private/*.{h,m}' rs.source_files = 'src/objective-c/RxLibrary/*.{h,m}', 'src/objective-c/RxLibrary/transformations/*.{h,m}', 'src/objective-c/RxLibrary/private/*.{h,m}'
@ -23,7 +21,7 @@ Pod::Spec.new do |s|
end end
s.subspec 'C-Core' do |cs| s.subspec 'C-Core' do |cs|
cs.summary = 'Core gRPC library, written in C' cs.summary = 'Core cross-platform gRPC library, written in C.'
cs.authors = { 'Craig Tiller' => 'ctiller@google.com', cs.authors = { 'Craig Tiller' => 'ctiller@google.com',
'David Klempner' => 'klempner@google.com', 'David Klempner' => 'klempner@google.com',
'Nicolas Noble' => 'nnoble@google.com', 'Nicolas Noble' => 'nnoble@google.com',
@ -38,32 +36,53 @@ Pod::Spec.new do |s|
cs.requires_arc = false cs.requires_arc = false
cs.libraries = 'z' cs.libraries = 'z'
cs.dependency 'OpenSSL', '~> 1.0.200' cs.dependency 'OpenSSL', '~> 1.0.200'
# This is a workaround for Cocoapods Issue #1437.
# It renames time.h and string.h to grpc_time.h and grpc_string.h.
cs.prepare_command = <<-CMD
DIR_TIME="grpc/support"
BAD_TIME="$DIR_TIME/time.h"
GOOD_TIME="$DIR_TIME/grpc_time.h"
if [ -f "include/$BAD_TIME" ];
then
grep -rl "$BAD_TIME" include/grpc src/core | xargs sed -i '' -e s@$BAD_TIME@$GOOD_TIME@g
mv "include/$BAD_TIME" "include/$GOOD_TIME"
fi
DIR_STRING="src/core/support"
BAD_STRING="$DIR_STRING/string.h"
GOOD_STRING="$DIR_STRING/grpc_string.h"
if [ -f "$BAD_STRING" ];
then
grep -rl "$BAD_STRING" include/grpc src/core | xargs sed -i '' -e s@$BAD_STRING@$GOOD_STRING@g
mv "$BAD_STRING" "$GOOD_STRING"
fi
CMD
end
s.subspec 'GRPCClient' do |gs|
gs.summary = 'Objective-C wrapper around the core gRPC library.'
gs.authors = { 'Jorge Canizales' => 'jcanizales@google.com' }
gs.source_files = 'src/objective-c/GRPCClient/*.{h,m}', 'src/objective-c/GRPCClient/private/*.{h,m}'
gs.private_header_files = 'src/objective-c/GRPCClient/private/*.h'
gs.dependency 'gRPC/C-Core'
# Is this needed in all dependents?
gs.xcconfig = { 'HEADER_SEARCH_PATHS' => '"$(PODS_ROOT)/Headers/Public/gRPC/include"' }
gs.dependency 'gRPC/RxLibrary'
# Certificates, to be able to establish TLS connections:
gs.resource_bundles = { 'gRPC' => ['etc/roots.pem'] }
end end
# This is a workaround for Cocoapods Issue #1437. s.subspec 'ProtoRPC' do |ps|
# It renames time.h and string.h to grpc_time.h and grpc_string.h. ps.summary = 'RPC library for ProtocolBuffers, based on gRPC'
s.prepare_command = <<-CMD ps.authors = { 'Jorge Canizales' => 'jcanizales@google.com' }
DIR_TIME="grpc/support"
BAD_TIME="$DIR_TIME/time.h" ps.source_files = 'src/objective-c/ProtoRPC/*.{h,m}'
GOOD_TIME="$DIR_TIME/grpc_time.h"
if [ -f "include/$BAD_TIME" ]; ps.dependency 'gRPC/GRPCClient'
then ps.dependency 'gRPC/RxLibrary'
grep -rl "$BAD_TIME" include/grpc src/core | xargs sed -i '' -e s@$BAD_TIME@$GOOD_TIME@g end
mv "include/$BAD_TIME" "include/$GOOD_TIME"
fi
DIR_STRING="src/core/support"
BAD_STRING="$DIR_STRING/string.h"
GOOD_STRING="$DIR_STRING/grpc_string.h"
if [ -f "$BAD_STRING" ];
then
grep -rl "$BAD_STRING" include/grpc src/core | xargs sed -i '' -e s@$BAD_STRING@$GOOD_STRING@g
mv "$BAD_STRING" "$GOOD_STRING"
fi
CMD
s.xcconfig = { 'HEADER_SEARCH_PATHS' => '"$(PODS_ROOT)/Headers/Public/gRPC/include"' }
# Certificates, to be able to establish TLS connections:
s.resource_bundles = { 'gRPC' => ['etc/roots.pem'] }
end end

@ -37,7 +37,8 @@
// A fully-qualified gRPC method name. Full qualification is needed because a gRPC endpoint can // A fully-qualified gRPC method name. Full qualification is needed because a gRPC endpoint can
// implement multiple interfaces. // implement multiple interfaces.
// TODO(jcanizales): Is this proto-specific, or actual part of gRPC? If the former, move one layer up. // TODO(jcanizales): Move to ProtoRPC package.
// TODO(jcanizales): Rename interface -> service.
@interface GRPCMethodName : NSObject @interface GRPCMethodName : NSObject
@property(nonatomic, readonly) NSString *package; @property(nonatomic, readonly) NSString *package;
@property(nonatomic, readonly) NSString *interface; @property(nonatomic, readonly) NSString *interface;

@ -0,0 +1,46 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#import <Foundation/Foundation.h>
#import <gRPC/GRPCCall.h>
@interface ProtoRPC : GRPCCall
- (instancetype)initWithHost:(NSString *)host
method:(GRPCMethodName *)method
requestsWriter:(id<GRXWriter>)requestsWriter
responseClass:(Class)responseClass
responsesWriteable:(id<GRXWriteable>)responsesWriteable NS_DESIGNATED_INITIALIZER;
- (void)start;
@end

@ -0,0 +1,91 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#import "ProtoRPC.h"
#import <gRPC/GRXWriteable.h>
#import <gRPC/GRXWriter.h>
#import <gRPC/GRXWriter+Transformations.h>
#import <ProtocolBuffers/ProtocolBuffers.h>
@implementation ProtoRPC {
id<GRXWriteable> _responseWriteable;
}
- (instancetype)initWithHost:(NSString *)host
method:(GRPCMethodName *)method
requestsWriter:(id<GRXWriter>)requestsWriter {
return [self initWithHost:host
method:method
requestsWriter:requestsWriter
responseClass:nil
responsesWriteable:nil];
}
// Designated initializer
- (instancetype)initWithHost:(NSString *)host
method:(GRPCMethodName *)method
requestsWriter:(id<GRXWriter>)requestsWriter
responseClass:(Class)responseClass
responsesWriteable:(id<GRXWriteable>)responsesWriteable {
// Because we can't tell the type system to constrain the class, we need to check at runtime:
if (![responseClass respondsToSelector:@selector(parseFromData:)]) {
[NSException raise:NSInvalidArgumentException
format:@"A protobuf class to parse the responses must be provided."];
}
// A writer that serializes the proto messages to send.
id<GRXWriter> bytesWriter =
[[[GRXWriter alloc] initWithWriter:requestsWriter] map:^id(PBGeneratedMessage *proto) {
return [proto data];
}];
if ((self = [super initWithHost:host method:method requestsWriter:bytesWriter])) {
// A writeable that parses the proto messages received.
_responseWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
[responsesWriteable didReceiveValue:[responseClass parseFromData:value]];
} completionHandler:^(NSError *errorOrNil) {
[responsesWriteable didFinishWithError:errorOrNil];
}];
}
return self;
}
- (void)start {
[self startWithWriteable:_responseWriteable];
}
- (void)startWithWriteable:(id<GRXWriteable>)writeable {
[super startWithWriteable:writeable];
// Break retain cycles.
_responseWriteable = nil;
}
@end

@ -0,0 +1,49 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#import <Foundation/Foundation.h>
@class ProtoRPC;
@protocol GRXWriteable;
@protocol GRXWriter;
@interface ProtoService : NSObject
- (instancetype)initWithHost:(NSString *)host
packageName:(NSString *)packageName
serviceName:(NSString *)serviceName NS_DESIGNATED_INITIALIZER;
- (ProtoRPC *)RPCToMethod:(NSString *)method
requestsWriter:(id<GRXWriter>)requestsWriter
responseClass:(Class)responseClass
responsesWriteable:(id<GRXWriteable>)responsesWriteable;
@end

@ -0,0 +1,81 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#import "ProtoService.h"
#import <gRPC/GRPCMethodName.h>
#import <gRPC/GRXWriteable.h>
#import <gRPC/GRXWriter.h>
#import "ProtoRPC.h"
@implementation ProtoService {
NSString *_host;
NSString *_packageName;
NSString *_serviceName;
}
- (instancetype)init {
return [self initWithHost:nil packageName:nil serviceName:nil];
}
// Designated initializer
- (instancetype)initWithHost:(NSString *)host
packageName:(NSString *)packageName
serviceName:(NSString *)serviceName {
if (!host || !serviceName) {
[NSException raise:NSInvalidArgumentException
format:@"Neither host nor serviceName can be nil."];
}
if ((self = [super init])) {
_host = [host copy];
_packageName = [packageName copy];
_serviceName = [serviceName copy];
}
return self;
}
- (ProtoRPC *)RPCToMethod:(NSString *)method
requestsWriter:(id<GRXWriter>)requestsWriter
responseClass:(Class)responseClass
responsesWriteable:(id<GRXWriteable>)responsesWriteable {
GRPCMethodName *methodName = [[GRPCMethodName alloc] initWithPackage:_packageName
interface:_serviceName
method:method];
return [[ProtoRPC alloc] initWithHost:_host
method:methodName
requestsWriter:requestsWriter
responseClass:responseClass
responsesWriteable:responsesWriteable];
}
@end

@ -50,10 +50,16 @@
typedef void (^GRXValueHandler)(id value); typedef void (^GRXValueHandler)(id value);
typedef void (^GRXCompletionHandler)(NSError *errorOrNil); typedef void (^GRXCompletionHandler)(NSError *errorOrNil);
typedef void (^GRXSingleValueHandler)(id value, NSError *errorOrNil);
typedef void (^GRXStreamHandler)(BOOL done, id value, NSError *error);
// Utility to create objects that conform to the GRXWriteable protocol, from // Utility to create objects that conform to the GRXWriteable protocol, from
// blocks that handle each of the two methods of the protocol. // blocks that handle each of the two methods of the protocol.
@interface GRXWriteable : NSObject<GRXWriteable> @interface GRXWriteable : NSObject<GRXWriteable>
+ (instancetype)writeableWithSingleValueHandler:(GRXSingleValueHandler)handler;
+ (instancetype)writeableWithStreamHandler:(GRXStreamHandler)handler;
- (instancetype)initWithValueHandler:(GRXValueHandler)valueHandler - (instancetype)initWithValueHandler:(GRXValueHandler)valueHandler
completionHandler:(GRXCompletionHandler)completionHandler completionHandler:(GRXCompletionHandler)completionHandler
NS_DESIGNATED_INITIALIZER; NS_DESIGNATED_INITIALIZER;

@ -38,6 +38,30 @@
GRXCompletionHandler _completionHandler; GRXCompletionHandler _completionHandler;
} }
+ (instancetype)writeableWithSingleValueHandler:(GRXSingleValueHandler)handler {
if (!handler) {
return [[self alloc] init];
}
return [[self alloc] initWithValueHandler:^(id value) {
handler(value, nil);
} completionHandler:^(NSError *errorOrNil) {
if (errorOrNil) {
handler(nil, errorOrNil);
}
}];
}
+ (instancetype)writeableWithStreamHandler:(GRXStreamHandler)handler {
if (!handler) {
return [[self alloc] init];
}
return [[self alloc] initWithValueHandler:^(id value) {
handler(NO, value, nil);
} completionHandler:^(NSError *errorOrNil) {
handler(YES, nil, errorOrNil);
}];
}
- (instancetype)init { - (instancetype)init {
return [self initWithValueHandler:nil completionHandler:nil]; return [self initWithValueHandler:nil completionHandler:nil];
} }

@ -14,4 +14,5 @@ Pod::Spec.new do |s|
s.requires_arc = true s.requires_arc = true
s.dependency 'ProtocolBuffers', '~> 1.9' s.dependency 'ProtocolBuffers', '~> 1.9'
s.dependency 'gRPC', '~> 0.0'
end end

@ -4,6 +4,7 @@
#import "Empty.pb.h" #import "Empty.pb.h"
#import "Messages.pb.h" #import "Messages.pb.h"
#import <gRPC/ProtoService.h>
// @@protoc_insertion_point(imports) // @@protoc_insertion_point(imports)
@class ObjectiveCFileOptions; @class ObjectiveCFileOptions;
@ -78,4 +79,89 @@
@end @end
@protocol GRXWriteable;
@protocol GRXWriter;
@protocol RMTTestService <NSObject>
#pragma mark EmptyCall(grpc.testing.Empty) returns (grpc.testing.Empty)
// One empty request followed by one empty response.
- (void)emptyCallWithRequest:(RMTEmpty *)request
handler:(void(^)(RMTEmpty *response, NSError *error))handler;
// Returns a not-yet-started RPC object.
- (ProtoRPC *)RPCToEmptyCallWithRequest:(RMTEmpty *)request
handler:(void(^)(RMTEmpty *response, NSError *error))handler;
#pragma mark UnaryCall(SimpleRequest) returns (SimpleResponse)
// One request followed by one response.
- (void)unaryCallWithRequest:(RMTSimpleRequest *)request
handler:(void(^)(RMTSimpleResponse *response, NSError *error))handler;
// Returns a not-yet-started RPC object.
- (ProtoRPC *)RPCToUnaryCallWithRequest:(RMTSimpleRequest *)request
handler:(void(^)(RMTSimpleResponse *response, NSError *error))handler;
#pragma mark StreamingOutputCall(StreamingOutputCallRequest) returns (stream StreamingOutputCallResponse)
// One request followed by a sequence of responses (streamed download).
// The server returns the payload with client desired type and sizes.
- (void)streamingOutputCallWithRequest:(RMTStreamingOutputCallRequest *)request
handler:(void(^)(BOOL done, RMTStreamingOutputCallResponse *response, NSError *error))handler;
// Returns a not-yet-started RPC object.
- (ProtoRPC *)RPCToStreamingOutputCallWithRequest:(RMTStreamingOutputCallRequest *)request
handler:(void(^)(BOOL done, RMTStreamingOutputCallResponse *response, NSError *error))handler;
#pragma mark StreamingInputCall(stream StreamingInputCallRequest) returns (StreamingInputCallResponse)
// A sequence of requests followed by one response (streamed upload).
// The server returns the aggregated size of client payload as the result.
- (void)streamingInputCallWithRequestsWriter:(id<GRXWriter>)request
handler:(void(^)(RMTStreamingInputCallResponse *response, NSError *error))handler;
// Returns a not-yet-started RPC object.
- (ProtoRPC *)RPCToStreamingInputCallWithRequestsWriter:(id<GRXWriter>)request
handler:(void(^)(RMTStreamingInputCallResponse *response, NSError *error))handler;
#pragma mark FullDuplexCall(stream StreamingOutputCallRequest) returns (stream StreamingOutputCallResponse)
// A sequence of requests with each request served by the server immediately.
// As one request could lead to multiple responses, this interface
// demonstrates the idea of full duplexing.
- (void)fullDuplexCallWithRequestsWriter:(id<GRXWriter>)request
handler:(void(^)(BOOL done, RMTStreamingOutputCallResponse *response, NSError *error))handler;
// Returns a not-yet-started RPC object.
- (ProtoRPC *)RPCToFullDuplexCallWithRequestsWriter:(id<GRXWriter>)request
handler:(void(^)(BOOL done, RMTStreamingOutputCallResponse *response, NSError *error))handler;
#pragma mark HalfDuplexCall(stream StreamingOutputCallRequest) returns (stream StreamingOutputCallResponse)
// A sequence of requests followed by a sequence of responses.
// The server buffers all the client requests and then serves them in order. A
// stream of responses are returned to the client when the server starts with
// first request.
- (void)halfDuplexCallWithRequestsWriter:(id<GRXWriter>)request
handler:(void(^)(BOOL done, RMTStreamingOutputCallResponse *response, NSError *error))handler;
// Returns a not-yet-started RPC object.
- (ProtoRPC *)RPCToHalfDuplexCallWithRequestsWriter:(id<GRXWriter>)request
handler:(void(^)(BOOL done, RMTStreamingOutputCallResponse *response, NSError *error))handler;
@end
// Basic service implementation, over gRPC, that only does marshalling and parsing.
@interface RMTTestService : ProtoService<RMTTestService>
- (instancetype)initWithHost:(NSString *)host NS_DESIGNATED_INITIALIZER;
@end
// @@protoc_insertion_point(global_scope) // @@protoc_insertion_point(global_scope)

@ -1,6 +1,10 @@
// Generated by the protocol buffer compiler. DO NOT EDIT! // Generated by the protocol buffer compiler. DO NOT EDIT!
#import "Test.pb.h" #import "Test.pb.h"
#import <gRPC/GRXWriteable.h>
#import <gRPC/GRXWriter+Immediate.h>
#import <gRPC/ProtoRPC.h>
// @@protoc_insertion_point(imports) // @@protoc_insertion_point(imports)
@implementation RMTTestRoot @implementation RMTTestRoot
@ -24,4 +28,136 @@ static PBExtensionRegistry* extensionRegistry = nil;
@end @end
static NSString *const kPackageName = @"grpc.testing";
static NSString *const kServiceName = @"TestService";
@implementation RMTTestService
// Designated initializer
- (instancetype)initWithHost:(NSString *)host {
return (self = [super initWithHost:host packageName:kPackageName serviceName:kServiceName]);
}
- (instancetype)initWithHost:(NSString *)host
packageName:(NSString *)packageName
serviceName:(NSString *)serviceName {
return [self initWithHost:host];
}
#pragma mark EmptyCall(grpc.testing.Empty) returns (grpc.testing.Empty)
// One empty request followed by one empty response.
- (void)emptyCallWithRequest:(RMTEmpty *)request
handler:(void(^)(RMTEmpty *response, NSError *error))handler {
[[self RPCToEmptyCallWithRequest:request handler:handler] start];
}
// Returns a not-yet-started RPC object.
- (ProtoRPC *)RPCToEmptyCallWithRequest:(RMTEmpty *)request
handler:(void(^)(RMTEmpty *response, NSError *error))handler {
return [self RPCToMethod:@"EmptyCall"
requestsWriter:[GRXWriter writerWithValue:request]
responseClass:[RMTEmpty class]
responsesWriteable:[GRXWriteable writeableWithSingleValueHandler:handler]];
}
#pragma mark UnaryCall(SimpleRequest) returns (SimpleResponse)
// One request followed by one response.
- (void)unaryCallWithRequest:(RMTSimpleRequest *)request
handler:(void(^)(RMTSimpleResponse *response, NSError *error))handler {
[[self RPCToUnaryCallWithRequest:request handler:handler] start];
}
// Returns a not-yet-started RPC object.
- (ProtoRPC *)RPCToUnaryCallWithRequest:(RMTSimpleRequest *)request
handler:(void(^)(RMTSimpleResponse *response, NSError *error))handler {
return [self RPCToMethod:@"UnaryCall"
requestsWriter:[GRXWriter writerWithValue:request]
responseClass:[RMTSimpleResponse class]
responsesWriteable:[GRXWriteable writeableWithSingleValueHandler:handler]];
}
#pragma mark StreamingOutputCall(StreamingOutputCallRequest) returns (stream StreamingOutputCallResponse)
// One request followed by a sequence of responses (streamed download).
// The server returns the payload with client desired type and sizes.
- (void)streamingOutputCallWithRequest:(RMTStreamingOutputCallRequest *)request
handler:(void(^)(BOOL done, RMTStreamingOutputCallResponse *response, NSError *error))handler {
[[self RPCToStreamingOutputCallWithRequest:request handler:handler] start];
}
// Returns a not-yet-started RPC object.
- (ProtoRPC *)RPCToStreamingOutputCallWithRequest:(RMTStreamingOutputCallRequest *)request
handler:(void(^)(BOOL done, RMTStreamingOutputCallResponse *response, NSError *error))handler {
return [self RPCToMethod:@"StreamingOutputCall"
requestsWriter:[GRXWriter writerWithValue:request]
responseClass:[RMTStreamingOutputCallResponse class]
responsesWriteable:[GRXWriteable writeableWithStreamHandler:handler]];
}
#pragma mark StreamingInputCall(stream StreamingInputCallRequest) returns (StreamingInputCallResponse)
// A sequence of requests followed by one response (streamed upload).
// The server returns the aggregated size of client payload as the result.
- (void)streamingInputCallWithRequestsWriter:(id<GRXWriter>)requestsWriter
handler:(void(^)(RMTStreamingInputCallResponse *response, NSError *error))handler {
[[self RPCToStreamingInputCallWithRequestsWriter:requestsWriter handler:handler] start];
}
// Returns a not-yet-started RPC object.
- (ProtoRPC *)RPCToStreamingInputCallWithRequestsWriter:(id<GRXWriter>)requestsWriter
handler:(void(^)(RMTStreamingInputCallResponse *response, NSError *error))handler {
return [self RPCToMethod:@"StreamingInputCall"
requestsWriter:requestsWriter
responseClass:[RMTStreamingInputCallResponse class]
responsesWriteable:[GRXWriteable writeableWithSingleValueHandler:handler]];
}
#pragma mark FullDuplexCall(stream StreamingOutputCallRequest) returns (stream StreamingOutputCallResponse)
// A sequence of requests with each request served by the server immediately.
// As one request could lead to multiple responses, this interface
// demonstrates the idea of full duplexing.
- (void)fullDuplexCallWithRequestsWriter:(id<GRXWriter>)requestsWriter
handler:(void(^)(BOOL done, RMTStreamingOutputCallResponse *response, NSError *error))handler {
[[self RPCToFullDuplexCallWithRequestsWriter:requestsWriter handler:handler] start];
}
// Returns a not-yet-started RPC object.
- (ProtoRPC *)RPCToFullDuplexCallWithRequestsWriter:(id<GRXWriter>)requestsWriter
handler:(void(^)(BOOL done, RMTStreamingOutputCallResponse *response, NSError *error))handler {
return [self RPCToMethod:@"FullDuplexCall"
requestsWriter:requestsWriter
responseClass:[RMTStreamingOutputCallResponse class]
responsesWriteable:[GRXWriteable writeableWithStreamHandler:handler]];
}
#pragma mark HalfDuplexCall(stream StreamingOutputCallRequest) returns (stream StreamingOutputCallResponse)
// A sequence of requests followed by a sequence of responses.
// The server buffers all the client requests and then serves them in order. A
// stream of responses are returned to the client when the server starts with
// first request.
- (void)halfDuplexCallWithRequestsWriter:(id<GRXWriter>)requestsWriter
handler:(void(^)(BOOL done, RMTStreamingOutputCallResponse *response, NSError *error))handler {
[[self RPCToHalfDuplexCallWithRequestsWriter:requestsWriter handler:handler] start];
}
// Returns a not-yet-started RPC object.
- (ProtoRPC *)RPCToHalfDuplexCallWithRequestsWriter:(id<GRXWriter>)requestsWriter
handler:(void(^)(BOOL done, RMTStreamingOutputCallResponse *response, NSError *error))handler {
return [self RPCToMethod:@"HalfDuplexCall"
requestsWriter:requestsWriter
responseClass:[RMTStreamingOutputCallResponse class]
responsesWriteable:[GRXWriteable writeableWithStreamHandler:handler]];
}
@end
// @@protoc_insertion_point(global_scope) // @@protoc_insertion_point(global_scope)

@ -8,6 +8,8 @@
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
60BBBBB15823BBF7639D7AA9 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DC7B7C4C0410F43B9621631 /* libPods.a */; }; 60BBBBB15823BBF7639D7AA9 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DC7B7C4C0410F43B9621631 /* libPods.a */; };
6340F0491AE66E3300FB6A3D /* RemoteProtoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6340F0481AE66E3300FB6A3D /* RemoteProtoTests.m */; };
6356D1DE1AC11FE00075FBBC /* RemoteTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6356D1DD1AC11FE00075FBBC /* RemoteTests.m */; };
6369A2701A9322E20015FC5C /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6369A26F1A9322E20015FC5C /* main.m */; }; 6369A2701A9322E20015FC5C /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6369A26F1A9322E20015FC5C /* main.m */; };
6369A2731A9322E20015FC5C /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6369A2721A9322E20015FC5C /* AppDelegate.m */; }; 6369A2731A9322E20015FC5C /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6369A2721A9322E20015FC5C /* AppDelegate.m */; };
6369A2761A9322E20015FC5C /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6369A2751A9322E20015FC5C /* ViewController.m */; }; 6369A2761A9322E20015FC5C /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6369A2751A9322E20015FC5C /* ViewController.m */; };
@ -15,7 +17,6 @@
6369A27B1A9322E20015FC5C /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6369A27A1A9322E20015FC5C /* Images.xcassets */; }; 6369A27B1A9322E20015FC5C /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6369A27A1A9322E20015FC5C /* Images.xcassets */; };
6369A27E1A9322E20015FC5C /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6369A27C1A9322E20015FC5C /* LaunchScreen.xib */; }; 6369A27E1A9322E20015FC5C /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6369A27C1A9322E20015FC5C /* LaunchScreen.xib */; };
6369A28A1A9322E20015FC5C /* SampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6369A2891A9322E20015FC5C /* SampleTests.m */; }; 6369A28A1A9322E20015FC5C /* SampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6369A2891A9322E20015FC5C /* SampleTests.m */; };
63D886A71AE73797000580D7 /* RemoteTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 63D886A61AE73797000580D7 /* RemoteTests.m */; };
FC81FE63CA655031F3524EC0 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DC7B7C4C0410F43B9621631 /* libPods.a */; }; FC81FE63CA655031F3524EC0 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2DC7B7C4C0410F43B9621631 /* libPods.a */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
@ -31,6 +32,8 @@
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
2DC7B7C4C0410F43B9621631 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; }; 2DC7B7C4C0410F43B9621631 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
6340F0481AE66E3300FB6A3D /* RemoteProtoTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RemoteProtoTests.m; sourceTree = "<group>"; };
6356D1DD1AC11FE00075FBBC /* RemoteTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RemoteTests.m; sourceTree = "<group>"; };
6369A26A1A9322E20015FC5C /* Sample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Sample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 6369A26A1A9322E20015FC5C /* Sample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Sample.app; sourceTree = BUILT_PRODUCTS_DIR; };
6369A26E1A9322E20015FC5C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 6369A26E1A9322E20015FC5C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
6369A26F1A9322E20015FC5C /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; }; 6369A26F1A9322E20015FC5C /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
@ -44,7 +47,6 @@
6369A2831A9322E20015FC5C /* SampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 6369A2831A9322E20015FC5C /* SampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
6369A2881A9322E20015FC5C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 6369A2881A9322E20015FC5C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
6369A2891A9322E20015FC5C /* SampleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SampleTests.m; sourceTree = "<group>"; }; 6369A2891A9322E20015FC5C /* SampleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SampleTests.m; sourceTree = "<group>"; };
63D886A61AE73797000580D7 /* RemoteTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RemoteTests.m; sourceTree = "<group>"; };
AC29DD6FCDF962F519FEBB0D /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = "<group>"; }; AC29DD6FCDF962F519FEBB0D /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = "<group>"; };
C68330F8D451CC6ACEABA09F /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = "<group>"; }; C68330F8D451CC6ACEABA09F /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
@ -116,9 +118,10 @@
6369A2861A9322E20015FC5C /* SampleTests */ = { 6369A2861A9322E20015FC5C /* SampleTests */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
63D886A61AE73797000580D7 /* RemoteTests.m */, 6340F0481AE66E3300FB6A3D /* RemoteProtoTests.m */,
6369A2891A9322E20015FC5C /* SampleTests.m */, 6369A2891A9322E20015FC5C /* SampleTests.m */,
6369A2871A9322E20015FC5C /* Supporting Files */, 6369A2871A9322E20015FC5C /* Supporting Files */,
6356D1DD1AC11FE00075FBBC /* RemoteTests.m */,
); );
path = SampleTests; path = SampleTests;
sourceTree = "<group>"; sourceTree = "<group>";
@ -326,7 +329,8 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
6369A28A1A9322E20015FC5C /* SampleTests.m in Sources */, 6369A28A1A9322E20015FC5C /* SampleTests.m in Sources */,
63D886A71AE73797000580D7 /* RemoteTests.m in Sources */, 6340F0491AE66E3300FB6A3D /* RemoteProtoTests.m in Sources */,
6356D1DE1AC11FE00075FBBC /* RemoteTests.m in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };

@ -0,0 +1,90 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#import <UIKit/UIKit.h>
#import <XCTest/XCTest.h>
#import <RemoteTest/Messages.pb.h>
#import <RemoteTest/Test.pb.h>
@interface RemoteProtoTests : XCTestCase
@end
@implementation RemoteProtoTests {
RMTTestService *_service;
}
- (void)setUp {
_service = [[RMTTestService alloc] initWithHost:@"grpc-test.sandbox.google.com"];
}
- (void)testEmptyRPC {
__weak XCTestExpectation *noRPCError = [self expectationWithDescription:@"RPC succeeded."];
__weak XCTestExpectation *responded = [self expectationWithDescription:@"Response received."];
[_service emptyCallWithRequest:[RMTEmpty defaultInstance]
handler:^(RMTEmpty *response, NSError *error) {
XCTAssertNil(error, @"Finished with unexpected error: %@", error);
[noRPCError fulfill];
XCTAssertNotNil(response, @"nil response received.");
[responded fulfill];
}];
[self waitForExpectationsWithTimeout:2. handler:nil];
}
- (void)testSimpleProtoRPC {
__weak XCTestExpectation *noRPCError = [self expectationWithDescription:@"RPC succeeded."];
__weak XCTestExpectation *responded = [self expectationWithDescription:@"Response received."];
__weak XCTestExpectation *validResponse = [self expectationWithDescription:@"Valid response."];
RMTSimpleRequest *request = [[[[[[RMTSimpleRequestBuilder alloc] init]
setResponseSize:100]
setFillUsername:YES]
setFillOauthScope:YES]
build];
[_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) {
XCTAssertNil(error, @"Finished with unexpected error: %@", error);
[noRPCError fulfill];
XCTAssertNotNil(response, @"nil response received.");
[responded fulfill];
// We expect empty strings, not nil:
XCTAssertNotNil(response.username, @"Response's username is nil.");
XCTAssertNotNil(response.oauthScope, @"Response's OAuth scope is nil.");
[validResponse fulfill];
}];
[self waitForExpectationsWithTimeout:2. handler:nil];
}
@end
Loading…
Cancel
Save