Replaced private ruby methods with internal c functions

pull/7216/head
Alexander Polcyn 9 years ago committed by Alex Polcyn
parent 0dccf10db7
commit d788b458cf
  1. 528
      src/ruby/ext/grpc/rb_compression_options.c
  2. 1
      src/ruby/lib/grpc.rb
  3. 93
      src/ruby/lib/grpc/core/compression_options.rb
  4. 266
      src/ruby/spec/compression_options_spec.rb

@ -48,7 +48,10 @@
static VALUE grpc_rb_cCompressionOptions = Qnil; static VALUE grpc_rb_cCompressionOptions = Qnil;
/* grpc_rb_compression_options wraps a grpc_compression_options. /* grpc_rb_compression_options wraps a grpc_compression_options.
* Note that ruby objects of this type don't carry any state in other * 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. */ * Ruby objects and don't have a mark for GC. */
typedef struct grpc_rb_compression_options { typedef struct grpc_rb_compression_options {
/* The actual compression options that's being wrapped */ /* The actual compression options that's being wrapped */
@ -120,107 +123,242 @@ VALUE grpc_rb_compression_options_disable_compression_algorithm_internal(
/* Provides a bitset as a ruby number that is suitable to pass to /* Provides a bitset as a ruby number that is suitable to pass to
* the GRPC core as a channel argument to enable compression algorithms. */ * the GRPC core as a channel argument to enable compression algorithms. */
VALUE grpc_rb_compression_options_get_enabled_algorithms_bitset(VALUE self) { /* Gets the compression internal enum value of a compression level given its
grpc_rb_compression_options *wrapper = NULL; * name. */
grpc_compression_level grpc_rb_compression_options_level_name_to_value_internal(
VALUE level_name) {
VALUE none_symbol = Qnil;
VALUE low_symbol = Qnil;
VALUE medium_symbol = Qnil;
VALUE high_symbol = Qnil;
Check_Type(level_name, T_SYMBOL);
/* Ruby symbols that correspond to names of valid compression levels */
none_symbol =
rb_const_get(grpc_rb_cCompressionOptions, rb_intern("COMPRESS_NONE_SYM"));
low_symbol =
rb_const_get(grpc_rb_cCompressionOptions, rb_intern("COMPRESS_LOW_SYM"));
medium_symbol = rb_const_get(grpc_rb_cCompressionOptions,
rb_intern("COMPRESS_MEDIUM_SYM"));
high_symbol =
rb_const_get(grpc_rb_cCompressionOptions, rb_intern("COMPRESS_HIGH_SYM"));
TypedData_Get_Struct(self, grpc_rb_compression_options, /* Check the compression level of the name passed in, and see which macro
&grpc_rb_compression_options_data_type, wrapper); * from the GRPC core header files match. */
return INT2NUM((int)wrapper->wrapped->enabled_algorithms_bitset); if (RTEST(rb_funcall(level_name, rb_intern("=="), 1, none_symbol)) != 0) {
return GRPC_COMPRESS_LEVEL_NONE;
} else if (RTEST(rb_funcall(level_name, rb_intern("=="), 1, low_symbol)) !=
0) {
return GRPC_COMPRESS_LEVEL_LOW;
} else if (RTEST(rb_funcall(level_name, rb_intern("=="), 1, medium_symbol)) !=
0) {
return GRPC_COMPRESS_LEVEL_MED;
} else if (RTEST(rb_funcall(level_name, rb_intern("=="), 1, high_symbol)) !=
0) {
return GRPC_COMPRESS_LEVEL_HIGH;
} else {
rb_raise(rb_eArgError,
"Unrecognized compression level name."
"Valid compression level names are none, low, medium, and high.");
}
} }
void grpc_rb_compression_options_set_default_level_helper( /* Wrapper over grpc_rb_compression_options_level_name_to_value available for
grpc_compression_options *compression_options, * use or testing.
grpc_compression_level level) { * Raises an exception for unrecognized level names. */
compression_options->default_level.is_set |= 1; VALUE grpc_rb_compression_options_level_name_to_value(VALUE self,
compression_options->default_level.level = level; VALUE level_name) {
return INT2NUM((int)grpc_rb_compression_options_level_name_to_value_internal(
level_name));
} }
/* Sets the default compression level, given the name of a compression level. /* Sets the default compression level, given the name of a compression level.
* Throws an error if no algorithm matched. */ * Throws an error if no algorithm matched. */
VALUE grpc_rb_compression_options_set_default_level(VALUE self, void grpc_rb_compression_options_set_default_level(
VALUE new_level) { grpc_compression_options *options, VALUE new_level_name) {
char *level_name = NULL; options->default_level.level =
grpc_rb_compression_options *wrapper = NULL; grpc_rb_compression_options_level_name_to_value_internal(new_level_name);
long name_len = 0; options->default_level.is_set = 1;
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 /* Gets the internal value of a compression algorithm suitable as the value
* in a GRPC core channel arguments hash. * 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. */ * Raises an error if the name of the algorithm passed in is invalid. */
void grpc_rb_compression_options_get_internal_value_of_algorithm( void grpc_rb_compression_options_algorithm_name_to_value_internal(
VALUE algorithm_name, grpc_compression_algorithm *compression_algorithm) { grpc_compression_algorithm *algorithm_value, VALUE algorithm_name) {
VALUE ruby_str = Qnil;
char *name_str = NULL; char *name_str = NULL;
long name_len = 0; long name_len = 0;
VALUE algorithm_name_as_string = Qnil;
/* Accept ruby symbol and string parameters. */ Check_Type(algorithm_name, T_SYMBOL);
ruby_str = rb_funcall(algorithm_name, rb_intern("to_s"), 0);
name_str = RSTRING_PTR(ruby_str); /* Convert the algorithm symbol to a ruby string, so that we can get the
name_len = RSTRING_LEN(ruby_str); * 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 /* Raise an error if the name isn't recognized as a compression algorithm by
* the algorithm parse function * the algorithm parse function
* in GRPC core. */ * in GRPC core. */
if (!grpc_compression_algorithm_parse(name_str, name_len, if (!grpc_compression_algorithm_parse(name_str, name_len, algorithm_value)) {
compression_algorithm)) { rb_raise(rb_eNameError, "Invalid compression algorithm name: %s",
rb_raise(rb_eNameError, StringValueCStr(algorithm_name_as_string));
"Invalid compression algorithm name.");
} }
} }
/* Wrapper around algorithm_name_to_value_internal function available for use or
* testing. */
VALUE grpc_rb_compression_options_algorithm_name_to_value(
VALUE self, VALUE algorithm_name) {
grpc_compression_algorithm algorithm_value;
grpc_rb_compression_options_algorithm_name_to_value_internal(&algorithm_value,
algorithm_name);
return INT2NUM((int)algorithm_value);
}
/* 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. /* 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. */ * Raises an error if the name is not a valid compression algorithm name. */
VALUE grpc_rb_compression_options_set_default_algorithm(VALUE self, void grpc_rb_compression_options_set_default_algorithm(
VALUE algorithm_name) { 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_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, TypedData_Get_Struct(self, grpc_rb_compression_options,
&grpc_rb_compression_options_data_type, wrapper); &grpc_rb_compression_options_data_type, wrapper);
compression_options = wrapper->wrapped;
grpc_rb_compression_options_get_internal_value_of_algorithm( /* Add key-value pairs to the new Ruby hash. It can be used
algorithm_name, &wrapper->wrapped->default_algorithm.algorithm); * as GRPC core channel arguments. */
wrapper->wrapped->default_algorithm.is_set |= 1; 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);
}
return Qnil; 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 rb_const_get(grpc_rb_cCompressionOptions,
rb_intern("COMPRESS_NONE_SYM"));
case GRPC_COMPRESS_LEVEL_LOW:
return rb_const_get(grpc_rb_cCompressionOptions,
rb_intern("COMPRESS_LOW_SYM"));
case GRPC_COMPRESS_LEVEL_MED:
return rb_const_get(grpc_rb_cCompressionOptions,
rb_intern("COMPRESS_MEDIUM_SYM"));
case GRPC_COMPRESS_LEVEL_HIGH:
return rb_const_get(grpc_rb_cCompressionOptions,
rb_intern("COMPRESS_HIGH_SYM"));
default:
rb_raise(
rb_eArgError,
"Failed to convert compression level value to name for value: %d",
(int)compression_value);
}
}
/* Wrapper of internal method that makes it available for use and testing. */
VALUE grpc_rb_compression_options_level_value_to_name(VALUE self,
VALUE compression_value) {
Check_Type(compression_value, T_FIXNUM);
return grpc_rb_compression_options_level_value_to_name_internal(
(grpc_compression_level)NUM2INT(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));
}
/* Wrapper of algorithm_to_name internal function available for ues and testing.
*/
VALUE grpc_rb_compression_options_algorithm_value_to_name(
VALUE self, VALUE algorithm_value) {
grpc_compression_algorithm algorithm_internal_value;
algorithm_internal_value =
(grpc_compression_algorithm)NUM2INT(algorithm_value);
return grpc_rb_compression_options_algorithm_value_to_name_internal(
algorithm_internal_value);
} }
/* Gets the internal value of the default compression level that is to be passed /* Gets the internal value of the default compression level that is to be passed
* to the * to the GRPC core as a channel argument value.
* the GRPC core as a channel argument value.
* A nil return value means that it hasn't been set. */ * A nil return value means that it hasn't been set. */
VALUE grpc_rb_compression_options_default_algorithm_internal_value(VALUE self) { VALUE grpc_rb_compression_options_get_default_algorithm_internal_value(
VALUE self) {
grpc_rb_compression_options *wrapper = NULL; grpc_rb_compression_options *wrapper = NULL;
TypedData_Get_Struct(self, grpc_rb_compression_options, TypedData_Get_Struct(self, grpc_rb_compression_options,
@ -228,15 +366,27 @@ VALUE grpc_rb_compression_options_default_algorithm_internal_value(VALUE self) {
if (wrapper->wrapped->default_algorithm.is_set) { if (wrapper->wrapped->default_algorithm.is_set) {
return INT2NUM(wrapper->wrapped->default_algorithm.algorithm); return INT2NUM(wrapper->wrapped->default_algorithm.algorithm);
} else {
return Qnil;
} }
return Qnil;
} }
/* Gets the internal value of the default compression level that is to be passed /* Gets the readable name of the default algorithm if one has been set.
* to the GRPC core as a channel argument value. * Returns nil if no algorithm has been set. */
* A nil return value means that it hasn't been set. */ VALUE grpc_rb_compression_options_get_default_algorithm(VALUE self) {
VALUE grpc_rb_compression_options_default_level_internal_value(VALUE self) { VALUE algorithm_value =
grpc_rb_compression_options_get_default_algorithm_internal_value(self);
if (RTEST(algorithm_value)) {
return grpc_rb_compression_options_algorithm_value_to_name(self,
algorithm_value);
}
return Qnil;
}
/* Gets the internal enum value of the default algorithm if one has been set.
* Returns nil if no default algorithm has been set. */
VALUE grpc_rb_compression_options_get_default_level_internal_value(VALUE self) {
grpc_rb_compression_options *wrapper = NULL; grpc_rb_compression_options *wrapper = NULL;
TypedData_Get_Struct(self, grpc_rb_compression_options, TypedData_Get_Struct(self, grpc_rb_compression_options,
@ -244,64 +394,121 @@ VALUE grpc_rb_compression_options_default_level_internal_value(VALUE self) {
if (wrapper->wrapped->default_level.is_set) { if (wrapper->wrapped->default_level.is_set) {
return INT2NUM((int)wrapper->wrapped->default_level.level); return INT2NUM((int)wrapper->wrapped->default_level.level);
} else {
return Qnil;
} }
return Qnil;
} }
/* Disables compression algorithms by their names. Raises an error if an unkown /* Gets the internal value of the default compression level that is to be passed
* name was passed. */ * to the GRPC core as a channel argument value.
VALUE grpc_rb_compression_options_disable_algorithms(int argc, VALUE *argv, * A nil return value means that it hasn't been set. */
VALUE self) { VALUE grpc_rb_compression_options_get_default_level(VALUE self) {
VALUE algorithm_names = Qnil; grpc_compression_level internal_value;
VALUE ruby_str = Qnil; VALUE ruby_value =
grpc_compression_algorithm internal_algorithm_value; grpc_rb_compression_options_get_default_level_internal_value(self);
if (RTEST(ruby_value)) {
internal_value = (grpc_compression_level)NUM2INT(ruby_value);
return grpc_rb_compression_options_level_value_to_name_internal(
internal_value);
}
return Qnil;
}
/* read variadic argument list of names into the algorithm_name ruby array. */ /* Gets a list of the disabled algorithms as readable names.
rb_scan_args(argc, argv, "0*", &algorithm_names); * Returns an empty list of 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 (int i = 0; i < RARRAY_LEN(algorithm_names); i++) { for (internal_value = GRPC_COMPRESS_NONE;
ruby_str = internal_value < GRPC_COMPRESS_ALGORITHMS_COUNT; internal_value++) {
rb_funcall(rb_ary_entry(algorithm_names, i), rb_intern("to_s"), 0); if (!grpc_compression_options_is_algorithm_enabled(wrapper->wrapped,
grpc_rb_compression_options_get_internal_value_of_algorithm( internal_value)) {
ruby_str, &internal_algorithm_value); rb_ary_push(disabled_algorithms,
rb_funcall(self, rb_intern("disable_algorithm_internal"), 1, grpc_rb_compression_options_algorithm_value_to_name_internal(
LONG2NUM((long)internal_algorithm_value)); internal_value));
}
} }
return disabled_algorithms;
}
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);
} }
/* Provides a ruby hash of GRPC core channel argument key-values that /* Initializes the compression options wrapper.
* correspond to the compression settings on this instance. */ * Takes an optional hash parameter.
VALUE grpc_rb_compression_options_to_hash(VALUE self) { *
* 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; grpc_rb_compression_options *wrapper = NULL;
grpc_compression_options *compression_options = NULL; VALUE default_algorithm = Qnil;
VALUE channel_arg_hash = rb_funcall(rb_cHash, rb_intern("new"), 0); 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, TypedData_Get_Struct(self, grpc_rb_compression_options,
&grpc_rb_compression_options_data_type, wrapper); &grpc_rb_compression_options_data_type, wrapper);
compression_options = wrapper->wrapped;
/* Add key-value pairs to the new Ruby hash. It can be used /* Set the default algorithm if one was chosen. */
* as GRPC core channel arguments. */ default_algorithm =
if (compression_options->default_level.is_set) { rb_hash_aref(hash_arg, ID2SYM(rb_intern("default_algorithm")));
rb_funcall(channel_arg_hash, rb_intern("[]="), 2, if (default_algorithm != Qnil) {
rb_str_new2(GRPC_COMPRESSION_CHANNEL_DEFAULT_LEVEL), grpc_rb_compression_options_set_default_algorithm(wrapper->wrapped,
INT2NUM((int)compression_options->default_level.level)); default_algorithm);
} }
if (compression_options->default_algorithm.is_set) { /* Set the default level if one was chosen. */
rb_funcall(channel_arg_hash, rb_intern("[]="), 2, default_level = rb_hash_aref(hash_arg, ID2SYM(rb_intern("default_level")));
rb_str_new2(GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM), if (default_level != Qnil) {
INT2NUM((int)compression_options->default_algorithm.algorithm)); grpc_rb_compression_options_set_default_level(wrapper->wrapped,
default_level);
} }
rb_funcall(channel_arg_hash, rb_intern("[]="), 2, /* Set the disabled algorithms if any were chosen. */
rb_str_new2(GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET), disabled_algorithms =
INT2NUM((int)compression_options->enabled_algorithms_bitset)); 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 channel_arg_hash; return self;
} }
void Init_grpc_compression_options() { void Init_grpc_compression_options() {
@ -312,40 +519,71 @@ void Init_grpc_compression_options() {
rb_define_alloc_func(grpc_rb_cCompressionOptions, rb_define_alloc_func(grpc_rb_cCompressionOptions,
grpc_rb_compression_options_alloc); grpc_rb_compression_options_alloc);
/* Private method for disabling algorithms by a variadic list of names. */ /* Initializes the ruby wrapper. #new method takes an optional hash argument.
rb_define_private_method(grpc_rb_cCompressionOptions, "disable_algorithms", */
grpc_rb_compression_options_disable_algorithms, -1); rb_define_method(grpc_rb_cCompressionOptions, "initialize",
/* Private method for disabling an algorithm by its enum value. */ grpc_rb_compression_options_init, -1);
rb_define_private_method(
grpc_rb_cCompressionOptions, "disable_algorithm_internal", /* Gets the bitset of enabled algorithms. */
grpc_rb_compression_options_disable_compression_algorithm_internal, 1); rb_define_method(grpc_rb_cCompressionOptions, "enabled_algorithms_bitset",
grpc_rb_compression_options_get_enabled_algorithms_bitset,
/* Private method for getting the bitset of enabled algorithms. */ 0);
rb_define_private_method(
grpc_rb_cCompressionOptions, "enabled_algorithms_bitset", /* Methods for getting the default algorithm, default level, and disabled
grpc_rb_compression_options_get_enabled_algorithms_bitset, 0); * algorithms as readable names. */
rb_define_method(grpc_rb_cCompressionOptions, "default_algorithm",
/* Private method for setting the default algorithm by name. */ grpc_rb_compression_options_get_default_algorithm, 0);
rb_define_private_method(grpc_rb_cCompressionOptions, "set_default_algorithm", rb_define_method(grpc_rb_cCompressionOptions, "default_level",
grpc_rb_compression_options_set_default_algorithm, grpc_rb_compression_options_get_default_level, 0);
1); rb_define_method(grpc_rb_cCompressionOptions, "disabled_algorithms",
/* Private method for getting the internal enum value of the default grpc_rb_compression_options_get_disabled_algorithms, 0);
* algorithm. */
rb_define_private_method( /* Methods for getting the internal enum default algorithm and level enum
* values of an instance. */
rb_define_method(
grpc_rb_cCompressionOptions, "default_algorithm_internal_value", grpc_rb_cCompressionOptions, "default_algorithm_internal_value",
grpc_rb_compression_options_default_algorithm_internal_value, 0); grpc_rb_compression_options_get_default_algorithm_internal_value, 0);
rb_define_method(grpc_rb_cCompressionOptions, "default_level_internal_value",
/* Private method for setting the default compression level by name. */ grpc_rb_compression_options_get_default_level_internal_value,
rb_define_private_method(grpc_rb_cCompressionOptions, "set_default_level", 0);
grpc_rb_compression_options_set_default_level, 1);
/* Determines whether or not an algorithm is enabled, given a readable
/* Private method for getting the internal enum value of the default level. */ * algorithm name.*/
rb_define_private_method( rb_define_method(grpc_rb_cCompressionOptions, "is_algorithm_enabled",
grpc_rb_cCompressionOptions, "default_level_internal_value", grpc_rb_compression_options_is_algorithm_enabled, 1);
grpc_rb_compression_options_default_level_internal_value, 0);
/* Methods for converting to and from algorithm enum values and their readable
/* Public method for returning a hash of the compression settings suitable * names. */
rb_define_singleton_method(
grpc_rb_cCompressionOptions, "algorithm_name_to_value",
grpc_rb_compression_options_algorithm_name_to_value, 1);
rb_define_singleton_method(
grpc_rb_cCompressionOptions, "algorithm_value_to_name",
grpc_rb_compression_options_algorithm_value_to_name, 1);
/* Methods for converting to and from compression level enum values and their
* readable names. */
rb_define_singleton_method(grpc_rb_cCompressionOptions, "level_name_to_value",
grpc_rb_compression_options_level_name_to_value,
1);
rb_define_singleton_method(grpc_rb_cCompressionOptions, "level_value_to_name",
grpc_rb_compression_options_level_value_to_name,
1);
/* Provides a hash of the compression settings suitable
* for passing to server or channel args. */ * for passing to server or channel args. */
rb_define_method(grpc_rb_cCompressionOptions, "to_hash", rb_define_method(grpc_rb_cCompressionOptions, "to_hash",
grpc_rb_compression_options_to_hash, 0); grpc_rb_compression_options_to_hash, 0);
rb_define_alias(grpc_rb_cCompressionOptions, "to_channel_arg_hash",
"to_hash");
/* Ruby symbols for the names of the different compression levels. */
rb_define_const(grpc_rb_cCompressionOptions, "COMPRESS_NONE_SYM",
ID2SYM(rb_intern("none")));
rb_define_const(grpc_rb_cCompressionOptions, "COMPRESS_LOW_SYM",
ID2SYM(rb_intern("low")));
rb_define_const(grpc_rb_cCompressionOptions, "COMPRESS_MEDIUM_SYM",
ID2SYM(rb_intern("medium")));
rb_define_const(grpc_rb_cCompressionOptions, "COMPRESS_HIGH_SYM",
ID2SYM(rb_intern("high")));
} }

@ -35,7 +35,6 @@ require_relative 'grpc/logconfig'
require_relative 'grpc/notifier' require_relative 'grpc/notifier'
require_relative 'grpc/version' require_relative 'grpc/version'
require_relative 'grpc/core/time_consts' require_relative 'grpc/core/time_consts'
require_relative 'grpc/core/compression_options'
require_relative 'grpc/generic/active_call' require_relative 'grpc/generic/active_call'
require_relative 'grpc/generic/client_stub' require_relative 'grpc/generic/client_stub'
require_relative 'grpc/generic/service' require_relative 'grpc/generic/service'

@ -1,93 +0,0 @@
# 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

@ -59,6 +59,13 @@ describe GRPC::Core::CompressionOptions do
high: 3 high: 3
} }
it 'compression level name constants should match expections' do
expect(GRPC::Core::CompressionOptions::COMPRESS_NONE_SYM).to eq(:none)
expect(GRPC::Core::CompressionOptions::COMPRESS_LOW_SYM).to eq(:low)
expect(GRPC::Core::CompressionOptions::COMPRESS_MEDIUM_SYM).to eq(:medium)
expect(GRPC::Core::CompressionOptions::COMPRESS_HIGH_SYM).to eq(:high)
end
it 'implements to_s' do it 'implements to_s' do
expect { GRPC::Core::CompressionOptions.new.to_s }.to_not raise_error expect { GRPC::Core::CompressionOptions.new.to_s }.to_not raise_error
end end
@ -79,23 +86,25 @@ describe GRPC::Core::CompressionOptions do
it 'gives the correct channel args after everything has been disabled' do it 'gives the correct channel args after everything has been disabled' do
options = GRPC::Core::CompressionOptions.new( options = GRPC::Core::CompressionOptions.new(
default_algorithm: 'identity', default_algorithm: :identity,
default_level: 'none', default_level: :none,
disabled_algorithms: [:gzip, :deflate] disabled_algorithms: ALGORITHMS.keys
) )
expect(options.to_hash).to( channel_arg_hash = options.to_hash
eql('grpc.default_compression_algorithm' => 0, expect(channel_arg_hash['grpc.default_compression_algorithm']).to eq(0)
'grpc.default_compression_level' => 0, expect(channel_arg_hash['grpc.default_compression_level']).to eq(0)
'grpc.compression_enabled_algorithms_bitset' => 0x1)
) # Don't care if the "identity" algorithm bit is set or unset
bitset = channel_arg_hash['grpc.compression_enabled_algorithms_bitset']
expect(bitset & ~ALGORITHM_BITS[:identity]).to eq(0)
end end
it 'gives correct channel args with all args set' do it 'gives correct channel args with all args set' do
options = GRPC::Core::CompressionOptions.new( options = GRPC::Core::CompressionOptions.new(
default_algorithm: 'gzip', default_algorithm: :gzip,
default_level: 'low', default_level: :low,
disabled_algorithms: ['deflate'] disabled_algorithms: [:deflate]
) )
expected_bitset = ALL_ENABLED_BITSET & ~ALGORITHM_BITS[:deflate] expected_bitset = ALL_ENABLED_BITSET & ~ALGORITHM_BITS[:deflate]
@ -109,8 +118,8 @@ describe GRPC::Core::CompressionOptions do
it 'gives correct channel args when no algorithms are disabled' do it 'gives correct channel args when no algorithms are disabled' do
options = GRPC::Core::CompressionOptions.new( options = GRPC::Core::CompressionOptions.new(
default_algorithm: 'identity', default_algorithm: :identity,
default_level: 'high' default_level: :high
) )
expect(options.to_hash).to( expect(options.to_hash).to(
@ -119,136 +128,181 @@ describe GRPC::Core::CompressionOptions do
'grpc.compression_enabled_algorithms_bitset' => ALL_ENABLED_BITSET) 'grpc.compression_enabled_algorithms_bitset' => ALL_ENABLED_BITSET)
) )
end end
end
# Raising an error in when attempting to set the default algorithm describe '#new with bad parameters' do
# to something that is also requested to be disabled it 'should fail with more than one parameter' do
it 'gives raises an error when the chosen default algorithm is disabled' do blk = proc { GRPC::Core::CompressionOptions.new(:gzip, :none) }
blk = proc do
GRPC::Core::CompressionOptions.new(
default_algorithm: :gzip,
disabled_algorithms: [:gzip])
end
expect { blk.call }.to raise_error expect { blk.call }.to raise_error
end end
end
# Test the private methods in the C extension that interact with it 'should fail with a non-hash parameter' do
# the wrapped grpc_compression_options. blk = proc { GRPC::Core::CompressionOptions.new(:gzip) }
# expect { blk.call }.to raise_error
# Using #send to call private methods. end
describe 'private internal methods' do end
it 'mutating functions and accessors should be private' do
options = GRPC::Core::CompressionOptions.new
[:disable_algorithm_internal, describe '#level_name_to_value' do
:disable_algorithms, it 'should give the correct internal values from compression level names' do
:set_default_algorithm, cls = GRPC::Core::CompressionOptions
:set_default_level, COMPRESS_LEVELS.each_pair do |name, internal_value|
:default_algorithm_internal_value, expect(cls.level_name_to_value(name)).to eq(internal_value)
:default_level_internal_value].each do |method_name|
expect(options.private_methods).to include(method_name)
end end
end end
describe '#disable_algorithms' do [:gzip, :deflate, :any, Object.new, 'none', 'low', 1].each do |name|
ALGORITHMS.each_pair do |name, internal_value| it "should fail for parameter #{name} of class #{name.class}" do
it "passes #{internal_value} to internal method for #{name}" do blk = proc do
options = GRPC::Core::CompressionOptions.new GRPC::Core::CompressionOptions.level_name_to_value(name)
expect(options).to receive(:disable_algorithm_internal)
.with(internal_value)
options.send(:disable_algorithms, name)
end end
expect { blk.call }.to raise_error
end end
end
end
it 'should work with multiple parameters' do describe '#level_value_to_name' do
options = GRPC::Core::CompressionOptions.new it 'should give the correct internal values from compression level names' do
cls = GRPC::Core::CompressionOptions
COMPRESS_LEVELS.each_pair do |name, internal_value|
expect(cls.level_value_to_name(internal_value)).to eq(name)
end
end
ALGORITHMS.values do |internal_value| [:gzip, :any, Object.new, '1', :low].each do |name|
expect(options).to receive(:disable_algorithm_internal) it "should fail for parameter #{name} of class #{name.class}" do
.with(internal_value) blk = proc do
GRPC::Core::CompressionOptions.level_value_to_name(name)
end end
expect { blk.call }.to raise_error
end
end
end
# disabled_algorithms is a private, variadic method describe '#algorithm_name_to_value' do
options.send(:disable_algorithms, *ALGORITHMS.keys) it 'should give the correct internal values from algorithm names' do
cls = GRPC::Core::CompressionOptions
ALGORITHMS.each_pair do |name, internal_value|
expect(cls.algorithm_name_to_value(name)).to eq(internal_value)
end end
end end
describe '#new default values' do ['gzip', 'deflate', :any, Object.new, :none, :low, 1].each do |name|
it 'should start out with all algorithms enabled' do it "should fail for parameter #{name} of class #{name.class}" do
options = GRPC::Core::CompressionOptions.new blk = proc do
bitset = options.send(:enabled_algorithms_bitset) GRPC::Core::CompressionOptions.algorithm_name_to_value(name)
expect(bitset).to eql(ALL_ENABLED_BITSET) end
expect { blk.call }.to raise_error
end end
end
end
it 'should start out with no default algorithm' do describe '#algorithm_value_to_name' do
options = GRPC::Core::CompressionOptions.new it 'should give the correct internal values from algorithm names' do
expect(options.send(:default_algorithm_internal_value)).to be_nil cls = GRPC::Core::CompressionOptions
ALGORITHMS.each_pair do |name, internal_value|
expect(cls.algorithm_value_to_name(internal_value)).to eq(name)
end end
end
it 'should start out with no default level' do ['gzip', :deflate, :any, Object.new, :low, '1'].each do |value|
options = GRPC::Core::CompressionOptions.new it "should fail for parameter #{value} of class #{value.class}" do
expect(options.send(:default_level_internal_value)).to be_nil blk = proc do
GRPC::Core::CompressionOptions.algorithm_value_to_name(value)
end
expect { blk.call }.to raise_error
end end
end end
end
describe '#enabled_algoritms_bitset' do describe '#default_algorithm and #default_algorithm_internal_value' do
it 'should respond to disabling one algorithm' do it 'can set the default algorithm and then read it back out' do
options = GRPC::Core::CompressionOptions.new ALGORITHMS.each_pair do |name, internal_value|
options.send(:disable_algorithms, :gzip) options = GRPC::Core::CompressionOptions.new(default_algorithm: name)
current_bitset = options.send(:enabled_algorithms_bitset) expect(options.default_algorithm).to eq(name)
expect(current_bitset & ALGORITHM_BITS[:gzip]).to be_zero expect(options.default_algorithm_internal_value).to eq(internal_value)
end end
end
it 'should respond to disabling multiple algorithms' do it 'returns nil if unset' do
options = GRPC::Core::CompressionOptions.new options = GRPC::Core::CompressionOptions.new
expect(options.default_algorithm).to be_nil
expect(options.default_algorithm_internal_value).to be_nil
end
end
# splitting up algorithms array since #disable_algorithms is variadic describe '#default_level and #default_level_internal_value' do
options.send(:disable_algorithms, *ALGORITHMS.keys) it 'can set the default level and read it back out' do
current_bitset = options.send(:enabled_algorithms_bitset) COMPRESS_LEVELS.each_pair do |name, internal_value|
expect(current_bitset).to eql(ALL_DISABLED_BITSET) options = GRPC::Core::CompressionOptions.new(default_level: name)
expect(options.default_level).to eq(name)
expect(options.default_level_internal_value).to eq(internal_value)
end end
end end
describe 'setting the default algorithm by name' do it 'returns nil if unset' do
it 'should set the internal value of the default algorithm' do options = GRPC::Core::CompressionOptions.new
ALGORITHMS.each_pair do |name, expected_internal_value| expect(options.default_level).to be_nil
options = GRPC::Core::CompressionOptions.new expect(options.default_level_internal_value).to be_nil
options.send(:set_default_algorithm, name) end
internal_value = options.send(:default_algorithm_internal_value) end
expect(internal_value).to eql(expected_internal_value)
end
end
it 'should fail with invalid algorithm names' do describe '#disabled_algorithms' do
[:none, :low, :huffman, :unkown, Object.new, 1].each do |name| it 'can set the disabled algorithms and read them back out' do
blk = proc do options = GRPC::Core::CompressionOptions.new(
options = GRPC::CoreCompressionOptions.new disabled_algorithms: [:gzip, :deflate])
options.send(:set_default_algorithm, name)
end [:gzip, :deflate].each do |name|
expect { blk.call }.to raise_error expect(options.disabled_algorithms.include?(name)).to eq(true)
end
end end
expect(options.disabled_algorithms.size).to eq(2)
end end
describe 'setting the default level by name' do it 'returns an empty list if no algorithms were disabled' do
it 'should set the internal value of the default compression value' do options = GRPC::Core::CompressionOptions.new
COMPRESS_LEVELS.each_pair do |level, expected_internal_value| expect(options.disabled_algorithms).to eq([])
options = GRPC::Core::CompressionOptions.new end
options.send(:set_default_level, level) end
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 describe '#is_algorithm_enabled' do
[:identity, :gzip, :unkown, :any, Object.new, 1].each do |name| it 'returns true if the algorithm is valid and not disabled' do
blk = proc do options = GRPC::Core::CompressionOptions.new(disabled_algorithms: [:gzip])
GRPC::Core::CompressionOptions.new.send(:set_default_level, name) expect(options.is_algorithm_enabled(:deflate)).to eq(true)
end end
expect { blk.call }.to raise_error
it 'returns false if the algorithm is valid and disabled' do
options = GRPC::Core::CompressionOptions.new(disabled_algorithms: [:gzip])
expect(options.is_algorithm_enabled(:gzip)).to eq(false)
end
[: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.is_algorithm_enabled(name)
end end
expect { blk.call }.to raise_error
end end
end end
end end
describe '#enabled_algoritms_bitset' do
it 'should respond to not disabling any algorithms' do
options = GRPC::Core::CompressionOptions.new
expect(options.enabled_algorithms_bitset).to eq(ALL_ENABLED_BITSET)
end
it 'should respond to disabling one algorithm' do
options = GRPC::Core::CompressionOptions.new(
disabled_algorithms: [:gzip])
expect(options.enabled_algorithms_bitset & ALGORITHM_BITS[:gzip]).to eq(0)
end
it 'should respond to disabling multiple algorithms' do
options = GRPC::Core::CompressionOptions.new(
disabled_algorithms: ALGORITHMS.keys)
expect(options.enabled_algorithms_bitset).to eql(ALL_DISABLED_BITSET)
end
end
end end

Loading…
Cancel
Save