Let override default response size limit

Still missing: Catch the C-library error to improve the error message.
pull/7572/head
Jorge Canizales 9 years ago
parent a062a7f2c5
commit 6af4addd55
  1. 4
      src/objective-c/GRPCClient/GRPCCall+ChannelArg.h
  2. 11
      src/objective-c/GRPCClient/GRPCCall+ChannelArg.m
  3. 6
      src/objective-c/GRPCClient/GRPCCall+Tests.h
  4. 3
      src/objective-c/GRPCClient/GRPCCall+Tests.m
  5. 16
      src/objective-c/GRPCClient/private/GRPCChannel.m
  6. 5
      src/objective-c/GRPCClient/private/GRPCHost.h
  7. 12
      src/objective-c/GRPCClient/private/GRPCHost.m
  8. 64
      src/objective-c/tests/InteropTests.m

@ -43,7 +43,9 @@
* Use the provided @c userAgentPrefix at the beginning of the HTTP User Agent string for all calls
* to the specified @c host.
*/
+ (void)setUserAgentPrefix:(NSString *)userAgentPrefix forHost:(NSString *)host;
+ (void)setUserAgentPrefix:(nonnull NSString *)userAgentPrefix forHost:(nonnull NSString *)host;
+ (void)setResponseSizeLimit:(NSUInteger)limit forHost:(nonnull NSString *)host;
+ (void)closeOpenConnections DEPRECATED_MSG_ATTRIBUTE("The API for this feature is experimental, "
"and might be removed or modified at any "

@ -37,15 +37,16 @@
@implementation GRPCCall (ChannelArg)
+ (void)setUserAgentPrefix:(NSString *)userAgentPrefix forHost:(NSString *)host {
if (!host) {
[NSException raise:NSInvalidArgumentException
format:@"host and userAgentPrefix must be provided."];
}
+ (void)setUserAgentPrefix:(nonnull NSString *)userAgentPrefix forHost:(nonnull NSString *)host {
GRPCHost *hostConfig = [GRPCHost hostWithAddress:host];
hostConfig.userAgentPrefix = userAgentPrefix;
}
+ (void)setResponseSizeLimit:(NSUInteger)limit forHost:(nonnull NSString *)host {
GRPCHost *hostConfig = [GRPCHost hostWithAddress:host];
hostConfig.responseSizeLimitOverride = @(limit);
}
+ (void)closeOpenConnections {
[GRPCHost flushChannelCache];
}

@ -57,4 +57,10 @@
* more than one invocation of the methods of this category.
*/
+ (void)useInsecureConnectionsForHost:(NSString *)host;
/**
* Resets all host configurations to their default values, and flushes all connections from the
* cache.
*/
+ (void)clearAllConfigurationsForTesting;
@end

@ -61,4 +61,7 @@
hostConfig.secure = NO;
}
+ (void)clearAllConfigurationsForTesting {
[GRPCHost clearAllHostsForTesting];
}
@end

@ -47,7 +47,7 @@
#endif
#import "GRPCCompletionQueue.h"
void freeChannelArgs(grpc_channel_args *channel_args) {
static void FreeChannelArgs(grpc_channel_args *channel_args) {
for (size_t i = 0; i < channel_args->num_args; ++i) {
grpc_arg *arg = &channel_args->args[i];
gpr_free(arg->key);
@ -65,7 +65,7 @@ void freeChannelArgs(grpc_channel_args *channel_args) {
* value responds to @c @selector(intValue). Otherwise, an exception will be raised. The caller of
* this function is responsible for calling @c freeChannelArgs on a non-NULL returned value.
*/
grpc_channel_args * buildChannelArgs(NSDictionary *dictionary) {
static grpc_channel_args *BuildChannelArgs(NSDictionary *dictionary) {
if (!dictionary) {
return NULL;
}
@ -115,10 +115,12 @@ grpc_channel_args * buildChannelArgs(NSDictionary *dictionary) {
}
if (self = [super init]) {
_channelArgs = buildChannelArgs(channelArgs);
_channelArgs = BuildChannelArgs(channelArgs);
_host = [host copy];
_unmanagedChannel = grpc_cronet_secure_channel_create(cronetEngine, _host.UTF8String, _channelArgs,
NULL);
_unmanagedChannel = grpc_cronet_secure_channel_create(cronetEngine,
_host.UTF8String,
_channelArgs,
NULL);
}
return self;
@ -138,7 +140,7 @@ grpc_channel_args * buildChannelArgs(NSDictionary *dictionary) {
}
if (self = [super init]) {
_channelArgs = buildChannelArgs(channelArgs);
_channelArgs = BuildChannelArgs(channelArgs);
_host = [host copy];
if (secure) {
_unmanagedChannel = grpc_secure_channel_create(credentials, _host.UTF8String, _channelArgs,
@ -155,7 +157,7 @@ grpc_channel_args * buildChannelArgs(NSDictionary *dictionary) {
// TODO(jcanizales): Be sure to add a test with a server that closes the connection prematurely,
// as in the past that made this call to crash.
grpc_channel_destroy(_unmanagedChannel);
freeChannelArgs(_channelArgs);
FreeChannelArgs(_channelArgs);
}
#ifdef GRPC_COMPILE_WITH_CRONET

@ -42,6 +42,7 @@ struct grpc_channel_credentials;
@interface GRPCHost : NSObject
+ (void)flushChannelCache;
+ (void)clearAllHostsForTesting;
@property(nonatomic, readonly) NSString *address;
@property(nonatomic, copy, nullable) NSString *userAgentPrefix;
@ -53,6 +54,10 @@ struct grpc_channel_credentials;
@property(nonatomic, copy, nullable) NSString *hostNameOverride;
/** The default response size limit is 4MB. Set this to override that default. */
@property(nonatomic, strong, nullable) NSNumber *responseSizeLimitOverride;
- (nullable instancetype)init NS_UNAVAILABLE;
/** Host objects initialized with the same address are the same. */
+ (nullable instancetype)hostWithAddress:(NSString *)address;

@ -49,7 +49,7 @@ NS_ASSUME_NONNULL_BEGIN
// TODO(jcanizales): Generate the version in a standalone header, from templates. Like
// templates/src/core/surface/version.c.template .
#define GRPC_OBJC_VERSION_STRING @"0.13.0"
#define GRPC_OBJC_VERSION_STRING @"1.0.0-pre1"
static NSMutableDictionary *kHostCache;
@ -113,6 +113,12 @@ static NSMutableDictionary *kHostCache;
}
}
+ (void)clearAllHostsForTesting {
@synchronized (kHostCache) {
kHostCache = [NSMutableDictionary dictionary];
}
}
- (nullable grpc_call *)unmanagedCallWithPath:(NSString *)path
completionQueue:(GRPCCompletionQueue *)queue {
GRPCChannel *channel;
@ -209,6 +215,10 @@ static NSMutableDictionary *kHostCache;
if (_secure && _hostNameOverride) {
args[@GRPC_SSL_TARGET_NAME_OVERRIDE_ARG] = _hostNameOverride;
}
if (_responseSizeLimitOverride) {
args[@GRPC_ARG_MAX_MESSAGE_LENGTH] = _responseSizeLimitOverride;
}
return args;
}

@ -80,10 +80,6 @@
#pragma mark Tests
#ifdef GRPC_COMPILE_WITH_CRONET
static cronet_engine *cronetEngine = NULL;
#endif
@implementation InteropTests {
RMTTestService *_service;
}
@ -93,14 +89,17 @@ static cronet_engine *cronetEngine = NULL;
}
- (void)setUp {
self.continueAfterFailure = NO;
[GRPCCall clearAllConfigurationsForTesting];
_service = self.class.host ? [RMTTestService serviceWithHost:self.class.host] : nil;
#ifdef GRPC_COMPILE_WITH_CRONET
if (cronetEngine == NULL) {
// Cronet setup
[Cronet setHttp2Enabled:YES];
[Cronet start];
cronetEngine = [Cronet getGlobalEngine];
[GRPCCall useCronetWithEngine:cronetEngine];
[GRPCCall useCronetWithEngine:[Cronet getGlobalEngine]];
}
#endif
}
@ -146,6 +145,59 @@ static cronet_engine *cronetEngine = NULL;
[self waitForExpectationsWithTimeout:16 handler:nil];
}
- (void)test4MBResponsesAreAccepted {
XCTAssertNotNil(self.class.host);
__weak XCTestExpectation *expectation = [self expectationWithDescription:@"MaxResponseSize"];
RMTSimpleRequest *request = [RMTSimpleRequest message];
const size_t kPayloadSize = 4 * 1024 * 1024 - 12; // 4MB - 12B of protobuf encoding overhead
request.responseSize = kPayloadSize;
[_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) {
XCTAssertNil(error, @"Finished with unexpected error: %@", error);
XCTAssertEqual(response.payload.body.length, kPayloadSize);
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:16 handler:nil];
}
- (void)testResponsesOverMaxSizeFailWithActionableMessage {
XCTAssertNotNil(self.class.host);
__weak XCTestExpectation *expectation = [self expectationWithDescription:@"ResponseOverMaxSize"];
RMTSimpleRequest *request = [RMTSimpleRequest message];
const size_t kPayloadSize = 4 * 1024 * 1024 - 11; // 1B over max size (see above test)
request.responseSize = kPayloadSize;
[_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) {
XCTAssertEqualObjects(error.localizedDescription, @"Max message size exceeded"); // TODO: Improve
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:16 handler:nil];
}
- (void)testResponsesOver4MBAreAcceptedIfOptedIn {
XCTAssertNotNil(self.class.host);
__weak XCTestExpectation *expectation =
[self expectationWithDescription:@"HigherResponseSizeLimit"];
RMTSimpleRequest *request = [RMTSimpleRequest message];
const size_t kPayloadSize = 5 * 1024 * 1024; // 5MB
request.responseSize = kPayloadSize;
[GRPCCall setResponseSizeLimit:6 * 1024 * 1024 forHost:self.class.host];
[_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) {
XCTAssertNil(error, @"Finished with unexpected error: %@", error);
XCTAssertEqual(response.payload.body.length, kPayloadSize);
[expectation fulfill];
}];
[self waitForExpectationsWithTimeout:16 handler:nil];
}
- (void)testClientStreamingRPC {
XCTAssertNotNil(self.class.host);
__weak XCTestExpectation *expectation = [self expectationWithDescription:@"ClientStreaming"];

Loading…
Cancel
Save