diff --git a/src/ruby/ext/grpc/rb_call.c b/src/ruby/ext/grpc/rb_call.c index 3be7c3b0c90..872f8e35eac 100644 --- a/src/ruby/ext/grpc/rb_call.c +++ b/src/ruby/ext/grpc/rb_call.c @@ -38,8 +38,8 @@ #include #include "rb_byte_buffer.h" #include "rb_completion_queue.h" +#include "rb_event.h" #include "rb_metadata.h" -#include "rb_status.h" #include "rb_grpc.h" /* id_cq is the name of the hidden ivar that preserves a reference to a @@ -270,8 +270,8 @@ static VALUE grpc_rb_call_get_status(VALUE self) { Saves a status object on the call. */ static VALUE grpc_rb_call_set_status(VALUE self, VALUE status) { - if (!NIL_P(status) && rb_obj_class(status) != rb_cStatus) { - rb_raise(rb_eTypeError, "bad status: got:<%s> want: ", + if (!NIL_P(status) && rb_obj_class(status) != rb_sStatus) { + rb_raise(rb_eTypeError, "bad status: got:<%s> want: ", rb_obj_classname(status)); return Qnil; } @@ -344,6 +344,11 @@ static VALUE grpc_rb_call_start_write(int argc, VALUE *argv, VALUE self) { } /* Queue a status for writing. + + call-seq: + tag = Object.new + call.write_status(200, "OK", tag) + REQUIRES: No other writes are pending on the call. It is only safe to start the next write after the corresponding write_accepted event is received. @@ -352,13 +357,13 @@ static VALUE grpc_rb_call_start_write(int argc, VALUE *argv, VALUE self) { Only callable on the server. Produces a GRPC_FINISHED event when the status is sent and the stream is fully closed */ -static VALUE grpc_rb_call_start_write_status(VALUE self, VALUE status, - VALUE tag) { +static VALUE grpc_rb_call_start_write_status(VALUE self, VALUE code, + VALUE status, VALUE tag) { grpc_call *call = NULL; - grpc_status *sts = grpc_rb_get_wrapped_status(status); grpc_call_error err; Data_Get_Struct(self, grpc_call, call); - err = grpc_call_start_write_status(call, *sts, ROBJECT(tag)); + err = grpc_call_start_write_status(call, NUM2UINT(code), + StringValueCStr(status), ROBJECT(tag)); if (err != GRPC_CALL_OK) { rb_raise(rb_eCallError, "start write status: %s (code=%d)", grpc_call_error_detail_of(err), err); @@ -522,7 +527,7 @@ void Init_google_rpc_call() { rb_define_method(rb_cCall, "start_read", grpc_rb_call_start_read, 1); rb_define_method(rb_cCall, "start_write", grpc_rb_call_start_write, -1); rb_define_method(rb_cCall, "start_write_status", - grpc_rb_call_start_write_status, 2); + grpc_rb_call_start_write_status, 3); rb_define_method(rb_cCall, "writes_done", grpc_rb_call_writes_done, 1); rb_define_method(rb_cCall, "status", grpc_rb_call_get_status, 0); rb_define_method(rb_cCall, "status=", grpc_rb_call_set_status, 1); diff --git a/src/ruby/ext/grpc/rb_event.c b/src/ruby/ext/grpc/rb_event.c index 93f36f80e8c..76ea6ad1033 100644 --- a/src/ruby/ext/grpc/rb_event.c +++ b/src/ruby/ext/grpc/rb_event.c @@ -40,7 +40,6 @@ #include "rb_byte_buffer.h" #include "rb_call.h" #include "rb_metadata.h" -#include "rb_status.h" /* rb_mCompletionType is a ruby module that holds the completion type values */ VALUE rb_mCompletionType = Qnil; @@ -132,6 +131,11 @@ static VALUE grpc_rb_event_metadata(VALUE self) { metadata = event->data.client_metadata_read.elements; break; + case GRPC_FINISHED: + count = event->data.finished.metadata_count; + metadata = event->data.finished.metadata_elements; + break; + case GRPC_SERVER_RPC_NEW: count = event->data.server_rpc_new.metadata_count; metadata = event->data.server_rpc_new.metadata_elements; @@ -139,8 +143,9 @@ static VALUE grpc_rb_event_metadata(VALUE self) { default: rb_raise(rb_eRuntimeError, - "bug: bad event type reading server metadata. got %d; want %d", - event->type, GRPC_SERVER_RPC_NEW); + "bug: bad event type metadata. got %d; want %d|%d:%d", + event->type, GRPC_CLIENT_METADATA_READ, GRPC_FINISHED, + GRPC_SERVER_RPC_NEW); return Qnil; } @@ -212,7 +217,13 @@ static VALUE grpc_rb_event_result(VALUE self) { return grpc_rb_event_metadata(self); case GRPC_FINISHED: - return grpc_rb_status_create_with_mark(self, &event->data.finished); + return rb_struct_new( + rb_sStatus, + UINT2NUM(event->data.finished.status), + (event->data.finished.details == NULL ? + Qnil : rb_str_new2(event->data.finished.details)), + grpc_rb_event_metadata(self), + NULL); break; case GRPC_SERVER_RPC_NEW: @@ -237,6 +248,9 @@ static VALUE grpc_rb_event_result(VALUE self) { /* rb_sNewServerRpc is the struct that holds new server rpc details. */ VALUE rb_sNewServerRpc = Qnil; +/* rb_sStatus is the struct that holds status details. */ +VALUE rb_sStatus = Qnil; + /* rb_cEvent is the Event class whose instances proxy grpc_event */ VALUE rb_cEvent = Qnil; @@ -250,6 +264,7 @@ void Init_google_rpc_event() { rb_cEvent = rb_define_class_under(rb_mGoogleRpcCore, "Event", rb_cObject); rb_sNewServerRpc = rb_struct_define("NewServerRpc", "method", "host", "deadline", "metadata", NULL); + rb_sStatus = rb_struct_define("Status", "code", "details", "metadata", NULL); /* Prevent allocation or inialization from ruby. */ rb_define_alloc_func(rb_cEvent, grpc_rb_cannot_alloc); diff --git a/src/ruby/ext/grpc/rb_event.h b/src/ruby/ext/grpc/rb_event.h index c398b6c6c81..459502c6479 100644 --- a/src/ruby/ext/grpc/rb_event.h +++ b/src/ruby/ext/grpc/rb_event.h @@ -39,6 +39,9 @@ /* rb_sNewServerRpc is the struct that holds new server rpc details. */ extern VALUE rb_sNewServerRpc; +/* rb_sStruct is the struct that holds status details. */ +extern VALUE rb_sStatus; + /* rb_cEvent is the Event class whose instances proxy grpc_event. */ extern VALUE rb_cEvent; diff --git a/src/ruby/ext/grpc/rb_grpc.c b/src/ruby/ext/grpc/rb_grpc.c index 9c54a05c45d..f0e432a6bca 100644 --- a/src/ruby/ext/grpc/rb_grpc.c +++ b/src/ruby/ext/grpc/rb_grpc.c @@ -48,7 +48,6 @@ #include "rb_server.h" #include "rb_credentials.h" #include "rb_server_credentials.h" -#include "rb_status.h" /* Define common vars and funcs declared in rb.h */ const RUBY_DATA_FUNC GC_NOT_MARKED = NULL; @@ -157,6 +156,39 @@ gpr_timespec grpc_rb_time_timeval(VALUE time, int interval) { return t; } +void Init_google_status_codes() { + /* Constants representing the status codes or grpc_status_code in status.h */ + VALUE rb_mStatusCodes = rb_define_module_under(rb_mGoogleRpcCore, + "StatusCodes"); + rb_define_const(rb_mStatusCodes, "OK", INT2NUM(GRPC_STATUS_OK)); + rb_define_const(rb_mStatusCodes, "CANCELLED", INT2NUM(GRPC_STATUS_CANCELLED)); + rb_define_const(rb_mStatusCodes, "UNKNOWN", INT2NUM(GRPC_STATUS_UNKNOWN)); + rb_define_const(rb_mStatusCodes, "INVALID_ARGUMENT", + INT2NUM(GRPC_STATUS_INVALID_ARGUMENT)); + rb_define_const(rb_mStatusCodes, "DEADLINE_EXCEEDED", + INT2NUM(GRPC_STATUS_DEADLINE_EXCEEDED)); + rb_define_const(rb_mStatusCodes, "NOT_FOUND", INT2NUM(GRPC_STATUS_NOT_FOUND)); + rb_define_const(rb_mStatusCodes, "ALREADY_EXISTS", + INT2NUM(GRPC_STATUS_ALREADY_EXISTS)); + rb_define_const(rb_mStatusCodes, "PERMISSION_DENIED", + INT2NUM(GRPC_STATUS_PERMISSION_DENIED)); + rb_define_const(rb_mStatusCodes, "UNAUTHENTICATED", + INT2NUM(GRPC_STATUS_UNAUTHENTICATED)); + rb_define_const(rb_mStatusCodes, "RESOURCE_EXHAUSTED", + INT2NUM(GRPC_STATUS_RESOURCE_EXHAUSTED)); + rb_define_const(rb_mStatusCodes, "FAILED_PRECONDITION", + INT2NUM(GRPC_STATUS_FAILED_PRECONDITION)); + rb_define_const(rb_mStatusCodes, "ABORTED", INT2NUM(GRPC_STATUS_ABORTED)); + rb_define_const(rb_mStatusCodes, "OUT_OF_RANGE", + INT2NUM(GRPC_STATUS_OUT_OF_RANGE)); + rb_define_const(rb_mStatusCodes, "UNIMPLEMENTED", + INT2NUM(GRPC_STATUS_UNIMPLEMENTED)); + rb_define_const(rb_mStatusCodes, "INTERNAL", INT2NUM(GRPC_STATUS_INTERNAL)); + rb_define_const(rb_mStatusCodes, "UNAVAILABLE", + INT2NUM(GRPC_STATUS_UNAVAILABLE)); + rb_define_const(rb_mStatusCodes, "DATA_LOSS", INT2NUM(GRPC_STATUS_DATA_LOSS)); +} + /* id_at is the constructor method of the ruby standard Time class. */ static ID id_at; @@ -233,6 +265,6 @@ void Init_grpc() { Init_google_rpc_metadata(); Init_google_rpc_server(); Init_google_rpc_server_credentials(); - Init_google_rpc_status(); + Init_google_status_codes(); Init_google_time_consts(); } diff --git a/src/ruby/ext/grpc/rb_status.c b/src/ruby/ext/grpc/rb_status.c deleted file mode 100644 index 4c1b6c733ac..00000000000 --- a/src/ruby/ext/grpc/rb_status.c +++ /dev/null @@ -1,244 +0,0 @@ -/* - * - * Copyright 2014, 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 "rb_status.h" - -#include -#include - -#include -#include -#include "rb_grpc.h" - -/* grpc_rb_status wraps a grpc_status. It provides a peer ruby object, 'mark' - * to minimize copying when a status is created from ruby. */ -typedef struct grpc_rb_status { - /* Holder of ruby objects involved in constructing the status */ - VALUE mark; - /* The actual status */ - grpc_status *wrapped; -} grpc_rb_status; - -/* Destroys Status instances. */ -static void grpc_rb_status_free(void *p) { - grpc_rb_status *status = NULL; - if (p == NULL) { - return; - }; - status = (grpc_rb_status *)p; - - /* Delete the wrapped object if the mark object is Qnil, which indicates that - * no other object is the actual owner. */ - if (status->wrapped != NULL && status->mark == Qnil) { - status->mark = Qnil; - if (status->wrapped->details) { - xfree(status->wrapped->details); - } - xfree(status->wrapped); - } - - xfree(p); -} - -/* Protects the mark object from GC */ -static void grpc_rb_status_mark(void *p) { - grpc_rb_status *status = NULL; - if (p == NULL) { - return; - } - status = (grpc_rb_status *)p; - - /* If it's not already cleaned up, mark the mark object */ - if (status->mark != Qnil) { - rb_gc_mark(status->mark); - } -} - -/* Allocates Status instances. - - Provides safe initial defaults for the instance fields. */ -static VALUE grpc_rb_status_alloc(VALUE cls) { - grpc_rb_status *wrapper = ALLOC(grpc_rb_status); - wrapper->wrapped = NULL; - wrapper->mark = Qnil; - return Data_Wrap_Struct(cls, grpc_rb_status_mark, grpc_rb_status_free, - wrapper); -} - -/* The name of the attribute used on the mark object to hold the details. */ -static ID id_details; - -/* Initializes Status instances. */ -static VALUE grpc_rb_status_init(VALUE self, VALUE code, VALUE details) { - grpc_rb_status *wrapper = NULL; - grpc_status *status = NULL; - Data_Get_Struct(self, grpc_rb_status, wrapper); - - /* Use a direct pointer to the original detail value to avoid copying. Assume - * that details is null-terminated. */ - status = ALLOC(grpc_status); - status->details = StringValueCStr(details); - status->code = NUM2INT(code); - wrapper->wrapped = status; - - /* Create the mark and add the original details object to it. */ - wrapper->mark = rb_class_new_instance(0, NULL, rb_cObject); - rb_ivar_set(wrapper->mark, id_details, details); - return self; -} - -/* Clones Status instances. - - Gives Status a consistent implementation of Ruby's object copy/dup - protocol. */ -static VALUE grpc_rb_status_init_copy(VALUE copy, VALUE orig) { - grpc_rb_status *orig_status = NULL; - grpc_rb_status *copy_status = NULL; - - if (copy == orig) { - return copy; - } - - /* Raise an error if orig is not a Status object or a subclass. */ - if (TYPE(orig) != T_DATA || - RDATA(orig)->dfree != (RUBY_DATA_FUNC)grpc_rb_status_free) { - rb_raise(rb_eTypeError, "not a %s", rb_obj_classname(rb_cStatus)); - } - - Data_Get_Struct(orig, grpc_rb_status, orig_status); - Data_Get_Struct(copy, grpc_rb_status, copy_status); - MEMCPY(copy_status, orig_status, grpc_rb_status, 1); - return copy; -} - -/* Gets the Status code. */ -static VALUE grpc_rb_status_code(VALUE self) { - grpc_rb_status *status = NULL; - Data_Get_Struct(self, grpc_rb_status, status); - return INT2NUM(status->wrapped->code); -} - -/* Gets the Status details. */ -static VALUE grpc_rb_status_details(VALUE self) { - VALUE from_ruby; - grpc_rb_status *wrapper = NULL; - grpc_status *status; - - Data_Get_Struct(self, grpc_rb_status, wrapper); - if (wrapper->mark != Qnil) { - from_ruby = rb_ivar_get(wrapper->mark, id_details); - if (from_ruby != Qnil) { - return from_ruby; - } - } - - status = wrapper->wrapped; - if (status == NULL || status->details == NULL) { - return Qnil; - } - - return rb_str_new2(status->details); -} - -void Init_google_status_codes() { - /* Constants representing the status codes or grpc_status_code in status.h */ - VALUE rb_mStatusCodes = rb_define_module_under(rb_mGoogleRpcCore, - "StatusCodes"); - rb_define_const(rb_mStatusCodes, "OK", INT2NUM(GRPC_STATUS_OK)); - rb_define_const(rb_mStatusCodes, "CANCELLED", INT2NUM(GRPC_STATUS_CANCELLED)); - rb_define_const(rb_mStatusCodes, "UNKNOWN", INT2NUM(GRPC_STATUS_UNKNOWN)); - rb_define_const(rb_mStatusCodes, "INVALID_ARGUMENT", - INT2NUM(GRPC_STATUS_INVALID_ARGUMENT)); - rb_define_const(rb_mStatusCodes, "DEADLINE_EXCEEDED", - INT2NUM(GRPC_STATUS_DEADLINE_EXCEEDED)); - rb_define_const(rb_mStatusCodes, "NOT_FOUND", INT2NUM(GRPC_STATUS_NOT_FOUND)); - rb_define_const(rb_mStatusCodes, "ALREADY_EXISTS", - INT2NUM(GRPC_STATUS_ALREADY_EXISTS)); - rb_define_const(rb_mStatusCodes, "PERMISSION_DENIED", - INT2NUM(GRPC_STATUS_PERMISSION_DENIED)); - rb_define_const(rb_mStatusCodes, "UNAUTHENTICATED", - INT2NUM(GRPC_STATUS_UNAUTHENTICATED)); - rb_define_const(rb_mStatusCodes, "RESOURCE_EXHAUSTED", - INT2NUM(GRPC_STATUS_RESOURCE_EXHAUSTED)); - rb_define_const(rb_mStatusCodes, "FAILED_PRECONDITION", - INT2NUM(GRPC_STATUS_FAILED_PRECONDITION)); - rb_define_const(rb_mStatusCodes, "ABORTED", INT2NUM(GRPC_STATUS_ABORTED)); - rb_define_const(rb_mStatusCodes, "OUT_OF_RANGE", - INT2NUM(GRPC_STATUS_OUT_OF_RANGE)); - rb_define_const(rb_mStatusCodes, "UNIMPLEMENTED", - INT2NUM(GRPC_STATUS_UNIMPLEMENTED)); - rb_define_const(rb_mStatusCodes, "INTERNAL", INT2NUM(GRPC_STATUS_INTERNAL)); - rb_define_const(rb_mStatusCodes, "UNAVAILABLE", - INT2NUM(GRPC_STATUS_UNAVAILABLE)); - rb_define_const(rb_mStatusCodes, "DATA_LOSS", INT2NUM(GRPC_STATUS_DATA_LOSS)); -} - -/* rb_cStatus is the Status class whose instances proxy grpc_status. */ -VALUE rb_cStatus = Qnil; - -/* Initializes the Status class. */ -void Init_google_rpc_status() { - rb_cStatus = rb_define_class_under(rb_mGoogleRpcCore, "Status", rb_cObject); - - /* Allocates an object whose memory is managed by the Ruby. */ - rb_define_alloc_func(rb_cStatus, grpc_rb_status_alloc); - - /* Provides a ruby constructor and support for dup/clone. */ - rb_define_method(rb_cStatus, "initialize", grpc_rb_status_init, 2); - rb_define_method(rb_cStatus, "initialize_copy", grpc_rb_status_init_copy, 1); - - /* Provides accessors for the code and details. */ - rb_define_method(rb_cStatus, "code", grpc_rb_status_code, 0); - rb_define_method(rb_cStatus, "details", grpc_rb_status_details, 0); - id_details = rb_intern("__details"); - Init_google_status_codes(); -} - -VALUE grpc_rb_status_create_with_mark(VALUE mark, grpc_status* s) { - grpc_rb_status *status = NULL; - if (s == NULL) { - return Qnil; - } - status = ALLOC(grpc_rb_status); - status->wrapped = s; - status->mark = mark; - return Data_Wrap_Struct(rb_cStatus, grpc_rb_status_mark, grpc_rb_status_free, - status); -} - -/* Gets the wrapped status from the ruby wrapper */ -grpc_status* grpc_rb_get_wrapped_status(VALUE v) { - grpc_rb_status *wrapper = NULL; - Data_Get_Struct(v, grpc_rb_status, wrapper); - return wrapper->wrapped; -} diff --git a/src/ruby/ext/grpc/rb_status.h b/src/ruby/ext/grpc/rb_status.h deleted file mode 100644 index ceb6f9f81e9..00000000000 --- a/src/ruby/ext/grpc/rb_status.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * - * Copyright 2014, 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_STATUS_H_ -#define GRPC_RB_STATUS_H_ - -#include -#include - -/* rb_cStatus is the Status class whose instances proxy grpc_status. */ -extern VALUE rb_cStatus; - -/* grpc_rb_status_create_with_mark creates a grpc_rb_status with a ruby mark - * object that will be kept alive while the status is alive. */ -extern VALUE grpc_rb_status_create_with_mark(VALUE mark, grpc_status *s); - -/* Gets the wrapped status from the ruby wrapper object */ -grpc_status* grpc_rb_get_wrapped_status(VALUE v); - -/* Initializes the Status class. */ -void Init_google_rpc_status(); - -#endif /* GRPC_RB_STATUS_H_ */ diff --git a/src/ruby/lib/grpc/generic/active_call.rb b/src/ruby/lib/grpc/generic/active_call.rb index 187c23843bf..b16c8f85632 100644 --- a/src/ruby/lib/grpc/generic/active_call.rb +++ b/src/ruby/lib/grpc/generic/active_call.rb @@ -207,6 +207,12 @@ module Google::RPC def finished ev = @cq.pluck(@finished_tag, INFINITE_FUTURE) raise "unexpected event: #{ev.inspect}" unless ev.type == FINISHED + if @call.metadata.nil? + @call.metadata = ev.result.metadata + else + @call.metadata.merge!(ev.result.metadata) + end + if ev.result.code != Core::StatusCodes::OK raise BadStatus.new(ev.result.code, ev.result.details) end @@ -252,7 +258,7 @@ module Google::RPC # FINISHED. def send_status(code=OK, details='', assert_finished=false) assert_queue_is_ready - @call.start_write_status(Core::Status.new(code, details), self) + @call.start_write_status(code, details, self) ev = @cq.pluck(self, INFINITE_FUTURE) assert_event_type(ev, FINISH_ACCEPTED) logger.debug("Status sent: #{code}:'#{details}'") @@ -310,7 +316,7 @@ module Google::RPC return enum_for(:each_remote_read) if !block_given? loop do resp = remote_read() - break if resp.is_a?Core::Status # is an OK status, bad statii raise + break if resp.is_a?Struct::Status # is an OK status, bad statii raise break if resp.nil? # the last response was received yield resp end @@ -340,7 +346,7 @@ module Google::RPC return enum_for(:each_remote_read_then_finish) if !block_given? loop do resp = remote_read - break if resp.is_a?Core::Status # is an OK status, bad statii raise + break if resp.is_a?Struct::Status # is an OK status, bad statii raise if resp.nil? # the last response was received, but not finished yet finished break @@ -363,7 +369,7 @@ module Google::RPC remote_send(req) writes_done(false) response = remote_read - if !response.is_a?(Core::Status) # finish if status not yet received + if !response.is_a?(Struct::Status) # finish if status not yet received finished end response @@ -388,7 +394,7 @@ module Google::RPC requests.each { |r| remote_send(r) } writes_done(false) response = remote_read - if !response.is_a?(Core::Status) # finish if status not yet received + if !response.is_a?(Struct::Status) # finish if status not yet received finished end response diff --git a/src/ruby/spec/call_spec.rb b/src/ruby/spec/call_spec.rb index 1332b3c3e85..8e8e3d3ae2f 100644 --- a/src/ruby/spec/call_spec.rb +++ b/src/ruby/spec/call_spec.rb @@ -88,29 +88,30 @@ describe GRPC::Core::Call do describe '#start_read' do it 'should fail if called immediately' do - expect { make_test_call.start_read(@tag) }.to raise_error GRPC::Core::CallError + blk = Proc.new { make_test_call.start_read(@tag) } + expect(&blk).to raise_error GRPC::Core::CallError end end describe '#start_write' do it 'should fail if called immediately' do bytes = GRPC::Core::ByteBuffer.new('test string') - expect { make_test_call.start_write(bytes, @tag) } - .to raise_error GRPC::Core::CallError + blk = Proc.new { make_test_call.start_write(bytes, @tag) } + expect(&blk).to raise_error GRPC::Core::CallError end end describe '#start_write_status' do it 'should fail if called immediately' do - sts = GRPC::Core::Status.new(153, 'test detail') - expect { make_test_call.start_write_status(sts, @tag) } - .to raise_error GRPC::Core::CallError + blk = Proc.new { make_test_call.start_write_status(153, 'x', @tag) } + expect(&blk).to raise_error GRPC::Core::CallError end end describe '#writes_done' do it 'should fail if called immediately' do - expect { make_test_call.writes_done(@tag) }.to raise_error GRPC::Core::CallError + blk = Proc.new { make_test_call.writes_done(Object.new) } + expect(&blk).to raise_error GRPC::Core::CallError end end @@ -153,9 +154,9 @@ describe GRPC::Core::Call do describe '#status' do it 'can save the status and read it back' do call = make_test_call - sts = GRPC::Core::Status.new(OK, 'OK') + sts = Struct::Status.new(OK, 'OK') expect { call.status = sts }.not_to raise_error - expect(call.status).to be(sts) + expect(call.status).to eq(sts) end it 'must be set to a status' do diff --git a/src/ruby/spec/client_server_spec.rb b/src/ruby/spec/client_server_spec.rb index 91abfc03136..5e68f524d66 100644 --- a/src/ruby/spec/client_server_spec.rb +++ b/src/ruby/spec/client_server_spec.rb @@ -154,8 +154,8 @@ shared_examples 'basic GRPC message delivery is OK' do server_call = ev.call server_call.server_accept(@server_queue, @server_finished_tag) server_call.server_end_initial_metadata() - sts = Status.new(StatusCodes::NOT_FOUND, 'not found') - server_call.start_write_status(sts, @server_tag) + server_call.start_write_status(StatusCodes::NOT_FOUND, 'not found', + @server_tag) # client gets an empty response for the read, preceeded by some metadata. call.start_read(@tag) @@ -175,8 +175,7 @@ shared_examples 'basic GRPC message delivery is OK' do call = new_client_call client_sends(call) server_call = server_receives_and_responds_with('server_response') - sts = Status.new(10101, 'status code is 10101') - server_call.start_write_status(sts, @server_tag) + server_call.start_write_status(10101, 'status code is 10101', @server_tag) # first the client says writes are done call.start_read(@tag) @@ -187,7 +186,7 @@ shared_examples 'basic GRPC message delivery is OK' do # but nothing happens until the server sends a status expect_next_event_on(@server_queue, FINISH_ACCEPTED, @server_tag) ev = expect_next_event_on(@server_queue, FINISHED, @server_finished_tag) - expect(ev.result).to be_a(Status) + expect(ev.result).to be_a(Struct::Status) # client gets FINISHED expect_next_event_on(@client_queue, FINISH_ACCEPTED, @tag) diff --git a/src/ruby/spec/status_spec.rb b/src/ruby/spec/status_spec.rb deleted file mode 100644 index 63dcefba040..00000000000 --- a/src/ruby/spec/status_spec.rb +++ /dev/null @@ -1,166 +0,0 @@ -# Copyright 2014, 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::StatusCodes do - - StatusCodes = GRPC::Core::StatusCodes - - before(:each) do - @known_types = { - :OK => 0, - :CANCELLED => 1, - :UNKNOWN => 2, - :INVALID_ARGUMENT => 3, - :DEADLINE_EXCEEDED => 4, - :NOT_FOUND => 5, - :ALREADY_EXISTS => 6, - :PERMISSION_DENIED => 7, - :RESOURCE_EXHAUSTED => 8, - :FAILED_PRECONDITION => 9, - :ABORTED => 10, - :OUT_OF_RANGE => 11, - :UNIMPLEMENTED => 12, - :INTERNAL => 13, - :UNAVAILABLE => 14, - :DATA_LOSS => 15, - :UNAUTHENTICATED => 16 - } - end - - it 'should have symbols for all the known status codes' do - m = StatusCodes - syms_and_codes = m.constants.collect { |c| [c, m.const_get(c)] } - expect(Hash[syms_and_codes]).to eq(@known_types) - end - -end - - -describe GRPC::Core::Status do - - Status = GRPC::Core::Status - - describe '#new' do - it 'should create new instances' do - expect { Status.new(142, 'test details') }.to_not raise_error - end - end - - describe '#details' do - it 'return the detail' do - sts = Status.new(142, 'test details') - expect(sts.details).to eq('test details') - end - end - - describe '#code' do - it 'should return the code' do - sts = Status.new(142, 'test details') - expect(sts.code).to eq(142) - end - end - - describe '#dup' do - it 'should create a copy that returns the correct details' do - sts = Status.new(142, 'test details') - expect(sts.dup.code).to eq(142) - end - - it 'should create a copy that returns the correct code' do - sts = Status.new(142, 'test details') - expect(sts.dup.details).to eq('test details') - end - end - - -end - - -describe GRPC::BadStatus do - - BadStatus = GRPC::BadStatus - - describe '#new' do - it 'should create new instances' do - expect { BadStatus.new(142, 'test details') }.to_not raise_error - end - end - - describe '#details' do - it 'return the detail' do - err = BadStatus.new(142, 'test details') - expect(err.details).to eq('test details') - end - end - - describe '#code' do - it 'should return the code' do - err = BadStatus.new(142, 'test details') - expect(err.code).to eq(142) - end - end - - describe '#dup' do - it 'should create a copy that returns the correct details' do - err = BadStatus.new(142, 'test details') - expect(err.dup.code).to eq(142) - end - - it 'should create a copy that returns the correct code' do - err = BadStatus.new(142, 'test details') - expect(err.dup.details).to eq('test details') - end - end - - describe '#to_status' do - it 'should create a Status with the same code and details' do - err = BadStatus.new(142, 'test details') - sts = err.to_status - expect(sts.code).to eq(142) - expect(sts.details).to eq('test details') - end - - it 'should create a copy that returns the correct code' do - err = BadStatus.new(142, 'test details') - expect(err.dup.details).to eq('test details') - end - end - - describe 'as an exception' do - - it 'can be raised' do - blk = Proc.new { raise BadStatus.new(343, 'status 343') } - expect(&blk).to raise_error(BadStatus) - end - end - -end