Adds support for trailing metadata
- removes the status class, replacing it with a Struct
- adds support for trailing metadata, merging into the call's initial metadata
- tracks []
Change on 2014/12/15 by temiola <temiola@google.com>
-------------
Created by MOE: http://code.google.com/p/moe-java
MOE_MIGRATED_REVID=82193372
diff --git a/src/ruby/ext/grpc/rb_call.c b/src/ruby/ext/grpc/rb_call.c
index 3be7c3b..872f8e3 100644
--- a/src/ruby/ext/grpc/rb_call.c
+++ b/src/ruby/ext/grpc/rb_call.c
@@ -38,8 +38,8 @@
#include <grpc/grpc.h>
#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 @@
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: <Status>",
+ if (!NIL_P(status) && rb_obj_class(status) != rb_sStatus) {
+ rb_raise(rb_eTypeError, "bad status: got:<%s> want: <Struct::Status>",
rb_obj_classname(status));
return Qnil;
}
@@ -344,6 +344,11 @@
}
/* 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 @@
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 @@
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 93f36f8..76ea6ad 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 @@
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 @@
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 @@
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 @@
/* 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 @@
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 c398b6c..459502c 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 9c54a05..f0e432a 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 @@
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 @@
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 4c1b6c7..0000000
--- 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 <ruby.h>
-#include <string.h>
-
-#include <grpc/grpc.h>
-#include <grpc/status.h>
-#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 ceb6f9f..0000000
--- 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 <grpc/grpc.h>
-#include <ruby.h>
-
-/* 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 187c238..b16c8f8 100644
--- a/src/ruby/lib/grpc/generic/active_call.rb
+++ b/src/ruby/lib/grpc/generic/active_call.rb
@@ -207,6 +207,12 @@
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 @@
# 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 @@
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 @@
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 @@
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 @@
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 1332b3c..8e8e3d3 100644
--- a/src/ruby/spec/call_spec.rb
+++ b/src/ruby/spec/call_spec.rb
@@ -88,29 +88,30 @@
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 '#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 91abfc0..5e68f52 100644
--- a/src/ruby/spec/client_server_spec.rb
+++ b/src/ruby/spec/client_server_spec.rb
@@ -154,8 +154,8 @@
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 @@
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 @@
# 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 63dcefb..0000000
--- 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