mirror of https://github.com/grpc/grpc.git
parent
c1bfe124ab
commit
0dccf10db7
6 changed files with 745 additions and 0 deletions
@ -0,0 +1,351 @@ |
||||
/*
|
||||
* |
||||
* 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; |
||||
|
||||
/* grpc_rb_compression_options wraps a grpc_compression_options.
|
||||
* 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; |
||||
} |
||||
|
||||
/* Provides a bitset as a ruby number that is suitable to pass to
|
||||
* the GRPC core as a channel argument to enable compression algorithms. */ |
||||
VALUE grpc_rb_compression_options_get_enabled_algorithms_bitset(VALUE self) { |
||||
grpc_rb_compression_options *wrapper = NULL; |
||||
|
||||
TypedData_Get_Struct(self, grpc_rb_compression_options, |
||||
&grpc_rb_compression_options_data_type, wrapper); |
||||
return INT2NUM((int)wrapper->wrapped->enabled_algorithms_bitset); |
||||
} |
||||
|
||||
void grpc_rb_compression_options_set_default_level_helper( |
||||
grpc_compression_options *compression_options, |
||||
grpc_compression_level level) { |
||||
compression_options->default_level.is_set |= 1; |
||||
compression_options->default_level.level = level; |
||||
} |
||||
|
||||
/* Sets the default compression level, given the name of a compression level.
|
||||
* Throws an error if no algorithm matched. */ |
||||
VALUE grpc_rb_compression_options_set_default_level(VALUE self, |
||||
VALUE new_level) { |
||||
char *level_name = NULL; |
||||
grpc_rb_compression_options *wrapper = NULL; |
||||
long name_len = 0; |
||||
VALUE ruby_str = Qnil; |
||||
|
||||
TypedData_Get_Struct(self, grpc_rb_compression_options, |
||||
&grpc_rb_compression_options_data_type, wrapper); |
||||
|
||||
/* Take both string and symbol parameters */ |
||||
ruby_str = rb_funcall(new_level, rb_intern("to_s"), 0); |
||||
|
||||
level_name = RSTRING_PTR(ruby_str); |
||||
name_len = RSTRING_LEN(ruby_str); |
||||
|
||||
/* Check the compression level of the name passed in, and see which macro
|
||||
* from the GRPC core header files match. */ |
||||
if (strncmp(level_name, "none", name_len) == 0) { |
||||
grpc_rb_compression_options_set_default_level_helper( |
||||
wrapper->wrapped, GRPC_COMPRESS_LEVEL_NONE); |
||||
} else if (strncmp(level_name, "low", name_len) == 0) { |
||||
grpc_rb_compression_options_set_default_level_helper( |
||||
wrapper->wrapped, GRPC_COMPRESS_LEVEL_LOW); |
||||
} else if (strncmp(level_name, "medium", name_len) == 0) { |
||||
grpc_rb_compression_options_set_default_level_helper( |
||||
wrapper->wrapped, GRPC_COMPRESS_LEVEL_MED); |
||||
} else if (strncmp(level_name, "high", name_len) == 0) { |
||||
grpc_rb_compression_options_set_default_level_helper( |
||||
wrapper->wrapped, GRPC_COMPRESS_LEVEL_HIGH); |
||||
} else { |
||||
rb_raise(rb_eNameError, |
||||
"Invalid compression level name. Supported levels: none, low, " |
||||
"medium, high"); |
||||
} |
||||
|
||||
return Qnil; |
||||
} |
||||
|
||||
/* Gets the internal value of a compression algorithm suitable as the value
|
||||
* in a GRPC core channel arguments hash. |
||||
* Raises an error if the name of the algorithm passed in is invalid. */ |
||||
void grpc_rb_compression_options_get_internal_value_of_algorithm( |
||||
VALUE algorithm_name, grpc_compression_algorithm *compression_algorithm) { |
||||
VALUE ruby_str = Qnil; |
||||
char *name_str = NULL; |
||||
long name_len = 0; |
||||
|
||||
/* Accept ruby symbol and string parameters. */ |
||||
ruby_str = rb_funcall(algorithm_name, rb_intern("to_s"), 0); |
||||
name_str = RSTRING_PTR(ruby_str); |
||||
name_len = RSTRING_LEN(ruby_str); |
||||
|
||||
/* 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, |
||||
compression_algorithm)) { |
||||
rb_raise(rb_eNameError, |
||||
"Invalid compression algorithm name."); |
||||
} |
||||
} |
||||
|
||||
/* 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. */ |
||||
VALUE grpc_rb_compression_options_set_default_algorithm(VALUE self, |
||||
VALUE algorithm_name) { |
||||
grpc_rb_compression_options *wrapper = NULL; |
||||
|
||||
TypedData_Get_Struct(self, grpc_rb_compression_options, |
||||
&grpc_rb_compression_options_data_type, wrapper); |
||||
|
||||
grpc_rb_compression_options_get_internal_value_of_algorithm( |
||||
algorithm_name, &wrapper->wrapped->default_algorithm.algorithm); |
||||
wrapper->wrapped->default_algorithm.is_set |= 1; |
||||
|
||||
return Qnil; |
||||
} |
||||
|
||||
/* Gets the internal value of the default compression level that is to be passed
|
||||
* to the |
||||
* the GRPC core as a channel argument value. |
||||
* A nil return value means that it hasn't been set. */ |
||||
VALUE grpc_rb_compression_options_default_algorithm_internal_value(VALUE self) { |
||||
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) { |
||||
return INT2NUM(wrapper->wrapped->default_algorithm.algorithm); |
||||
} else { |
||||
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_default_level_internal_value(VALUE self) { |
||||
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) { |
||||
return INT2NUM((int)wrapper->wrapped->default_level.level); |
||||
} else { |
||||
return Qnil; |
||||
} |
||||
} |
||||
|
||||
/* Disables compression algorithms by their names. Raises an error if an unkown
|
||||
* name was passed. */ |
||||
VALUE grpc_rb_compression_options_disable_algorithms(int argc, VALUE *argv, |
||||
VALUE self) { |
||||
VALUE algorithm_names = Qnil; |
||||
VALUE ruby_str = Qnil; |
||||
grpc_compression_algorithm internal_algorithm_value; |
||||
|
||||
/* read variadic argument list of names into the algorithm_name ruby array. */ |
||||
rb_scan_args(argc, argv, "0*", &algorithm_names); |
||||
|
||||
for (int i = 0; i < RARRAY_LEN(algorithm_names); i++) { |
||||
ruby_str = |
||||
rb_funcall(rb_ary_entry(algorithm_names, i), rb_intern("to_s"), 0); |
||||
grpc_rb_compression_options_get_internal_value_of_algorithm( |
||||
ruby_str, &internal_algorithm_value); |
||||
rb_funcall(self, rb_intern("disable_algorithm_internal"), 1, |
||||
LONG2NUM((long)internal_algorithm_value)); |
||||
} |
||||
|
||||
return Qnil; |
||||
} |
||||
|
||||
/* 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_funcall(rb_cHash, rb_intern("new"), 0); |
||||
|
||||
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) { |
||||
rb_funcall(channel_arg_hash, rb_intern("[]="), 2, |
||||
rb_str_new2(GRPC_COMPRESSION_CHANNEL_DEFAULT_LEVEL), |
||||
INT2NUM((int)compression_options->default_level.level)); |
||||
} |
||||
|
||||
if (compression_options->default_algorithm.is_set) { |
||||
rb_funcall(channel_arg_hash, rb_intern("[]="), 2, |
||||
rb_str_new2(GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM), |
||||
INT2NUM((int)compression_options->default_algorithm.algorithm)); |
||||
} |
||||
|
||||
rb_funcall(channel_arg_hash, rb_intern("[]="), 2, |
||||
rb_str_new2(GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET), |
||||
INT2NUM((int)compression_options->enabled_algorithms_bitset)); |
||||
|
||||
return channel_arg_hash; |
||||
} |
||||
|
||||
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); |
||||
|
||||
/* Private method for disabling algorithms by a variadic list of names. */ |
||||
rb_define_private_method(grpc_rb_cCompressionOptions, "disable_algorithms", |
||||
grpc_rb_compression_options_disable_algorithms, -1); |
||||
/* Private method for disabling an algorithm by its enum value. */ |
||||
rb_define_private_method( |
||||
grpc_rb_cCompressionOptions, "disable_algorithm_internal", |
||||
grpc_rb_compression_options_disable_compression_algorithm_internal, 1); |
||||
|
||||
/* Private method for getting the bitset of enabled algorithms. */ |
||||
rb_define_private_method( |
||||
grpc_rb_cCompressionOptions, "enabled_algorithms_bitset", |
||||
grpc_rb_compression_options_get_enabled_algorithms_bitset, 0); |
||||
|
||||
/* Private method for setting the default algorithm by name. */ |
||||
rb_define_private_method(grpc_rb_cCompressionOptions, "set_default_algorithm", |
||||
grpc_rb_compression_options_set_default_algorithm, |
||||
1); |
||||
/* Private method for getting the internal enum value of the default
|
||||
* algorithm. */ |
||||
rb_define_private_method( |
||||
grpc_rb_cCompressionOptions, "default_algorithm_internal_value", |
||||
grpc_rb_compression_options_default_algorithm_internal_value, 0); |
||||
|
||||
/* Private method for setting the default compression level by name. */ |
||||
rb_define_private_method(grpc_rb_cCompressionOptions, "set_default_level", |
||||
grpc_rb_compression_options_set_default_level, 1); |
||||
|
||||
/* Private method for getting the internal enum value of the default level. */ |
||||
rb_define_private_method( |
||||
grpc_rb_cCompressionOptions, "default_level_internal_value", |
||||
grpc_rb_compression_options_default_level_internal_value, 0); |
||||
|
||||
/* Public method for returning 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); |
||||
} |
@ -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_ */ |
@ -0,0 +1,93 @@ |
||||
# 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_relative '../grpc' |
||||
|
||||
# GRPC contains the General RPC module. |
||||
module GRPC |
||||
module Core |
||||
# Wrapper for grpc_compression_options in core |
||||
# This class is defined as a C extension but is reopened here |
||||
# to add the initialization logic. |
||||
# |
||||
# This class wraps a GRPC core compression options. |
||||
# |
||||
# It can be used to create a channel argument key-value hash |
||||
# with keys and values that correspond to the compression settings |
||||
# provided here. |
||||
# |
||||
# call-seq: |
||||
# options = CompressionOptions.new( |
||||
# default_level: low, |
||||
# disabled_algorithms: [:<valid_algorithm_name>]) |
||||
# |
||||
# channel_args = Hash.new[...] |
||||
# channel_args_with_compression_args = channel_args.merge(options) |
||||
class CompressionOptions |
||||
alias_method :to_channel_arg_hash, :to_hash |
||||
|
||||
# Initializes a CompresionOptions instance. |
||||
# Starts out with all available compression |
||||
# algorithms enabled by default. |
||||
# |
||||
# Valid algorithms are those supported by the GRPC core |
||||
# |
||||
# @param default_level [String | Symbol] |
||||
# one of 'none', 'low', 'medium', 'high' |
||||
# @param default_algorithm [String | Symbol] |
||||
# a valid GRPC algorithm |
||||
# @param disabled_algorithms [Array<String, Symbol>] |
||||
# can contain valid GRPC algorithm names |
||||
def initialize(default_algorithm: nil, |
||||
default_level: nil, |
||||
disabled_algorithms: []) |
||||
# Convert possible symbols to strings for comparisons |
||||
disabled_algorithms = disabled_algorithms.map(&:to_s) |
||||
|
||||
if disabled_algorithms.include?(default_algorithm.to_s) |
||||
fail ArgumentError("#{default_algorithm} is in disabled_algorithms") |
||||
end |
||||
|
||||
set_default_algorithm(default_algorithm.to_s) unless |
||||
default_algorithm.nil? |
||||
|
||||
set_default_level(default_level.to_s) unless |
||||
default_level.nil? |
||||
|
||||
# *disabled_algorithms spreads array into variadic method parameters |
||||
disable_algorithms(*disabled_algorithms) unless |
||||
disabled_algorithms.nil? || disabled_algorithms.empty? |
||||
end |
||||
|
||||
def to_s |
||||
to_hash.to_s |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,254 @@ |
||||
# 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 |
||||
# Names of supported compression algorithms and their internal enum values |
||||
ALGORITHMS = { |
||||
identity: 0, |
||||
deflate: 1, |
||||
gzip: 2 |
||||
} |
||||
|
||||
# Compression algorithms and their corresponding bits in the internal |
||||
# enabled algorithms bitset for GRPC core channel args. |
||||
ALGORITHM_BITS = { |
||||
identity: 0x1, |
||||
deflate: 0x2, |
||||
gzip: 0x4 |
||||
} |
||||
|
||||
# "enabled algorithms bitset" when all compression algorithms are enabled |
||||
ALL_ENABLED_BITSET = 0x7 |
||||
|
||||
# "enabled algorithms bitset" when all compression algorithms are disabled |
||||
ALL_DISABLED_BITSET = 0x0 |
||||
|
||||
# Names of valid supported compression levels and their internal enum values |
||||
COMPRESS_LEVELS = { |
||||
none: 0, |
||||
low: 1, |
||||
medium: 2, |
||||
high: 3 |
||||
} |
||||
|
||||
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 eql(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 and converting to channel args hash' do |
||||
it 'gives the correct channel args when nothing has been adjusted yet' do |
||||
expect(GRPC::Core::CompressionOptions.new.to_hash).to( |
||||
eql('grpc.compression_enabled_algorithms_bitset' => 0x7)) |
||||
end |
||||
|
||||
it 'gives the correct channel args after everything has been disabled' do |
||||
options = GRPC::Core::CompressionOptions.new( |
||||
default_algorithm: 'identity', |
||||
default_level: 'none', |
||||
disabled_algorithms: [:gzip, :deflate] |
||||
) |
||||
|
||||
expect(options.to_hash).to( |
||||
eql('grpc.default_compression_algorithm' => 0, |
||||
'grpc.default_compression_level' => 0, |
||||
'grpc.compression_enabled_algorithms_bitset' => 0x1) |
||||
) |
||||
end |
||||
|
||||
it 'gives correct channel args with all args set' do |
||||
options = GRPC::Core::CompressionOptions.new( |
||||
default_algorithm: 'gzip', |
||||
default_level: 'low', |
||||
disabled_algorithms: ['deflate'] |
||||
) |
||||
|
||||
expected_bitset = ALL_ENABLED_BITSET & ~ALGORITHM_BITS[:deflate] |
||||
|
||||
expect(options.to_hash).to( |
||||
eql('grpc.default_compression_algorithm' => ALGORITHMS[:gzip], |
||||
'grpc.default_compression_level' => COMPRESS_LEVELS[:low], |
||||
'grpc.compression_enabled_algorithms_bitset' => expected_bitset) |
||||
) |
||||
end |
||||
|
||||
it 'gives correct channel args when no algorithms are disabled' do |
||||
options = GRPC::Core::CompressionOptions.new( |
||||
default_algorithm: 'identity', |
||||
default_level: 'high' |
||||
) |
||||
|
||||
expect(options.to_hash).to( |
||||
eql('grpc.default_compression_algorithm' => ALGORITHMS[:identity], |
||||
'grpc.default_compression_level' => COMPRESS_LEVELS[:high], |
||||
'grpc.compression_enabled_algorithms_bitset' => ALL_ENABLED_BITSET) |
||||
) |
||||
end |
||||
|
||||
# Raising an error in when attempting to set the default algorithm |
||||
# to something that is also requested to be disabled |
||||
it 'gives raises an error when the chosen default algorithm is disabled' do |
||||
blk = proc do |
||||
GRPC::Core::CompressionOptions.new( |
||||
default_algorithm: :gzip, |
||||
disabled_algorithms: [:gzip]) |
||||
end |
||||
expect { blk.call }.to raise_error |
||||
end |
||||
end |
||||
|
||||
# Test the private methods in the C extension that interact with |
||||
# the wrapped grpc_compression_options. |
||||
# |
||||
# Using #send to call private methods. |
||||
describe 'private internal methods' do |
||||
it 'mutating functions and accessors should be private' do |
||||
options = GRPC::Core::CompressionOptions.new |
||||
|
||||
[:disable_algorithm_internal, |
||||
:disable_algorithms, |
||||
:set_default_algorithm, |
||||
:set_default_level, |
||||
:default_algorithm_internal_value, |
||||
:default_level_internal_value].each do |method_name| |
||||
expect(options.private_methods).to include(method_name) |
||||
end |
||||
end |
||||
|
||||
describe '#disable_algorithms' do |
||||
ALGORITHMS.each_pair do |name, internal_value| |
||||
it "passes #{internal_value} to internal method for #{name}" do |
||||
options = GRPC::Core::CompressionOptions.new |
||||
expect(options).to receive(:disable_algorithm_internal) |
||||
.with(internal_value) |
||||
|
||||
options.send(:disable_algorithms, name) |
||||
end |
||||
end |
||||
|
||||
it 'should work with multiple parameters' do |
||||
options = GRPC::Core::CompressionOptions.new |
||||
|
||||
ALGORITHMS.values do |internal_value| |
||||
expect(options).to receive(:disable_algorithm_internal) |
||||
.with(internal_value) |
||||
end |
||||
|
||||
# disabled_algorithms is a private, variadic method |
||||
options.send(:disable_algorithms, *ALGORITHMS.keys) |
||||
end |
||||
end |
||||
|
||||
describe '#new default values' do |
||||
it 'should start out with all algorithms enabled' do |
||||
options = GRPC::Core::CompressionOptions.new |
||||
bitset = options.send(:enabled_algorithms_bitset) |
||||
expect(bitset).to eql(ALL_ENABLED_BITSET) |
||||
end |
||||
|
||||
it 'should start out with no default algorithm' do |
||||
options = GRPC::Core::CompressionOptions.new |
||||
expect(options.send(:default_algorithm_internal_value)).to be_nil |
||||
end |
||||
|
||||
it 'should start out with no default level' do |
||||
options = GRPC::Core::CompressionOptions.new |
||||
expect(options.send(:default_level_internal_value)).to be_nil |
||||
end |
||||
end |
||||
|
||||
describe '#enabled_algoritms_bitset' do |
||||
it 'should respond to disabling one algorithm' do |
||||
options = GRPC::Core::CompressionOptions.new |
||||
options.send(:disable_algorithms, :gzip) |
||||
current_bitset = options.send(:enabled_algorithms_bitset) |
||||
expect(current_bitset & ALGORITHM_BITS[:gzip]).to be_zero |
||||
end |
||||
|
||||
it 'should respond to disabling multiple algorithms' do |
||||
options = GRPC::Core::CompressionOptions.new |
||||
|
||||
# splitting up algorithms array since #disable_algorithms is variadic |
||||
options.send(:disable_algorithms, *ALGORITHMS.keys) |
||||
current_bitset = options.send(:enabled_algorithms_bitset) |
||||
expect(current_bitset).to eql(ALL_DISABLED_BITSET) |
||||
end |
||||
end |
||||
|
||||
describe 'setting the default algorithm by name' do |
||||
it 'should set the internal value of the default algorithm' do |
||||
ALGORITHMS.each_pair do |name, expected_internal_value| |
||||
options = GRPC::Core::CompressionOptions.new |
||||
options.send(:set_default_algorithm, name) |
||||
internal_value = options.send(:default_algorithm_internal_value) |
||||
expect(internal_value).to eql(expected_internal_value) |
||||
end |
||||
end |
||||
|
||||
it 'should fail with invalid algorithm names' do |
||||
[:none, :low, :huffman, :unkown, Object.new, 1].each do |name| |
||||
blk = proc do |
||||
options = GRPC::CoreCompressionOptions.new |
||||
options.send(:set_default_algorithm, name) |
||||
end |
||||
expect { blk.call }.to raise_error |
||||
end |
||||
end |
||||
end |
||||
|
||||
describe 'setting the default level by name' do |
||||
it 'should set the internal value of the default compression value' do |
||||
COMPRESS_LEVELS.each_pair do |level, expected_internal_value| |
||||
options = GRPC::Core::CompressionOptions.new |
||||
options.send(:set_default_level, level) |
||||
internal_value = options.send(:default_level_internal_value) |
||||
expect(internal_value).to eql(expected_internal_value) |
||||
end |
||||
end |
||||
|
||||
it 'should fail with invalid names' do |
||||
[:identity, :gzip, :unkown, :any, Object.new, 1].each do |name| |
||||
blk = proc do |
||||
GRPC::Core::CompressionOptions.new.send(:set_default_level, name) |
||||
end |
||||
expect { blk.call }.to raise_error |
||||
end |
||||
end |
||||
end |
||||
end |
||||
end |
Loading…
Reference in new issue