mirror of https://github.com/grpc/grpc.git
commit
1e868f0f95
174 changed files with 4505 additions and 1148 deletions
@ -0,0 +1,228 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2017 gRPC authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
* |
||||
*/ |
||||
|
||||
#include <grpc/support/alloc.h> |
||||
#include <grpc/support/log.h> |
||||
|
||||
#include "src/core/lib/compression/stream_compression_gzip.h" |
||||
#include "src/core/lib/iomgr/exec_ctx.h" |
||||
#include "src/core/lib/slice/slice_internal.h" |
||||
|
||||
#define OUTPUT_BLOCK_SIZE (1024) |
||||
|
||||
typedef struct grpc_stream_compression_context_gzip { |
||||
grpc_stream_compression_context base; |
||||
|
||||
z_stream zs; |
||||
int (*flate)(z_stream *zs, int flush); |
||||
} grpc_stream_compression_context_gzip; |
||||
|
||||
static bool gzip_flate(grpc_stream_compression_context_gzip *ctx, |
||||
grpc_slice_buffer *in, grpc_slice_buffer *out, |
||||
size_t *output_size, size_t max_output_size, int flush, |
||||
bool *end_of_context) { |
||||
GPR_ASSERT(flush == 0 || flush == Z_SYNC_FLUSH || flush == Z_FINISH); |
||||
/* Full flush is not allowed when inflating. */ |
||||
GPR_ASSERT(!(ctx->flate == inflate && (flush == Z_FINISH))); |
||||
|
||||
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; |
||||
int r; |
||||
bool eoc = false; |
||||
size_t original_max_output_size = max_output_size; |
||||
while (max_output_size > 0 && (in->length > 0 || flush) && !eoc) { |
||||
size_t slice_size = max_output_size < OUTPUT_BLOCK_SIZE ? max_output_size |
||||
: OUTPUT_BLOCK_SIZE; |
||||
grpc_slice slice_out = GRPC_SLICE_MALLOC(slice_size); |
||||
ctx->zs.avail_out = (uInt)slice_size; |
||||
ctx->zs.next_out = GRPC_SLICE_START_PTR(slice_out); |
||||
while (ctx->zs.avail_out > 0 && in->length > 0 && !eoc) { |
||||
grpc_slice slice = grpc_slice_buffer_take_first(in); |
||||
ctx->zs.avail_in = (uInt)GRPC_SLICE_LENGTH(slice); |
||||
ctx->zs.next_in = GRPC_SLICE_START_PTR(slice); |
||||
r = ctx->flate(&ctx->zs, Z_NO_FLUSH); |
||||
if (r < 0 && r != Z_BUF_ERROR) { |
||||
gpr_log(GPR_ERROR, "zlib error (%d)", r); |
||||
grpc_slice_unref_internal(&exec_ctx, slice_out); |
||||
grpc_exec_ctx_finish(&exec_ctx); |
||||
return false; |
||||
} else if (r == Z_STREAM_END && ctx->flate == inflate) { |
||||
eoc = true; |
||||
} |
||||
if (ctx->zs.avail_in > 0) { |
||||
grpc_slice_buffer_undo_take_first( |
||||
in, |
||||
grpc_slice_sub(slice, GRPC_SLICE_LENGTH(slice) - ctx->zs.avail_in, |
||||
GRPC_SLICE_LENGTH(slice))); |
||||
} |
||||
grpc_slice_unref_internal(&exec_ctx, slice); |
||||
} |
||||
if (flush != 0 && ctx->zs.avail_out > 0 && !eoc) { |
||||
GPR_ASSERT(in->length == 0); |
||||
r = ctx->flate(&ctx->zs, flush); |
||||
if (flush == Z_SYNC_FLUSH) { |
||||
switch (r) { |
||||
case Z_OK: |
||||
/* Maybe flush is not complete; just made some partial progress. */ |
||||
if (ctx->zs.avail_out > 0) { |
||||
flush = 0; |
||||
} |
||||
break; |
||||
case Z_BUF_ERROR: |
||||
case Z_STREAM_END: |
||||
flush = 0; |
||||
break; |
||||
default: |
||||
gpr_log(GPR_ERROR, "zlib error (%d)", r); |
||||
grpc_slice_unref_internal(&exec_ctx, slice_out); |
||||
grpc_exec_ctx_finish(&exec_ctx); |
||||
return false; |
||||
} |
||||
} else if (flush == Z_FINISH) { |
||||
switch (r) { |
||||
case Z_OK: |
||||
case Z_BUF_ERROR: |
||||
/* Wait for the next loop to assign additional output space. */ |
||||
GPR_ASSERT(ctx->zs.avail_out == 0); |
||||
break; |
||||
case Z_STREAM_END: |
||||
flush = 0; |
||||
break; |
||||
default: |
||||
gpr_log(GPR_ERROR, "zlib error (%d)", r); |
||||
grpc_slice_unref_internal(&exec_ctx, slice_out); |
||||
grpc_exec_ctx_finish(&exec_ctx); |
||||
return false; |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (ctx->zs.avail_out == 0) { |
||||
grpc_slice_buffer_add(out, slice_out); |
||||
} else if (ctx->zs.avail_out < slice_size) { |
||||
slice_out.data.refcounted.length -= ctx->zs.avail_out; |
||||
grpc_slice_buffer_add(out, slice_out); |
||||
} else { |
||||
grpc_slice_unref_internal(&exec_ctx, slice_out); |
||||
} |
||||
max_output_size -= (slice_size - ctx->zs.avail_out); |
||||
} |
||||
grpc_exec_ctx_finish(&exec_ctx); |
||||
if (end_of_context) { |
||||
*end_of_context = eoc; |
||||
} |
||||
if (output_size) { |
||||
*output_size = original_max_output_size - max_output_size; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
static bool grpc_stream_compress_gzip(grpc_stream_compression_context *ctx, |
||||
grpc_slice_buffer *in, |
||||
grpc_slice_buffer *out, |
||||
size_t *output_size, |
||||
size_t max_output_size, |
||||
grpc_stream_compression_flush flush) { |
||||
if (ctx == NULL) { |
||||
return false; |
||||
} |
||||
grpc_stream_compression_context_gzip *gzip_ctx = |
||||
(grpc_stream_compression_context_gzip *)ctx; |
||||
GPR_ASSERT(gzip_ctx->flate == deflate); |
||||
int gzip_flush; |
||||
switch (flush) { |
||||
case GRPC_STREAM_COMPRESSION_FLUSH_NONE: |
||||
gzip_flush = 0; |
||||
break; |
||||
case GRPC_STREAM_COMPRESSION_FLUSH_SYNC: |
||||
gzip_flush = Z_SYNC_FLUSH; |
||||
break; |
||||
case GRPC_STREAM_COMPRESSION_FLUSH_FINISH: |
||||
gzip_flush = Z_FINISH; |
||||
break; |
||||
default: |
||||
gzip_flush = 0; |
||||
} |
||||
return gzip_flate(gzip_ctx, in, out, output_size, max_output_size, gzip_flush, |
||||
NULL); |
||||
} |
||||
|
||||
static bool grpc_stream_decompress_gzip(grpc_stream_compression_context *ctx, |
||||
grpc_slice_buffer *in, |
||||
grpc_slice_buffer *out, |
||||
size_t *output_size, |
||||
size_t max_output_size, |
||||
bool *end_of_context) { |
||||
if (ctx == NULL) { |
||||
return false; |
||||
} |
||||
grpc_stream_compression_context_gzip *gzip_ctx = |
||||
(grpc_stream_compression_context_gzip *)ctx; |
||||
GPR_ASSERT(gzip_ctx->flate == inflate); |
||||
return gzip_flate(gzip_ctx, in, out, output_size, max_output_size, |
||||
Z_SYNC_FLUSH, end_of_context); |
||||
} |
||||
|
||||
static grpc_stream_compression_context * |
||||
grpc_stream_compression_context_create_gzip( |
||||
grpc_stream_compression_method method) { |
||||
GPR_ASSERT(method == GRPC_STREAM_COMPRESSION_GZIP_COMPRESS || |
||||
method == GRPC_STREAM_COMPRESSION_GZIP_DECOMPRESS); |
||||
grpc_stream_compression_context_gzip *gzip_ctx = |
||||
(grpc_stream_compression_context_gzip *)gpr_zalloc( |
||||
sizeof(grpc_stream_compression_context_gzip)); |
||||
int r; |
||||
if (gzip_ctx == NULL) { |
||||
return NULL; |
||||
} |
||||
if (method == GRPC_STREAM_COMPRESSION_GZIP_DECOMPRESS) { |
||||
r = inflateInit2(&gzip_ctx->zs, 0x1F); |
||||
gzip_ctx->flate = inflate; |
||||
} else { |
||||
r = deflateInit2(&gzip_ctx->zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 0x1F, 8, |
||||
Z_DEFAULT_STRATEGY); |
||||
gzip_ctx->flate = deflate; |
||||
} |
||||
if (r != Z_OK) { |
||||
gpr_free(gzip_ctx); |
||||
return NULL; |
||||
} |
||||
|
||||
gzip_ctx->base.vtable = &grpc_stream_compression_gzip_vtable; |
||||
return (grpc_stream_compression_context *)gzip_ctx; |
||||
} |
||||
|
||||
static void grpc_stream_compression_context_destroy_gzip( |
||||
grpc_stream_compression_context *ctx) { |
||||
if (ctx == NULL) { |
||||
return; |
||||
} |
||||
grpc_stream_compression_context_gzip *gzip_ctx = |
||||
(grpc_stream_compression_context_gzip *)ctx; |
||||
if (gzip_ctx->flate == inflate) { |
||||
inflateEnd(&gzip_ctx->zs); |
||||
} else { |
||||
deflateEnd(&gzip_ctx->zs); |
||||
} |
||||
gpr_free(ctx); |
||||
} |
||||
|
||||
const grpc_stream_compression_vtable grpc_stream_compression_gzip_vtable = { |
||||
.compress = grpc_stream_compress_gzip, |
||||
.decompress = grpc_stream_decompress_gzip, |
||||
.context_create = grpc_stream_compression_context_create_gzip, |
||||
.context_destroy = grpc_stream_compression_context_destroy_gzip}; |
@ -0,0 +1,26 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2017 gRPC authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef GRPC_CORE_LIB_COMPRESSION_STREAM_COMPRESSION_GZIP_H |
||||
#define GRPC_CORE_LIB_COMPRESSION_STREAM_COMPRESSION_GZIP_H |
||||
|
||||
#include "src/core/lib/compression/stream_compression.h" |
||||
|
||||
extern const grpc_stream_compression_vtable grpc_stream_compression_gzip_vtable; |
||||
|
||||
#endif |
@ -0,0 +1,94 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2017 gRPC authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
* |
||||
*/ |
||||
|
||||
#include <grpc/support/alloc.h> |
||||
#include <grpc/support/log.h> |
||||
|
||||
#include "src/core/lib/compression/stream_compression_identity.h" |
||||
#include "src/core/lib/iomgr/exec_ctx.h" |
||||
#include "src/core/lib/slice/slice_internal.h" |
||||
|
||||
#define OUTPUT_BLOCK_SIZE (1024) |
||||
|
||||
/* Singleton context used for all identity streams. */ |
||||
static grpc_stream_compression_context identity_ctx = { |
||||
.vtable = &grpc_stream_compression_identity_vtable}; |
||||
|
||||
static void grpc_stream_compression_pass_through(grpc_slice_buffer *in, |
||||
grpc_slice_buffer *out, |
||||
size_t *output_size, |
||||
size_t max_output_size) { |
||||
if (max_output_size >= in->length) { |
||||
if (output_size) { |
||||
*output_size = in->length; |
||||
} |
||||
grpc_slice_buffer_move_into(in, out); |
||||
} else { |
||||
if (output_size) { |
||||
*output_size = max_output_size; |
||||
} |
||||
grpc_slice_buffer_move_first(in, max_output_size, out); |
||||
} |
||||
} |
||||
|
||||
static bool grpc_stream_compress_identity(grpc_stream_compression_context *ctx, |
||||
grpc_slice_buffer *in, |
||||
grpc_slice_buffer *out, |
||||
size_t *output_size, |
||||
size_t max_output_size, |
||||
grpc_stream_compression_flush flush) { |
||||
if (ctx == NULL) { |
||||
return false; |
||||
} |
||||
grpc_stream_compression_pass_through(in, out, output_size, max_output_size); |
||||
return true; |
||||
} |
||||
|
||||
static bool grpc_stream_decompress_identity( |
||||
grpc_stream_compression_context *ctx, grpc_slice_buffer *in, |
||||
grpc_slice_buffer *out, size_t *output_size, size_t max_output_size, |
||||
bool *end_of_context) { |
||||
if (ctx == NULL) { |
||||
return false; |
||||
} |
||||
grpc_stream_compression_pass_through(in, out, output_size, max_output_size); |
||||
if (end_of_context) { |
||||
*end_of_context = false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
static grpc_stream_compression_context * |
||||
grpc_stream_compression_context_create_identity( |
||||
grpc_stream_compression_method method) { |
||||
GPR_ASSERT(method == GRPC_STREAM_COMPRESSION_IDENTITY_COMPRESS || |
||||
method == GRPC_STREAM_COMPRESSION_IDENTITY_DECOMPRESS); |
||||
/* No context needed in this case. Use fake context instead. */ |
||||
return (grpc_stream_compression_context *)&identity_ctx; |
||||
} |
||||
|
||||
static void grpc_stream_compression_context_destroy_identity( |
||||
grpc_stream_compression_context *ctx) { |
||||
return; |
||||
} |
||||
|
||||
const grpc_stream_compression_vtable grpc_stream_compression_identity_vtable = { |
||||
.compress = grpc_stream_compress_identity, |
||||
.decompress = grpc_stream_decompress_identity, |
||||
.context_create = grpc_stream_compression_context_create_identity, |
||||
.context_destroy = grpc_stream_compression_context_destroy_identity}; |
@ -0,0 +1,27 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2017 gRPC authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef GRPC_CORE_LIB_COMPRESSION_STREAM_COMPRESSION_IDENTITY_H |
||||
#define GRPC_CORE_LIB_COMPRESSION_STREAM_COMPRESSION_IDENTITY_H |
||||
|
||||
#include "src/core/lib/compression/stream_compression.h" |
||||
|
||||
extern const grpc_stream_compression_vtable |
||||
grpc_stream_compression_identity_vtable; |
||||
|
||||
#endif |
@ -0,0 +1,53 @@ |
||||
# Copyright 2017 gRPC authors. |
||||
# |
||||
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||
# you may not use this file except in compliance with the License. |
||||
# You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
|
||||
# GRPC contains the General RPC module. |
||||
module GRPC |
||||
## |
||||
# Represents a registry of added interceptors available for enumeration. |
||||
# The registry can be used for both server and client interceptors. |
||||
# This class is internal to gRPC and not meant for public usage. |
||||
# |
||||
class InterceptorRegistry |
||||
## |
||||
# An error raised when an interceptor is attempted to be added |
||||
# that does not extend GRPC::Interceptor |
||||
# |
||||
class DescendantError < StandardError; end |
||||
|
||||
## |
||||
# Initialize the registry with an empty interceptor list |
||||
# This is an EXPERIMENTAL API. |
||||
# |
||||
def initialize(interceptors = []) |
||||
@interceptors = [] |
||||
interceptors.each do |i| |
||||
base = GRPC::Interceptor |
||||
unless i.class.ancestors.include?(base) |
||||
fail DescendantError, "Interceptors must descend from #{base}" |
||||
end |
||||
@interceptors << i |
||||
end |
||||
end |
||||
|
||||
## |
||||
# Builds an interception context from this registry |
||||
# |
||||
# @return [InterceptionContext] |
||||
# |
||||
def build_context |
||||
InterceptionContext.new(@interceptors) |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,186 @@ |
||||
# Copyright 2017 gRPC authors. |
||||
# |
||||
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||
# you may not use this file except in compliance with the License. |
||||
# You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
require_relative 'interceptor_registry' |
||||
|
||||
# GRPC contains the General RPC module. |
||||
module GRPC |
||||
## |
||||
# Base class for interception in GRPC |
||||
# |
||||
class Interceptor |
||||
## |
||||
# @param [Hash] options A hash of options that will be used |
||||
# by the interceptor. This is an EXPERIMENTAL API. |
||||
# |
||||
def initialize(options = {}) |
||||
@options = options || {} |
||||
end |
||||
end |
||||
|
||||
## |
||||
# ClientInterceptor allows for wrapping outbound gRPC client stub requests. |
||||
# This is an EXPERIMENTAL API. |
||||
# |
||||
class ClientInterceptor < Interceptor |
||||
## |
||||
# Intercept a unary request response call |
||||
# |
||||
# @param [Object] request |
||||
# @param [GRPC::ActiveCall] call |
||||
# @param [Method] method |
||||
# @param [Hash] metadata |
||||
# |
||||
def request_response(request:, call:, method:, metadata:) |
||||
GRPC.logger.debug "Intercepting request response method #{method}" \ |
||||
" for request #{request} with call #{call} and metadata: #{metadata}" |
||||
yield |
||||
end |
||||
|
||||
## |
||||
# Intercept a client streaming call |
||||
# |
||||
# @param [Enumerable] requests |
||||
# @param [GRPC::ActiveCall] call |
||||
# @param [Method] method |
||||
# @param [Hash] metadata |
||||
# |
||||
def client_streamer(requests:, call:, method:, metadata:) |
||||
GRPC.logger.debug "Intercepting client streamer method #{method}" \ |
||||
" for requests #{requests} with call #{call} and metadata: #{metadata}" |
||||
yield |
||||
end |
||||
|
||||
## |
||||
# Intercept a server streaming call |
||||
# |
||||
# @param [Object] request |
||||
# @param [GRPC::ActiveCall] call |
||||
# @param [Method] method |
||||
# @param [Hash] metadata |
||||
# |
||||
def server_streamer(request:, call:, method:, metadata:) |
||||
GRPC.logger.debug "Intercepting server streamer method #{method}" \ |
||||
" for request #{request} with call #{call} and metadata: #{metadata}" |
||||
yield |
||||
end |
||||
|
||||
## |
||||
# Intercept a BiDi streaming call |
||||
# |
||||
# @param [Enumerable] requests |
||||
# @param [GRPC::ActiveCall] call |
||||
# @param [Method] method |
||||
# @param [Hash] metadata |
||||
# |
||||
def bidi_streamer(requests:, call:, method:, metadata:) |
||||
GRPC.logger.debug "Intercepting bidi streamer method #{method}" \ |
||||
" for requests #{requests} with call #{call} and metadata: #{metadata}" |
||||
yield |
||||
end |
||||
end |
||||
|
||||
## |
||||
# ServerInterceptor allows for wrapping gRPC server execution handling. |
||||
# This is an EXPERIMENTAL API. |
||||
# |
||||
class ServerInterceptor < Interceptor |
||||
## |
||||
# Intercept a unary request response call. |
||||
# |
||||
# @param [Object] request |
||||
# @param [GRPC::ActiveCall::SingleReqView] call |
||||
# @param [Method] method |
||||
# |
||||
def request_response(request:, call:, method:) |
||||
GRPC.logger.debug "Intercepting request response method #{method}" \ |
||||
" for request #{request} with call #{call}" |
||||
yield |
||||
end |
||||
|
||||
## |
||||
# Intercept a client streaming call |
||||
# |
||||
# @param [GRPC::ActiveCall::MultiReqView] call |
||||
# @param [Method] method |
||||
# |
||||
def client_streamer(call:, method:) |
||||
GRPC.logger.debug "Intercepting client streamer method #{method}" \ |
||||
" with call #{call}" |
||||
yield |
||||
end |
||||
|
||||
## |
||||
# Intercept a server streaming call |
||||
# |
||||
# @param [Object] request |
||||
# @param [GRPC::ActiveCall::SingleReqView] call |
||||
# @param [Method] method |
||||
# |
||||
def server_streamer(request:, call:, method:) |
||||
GRPC.logger.debug "Intercepting server streamer method #{method}" \ |
||||
" for request #{request} with call #{call}" |
||||
yield |
||||
end |
||||
|
||||
## |
||||
# Intercept a BiDi streaming call |
||||
# |
||||
# @param [Enumerable<Object>] requests |
||||
# @param [GRPC::ActiveCall::MultiReqView] call |
||||
# @param [Method] method |
||||
# |
||||
def bidi_streamer(requests:, call:, method:) |
||||
GRPC.logger.debug "Intercepting bidi streamer method #{method}" \ |
||||
" for requests #{requests} with call #{call}" |
||||
yield |
||||
end |
||||
end |
||||
|
||||
## |
||||
# Represents the context in which an interceptor runs. Used to provide an |
||||
# injectable mechanism for handling interception. This is an EXPERIMENTAL API. |
||||
# |
||||
class InterceptionContext |
||||
## |
||||
# @param [Array<GRPC::Interceptor>] |
||||
# |
||||
def initialize(interceptors = []) |
||||
@interceptors = interceptors.dup |
||||
end |
||||
|
||||
## |
||||
# Intercept the call and fire out to interceptors in a FIFO execution. |
||||
# This is an EXPERIMENTAL API. |
||||
# |
||||
# @param [Symbol] type The request type |
||||
# @param [Hash] args The arguments for the call |
||||
# |
||||
def intercept!(type, args = {}) |
||||
return yield if @interceptors.none? |
||||
|
||||
i = @interceptors.pop |
||||
return yield unless i |
||||
|
||||
i.send(type, args) do |
||||
if @interceptors.any? |
||||
intercept!(type, args) do |
||||
yield |
||||
end |
||||
else |
||||
yield |
||||
end |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,153 @@ |
||||
# Copyright 2017 gRPC authors. |
||||
# |
||||
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||
# you may not use this file except in compliance with the License. |
||||
# You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
require 'spec_helper' |
||||
|
||||
describe 'Client Interceptors' do |
||||
let(:interceptor) { TestClientInterceptor.new } |
||||
let(:interceptors_opts) { { interceptors: [interceptor] } } |
||||
let(:request) { EchoMsg.new } |
||||
let(:service) { EchoService } |
||||
|
||||
before(:each) do |
||||
build_rpc_server |
||||
end |
||||
|
||||
context 'when a client interceptor is added' do |
||||
context 'with a request/response call' do |
||||
it 'should be called', server: true do |
||||
expect(interceptor).to receive(:request_response) |
||||
.once.and_call_original |
||||
|
||||
run_services_on_server(@server, services: [service]) do |
||||
stub = build_insecure_stub(EchoStub, opts: interceptors_opts) |
||||
expect_any_instance_of(GRPC::ActiveCall).to receive(:request_response) |
||||
.once.and_call_original |
||||
expect(stub.an_rpc(request)).to be_a(EchoMsg) |
||||
end |
||||
end |
||||
|
||||
it 'can modify outgoing metadata', server: true do |
||||
expect(interceptor).to receive(:request_response) |
||||
.once.and_call_original |
||||
|
||||
run_services_on_server(@server, services: [service]) do |
||||
stub = build_insecure_stub(EchoStub, opts: interceptors_opts) |
||||
expect_any_instance_of(GRPC::ActiveCall).to receive(:request_response) |
||||
.with(request, metadata: { 'foo' => 'bar_from_request_response' }) |
||||
.once.and_call_original |
||||
expect(stub.an_rpc(request)).to be_a(EchoMsg) |
||||
end |
||||
end |
||||
end |
||||
|
||||
context 'with a client streaming call' do |
||||
it 'should be called', server: true do |
||||
expect(interceptor).to receive(:client_streamer) |
||||
.once.and_call_original |
||||
|
||||
run_services_on_server(@server, services: [service]) do |
||||
stub = build_insecure_stub(EchoStub, opts: interceptors_opts) |
||||
expect_any_instance_of(GRPC::ActiveCall).to receive(:client_streamer) |
||||
.once.and_call_original |
||||
requests = [EchoMsg.new, EchoMsg.new] |
||||
expect(stub.a_client_streaming_rpc(requests)).to be_a(EchoMsg) |
||||
end |
||||
end |
||||
|
||||
it 'can modify outgoing metadata', server: true do |
||||
expect(interceptor).to receive(:client_streamer) |
||||
.once.and_call_original |
||||
|
||||
run_services_on_server(@server, services: [service]) do |
||||
stub = build_insecure_stub(EchoStub, opts: interceptors_opts) |
||||
requests = [EchoMsg.new, EchoMsg.new] |
||||
expect_any_instance_of(GRPC::ActiveCall).to receive(:client_streamer) |
||||
.with(requests, metadata: { 'foo' => 'bar_from_client_streamer' }) |
||||
.once.and_call_original |
||||
expect(stub.a_client_streaming_rpc(requests)).to be_a(EchoMsg) |
||||
end |
||||
end |
||||
end |
||||
|
||||
context 'with a server streaming call' do |
||||
it 'should be called', server: true do |
||||
expect(interceptor).to receive(:server_streamer) |
||||
.once.and_call_original |
||||
|
||||
run_services_on_server(@server, services: [service]) do |
||||
stub = build_insecure_stub(EchoStub, opts: interceptors_opts) |
||||
request = EchoMsg.new |
||||
expect_any_instance_of(GRPC::ActiveCall).to receive(:server_streamer) |
||||
.once.and_call_original |
||||
responses = stub.a_server_streaming_rpc(request) |
||||
responses.each do |r| |
||||
expect(r).to be_a(EchoMsg) |
||||
end |
||||
end |
||||
end |
||||
|
||||
it 'can modify outgoing metadata', server: true do |
||||
expect(interceptor).to receive(:server_streamer) |
||||
.once.and_call_original |
||||
|
||||
run_services_on_server(@server, services: [service]) do |
||||
stub = build_insecure_stub(EchoStub, opts: interceptors_opts) |
||||
request = EchoMsg.new |
||||
expect_any_instance_of(GRPC::ActiveCall).to receive(:server_streamer) |
||||
.with(request, metadata: { 'foo' => 'bar_from_server_streamer' }) |
||||
.once.and_call_original |
||||
responses = stub.a_server_streaming_rpc(request) |
||||
responses.each do |r| |
||||
expect(r).to be_a(EchoMsg) |
||||
end |
||||
end |
||||
end |
||||
end |
||||
|
||||
context 'with a bidi call' do |
||||
it 'should be called', server: true do |
||||
expect(interceptor).to receive(:bidi_streamer) |
||||
.once.and_call_original |
||||
|
||||
run_services_on_server(@server, services: [service]) do |
||||
stub = build_insecure_stub(EchoStub, opts: interceptors_opts) |
||||
expect_any_instance_of(GRPC::ActiveCall).to receive(:bidi_streamer) |
||||
.once.and_call_original |
||||
requests = [EchoMsg.new, EchoMsg.new] |
||||
responses = stub.a_bidi_rpc(requests) |
||||
responses.each do |r| |
||||
expect(r).to be_a(EchoMsg) |
||||
end |
||||
end |
||||
end |
||||
|
||||
it 'can modify outgoing metadata', server: true do |
||||
expect(interceptor).to receive(:bidi_streamer) |
||||
.once.and_call_original |
||||
|
||||
run_services_on_server(@server, services: [service]) do |
||||
stub = build_insecure_stub(EchoStub, opts: interceptors_opts) |
||||
requests = [EchoMsg.new, EchoMsg.new] |
||||
expect_any_instance_of(GRPC::ActiveCall).to receive(:bidi_streamer) |
||||
.with(requests, metadata: { 'foo' => 'bar_from_bidi_streamer' }) |
||||
.once.and_call_original |
||||
responses = stub.a_bidi_rpc(requests) |
||||
responses.each do |r| |
||||
expect(r).to be_a(EchoMsg) |
||||
end |
||||
end |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,65 @@ |
||||
# Copyright 2017 gRPC authors. |
||||
# |
||||
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||
# you may not use this file except in compliance with the License. |
||||
# You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
require 'spec_helper' |
||||
|
||||
describe GRPC::InterceptorRegistry do |
||||
let(:server) { RpcServer.new } |
||||
let(:interceptor) { TestServerInterceptor.new } |
||||
let(:interceptors) { [interceptor] } |
||||
let(:registry) { described_class.new(interceptors) } |
||||
|
||||
describe 'initialization' do |
||||
subject { registry } |
||||
|
||||
context 'with an interceptor extending GRPC::ServerInterceptor' do |
||||
it 'should add the interceptor to the registry' do |
||||
subject |
||||
is = registry.instance_variable_get('@interceptors') |
||||
expect(is.count).to eq 1 |
||||
expect(is.first).to eq interceptor |
||||
end |
||||
end |
||||
|
||||
context 'with multiple interceptors' do |
||||
let(:interceptor2) { TestServerInterceptor.new } |
||||
let(:interceptor3) { TestServerInterceptor.new } |
||||
let(:interceptors) { [interceptor, interceptor2, interceptor3] } |
||||
|
||||
it 'should maintain order of insertion when iterated against' do |
||||
subject |
||||
is = registry.instance_variable_get('@interceptors') |
||||
expect(is.count).to eq 3 |
||||
is.each_with_index do |i, idx| |
||||
case idx |
||||
when 0 |
||||
expect(i).to eq interceptor |
||||
when 1 |
||||
expect(i).to eq interceptor2 |
||||
when 2 |
||||
expect(i).to eq interceptor3 |
||||
end |
||||
end |
||||
end |
||||
end |
||||
|
||||
context 'with an interceptor not extending GRPC::ServerInterceptor' do |
||||
let(:interceptor) { Class } |
||||
let(:err) { GRPC::InterceptorRegistry::DescendantError } |
||||
|
||||
it 'should raise an InvalidArgument exception' do |
||||
expect { subject }.to raise_error(err) |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,218 @@ |
||||
# Copyright 2017 gRPC authors. |
||||
# |
||||
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||
# you may not use this file except in compliance with the License. |
||||
# You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
require 'spec_helper' |
||||
|
||||
describe 'Server Interceptors' do |
||||
let(:interceptor) { TestServerInterceptor.new } |
||||
let(:request) { EchoMsg.new } |
||||
let(:trailing_metadata) { {} } |
||||
let(:service) { EchoService.new(trailing_metadata) } |
||||
let(:interceptors) { [] } |
||||
|
||||
before(:each) do |
||||
build_rpc_server(server_opts: { interceptors: interceptors }) |
||||
end |
||||
|
||||
context 'when a server interceptor is added' do |
||||
let(:interceptors) { [interceptor] } |
||||
let(:client_metadata) { { client_md: 'test' } } |
||||
let(:client_call_opts) { { metadata: client_metadata, return_op: true } } |
||||
|
||||
context 'with a request/response call' do |
||||
let(:trailing_metadata) { { server_om: 'from_request_response' } } |
||||
|
||||
it 'should be called', server: true do |
||||
expect(interceptor).to receive(:request_response) |
||||
.once.and_call_original |
||||
|
||||
run_services_on_server(@server, services: [service]) do |
||||
stub = build_insecure_stub(EchoStub) |
||||
expect(stub.an_rpc(request)).to be_a(EchoMsg) |
||||
end |
||||
end |
||||
|
||||
it 'can modify trailing metadata', server: true do |
||||
expect(interceptor).to receive(:request_response) |
||||
.once.and_call_original |
||||
|
||||
run_services_on_server(@server, services: [service]) do |
||||
stub = build_insecure_stub(EchoStub) |
||||
expect_any_instance_of(GRPC::ActiveCall).to( |
||||
receive(:request_response).with(request, metadata: client_metadata) |
||||
.once.and_call_original |
||||
) |
||||
op = stub.an_rpc(request, client_call_opts) |
||||
msg = op.execute |
||||
expect(op.trailing_metadata).to eq( |
||||
'interc' => 'from_request_response', |
||||
'server_om' => 'from_request_response' |
||||
) |
||||
expect(msg).to be_a(EchoMsg) |
||||
end |
||||
end |
||||
end |
||||
|
||||
context 'with a client streaming call' do |
||||
let(:trailing_metadata) { { server_om: 'from_client_streamer' } } |
||||
let(:requests) { [EchoMsg.new, EchoMsg.new] } |
||||
|
||||
it 'should be called', server: true do |
||||
expect(interceptor).to receive(:client_streamer) |
||||
.once.and_call_original |
||||
|
||||
run_services_on_server(@server, services: [service]) do |
||||
stub = build_insecure_stub(EchoStub) |
||||
expect(stub.a_client_streaming_rpc(requests)).to be_a(EchoMsg) |
||||
end |
||||
end |
||||
|
||||
it 'can modify trailing metadata', server: true do |
||||
expect(interceptor).to receive(:client_streamer) |
||||
.once.and_call_original |
||||
|
||||
run_services_on_server(@server, services: [service]) do |
||||
stub = build_insecure_stub(EchoStub) |
||||
expect_any_instance_of(GRPC::ActiveCall).to( |
||||
receive(:client_streamer).with(requests) |
||||
.once.and_call_original |
||||
) |
||||
op = stub.a_client_streaming_rpc(requests, client_call_opts) |
||||
msg = op.execute |
||||
expect(op.trailing_metadata).to eq( |
||||
'interc' => 'from_client_streamer', |
||||
'server_om' => 'from_client_streamer' |
||||
) |
||||
expect(msg).to be_a(EchoMsg) |
||||
end |
||||
end |
||||
end |
||||
|
||||
context 'with a server streaming call' do |
||||
let(:trailing_metadata) { { server_om: 'from_server_streamer' } } |
||||
let(:request) { EchoMsg.new } |
||||
|
||||
it 'should be called', server: true do |
||||
expect(interceptor).to receive(:server_streamer) |
||||
.once.and_call_original |
||||
|
||||
run_services_on_server(@server, services: [service]) do |
||||
stub = build_insecure_stub(EchoStub) |
||||
responses = stub.a_server_streaming_rpc(request) |
||||
responses.each do |r| |
||||
expect(r).to be_a(EchoMsg) |
||||
end |
||||
end |
||||
end |
||||
|
||||
it 'can modify trailing metadata', server: true do |
||||
expect(interceptor).to receive(:server_streamer) |
||||
.once.and_call_original |
||||
|
||||
run_services_on_server(@server, services: [service]) do |
||||
stub = build_insecure_stub(EchoStub) |
||||
expect_any_instance_of(GRPC::ActiveCall).to( |
||||
receive(:server_streamer).with(request) |
||||
.once.and_call_original |
||||
) |
||||
op = stub.a_server_streaming_rpc(request, client_call_opts) |
||||
responses = op.execute |
||||
responses.each do |r| |
||||
expect(r).to be_a(EchoMsg) |
||||
end |
||||
expect(op.trailing_metadata).to eq( |
||||
'interc' => 'from_server_streamer', |
||||
'server_om' => 'from_server_streamer' |
||||
) |
||||
end |
||||
end |
||||
end |
||||
|
||||
context 'with a bidi call' do |
||||
let(:trailing_metadata) { { server_om: 'from_bidi_streamer' } } |
||||
let(:requests) { [EchoMsg.new, EchoMsg.new] } |
||||
|
||||
it 'should be called', server: true do |
||||
expect(interceptor).to receive(:bidi_streamer) |
||||
.once.and_call_original |
||||
|
||||
run_services_on_server(@server, services: [service]) do |
||||
stub = build_insecure_stub(EchoStub) |
||||
responses = stub.a_bidi_rpc(requests) |
||||
responses.each do |r| |
||||
expect(r).to be_a(EchoMsg) |
||||
end |
||||
end |
||||
end |
||||
|
||||
it 'can modify trailing metadata', server: true do |
||||
expect(interceptor).to receive(:bidi_streamer) |
||||
.once.and_call_original |
||||
|
||||
run_services_on_server(@server, services: [service]) do |
||||
stub = build_insecure_stub(EchoStub) |
||||
expect_any_instance_of(GRPC::ActiveCall).to( |
||||
receive(:bidi_streamer).with(requests) |
||||
.once.and_call_original |
||||
) |
||||
op = stub.a_bidi_rpc(requests, client_call_opts) |
||||
responses = op.execute |
||||
responses.each do |r| |
||||
expect(r).to be_a(EchoMsg) |
||||
end |
||||
expect(op.trailing_metadata).to eq( |
||||
'interc' => 'from_bidi_streamer', |
||||
'server_om' => 'from_bidi_streamer' |
||||
) |
||||
end |
||||
end |
||||
end |
||||
end |
||||
|
||||
context 'when multiple interceptors are added' do |
||||
let(:interceptor2) { TestServerInterceptor.new } |
||||
let(:interceptor3) { TestServerInterceptor.new } |
||||
let(:interceptors) do |
||||
[ |
||||
interceptor, |
||||
interceptor2, |
||||
interceptor3 |
||||
] |
||||
end |
||||
|
||||
it 'each should be called', server: true do |
||||
expect(interceptor).to receive(:request_response) |
||||
.once.and_call_original |
||||
expect(interceptor2).to receive(:request_response) |
||||
.once.and_call_original |
||||
expect(interceptor3).to receive(:request_response) |
||||
.once.and_call_original |
||||
|
||||
run_services_on_server(@server, services: [service]) do |
||||
stub = build_insecure_stub(EchoStub) |
||||
expect(stub.an_rpc(request)).to be_a(EchoMsg) |
||||
end |
||||
end |
||||
end |
||||
|
||||
context 'when an interceptor is not added' do |
||||
it 'should not be called', server: true do |
||||
expect(interceptor).to_not receive(:call) |
||||
|
||||
run_services_on_server(@server, services: [service]) do |
||||
stub = build_insecure_stub(EchoStub) |
||||
expect(stub.an_rpc(request)).to be_a(EchoMsg) |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,73 @@ |
||||
# Copyright 2017 gRPC authors. |
||||
# |
||||
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||
# you may not use this file except in compliance with the License. |
||||
# You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
|
||||
# GRPC contains the General RPC module. |
||||
module GRPC |
||||
## |
||||
# GRPC RSpec base module |
||||
# |
||||
module Spec |
||||
## |
||||
# A module that is used for providing generic helpers across the |
||||
# GRPC test suite |
||||
# |
||||
module Helpers |
||||
# Shortcut syntax for a GRPC RPC Server |
||||
RpcServer = GRPC::RpcServer |
||||
|
||||
## |
||||
# Build an RPC server used for testing |
||||
# |
||||
def build_rpc_server(server_opts: {}, |
||||
client_opts: {}) |
||||
@server = RpcServer.new({ poll_period: 1 }.merge(server_opts)) |
||||
@port = @server.add_http2_port('0.0.0.0:0', :this_port_is_insecure) |
||||
@host = "0.0.0.0:#{@port}" |
||||
@client_opts = client_opts |
||||
@server |
||||
end |
||||
|
||||
## |
||||
# Run services on an RPC server, yielding to allow testing within |
||||
# |
||||
# @param [RpcServer] server |
||||
# @param [Array<Class>] services |
||||
# |
||||
def run_services_on_server(server, services: []) |
||||
services.each do |s| |
||||
server.handle(s) |
||||
end |
||||
t = Thread.new { server.run } |
||||
server.wait_till_running |
||||
|
||||
yield |
||||
|
||||
server.stop |
||||
t.join |
||||
end |
||||
|
||||
## |
||||
# Build an insecure stub from a given stub class |
||||
# |
||||
# @param [Class] klass |
||||
# @param [String] host |
||||
# |
||||
def build_insecure_stub(klass, host: nil, opts: nil) |
||||
host ||= @host |
||||
opts ||= @client_opts |
||||
klass.new(host, :this_channel_is_insecure, **opts) |
||||
end |
||||
end |
||||
end |
||||
end |
@ -0,0 +1,147 @@ |
||||
# Copyright 2017 gRPC authors. |
||||
# |
||||
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||
# you may not use this file except in compliance with the License. |
||||
# You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
|
||||
# Test stubs for various scenarios |
||||
require 'grpc' |
||||
|
||||
# A test message |
||||
class EchoMsg |
||||
def self.marshal(_o) |
||||
'' |
||||
end |
||||
|
||||
def self.unmarshal(_o) |
||||
EchoMsg.new |
||||
end |
||||
end |
||||
|
||||
# A test service with an echo implementation. |
||||
class EchoService |
||||
include GRPC::GenericService |
||||
rpc :an_rpc, EchoMsg, EchoMsg |
||||
rpc :a_client_streaming_rpc, stream(EchoMsg), EchoMsg |
||||
rpc :a_server_streaming_rpc, EchoMsg, stream(EchoMsg) |
||||
rpc :a_bidi_rpc, stream(EchoMsg), stream(EchoMsg) |
||||
attr_reader :received_md |
||||
|
||||
def initialize(**kw) |
||||
@trailing_metadata = kw |
||||
@received_md = [] |
||||
end |
||||
|
||||
def an_rpc(req, call) |
||||
GRPC.logger.info('echo service received a request') |
||||
call.output_metadata.update(@trailing_metadata) |
||||
@received_md << call.metadata unless call.metadata.nil? |
||||
req |
||||
end |
||||
|
||||
def a_client_streaming_rpc(call) |
||||
# iterate through requests so call can complete |
||||
call.output_metadata.update(@trailing_metadata) |
||||
call.each_remote_read.each { |r| p r } |
||||
EchoMsg.new |
||||
end |
||||
|
||||
def a_server_streaming_rpc(_req, call) |
||||
call.output_metadata.update(@trailing_metadata) |
||||
[EchoMsg.new, EchoMsg.new] |
||||
end |
||||
|
||||
def a_bidi_rpc(requests, call) |
||||
call.output_metadata.update(@trailing_metadata) |
||||
requests.each { |r| p r } |
||||
[EchoMsg.new, EchoMsg.new] |
||||
end |
||||
end |
||||
|
||||
EchoStub = EchoService.rpc_stub_class |
||||
|
||||
# For testing server interceptors |
||||
class TestServerInterceptor < GRPC::ServerInterceptor |
||||
def request_response(request:, call:, method:) |
||||
p "Received request/response call at method #{method}" \ |
||||
" with request #{request} for call #{call}" |
||||
call.output_metadata[:interc] = 'from_request_response' |
||||
p "[GRPC::Ok] (#{method.owner.name}.#{method.name})" |
||||
yield |
||||
end |
||||
|
||||
def client_streamer(call:, method:) |
||||
call.output_metadata[:interc] = 'from_client_streamer' |
||||
call.each_remote_read.each do |r| |
||||
p "In interceptor: #{r}" |
||||
end |
||||
p "Received client streamer call at method #{method} for call #{call}" |
||||
yield |
||||
end |
||||
|
||||
def server_streamer(request:, call:, method:) |
||||
p "Received server streamer call at method #{method} with request" \ |
||||
" #{request} for call #{call}" |
||||
call.output_metadata[:interc] = 'from_server_streamer' |
||||
yield |
||||
end |
||||
|
||||
def bidi_streamer(requests:, call:, method:) |
||||
requests.each do |r| |
||||
p "Bidi request: #{r}" |
||||
end |
||||
p "Received bidi streamer call at method #{method} with requests" \ |
||||
" #{requests} for call #{call}" |
||||
call.output_metadata[:interc] = 'from_bidi_streamer' |
||||
yield |
||||
end |
||||
end |
||||
|
||||
# For testing client interceptors |
||||
class TestClientInterceptor < GRPC::ClientInterceptor |
||||
def request_response(request:, call:, method:, metadata: {}) |
||||
p "Intercepted request/response call at method #{method}" \ |
||||
" with request #{request} for call #{call}" \ |
||||
" and metadata: #{metadata}" |
||||
metadata['foo'] = 'bar_from_request_response' |
||||
yield |
||||
end |
||||
|
||||
def client_streamer(requests:, call:, method:, metadata: {}) |
||||
p "Received client streamer call at method #{method}" \ |
||||
" with requests #{requests} for call #{call}" \ |
||||
" and metadata: #{metadata}" |
||||
requests.each do |r| |
||||
p "In client interceptor: #{r}" |
||||
end |
||||
metadata['foo'] = 'bar_from_client_streamer' |
||||
yield |
||||
end |
||||
|
||||
def server_streamer(request:, call:, method:, metadata: {}) |
||||
p "Received server streamer call at method #{method}" \ |
||||
" with request #{request} for call #{call}" \ |
||||
" and metadata: #{metadata}" |
||||
metadata['foo'] = 'bar_from_server_streamer' |
||||
yield |
||||
end |
||||
|
||||
def bidi_streamer(requests:, call:, method:, metadata: {}) |
||||
p "Received bidi streamer call at method #{method}" \ |
||||
"with requests #{requests} for call #{call}" \ |
||||
" and metadata: #{metadata}" |
||||
requests.each do |r| |
||||
p "In client interceptor: #{r}" |
||||
end |
||||
metadata['foo'] = 'bar_from_bidi_streamer' |
||||
yield |
||||
end |
||||
end |
@ -0,0 +1,4 @@ |
||||
%YAML 1.2 |
||||
--- | |
||||
<%namespace file="create_private_dns_zone_defs.include" import="*"/>\ |
||||
${create_private_dns_zone(resolver_gce_integration_tests_zone_id, resolver_tests_common_zone_name)} |
@ -0,0 +1,32 @@ |
||||
<%def name="create_private_dns_zone(resolver_gce_integration_tests_zone_id, resolver_tests_common_zone_name)">#!/bin/bash |
||||
# Copyright 2015 gRPC authors. |
||||
# |
||||
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||
# you may not use this file except in compliance with the License. |
||||
# You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
|
||||
# This file is auto-generated |
||||
|
||||
set -ex |
||||
|
||||
cd $(dirname $0)/../../.. |
||||
|
||||
gcloud alpha dns managed-zones create \\ |
||||
|
||||
${resolver_gce_integration_tests_zone_id} \\ |
||||
|
||||
--dns-name=${resolver_tests_common_zone_name} \\ |
||||
|
||||
--description="GCE-DNS-private-zone-for-GRPC-testing" \\ |
||||
|
||||
--visibility=private \\ |
||||
|
||||
--networks=default</%def> |
@ -0,0 +1,4 @@ |
||||
%YAML 1.2 |
||||
--- | |
||||
<%namespace file="private_dns_zone_init_defs.include" import="*"/>\ |
||||
${private_dns_zone_init(all_integration_test_records, resolver_gce_integration_tests_zone_id, resolver_tests_common_zone_name)} |
@ -0,0 +1,40 @@ |
||||
<%def name="private_dns_zone_init(records,resolver_gce_integration_tests_zone_id,resolver_tests_common_zone_name)">#!/bin/bash |
||||
# Copyright 2015 gRPC authors. |
||||
# |
||||
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||
# you may not use this file except in compliance with the License. |
||||
# You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
|
||||
# This file is auto-generated |
||||
|
||||
set -ex |
||||
|
||||
cd $(dirname $0)/../../.. |
||||
|
||||
gcloud dns record-sets transaction start -z=${resolver_gce_integration_tests_zone_id} |
||||
|
||||
% for r in records: |
||||
gcloud dns record-sets transaction add \\ |
||||
|
||||
-z=${resolver_gce_integration_tests_zone_id} \\ |
||||
|
||||
--name=${r['name']}.${resolver_tests_common_zone_name} \\ |
||||
|
||||
--type=${r['type']} \\ |
||||
|
||||
--ttl=${r['ttl']} \\ |
||||
|
||||
${r['data']} |
||||
|
||||
% endfor |
||||
gcloud dns record-sets transaction describe -z=${resolver_gce_integration_tests_zone_id} |
||||
gcloud dns record-sets transaction execute -z=${resolver_gce_integration_tests_zone_id} |
||||
gcloud dns record-sets list -z=${resolver_gce_integration_tests_zone_id}</%def> |
@ -0,0 +1,64 @@ |
||||
<%def name="resolver_gce_integration_tests(tests, records, resolver_tests_common_zone_name)">#!/bin/bash |
||||
# Copyright 2015 gRPC authors. |
||||
# |
||||
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||
# you may not use this file except in compliance with the License. |
||||
# You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
|
||||
# This file is auto-generated |
||||
|
||||
set -ex |
||||
|
||||
if [[ "$GRPC_DNS_RESOLVER" == "" ]]; then |
||||
export GRPC_DNS_RESOLVER=ares |
||||
elif [[ "$GRPC_DNS_RESOLVER" != ares ]]; then |
||||
echo "Unexpected: GRPC_DNS_RESOLVER=$GRPC_DNS_RESOLVER. This test only works with c-ares resolver" |
||||
exit 1 |
||||
fi |
||||
|
||||
cd $(dirname $0)/../../.. |
||||
|
||||
if [[ "$CONFIG" == "" ]]; then |
||||
export CONFIG=opt |
||||
fi |
||||
make resolver_component_test |
||||
echo "Sanity check DNS records are resolveable with dig:" |
||||
EXIT_CODE=0 |
||||
|
||||
% for r in records: |
||||
ONE_FAILED=0 |
||||
dig ${r['type']} ${r['name']}.${resolver_tests_common_zone_name} | grep 'ANSWER SECTION' || ONE_FAILED=1 |
||||
if [[ "$ONE_FAILED" != 0 ]]; then |
||||
echo "Sanity check: dig ${r['type']} ${r['name']}.${resolver_tests_common_zone_name} FAILED" |
||||
exit 1 |
||||
fi |
||||
|
||||
% endfor |
||||
echo "Sanity check PASSED. Run resolver tests:" |
||||
|
||||
% for test in tests: |
||||
ONE_FAILED=0 |
||||
bins/$CONFIG/resolver_component_test \\ |
||||
|
||||
--target_name='${test['target_name']}' \\ |
||||
|
||||
--expected_addrs='${test['expected_addrs']}' \\ |
||||
|
||||
--expected_chosen_service_config='${test['expected_chosen_service_config']}' \\ |
||||
|
||||
--expected_lb_policy='${test['expected_lb_policy']}' || ONE_FAILED=1 |
||||
if [[ "$ONE_FAILED" != 0 ]]; then |
||||
echo "Test based on target record: ${test['target_name']} FAILED" |
||||
EXIT_CODE=1 |
||||
fi |
||||
|
||||
% endfor |
||||
exit $EXIT_CODE</%def> |
@ -0,0 +1,4 @@ |
||||
%YAML 1.2 |
||||
--- | |
||||
<%namespace file="resolver_gce_integration_tests_defs.include" import="*"/>\ |
||||
${resolver_gce_integration_tests(resolver_gce_integration_test_cases, all_integration_test_records, resolver_tests_common_zone_name)} |
@ -1,5 +1,5 @@ |
||||
RUN apt-get update && apt-get -y install wget |
||||
RUN echo deb http://llvm.org/apt/wily/ llvm-toolchain-wily-3.8 main >> /etc/apt/sources.list |
||||
RUN echo deb-src http://llvm.org/apt/wily/ llvm-toolchain-wily-3.8 main >> /etc/apt/sources.list |
||||
RUN wget -O - http://llvm.org/apt/llvm-snapshot.gpg.key| apt-key add - |
||||
RUN echo "deb http://llvm.org/apt/jessie/ llvm-toolchain-jessie-3.8 main" >> /etc/apt/sources.list |
||||
RUN echo "deb-src http://llvm.org/apt/jessie/ llvm-toolchain-jessie-3.8 main" >> /etc/apt/sources.list |
||||
RUN wget -O - http://llvm.org/apt/llvm-snapshot.gpg.key | apt-key add - |
||||
RUN apt-get update && apt-get -y install clang-format-3.8 |
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue