commit
898d84d309
71 changed files with 3551 additions and 585 deletions
After Width: | Height: | Size: 39 KiB |
@ -0,0 +1,394 @@ |
||||
/* |
||||
* |
||||
* 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. |
||||
* |
||||
*/ |
||||
|
||||
/* |
||||
* This test file is derived from fixture h2_ssl.c in core end2end test |
||||
* (test/core/end2end/fixture/h2_ssl.c). The structure of the fixture is |
||||
* preserved as much as possible |
||||
* |
||||
* This fixture creates a server full stack using chttp2 and a client |
||||
* full stack using Cronet. End-to-end tests are run against this |
||||
* configuration |
||||
* |
||||
*/ |
||||
|
||||
|
||||
#import <XCTest/XCTest.h> |
||||
#include "test/core/end2end/end2end_tests.h" |
||||
|
||||
#include <stdio.h> |
||||
#include <string.h> |
||||
|
||||
#include <grpc/support/alloc.h> |
||||
#include <grpc/support/host_port.h> |
||||
#include <grpc/support/log.h> |
||||
|
||||
#include "src/core/lib/channel/channel_args.h" |
||||
#include "src/core/lib/security/credentials/credentials.h" |
||||
#include "src/core/lib/support/env.h" |
||||
#include "src/core/lib/support/string.h" |
||||
#include "src/core/lib/support/tmpfile.h" |
||||
#include "test/core/end2end/data/ssl_test_data.h" |
||||
#include "test/core/util/port.h" |
||||
#include "test/core/util/test_config.h" |
||||
|
||||
#include <grpc/grpc_cronet.h> |
||||
#import <Cronet/Cronet.h> |
||||
|
||||
typedef struct fullstack_secure_fixture_data { |
||||
char *localaddr; |
||||
} fullstack_secure_fixture_data; |
||||
|
||||
static grpc_end2end_test_fixture chttp2_create_fixture_secure_fullstack( |
||||
grpc_channel_args *client_args, grpc_channel_args *server_args) { |
||||
grpc_end2end_test_fixture f; |
||||
int port = grpc_pick_unused_port_or_die(); |
||||
fullstack_secure_fixture_data *ffd = |
||||
gpr_malloc(sizeof(fullstack_secure_fixture_data)); |
||||
memset(&f, 0, sizeof(f)); |
||||
|
||||
gpr_join_host_port(&ffd->localaddr, "localhost", port); |
||||
|
||||
f.fixture_data = ffd; |
||||
f.cq = grpc_completion_queue_create(NULL); |
||||
|
||||
return f; |
||||
} |
||||
|
||||
static void process_auth_failure(void *state, grpc_auth_context *ctx, |
||||
const grpc_metadata *md, size_t md_count, |
||||
grpc_process_auth_metadata_done_cb cb, |
||||
void *user_data) { |
||||
GPR_ASSERT(state == NULL); |
||||
cb(user_data, NULL, 0, NULL, 0, GRPC_STATUS_UNAUTHENTICATED, NULL); |
||||
} |
||||
|
||||
static void cronet_init_client_secure_fullstack( |
||||
grpc_end2end_test_fixture *f, grpc_channel_args *client_args, |
||||
cronet_engine *cronetEngine) { |
||||
fullstack_secure_fixture_data *ffd = f->fixture_data; |
||||
f->client = |
||||
grpc_cronet_secure_channel_create(cronetEngine, ffd->localaddr, client_args, NULL); |
||||
GPR_ASSERT(f->client != NULL); |
||||
} |
||||
|
||||
static void chttp2_init_server_secure_fullstack( |
||||
grpc_end2end_test_fixture *f, grpc_channel_args *server_args, |
||||
grpc_server_credentials *server_creds) { |
||||
fullstack_secure_fixture_data *ffd = f->fixture_data; |
||||
if (f->server) { |
||||
grpc_server_destroy(f->server); |
||||
} |
||||
f->server = grpc_server_create(server_args, NULL); |
||||
grpc_server_register_completion_queue(f->server, f->cq, NULL); |
||||
GPR_ASSERT(grpc_server_add_secure_http2_port(f->server, ffd->localaddr, |
||||
server_creds)); |
||||
grpc_server_credentials_release(server_creds); |
||||
grpc_server_start(f->server); |
||||
} |
||||
|
||||
static void chttp2_tear_down_secure_fullstack(grpc_end2end_test_fixture *f) { |
||||
fullstack_secure_fixture_data *ffd = f->fixture_data; |
||||
gpr_free(ffd->localaddr); |
||||
gpr_free(ffd); |
||||
} |
||||
|
||||
static void cronet_init_client_simple_ssl_secure_fullstack( |
||||
grpc_end2end_test_fixture *f, grpc_channel_args *client_args) { |
||||
grpc_arg ssl_name_override = {GRPC_ARG_STRING, |
||||
GRPC_SSL_TARGET_NAME_OVERRIDE_ARG, |
||||
{"foo.test.google.fr"}}; |
||||
|
||||
grpc_channel_args *new_client_args = |
||||
grpc_channel_args_copy_and_add(client_args, &ssl_name_override, 1); |
||||
[Cronet setHttp2Enabled:YES]; |
||||
[Cronet start]; |
||||
cronet_engine *cronetEngine = [Cronet getGlobalEngine]; |
||||
|
||||
cronet_init_client_secure_fullstack(f, new_client_args, cronetEngine); |
||||
grpc_channel_args_destroy(new_client_args); |
||||
} |
||||
|
||||
static int fail_server_auth_check(grpc_channel_args *server_args) { |
||||
size_t i; |
||||
if (server_args == NULL) return 0; |
||||
for (i = 0; i < server_args->num_args; i++) { |
||||
if (strcmp(server_args->args[i].key, FAIL_AUTH_CHECK_SERVER_ARG_NAME) == |
||||
0) { |
||||
return 1; |
||||
} |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
static void chttp2_init_server_simple_ssl_secure_fullstack( |
||||
grpc_end2end_test_fixture *f, grpc_channel_args *server_args) { |
||||
grpc_ssl_pem_key_cert_pair pem_cert_key_pair = {test_server1_key, |
||||
test_server1_cert}; |
||||
grpc_server_credentials *ssl_creds = |
||||
grpc_ssl_server_credentials_create(NULL, &pem_cert_key_pair, 1, 0, NULL); |
||||
if (fail_server_auth_check(server_args)) { |
||||
grpc_auth_metadata_processor processor = {process_auth_failure, NULL, NULL}; |
||||
grpc_server_credentials_set_auth_metadata_processor(ssl_creds, processor); |
||||
} |
||||
chttp2_init_server_secure_fullstack(f, server_args, ssl_creds); |
||||
} |
||||
|
||||
/* All test configurations */ |
||||
|
||||
static grpc_end2end_test_config configs[] = { |
||||
{"chttp2/simple_ssl_fullstack", |
||||
FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | |
||||
FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS, |
||||
chttp2_create_fixture_secure_fullstack, |
||||
cronet_init_client_simple_ssl_secure_fullstack, |
||||
chttp2_init_server_simple_ssl_secure_fullstack, |
||||
chttp2_tear_down_secure_fullstack}, |
||||
}; |
||||
|
||||
|
||||
|
||||
static char *roots_filename; |
||||
|
||||
@interface CoreCronetEnd2EndTests : XCTestCase |
||||
|
||||
@end |
||||
|
||||
@implementation CoreCronetEnd2EndTests |
||||
|
||||
|
||||
// The setUp() function is run before the test cases run and only run once |
||||
+ (void)setUp { |
||||
[super setUp]; |
||||
|
||||
FILE *roots_file; |
||||
size_t roots_size = strlen(test_root_cert); |
||||
|
||||
char *argv[] = {"CoreCronetEnd2EndTests"}; |
||||
grpc_test_init(1, argv); |
||||
grpc_end2end_tests_pre_init(); |
||||
|
||||
/* Set the SSL roots env var. */ |
||||
roots_file = gpr_tmpfile("chttp2_simple_ssl_fullstack_test", &roots_filename); |
||||
GPR_ASSERT(roots_filename != NULL); |
||||
GPR_ASSERT(roots_file != NULL); |
||||
GPR_ASSERT(fwrite(test_root_cert, 1, roots_size, roots_file) == roots_size); |
||||
fclose(roots_file); |
||||
gpr_setenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR, roots_filename); |
||||
|
||||
grpc_init(); |
||||
|
||||
} |
||||
|
||||
// The tearDown() function is run after all test cases finish running |
||||
+ (void)tearDown { |
||||
grpc_shutdown(); |
||||
|
||||
/* Cleanup. */ |
||||
remove(roots_filename); |
||||
gpr_free(roots_filename); |
||||
|
||||
[super tearDown]; |
||||
} |
||||
|
||||
- (void)testIndividualCase:(char*)test_case { |
||||
char *argv[] = {"h2_ssl", test_case}; |
||||
|
||||
for (int i = 0; i < sizeof(configs) / sizeof(*configs); i++) { |
||||
grpc_end2end_tests(sizeof(argv) / sizeof(argv[0]), argv, configs[i]); |
||||
} |
||||
} |
||||
|
||||
// TODO(mxyan): Use NSStringFromSelector(_cmd) to acquire test name from the |
||||
// test case method name, so that bodies of test cases can stay identical |
||||
- (void)testBadHostname { |
||||
[self testIndividualCase:"bad_hostname"]; |
||||
} |
||||
|
||||
- (void)testBinaryMetadata { |
||||
[self testIndividualCase:"binary_metadata"]; |
||||
} |
||||
|
||||
- (void)testCallCreds { |
||||
[self testIndividualCase:"call_creds"]; |
||||
} |
||||
|
||||
- (void)testCancelAfterAccept { |
||||
[self testIndividualCase:"cancel_after_accept"]; |
||||
} |
||||
|
||||
- (void)testCancelAfterClientDone { |
||||
[self testIndividualCase:"cancel_after_client_done"]; |
||||
} |
||||
|
||||
- (void)testCancelAfterInvoke { |
||||
[self testIndividualCase:"cancel_after_invoke"]; |
||||
} |
||||
|
||||
- (void)testCancelBeforeInvoke { |
||||
[self testIndividualCase:"cancel_before_invoke"]; |
||||
} |
||||
|
||||
- (void)testCancelInAVacuum { |
||||
[self testIndividualCase:"cancel_in_a_vacuum"]; |
||||
} |
||||
|
||||
- (void)testCancelWithStatus { |
||||
[self testIndividualCase:"cancel_with_status"]; |
||||
} |
||||
|
||||
- (void)testCompressedPayload { |
||||
[self testIndividualCase:"compressed_payload"]; |
||||
} |
||||
|
||||
- (void)testConnectivity { |
||||
[self testIndividualCase:"connectivity"]; |
||||
} |
||||
|
||||
- (void)testDefaultHost { |
||||
[self testIndividualCase:"default_host"]; |
||||
} |
||||
|
||||
- (void)testDisappearingServer { |
||||
[self testIndividualCase:"disappearing_server"]; |
||||
} |
||||
|
||||
- (void)testEmptyBatch { |
||||
[self testIndividualCase:"empty_batch"]; |
||||
} |
||||
|
||||
- (void)testFilterCausesClose { |
||||
[self testIndividualCase:"filter_causes_close"]; |
||||
} |
||||
|
||||
- (void)testGracefulServerShutdown { |
||||
[self testIndividualCase:"graceful_server_shutdown"]; |
||||
} |
||||
|
||||
- (void)testHighInitialSeqno { |
||||
[self testIndividualCase:"high_initial_seqno"]; |
||||
} |
||||
|
||||
- (void)testHpackSize { |
||||
[self testIndividualCase:"hpack_size"]; |
||||
} |
||||
|
||||
- (void)testIdempotentRequest { |
||||
[self testIndividualCase:"idempotent_request"]; |
||||
} |
||||
|
||||
- (void)testInvokeLargeRequest { |
||||
[self testIndividualCase:"invoke_large_request"]; |
||||
} |
||||
|
||||
- (void)testLargeMetadata { |
||||
[self testIndividualCase:"large_metadata"]; |
||||
} |
||||
|
||||
- (void)testMaxConcurrentStreams { |
||||
[self testIndividualCase:"max_concurrent_streams"]; |
||||
} |
||||
|
||||
- (void)testMaxMessageLength { |
||||
[self testIndividualCase:"max_message_length"]; |
||||
} |
||||
|
||||
- (void)testNegativeDeadline { |
||||
[self testIndividualCase:"negative_deadline"]; |
||||
} |
||||
|
||||
- (void)testNetworkStatusChange { |
||||
[self testIndividualCase:"network_status_change"]; |
||||
} |
||||
|
||||
- (void)testNoOp { |
||||
[self testIndividualCase:"no_op"]; |
||||
} |
||||
|
||||
- (void)testPayload { |
||||
[self testIndividualCase:"payload"]; |
||||
} |
||||
|
||||
- (void)testPing { |
||||
[self testIndividualCase:"ping"]; |
||||
} |
||||
|
||||
- (void)testPingPongStreaming { |
||||
[self testIndividualCase:"ping_pong_streaming"]; |
||||
} |
||||
|
||||
- (void)testRegisteredCall { |
||||
[self testIndividualCase:"registered_call"]; |
||||
} |
||||
|
||||
- (void)testRequestWithFlags { |
||||
[self testIndividualCase:"request_with_flags"]; |
||||
} |
||||
|
||||
- (void)testRequestWithPayload { |
||||
[self testIndividualCase:"request_with_payload"]; |
||||
} |
||||
|
||||
- (void)testServerFinishesRequest { |
||||
[self testIndividualCase:"server_finishes_request"]; |
||||
} |
||||
|
||||
- (void)testShutdownFinishesCalls { |
||||
[self testIndividualCase:"shutdown_finishes_calls"]; |
||||
} |
||||
|
||||
- (void)testShutdownFinishesTags { |
||||
[self testIndividualCase:"shutdown_finishes_tags"]; |
||||
} |
||||
|
||||
- (void)testSimpleDelayedRequest { |
||||
[self testIndividualCase:"simple_delayed_request"]; |
||||
} |
||||
|
||||
- (void)testSimpleMetadata { |
||||
[self testIndividualCase:"simple_metadata"]; |
||||
} |
||||
|
||||
- (void)testSimpleRequest { |
||||
[self testIndividualCase:"simple_request"]; |
||||
} |
||||
|
||||
- (void)testStreamingErrorResponse { |
||||
[self testIndividualCase:"streaming_error_response"]; |
||||
} |
||||
|
||||
- (void)testTrailingMetadata { |
||||
[self testIndividualCase:"trailing_metadata"]; |
||||
} |
||||
|
||||
@end |
@ -0,0 +1,24 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> |
||||
<plist version="1.0"> |
||||
<dict> |
||||
<key>CFBundleDevelopmentRegion</key> |
||||
<string>en</string> |
||||
<key>CFBundleExecutable</key> |
||||
<string>$(EXECUTABLE_NAME)</string> |
||||
<key>CFBundleIdentifier</key> |
||||
<string>gRPC.$(PRODUCT_NAME:rfc1034identifier)</string> |
||||
<key>CFBundleInfoDictionaryVersion</key> |
||||
<string>6.0</string> |
||||
<key>CFBundleName</key> |
||||
<string>$(PRODUCT_NAME)</string> |
||||
<key>CFBundlePackageType</key> |
||||
<string>BNDL</string> |
||||
<key>CFBundleShortVersionString</key> |
||||
<string>1.0</string> |
||||
<key>CFBundleSignature</key> |
||||
<string>????</string> |
||||
<key>CFBundleVersion</key> |
||||
<string>1</string> |
||||
</dict> |
||||
</plist> |
@ -0,0 +1,99 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<Scheme |
||||
LastUpgradeVersion = "0730" |
||||
version = "1.3"> |
||||
<BuildAction |
||||
parallelizeBuildables = "YES" |
||||
buildImplicitDependencies = "YES"> |
||||
<BuildActionEntries> |
||||
<BuildActionEntry |
||||
buildForTesting = "YES" |
||||
buildForRunning = "YES" |
||||
buildForProfiling = "NO" |
||||
buildForArchiving = "NO" |
||||
buildForAnalyzing = "YES"> |
||||
<BuildableReference |
||||
BuildableIdentifier = "primary" |
||||
BlueprintIdentifier = "5E8A5DA31D3840B4000F8BC4" |
||||
BuildableName = "CoreCronetEnd2EndTests.xctest" |
||||
BlueprintName = "CoreCronetEnd2EndTests" |
||||
ReferencedContainer = "container:Tests.xcodeproj"> |
||||
</BuildableReference> |
||||
</BuildActionEntry> |
||||
</BuildActionEntries> |
||||
</BuildAction> |
||||
<TestAction |
||||
buildConfiguration = "Debug" |
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" |
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" |
||||
shouldUseLaunchSchemeArgsEnv = "YES"> |
||||
<Testables> |
||||
<TestableReference |
||||
skipped = "NO"> |
||||
<BuildableReference |
||||
BuildableIdentifier = "primary" |
||||
BlueprintIdentifier = "5E8A5DA31D3840B4000F8BC4" |
||||
BuildableName = "CoreCronetEnd2EndTests.xctest" |
||||
BlueprintName = "CoreCronetEnd2EndTests" |
||||
ReferencedContainer = "container:Tests.xcodeproj"> |
||||
</BuildableReference> |
||||
</TestableReference> |
||||
</Testables> |
||||
<MacroExpansion> |
||||
<BuildableReference |
||||
BuildableIdentifier = "primary" |
||||
BlueprintIdentifier = "5E8A5DA31D3840B4000F8BC4" |
||||
BuildableName = "CoreCronetEnd2EndTests.xctest" |
||||
BlueprintName = "CoreCronetEnd2EndTests" |
||||
ReferencedContainer = "container:Tests.xcodeproj"> |
||||
</BuildableReference> |
||||
</MacroExpansion> |
||||
<AdditionalOptions> |
||||
</AdditionalOptions> |
||||
</TestAction> |
||||
<LaunchAction |
||||
buildConfiguration = "Debug" |
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" |
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" |
||||
launchStyle = "0" |
||||
useCustomWorkingDirectory = "NO" |
||||
ignoresPersistentStateOnLaunch = "NO" |
||||
debugDocumentVersioning = "YES" |
||||
debugServiceExtension = "internal" |
||||
allowLocationSimulation = "YES"> |
||||
<MacroExpansion> |
||||
<BuildableReference |
||||
BuildableIdentifier = "primary" |
||||
BlueprintIdentifier = "5E8A5DA31D3840B4000F8BC4" |
||||
BuildableName = "CoreCronetEnd2EndTests.xctest" |
||||
BlueprintName = "CoreCronetEnd2EndTests" |
||||
ReferencedContainer = "container:Tests.xcodeproj"> |
||||
</BuildableReference> |
||||
</MacroExpansion> |
||||
<AdditionalOptions> |
||||
</AdditionalOptions> |
||||
</LaunchAction> |
||||
<ProfileAction |
||||
buildConfiguration = "Release" |
||||
shouldUseLaunchSchemeArgsEnv = "YES" |
||||
savedToolIdentifier = "" |
||||
useCustomWorkingDirectory = "NO" |
||||
debugDocumentVersioning = "YES"> |
||||
<MacroExpansion> |
||||
<BuildableReference |
||||
BuildableIdentifier = "primary" |
||||
BlueprintIdentifier = "5E8A5DA31D3840B4000F8BC4" |
||||
BuildableName = "CoreCronetEnd2EndTests.xctest" |
||||
BlueprintName = "CoreCronetEnd2EndTests" |
||||
ReferencedContainer = "container:Tests.xcodeproj"> |
||||
</BuildableReference> |
||||
</MacroExpansion> |
||||
</ProfileAction> |
||||
<AnalyzeAction |
||||
buildConfiguration = "Debug"> |
||||
</AnalyzeAction> |
||||
<ArchiveAction |
||||
buildConfiguration = "Release" |
||||
revealArchiveInOrganizer = "YES"> |
||||
</ArchiveAction> |
||||
</Scheme> |
@ -0,0 +1,464 @@ |
||||
/*
|
||||
* |
||||
* 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. |
||||
* |
||||
*/ |
||||
|
||||
#include <ruby/ruby.h> |
||||
|
||||
#include "rb_compression_options.h" |
||||
#include "rb_grpc_imports.generated.h" |
||||
|
||||
#include <grpc/compression.h> |
||||
#include <grpc/grpc.h> |
||||
#include <grpc/impl/codegen/alloc.h> |
||||
#include <grpc/impl/codegen/compression_types.h> |
||||
#include <grpc/impl/codegen/grpc_types.h> |
||||
#include <string.h> |
||||
|
||||
#include "rb_grpc.h" |
||||
|
||||
static VALUE grpc_rb_cCompressionOptions = Qnil; |
||||
|
||||
/* Ruby Ids for the names of valid compression levels. */ |
||||
static VALUE id_compress_level_none = Qnil; |
||||
static VALUE id_compress_level_low = Qnil; |
||||
static VALUE id_compress_level_medium = Qnil; |
||||
static VALUE id_compress_level_high = Qnil; |
||||
|
||||
/* grpc_rb_compression_options wraps a grpc_compression_options.
|
||||
* It can be used to get the channel argument key-values for specific |
||||
* compression settings. */ |
||||
|
||||
/* Note that ruby objects of this type don't carry any state in other
|
||||
* Ruby objects and don't have a mark for GC. */ |
||||
typedef struct grpc_rb_compression_options { |
||||
/* The actual compression options that's being wrapped */ |
||||
grpc_compression_options *wrapped; |
||||
} grpc_rb_compression_options; |
||||
|
||||
/* Destroys the compression options instances and free the
|
||||
* wrapped grpc compression options. */ |
||||
static void grpc_rb_compression_options_free(void *p) { |
||||
grpc_rb_compression_options *wrapper = NULL; |
||||
if (p == NULL) { |
||||
return; |
||||
}; |
||||
wrapper = (grpc_rb_compression_options *)p; |
||||
|
||||
if (wrapper->wrapped != NULL) { |
||||
gpr_free(wrapper->wrapped); |
||||
wrapper->wrapped = NULL; |
||||
} |
||||
|
||||
xfree(p); |
||||
} |
||||
|
||||
/* Ruby recognized data type for the CompressionOptions class. */ |
||||
static rb_data_type_t grpc_rb_compression_options_data_type = { |
||||
"grpc_compression_options", |
||||
{NULL, |
||||
grpc_rb_compression_options_free, |
||||
GRPC_RB_MEMSIZE_UNAVAILABLE, |
||||
{NULL, NULL}}, |
||||
NULL, |
||||
NULL, |
||||
#ifdef RUBY_TYPED_FREE_IMMEDIATELY |
||||
RUBY_TYPED_FREE_IMMEDIATELY |
||||
#endif |
||||
}; |
||||
|
||||
/* Allocates CompressionOptions instances.
|
||||
Allocate the wrapped grpc compression options and |
||||
initialize it here too. */ |
||||
static VALUE grpc_rb_compression_options_alloc(VALUE cls) { |
||||
grpc_rb_compression_options *wrapper = |
||||
gpr_malloc(sizeof(grpc_rb_compression_options)); |
||||
wrapper->wrapped = NULL; |
||||
wrapper->wrapped = gpr_malloc(sizeof(grpc_compression_options)); |
||||
grpc_compression_options_init(wrapper->wrapped); |
||||
|
||||
return TypedData_Wrap_Struct(cls, &grpc_rb_compression_options_data_type, |
||||
wrapper); |
||||
} |
||||
|
||||
/* Disables a compression algorithm, given the GRPC core internal number of a
|
||||
* compression algorithm. */ |
||||
VALUE grpc_rb_compression_options_disable_compression_algorithm_internal( |
||||
VALUE self, VALUE algorithm_to_disable) { |
||||
grpc_compression_algorithm compression_algorithm = 0; |
||||
grpc_rb_compression_options *wrapper = NULL; |
||||
|
||||
TypedData_Get_Struct(self, grpc_rb_compression_options, |
||||
&grpc_rb_compression_options_data_type, wrapper); |
||||
compression_algorithm = |
||||
(grpc_compression_algorithm)NUM2INT(algorithm_to_disable); |
||||
|
||||
grpc_compression_options_disable_algorithm(wrapper->wrapped, |
||||
compression_algorithm); |
||||
|
||||
return Qnil; |
||||
} |
||||
|
||||
/* Gets the compression internal enum value of a compression level given its
|
||||
* name. */ |
||||
grpc_compression_level grpc_rb_compression_options_level_name_to_value_internal( |
||||
VALUE level_name) { |
||||
Check_Type(level_name, T_SYMBOL); |
||||
|
||||
/* Check the compression level of the name passed in, and see which macro
|
||||
* from the GRPC core header files match. */ |
||||
if (id_compress_level_none == SYM2ID(level_name)) { |
||||
return GRPC_COMPRESS_LEVEL_NONE; |
||||
} else if (id_compress_level_low == SYM2ID(level_name)) { |
||||
return GRPC_COMPRESS_LEVEL_LOW; |
||||
} else if (id_compress_level_medium == SYM2ID(level_name)) { |
||||
return GRPC_COMPRESS_LEVEL_MED; |
||||
} else if (id_compress_level_high == SYM2ID(level_name)) { |
||||
return GRPC_COMPRESS_LEVEL_HIGH; |
||||
} |
||||
|
||||
rb_raise(rb_eArgError, |
||||
"Unrecognized compression level name." |
||||
"Valid compression level names are none, low, medium, and high."); |
||||
|
||||
/* Dummy return statement. */ |
||||
return GRPC_COMPRESS_LEVEL_NONE; |
||||
} |
||||
|
||||
/* Sets the default compression level, given the name of a compression level.
|
||||
* Throws an error if no algorithm matched. */ |
||||
void grpc_rb_compression_options_set_default_level( |
||||
grpc_compression_options *options, VALUE new_level_name) { |
||||
options->default_level.level = |
||||
grpc_rb_compression_options_level_name_to_value_internal(new_level_name); |
||||
options->default_level.is_set = 1; |
||||
} |
||||
|
||||
/* Gets the internal value of a compression algorithm suitable as the value
|
||||
* in a GRPC core channel arguments hash. |
||||
* algorithm_value is an out parameter. |
||||
* Raises an error if the name of the algorithm passed in is invalid. */ |
||||
void grpc_rb_compression_options_algorithm_name_to_value_internal( |
||||
grpc_compression_algorithm *algorithm_value, VALUE algorithm_name) { |
||||
char *name_str = NULL; |
||||
long name_len = 0; |
||||
VALUE algorithm_name_as_string = Qnil; |
||||
|
||||
Check_Type(algorithm_name, T_SYMBOL); |
||||
|
||||
/* Convert the algorithm symbol to a ruby string, so that we can get the
|
||||
* correct C string out of it. */ |
||||
algorithm_name_as_string = rb_funcall(algorithm_name, rb_intern("to_s"), 0); |
||||
|
||||
name_str = RSTRING_PTR(algorithm_name_as_string); |
||||
name_len = RSTRING_LEN(algorithm_name_as_string); |
||||
|
||||
/* Raise an error if the name isn't recognized as a compression algorithm by
|
||||
* the algorithm parse function |
||||
* in GRPC core. */ |
||||
if (!grpc_compression_algorithm_parse(name_str, name_len, algorithm_value)) { |
||||
rb_raise(rb_eNameError, "Invalid compression algorithm name: %s", |
||||
StringValueCStr(algorithm_name_as_string)); |
||||
} |
||||
} |
||||
|
||||
/* Indicates whether a given algorithm is enabled on this instance, given the
|
||||
* readable algorithm name. */ |
||||
VALUE grpc_rb_compression_options_is_algorithm_enabled(VALUE self, |
||||
VALUE algorithm_name) { |
||||
grpc_rb_compression_options *wrapper = NULL; |
||||
grpc_compression_algorithm internal_algorithm_value; |
||||
|
||||
TypedData_Get_Struct(self, grpc_rb_compression_options, |
||||
&grpc_rb_compression_options_data_type, wrapper); |
||||
grpc_rb_compression_options_algorithm_name_to_value_internal( |
||||
&internal_algorithm_value, algorithm_name); |
||||
|
||||
if (grpc_compression_options_is_algorithm_enabled(wrapper->wrapped, |
||||
internal_algorithm_value)) { |
||||
return Qtrue; |
||||
} |
||||
return Qfalse; |
||||
} |
||||
|
||||
/* Sets the default algorithm to the name of the algorithm passed in.
|
||||
* Raises an error if the name is not a valid compression algorithm name. */ |
||||
void grpc_rb_compression_options_set_default_algorithm( |
||||
grpc_compression_options *options, VALUE algorithm_name) { |
||||
grpc_rb_compression_options_algorithm_name_to_value_internal( |
||||
&options->default_algorithm.algorithm, algorithm_name); |
||||
options->default_algorithm.is_set = 1; |
||||
} |
||||
|
||||
/* Disables an algorithm on the current instance, given the name of an
|
||||
* algorithm. |
||||
* Fails if the algorithm name is invalid. */ |
||||
void grpc_rb_compression_options_disable_algorithm( |
||||
grpc_compression_options *compression_options, VALUE algorithm_name) { |
||||
grpc_compression_algorithm internal_algorithm_value; |
||||
|
||||
grpc_rb_compression_options_algorithm_name_to_value_internal( |
||||
&internal_algorithm_value, algorithm_name); |
||||
grpc_compression_options_disable_algorithm(compression_options, |
||||
internal_algorithm_value); |
||||
} |
||||
|
||||
/* Provides a ruby hash of GRPC core channel argument key-values that
|
||||
* correspond to the compression settings on this instance. */ |
||||
VALUE grpc_rb_compression_options_to_hash(VALUE self) { |
||||
grpc_rb_compression_options *wrapper = NULL; |
||||
grpc_compression_options *compression_options = NULL; |
||||
VALUE channel_arg_hash = rb_hash_new(); |
||||
VALUE key = Qnil; |
||||
VALUE value = Qnil; |
||||
|
||||
TypedData_Get_Struct(self, grpc_rb_compression_options, |
||||
&grpc_rb_compression_options_data_type, wrapper); |
||||
compression_options = wrapper->wrapped; |
||||
|
||||
/* Add key-value pairs to the new Ruby hash. It can be used
|
||||
* as GRPC core channel arguments. */ |
||||
if (compression_options->default_level.is_set) { |
||||
key = rb_str_new2(GRPC_COMPRESSION_CHANNEL_DEFAULT_LEVEL); |
||||
value = INT2NUM((int)compression_options->default_level.level); |
||||
rb_hash_aset(channel_arg_hash, key, value); |
||||
} |
||||
|
||||
if (compression_options->default_algorithm.is_set) { |
||||
key = rb_str_new2(GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM); |
||||
value = INT2NUM((int)compression_options->default_algorithm.algorithm); |
||||
rb_hash_aset(channel_arg_hash, key, value); |
||||
} |
||||
|
||||
key = rb_str_new2(GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET); |
||||
value = INT2NUM((int)compression_options->enabled_algorithms_bitset); |
||||
rb_hash_aset(channel_arg_hash, key, value); |
||||
|
||||
return channel_arg_hash; |
||||
} |
||||
|
||||
/* Converts an internal enum level value to a readable level name.
|
||||
* Fails if the level value is invalid. */ |
||||
VALUE grpc_rb_compression_options_level_value_to_name_internal( |
||||
grpc_compression_level compression_value) { |
||||
switch (compression_value) { |
||||
case GRPC_COMPRESS_LEVEL_NONE: |
||||
return ID2SYM(id_compress_level_none); |
||||
case GRPC_COMPRESS_LEVEL_LOW: |
||||
return ID2SYM(id_compress_level_low); |
||||
case GRPC_COMPRESS_LEVEL_MED: |
||||
return ID2SYM(id_compress_level_medium); |
||||
case GRPC_COMPRESS_LEVEL_HIGH: |
||||
return ID2SYM(id_compress_level_high); |
||||
default: |
||||
rb_raise( |
||||
rb_eArgError, |
||||
"Failed to convert compression level value to name for value: %d", |
||||
(int)compression_value); |
||||
} |
||||
} |
||||
|
||||
/* Converts an algorithm internal enum value to a readable name.
|
||||
* Fails if the enum value is invalid. */ |
||||
VALUE grpc_rb_compression_options_algorithm_value_to_name_internal( |
||||
grpc_compression_algorithm internal_value) { |
||||
char *algorithm_name = NULL; |
||||
|
||||
if (!grpc_compression_algorithm_name(internal_value, &algorithm_name)) { |
||||
rb_raise(rb_eArgError, "Failed to convert algorithm value to name"); |
||||
} |
||||
|
||||
return ID2SYM(rb_intern(algorithm_name)); |
||||
} |
||||
|
||||
/* Gets the readable name of the default algorithm if one has been set.
|
||||
* Returns nil if no algorithm has been set. */ |
||||
VALUE grpc_rb_compression_options_get_default_algorithm(VALUE self) { |
||||
grpc_compression_algorithm internal_value; |
||||
grpc_rb_compression_options *wrapper = NULL; |
||||
|
||||
TypedData_Get_Struct(self, grpc_rb_compression_options, |
||||
&grpc_rb_compression_options_data_type, wrapper); |
||||
|
||||
if (wrapper->wrapped->default_algorithm.is_set) { |
||||
internal_value = wrapper->wrapped->default_algorithm.algorithm; |
||||
return grpc_rb_compression_options_algorithm_value_to_name_internal( |
||||
internal_value); |
||||
} |
||||
|
||||
return Qnil; |
||||
} |
||||
|
||||
/* Gets the internal value of the default compression level that is to be passed
|
||||
* to the GRPC core as a channel argument value. |
||||
* A nil return value means that it hasn't been set. */ |
||||
VALUE grpc_rb_compression_options_get_default_level(VALUE self) { |
||||
grpc_compression_level internal_value; |
||||
grpc_rb_compression_options *wrapper = NULL; |
||||
|
||||
TypedData_Get_Struct(self, grpc_rb_compression_options, |
||||
&grpc_rb_compression_options_data_type, wrapper); |
||||
|
||||
if (wrapper->wrapped->default_level.is_set) { |
||||
internal_value = wrapper->wrapped->default_level.level; |
||||
return grpc_rb_compression_options_level_value_to_name_internal( |
||||
internal_value); |
||||
} |
||||
|
||||
return Qnil; |
||||
} |
||||
|
||||
/* Gets a list of the disabled algorithms as readable names.
|
||||
* Returns an empty list if no algorithms have been disabled. */ |
||||
VALUE grpc_rb_compression_options_get_disabled_algorithms(VALUE self) { |
||||
VALUE disabled_algorithms = rb_ary_new(); |
||||
grpc_compression_algorithm internal_value; |
||||
grpc_rb_compression_options *wrapper = NULL; |
||||
|
||||
TypedData_Get_Struct(self, grpc_rb_compression_options, |
||||
&grpc_rb_compression_options_data_type, wrapper); |
||||
|
||||
for (internal_value = GRPC_COMPRESS_NONE; |
||||
internal_value < GRPC_COMPRESS_ALGORITHMS_COUNT; internal_value++) { |
||||
if (!grpc_compression_options_is_algorithm_enabled(wrapper->wrapped, |
||||
internal_value)) { |
||||
rb_ary_push(disabled_algorithms, |
||||
grpc_rb_compression_options_algorithm_value_to_name_internal( |
||||
internal_value)); |
||||
} |
||||
} |
||||
return disabled_algorithms; |
||||
} |
||||
|
||||
/* Initializes the compression options wrapper.
|
||||
* Takes an optional hash parameter. |
||||
* |
||||
* Example call-seq: |
||||
* options = CompressionOptions.new( |
||||
* default_level: :none, |
||||
* disabled_algorithms: [:gzip] |
||||
* ) |
||||
* channel_arg hash = Hash.new[...] |
||||
* channel_arg_hash_with_compression_options = channel_arg_hash.merge(options) |
||||
*/ |
||||
VALUE grpc_rb_compression_options_init(int argc, VALUE *argv, VALUE self) { |
||||
grpc_rb_compression_options *wrapper = NULL; |
||||
VALUE default_algorithm = Qnil; |
||||
VALUE default_level = Qnil; |
||||
VALUE disabled_algorithms = Qnil; |
||||
VALUE algorithm_name = Qnil; |
||||
VALUE hash_arg = Qnil; |
||||
|
||||
rb_scan_args(argc, argv, "01", &hash_arg); |
||||
|
||||
/* Check if the hash parameter was passed, or if invalid arguments were
|
||||
* passed. */ |
||||
if (hash_arg == Qnil) { |
||||
return self; |
||||
} else if (TYPE(hash_arg) != T_HASH || argc > 1) { |
||||
rb_raise(rb_eArgError, |
||||
"Invalid arguments. Expecting optional hash parameter"); |
||||
} |
||||
|
||||
TypedData_Get_Struct(self, grpc_rb_compression_options, |
||||
&grpc_rb_compression_options_data_type, wrapper); |
||||
|
||||
/* Set the default algorithm if one was chosen. */ |
||||
default_algorithm = |
||||
rb_hash_aref(hash_arg, ID2SYM(rb_intern("default_algorithm"))); |
||||
if (default_algorithm != Qnil) { |
||||
grpc_rb_compression_options_set_default_algorithm(wrapper->wrapped, |
||||
default_algorithm); |
||||
} |
||||
|
||||
/* Set the default level if one was chosen. */ |
||||
default_level = rb_hash_aref(hash_arg, ID2SYM(rb_intern("default_level"))); |
||||
if (default_level != Qnil) { |
||||
grpc_rb_compression_options_set_default_level(wrapper->wrapped, |
||||
default_level); |
||||
} |
||||
|
||||
/* Set the disabled algorithms if any were chosen. */ |
||||
disabled_algorithms = |
||||
rb_hash_aref(hash_arg, ID2SYM(rb_intern("disabled_algorithms"))); |
||||
if (disabled_algorithms != Qnil) { |
||||
Check_Type(disabled_algorithms, T_ARRAY); |
||||
|
||||
for (int i = 0; i < RARRAY_LEN(disabled_algorithms); i++) { |
||||
algorithm_name = rb_ary_entry(disabled_algorithms, i); |
||||
grpc_rb_compression_options_disable_algorithm(wrapper->wrapped, |
||||
algorithm_name); |
||||
} |
||||
} |
||||
|
||||
return self; |
||||
} |
||||
|
||||
void Init_grpc_compression_options() { |
||||
grpc_rb_cCompressionOptions = rb_define_class_under( |
||||
grpc_rb_mGrpcCore, "CompressionOptions", rb_cObject); |
||||
|
||||
/* Allocates an object managed by the ruby runtime. */ |
||||
rb_define_alloc_func(grpc_rb_cCompressionOptions, |
||||
grpc_rb_compression_options_alloc); |
||||
|
||||
/* Initializes the ruby wrapper. #new method takes an optional hash argument.
|
||||
*/ |
||||
rb_define_method(grpc_rb_cCompressionOptions, "initialize", |
||||
grpc_rb_compression_options_init, -1); |
||||
|
||||
/* Methods for getting the default algorithm, default level, and disabled
|
||||
* algorithms as readable names. */ |
||||
rb_define_method(grpc_rb_cCompressionOptions, "default_algorithm", |
||||
grpc_rb_compression_options_get_default_algorithm, 0); |
||||
rb_define_method(grpc_rb_cCompressionOptions, "default_level", |
||||
grpc_rb_compression_options_get_default_level, 0); |
||||
rb_define_method(grpc_rb_cCompressionOptions, "disabled_algorithms", |
||||
grpc_rb_compression_options_get_disabled_algorithms, 0); |
||||
|
||||
/* Determines whether or not an algorithm is enabled, given a readable
|
||||
* algorithm name.*/ |
||||
rb_define_method(grpc_rb_cCompressionOptions, "algorithm_enabled?", |
||||
grpc_rb_compression_options_is_algorithm_enabled, 1); |
||||
|
||||
/* Provides a hash of the compression settings suitable
|
||||
* for passing to server or channel args. */ |
||||
rb_define_method(grpc_rb_cCompressionOptions, "to_hash", |
||||
grpc_rb_compression_options_to_hash, 0); |
||||
rb_define_alias(grpc_rb_cCompressionOptions, "to_channel_arg_hash", |
||||
"to_hash"); |
||||
|
||||
/* Ruby ids for the names of the different compression levels. */ |
||||
id_compress_level_none = rb_intern("none"); |
||||
id_compress_level_low = rb_intern("low"); |
||||
id_compress_level_medium = rb_intern("medium"); |
||||
id_compress_level_high = rb_intern("high"); |
||||
} |
@ -0,0 +1,44 @@ |
||||
/*
|
||||
* |
||||
* 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. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef GRPC_RB_COMPRESSION_OPTIONS_H_ |
||||
#define GRPC_RB_COMPRESSION_OPTIONS_H_ |
||||
|
||||
#include <ruby/ruby.h> |
||||
|
||||
#include <grpc/grpc.h> |
||||
|
||||
/* Initializes the compression options ruby wrapper. */ |
||||
void Init_grpc_compression_options(); |
||||
|
||||
#endif /* GRPC_RB_COMPRESSION_OPTIONS_H_ */ |
@ -1,15 +0,0 @@ |
||||
# Generated by the protocol buffer compiler. DO NOT EDIT! |
||||
# source: test/proto/empty.proto |
||||
|
||||
require 'google/protobuf' |
||||
|
||||
Google::Protobuf::DescriptorPool.generated_pool.build do |
||||
add_message "grpc.testing.Empty" do |
||||
end |
||||
end |
||||
|
||||
module Grpc |
||||
module Testing |
||||
Empty = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.Empty").msgclass |
||||
end |
||||
end |
@ -1,80 +0,0 @@ |
||||
# Generated by the protocol buffer compiler. DO NOT EDIT! |
||||
# source: test/proto/messages.proto |
||||
|
||||
require 'google/protobuf' |
||||
|
||||
Google::Protobuf::DescriptorPool.generated_pool.build do |
||||
add_message "grpc.testing.Payload" do |
||||
optional :type, :enum, 1, "grpc.testing.PayloadType" |
||||
optional :body, :bytes, 2 |
||||
end |
||||
add_message "grpc.testing.EchoStatus" do |
||||
optional :code, :int32, 1 |
||||
optional :message, :string, 2 |
||||
end |
||||
add_message "grpc.testing.SimpleRequest" do |
||||
optional :response_type, :enum, 1, "grpc.testing.PayloadType" |
||||
optional :response_size, :int32, 2 |
||||
optional :payload, :message, 3, "grpc.testing.Payload" |
||||
optional :fill_username, :bool, 4 |
||||
optional :fill_oauth_scope, :bool, 5 |
||||
optional :response_compression, :enum, 6, "grpc.testing.CompressionType" |
||||
optional :response_status, :message, 7, "grpc.testing.EchoStatus" |
||||
end |
||||
add_message "grpc.testing.SimpleResponse" do |
||||
optional :payload, :message, 1, "grpc.testing.Payload" |
||||
optional :username, :string, 2 |
||||
optional :oauth_scope, :string, 3 |
||||
end |
||||
add_message "grpc.testing.StreamingInputCallRequest" do |
||||
optional :payload, :message, 1, "grpc.testing.Payload" |
||||
end |
||||
add_message "grpc.testing.StreamingInputCallResponse" do |
||||
optional :aggregated_payload_size, :int32, 1 |
||||
end |
||||
add_message "grpc.testing.ResponseParameters" do |
||||
optional :size, :int32, 1 |
||||
optional :interval_us, :int32, 2 |
||||
end |
||||
add_message "grpc.testing.StreamingOutputCallRequest" do |
||||
optional :response_type, :enum, 1, "grpc.testing.PayloadType" |
||||
repeated :response_parameters, :message, 2, "grpc.testing.ResponseParameters" |
||||
optional :payload, :message, 3, "grpc.testing.Payload" |
||||
optional :response_compression, :enum, 6, "grpc.testing.CompressionType" |
||||
optional :response_status, :message, 7, "grpc.testing.EchoStatus" |
||||
end |
||||
add_message "grpc.testing.StreamingOutputCallResponse" do |
||||
optional :payload, :message, 1, "grpc.testing.Payload" |
||||
end |
||||
add_message "grpc.testing.ReconnectInfo" do |
||||
optional :passed, :bool, 1 |
||||
repeated :backoff_ms, :int32, 2 |
||||
end |
||||
add_enum "grpc.testing.PayloadType" do |
||||
value :COMPRESSABLE, 0 |
||||
value :UNCOMPRESSABLE, 1 |
||||
value :RANDOM, 2 |
||||
end |
||||
add_enum "grpc.testing.CompressionType" do |
||||
value :NONE, 0 |
||||
value :GZIP, 1 |
||||
value :DEFLATE, 2 |
||||
end |
||||
end |
||||
|
||||
module Grpc |
||||
module Testing |
||||
Payload = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.Payload").msgclass |
||||
EchoStatus = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.EchoStatus").msgclass |
||||
SimpleRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.SimpleRequest").msgclass |
||||
SimpleResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.SimpleResponse").msgclass |
||||
StreamingInputCallRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.StreamingInputCallRequest").msgclass |
||||
StreamingInputCallResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.StreamingInputCallResponse").msgclass |
||||
ResponseParameters = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.ResponseParameters").msgclass |
||||
StreamingOutputCallRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.StreamingOutputCallRequest").msgclass |
||||
StreamingOutputCallResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.StreamingOutputCallResponse").msgclass |
||||
ReconnectInfo = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.ReconnectInfo").msgclass |
||||
PayloadType = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.PayloadType").enummodule |
||||
CompressionType = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.CompressionType").enummodule |
||||
end |
||||
end |
@ -1,14 +0,0 @@ |
||||
# Generated by the protocol buffer compiler. DO NOT EDIT! |
||||
# source: test/proto/test.proto |
||||
|
||||
require 'google/protobuf' |
||||
|
||||
require 'test/proto/empty' |
||||
require 'test/proto/messages' |
||||
Google::Protobuf::DescriptorPool.generated_pool.build do |
||||
end |
||||
|
||||
module Grpc |
||||
module Testing |
||||
end |
||||
end |
@ -1,64 +0,0 @@ |
||||
# Generated by the protocol buffer compiler. DO NOT EDIT! |
||||
# Source: test/proto/test.proto for package 'grpc.testing' |
||||
|
||||
require 'grpc' |
||||
require 'test/proto/test' |
||||
|
||||
module Grpc |
||||
module Testing |
||||
module TestService |
||||
|
||||
# TODO: add proto service documentation here |
||||
class Service |
||||
|
||||
include GRPC::GenericService |
||||
|
||||
self.marshal_class_method = :encode |
||||
self.unmarshal_class_method = :decode |
||||
self.service_name = 'grpc.testing.TestService' |
||||
|
||||
rpc :EmptyCall, Empty, Empty |
||||
rpc :UnaryCall, SimpleRequest, SimpleResponse |
||||
rpc :StreamingOutputCall, StreamingOutputCallRequest, stream(StreamingOutputCallResponse) |
||||
rpc :StreamingInputCall, stream(StreamingInputCallRequest), StreamingInputCallResponse |
||||
rpc :FullDuplexCall, stream(StreamingOutputCallRequest), stream(StreamingOutputCallResponse) |
||||
rpc :HalfDuplexCall, stream(StreamingOutputCallRequest), stream(StreamingOutputCallResponse) |
||||
end |
||||
|
||||
Stub = Service.rpc_stub_class |
||||
end |
||||
module UnimplementedService |
||||
|
||||
# TODO: add proto service documentation here |
||||
class Service |
||||
|
||||
include GRPC::GenericService |
||||
|
||||
self.marshal_class_method = :encode |
||||
self.unmarshal_class_method = :decode |
||||
self.service_name = 'grpc.testing.UnimplementedService' |
||||
|
||||
rpc :UnimplementedCall, Empty, Empty |
||||
end |
||||
|
||||
Stub = Service.rpc_stub_class |
||||
end |
||||
module ReconnectService |
||||
|
||||
# TODO: add proto service documentation here |
||||
class Service |
||||
|
||||
include GRPC::GenericService |
||||
|
||||
self.marshal_class_method = :encode |
||||
self.unmarshal_class_method = :decode |
||||
self.service_name = 'grpc.testing.ReconnectService' |
||||
|
||||
rpc :Start, Empty, Empty |
||||
rpc :Stop, Empty, ReconnectInfo |
||||
end |
||||
|
||||
Stub = Service.rpc_stub_class |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,164 @@ |
||||
# 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. |
||||
|
||||
require 'grpc' |
||||
|
||||
describe GRPC::Core::CompressionOptions do |
||||
# Note these constants should be updated |
||||
# according to what the core lib provides. |
||||
|
||||
# Names of supported compression algorithms |
||||
ALGORITHMS = [:identity, :deflate, :gzip] |
||||
|
||||
# Names of valid supported compression levels |
||||
COMPRESS_LEVELS = [:none, :low, :medium, :high] |
||||
|
||||
it 'implements to_s' do |
||||
expect { GRPC::Core::CompressionOptions.new.to_s }.to_not raise_error |
||||
end |
||||
|
||||
it '#to_channel_arg_hash gives the same result as #to_hash' do |
||||
options = GRPC::Core::CompressionOptions.new |
||||
expect(options.to_channel_arg_hash).to eq(options.to_hash) |
||||
end |
||||
|
||||
# Test the normal call sequence of creating an instance |
||||
# and then obtaining the resulting channel-arg hash that |
||||
# corresponds to the compression settings of the instance |
||||
describe 'creating, reading, and converting to channel args hash' do |
||||
it 'works when no optional args were provided' do |
||||
options = GRPC::Core::CompressionOptions.new |
||||
|
||||
ALGORITHMS.each do |algorithm| |
||||
expect(options.algorithm_enabled?(algorithm)).to be true |
||||
end |
||||
|
||||
expect(options.disabled_algorithms).to be_empty |
||||
expect(options.default_algorithm).to be nil |
||||
expect(options.default_level).to be nil |
||||
expect(options.to_hash).to be_instance_of(Hash) |
||||
end |
||||
|
||||
it 'works when disabling multiple algorithms' do |
||||
options = GRPC::Core::CompressionOptions.new( |
||||
default_algorithm: :identity, |
||||
default_level: :none, |
||||
disabled_algorithms: [:gzip, :deflate] |
||||
) |
||||
|
||||
[:gzip, :deflate].each do |algorithm| |
||||
expect(options.algorithm_enabled?(algorithm)).to be false |
||||
expect(options.disabled_algorithms.include?(algorithm)).to be true |
||||
end |
||||
|
||||
expect(options.default_algorithm).to be(:identity) |
||||
expect(options.default_level).to be(:none) |
||||
expect(options.to_hash).to be_instance_of(Hash) |
||||
end |
||||
|
||||
it 'works when all optional args have been set' do |
||||
options = GRPC::Core::CompressionOptions.new( |
||||
default_algorithm: :gzip, |
||||
default_level: :low, |
||||
disabled_algorithms: [:deflate] |
||||
) |
||||
|
||||
expect(options.algorithm_enabled?(:deflate)).to be false |
||||
expect(options.algorithm_enabled?(:gzip)).to be true |
||||
expect(options.disabled_algorithms).to eq([:deflate]) |
||||
|
||||
expect(options.default_algorithm).to be(:gzip) |
||||
expect(options.default_level).to be(:low) |
||||
expect(options.to_hash).to be_instance_of(Hash) |
||||
end |
||||
|
||||
it 'doesnt fail when no algorithms are disabled' do |
||||
options = GRPC::Core::CompressionOptions.new( |
||||
default_algorithm: :identity, |
||||
default_level: :high |
||||
) |
||||
|
||||
ALGORITHMS.each do |algorithm| |
||||
expect(options.algorithm_enabled?(algorithm)).to be(true) |
||||
end |
||||
|
||||
expect(options.disabled_algorithms).to be_empty |
||||
expect(options.default_algorithm).to be(:identity) |
||||
expect(options.default_level).to be(:high) |
||||
expect(options.to_hash).to be_instance_of(Hash) |
||||
end |
||||
end |
||||
|
||||
describe '#new with bad parameters' do |
||||
it 'should fail with more than one parameter' do |
||||
blk = proc { GRPC::Core::CompressionOptions.new(:gzip, :none) } |
||||
expect { blk.call }.to raise_error |
||||
end |
||||
|
||||
it 'should fail with a non-hash parameter' do |
||||
blk = proc { GRPC::Core::CompressionOptions.new(:gzip) } |
||||
expect { blk.call }.to raise_error |
||||
end |
||||
end |
||||
|
||||
describe '#default_algorithm' do |
||||
it 'returns nil if unset' do |
||||
options = GRPC::Core::CompressionOptions.new |
||||
expect(options.default_algorithm).to be(nil) |
||||
end |
||||
end |
||||
|
||||
describe '#default_level' do |
||||
it 'returns nil if unset' do |
||||
options = GRPC::Core::CompressionOptions.new |
||||
expect(options.default_level).to be(nil) |
||||
end |
||||
end |
||||
|
||||
describe '#disabled_algorithms' do |
||||
it 'returns an empty list if no algorithms were disabled' do |
||||
options = GRPC::Core::CompressionOptions.new |
||||
expect(options.disabled_algorithms).to be_empty |
||||
end |
||||
end |
||||
|
||||
describe '#algorithm_enabled?' do |
||||
[:none, :any, 'gzip', Object.new, 1].each do |name| |
||||
it "should fail for parameter ${name} of class #{name.class}" do |
||||
options = GRPC::Core::CompressionOptions.new( |
||||
disabled_algorithms: [:gzip]) |
||||
|
||||
blk = proc do |
||||
options.algorithm_enabled?(name) |
||||
end |
||||
expect { blk.call }.to raise_error |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,21 @@ |
||||
<!DOCTYPE html> |
||||
<html lang="en"> |
||||
<head><title>Performance Test Result</title></head> |
||||
<body> |
||||
<h2>Performance Test Result</h2> |
||||
<table style="width:50%" border="1"> |
||||
<% sorted_test_cases = sorted(resultset.keys()) %> |
||||
% for test_case in sorted_test_cases: |
||||
<tr><td bgcolor="#00BFFF" style="width:30%"><b>${test_case}</b></td> |
||||
<% result = resultset[test_case] %> |
||||
<td> |
||||
% for k, v in result.iteritems(): |
||||
${k}: ${v}<br> |
||||
% endfor |
||||
</td> |
||||
</tr> |
||||
% endfor |
||||
</table> |
||||
|
||||
</body> |
||||
</html> |
Loading…
Reference in new issue