diff options
author | 2017-07-21 16:06:17 -0700 | |
---|---|---|
committer | 2017-07-21 16:06:17 -0700 | |
commit | 288076d9180ca3c9a4bcd377ef04aa98b45f7d3b (patch) | |
tree | 06b66cb1128a11fdccff305ebbba9011222a42b3 /test/core/end2end | |
parent | c5fe5ccc695cd5f1aa040e62429f663b9795e327 (diff) | |
parent | 781fd6f6ea03645a520cd5c675da67ab61f87e4b (diff) |
Merge github.com:grpc/grpc into write_completion
Diffstat (limited to 'test/core/end2end')
-rw-r--r-- | test/core/end2end/end2end_nosec_tests.c | 8 | ||||
-rw-r--r-- | test/core/end2end/end2end_tests.c | 8 | ||||
-rw-r--r-- | test/core/end2end/fixtures/h2_http_proxy.c | 19 | ||||
-rw-r--r-- | test/core/end2end/fixtures/http_proxy_fixture.c | 52 | ||||
-rw-r--r-- | test/core/end2end/fixtures/http_proxy_fixture.h | 19 | ||||
-rwxr-xr-x | test/core/end2end/gen_build_yaml.py | 14 | ||||
-rwxr-xr-x | test/core/end2end/generate_tests.bzl | 17 | ||||
-rw-r--r-- | test/core/end2end/tests/proxy_auth.c | 235 |
8 files changed, 355 insertions, 17 deletions
diff --git a/test/core/end2end/end2end_nosec_tests.c b/test/core/end2end/end2end_nosec_tests.c index ae1db54f1a..6a061a4e2d 100644 --- a/test/core/end2end/end2end_nosec_tests.c +++ b/test/core/end2end/end2end_nosec_tests.c @@ -106,6 +106,8 @@ extern void ping(grpc_end2end_test_config config); extern void ping_pre_init(void); extern void ping_pong_streaming(grpc_end2end_test_config config); extern void ping_pong_streaming_pre_init(void); +extern void proxy_auth(grpc_end2end_test_config config); +extern void proxy_auth_pre_init(void); extern void registered_call(grpc_end2end_test_config config); extern void registered_call_pre_init(void); extern void request_with_flags(grpc_end2end_test_config config); @@ -181,6 +183,7 @@ void grpc_end2end_tests_pre_init(void) { payload_pre_init(); ping_pre_init(); ping_pong_streaming_pre_init(); + proxy_auth_pre_init(); registered_call_pre_init(); request_with_flags_pre_init(); request_with_payload_pre_init(); @@ -244,6 +247,7 @@ void grpc_end2end_tests(int argc, char **argv, payload(config); ping(config); ping_pong_streaming(config); + proxy_auth(config); registered_call(config); request_with_flags(config); request_with_payload(config); @@ -416,6 +420,10 @@ void grpc_end2end_tests(int argc, char **argv, ping_pong_streaming(config); continue; } + if (0 == strcmp("proxy_auth", argv[i])) { + proxy_auth(config); + continue; + } if (0 == strcmp("registered_call", argv[i])) { registered_call(config); continue; diff --git a/test/core/end2end/end2end_tests.c b/test/core/end2end/end2end_tests.c index d18dd9c7b6..3fc7c3fb6c 100644 --- a/test/core/end2end/end2end_tests.c +++ b/test/core/end2end/end2end_tests.c @@ -108,6 +108,8 @@ extern void ping(grpc_end2end_test_config config); extern void ping_pre_init(void); extern void ping_pong_streaming(grpc_end2end_test_config config); extern void ping_pong_streaming_pre_init(void); +extern void proxy_auth(grpc_end2end_test_config config); +extern void proxy_auth_pre_init(void); extern void registered_call(grpc_end2end_test_config config); extern void registered_call_pre_init(void); extern void request_with_flags(grpc_end2end_test_config config); @@ -184,6 +186,7 @@ void grpc_end2end_tests_pre_init(void) { payload_pre_init(); ping_pre_init(); ping_pong_streaming_pre_init(); + proxy_auth_pre_init(); registered_call_pre_init(); request_with_flags_pre_init(); request_with_payload_pre_init(); @@ -248,6 +251,7 @@ void grpc_end2end_tests(int argc, char **argv, payload(config); ping(config); ping_pong_streaming(config); + proxy_auth(config); registered_call(config); request_with_flags(config); request_with_payload(config); @@ -424,6 +428,10 @@ void grpc_end2end_tests(int argc, char **argv, ping_pong_streaming(config); continue; } + if (0 == strcmp("proxy_auth", argv[i])) { + proxy_auth(config); + continue; + } if (0 == strcmp("registered_call", argv[i])) { registered_call(config); continue; diff --git a/test/core/end2end/fixtures/h2_http_proxy.c b/test/core/end2end/fixtures/h2_http_proxy.c index f8c88e5953..6145892365 100644 --- a/test/core/end2end/fixtures/h2_http_proxy.c +++ b/test/core/end2end/fixtures/h2_http_proxy.c @@ -47,11 +47,13 @@ static grpc_end2end_test_fixture chttp2_create_fixture_fullstack( grpc_channel_args *client_args, grpc_channel_args *server_args) { grpc_end2end_test_fixture f; memset(&f, 0, sizeof(f)); - fullstack_fixture_data *ffd = gpr_malloc(sizeof(fullstack_fixture_data)); const int server_port = grpc_pick_unused_port_or_die(); gpr_join_host_port(&ffd->server_addr, "localhost", server_port); - ffd->proxy = grpc_end2end_http_proxy_create(); + + /* Passing client_args to proxy_create for the case of checking for proxy auth + */ + ffd->proxy = grpc_end2end_http_proxy_create(client_args); f.fixture_data = ffd; f.cq = grpc_completion_queue_create_for_next(NULL); @@ -64,8 +66,17 @@ void chttp2_init_client_fullstack(grpc_end2end_test_fixture *f, grpc_channel_args *client_args) { fullstack_fixture_data *ffd = f->fixture_data; char *proxy_uri; - gpr_asprintf(&proxy_uri, "http://%s", - grpc_end2end_http_proxy_get_proxy_name(ffd->proxy)); + + /* If testing for proxy auth, add credentials to proxy uri */ + const grpc_arg *proxy_auth_arg = + grpc_channel_args_find(client_args, GRPC_ARG_HTTP_PROXY_AUTH_CREDS); + if (proxy_auth_arg == NULL || proxy_auth_arg->type != GRPC_ARG_STRING) { + gpr_asprintf(&proxy_uri, "http://%s", + grpc_end2end_http_proxy_get_proxy_name(ffd->proxy)); + } else { + gpr_asprintf(&proxy_uri, "http://%s@%s", proxy_auth_arg->value.string, + grpc_end2end_http_proxy_get_proxy_name(ffd->proxy)); + } gpr_setenv("http_proxy", proxy_uri); gpr_free(proxy_uri); f->client = grpc_insecure_channel_create(ffd->server_addr, client_args, NULL); diff --git a/test/core/end2end/fixtures/http_proxy_fixture.c b/test/core/end2end/fixtures/http_proxy_fixture.c index 54693c4900..a4cfc77bcb 100644 --- a/test/core/end2end/fixtures/http_proxy_fixture.c +++ b/test/core/end2end/fixtures/http_proxy_fixture.c @@ -22,6 +22,7 @@ #include <string.h> +#include <grpc/grpc.h> #include <grpc/slice_buffer.h> #include <grpc/support/alloc.h> #include <grpc/support/atm.h> @@ -46,7 +47,9 @@ #include "src/core/lib/iomgr/tcp_client.h" #include "src/core/lib/iomgr/tcp_server.h" #include "src/core/lib/iomgr/timer.h" +#include "src/core/lib/slice/b64.h" #include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/support/string.h" #include "test/core/util/port.h" struct grpc_end2end_http_proxy { @@ -304,6 +307,28 @@ static void on_server_connect_done(grpc_exec_ctx* exec_ctx, void* arg, &conn->on_write_response_done); } +/** + * Parses the proxy auth header value to check if it matches :- + * Basic <base64_encoded_expected_cred> + * Returns true if it matches, false otherwise + */ +static bool proxy_auth_header_matches(grpc_exec_ctx* exec_ctx, + char* proxy_auth_header_val, + char* expected_cred) { + GPR_ASSERT(proxy_auth_header_val != NULL); + GPR_ASSERT(expected_cred != NULL); + if (strncmp(proxy_auth_header_val, "Basic ", 6) != 0) { + return false; + } + proxy_auth_header_val += 6; + grpc_slice decoded_slice = + grpc_base64_decode(exec_ctx, proxy_auth_header_val, 0); + const bool header_matches = + grpc_slice_str_cmp(decoded_slice, expected_cred) == 0; + grpc_slice_unref_internal(exec_ctx, decoded_slice); + return header_matches; +} + // Callback to read the HTTP CONNECT request. // TODO(roth): Technically, for any of the failure modes handled by this // function, we should handle the error by returning an HTTP response to @@ -352,6 +377,28 @@ static void on_read_request_done(grpc_exec_ctx* exec_ctx, void* arg, GRPC_ERROR_UNREF(error); return; } + // If proxy auth is being used, check if the header is present and as expected + const grpc_arg* proxy_auth_arg = grpc_channel_args_find( + conn->proxy->channel_args, GRPC_ARG_HTTP_PROXY_AUTH_CREDS); + if (proxy_auth_arg != NULL && proxy_auth_arg->type == GRPC_ARG_STRING) { + bool client_authenticated = false; + for (size_t i = 0; i < conn->http_request.hdr_count; i++) { + if (strcmp(conn->http_request.hdrs[i].key, "Proxy-Authorization") == 0) { + client_authenticated = proxy_auth_header_matches( + exec_ctx, conn->http_request.hdrs[i].value, + proxy_auth_arg->value.string); + break; + } + } + if (!client_authenticated) { + const char* msg = "HTTP Connect could not verify authentication"; + error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(msg); + proxy_connection_failed(exec_ctx, conn, true /* is_client */, + "HTTP proxy read request", error); + GRPC_ERROR_UNREF(error); + return; + } + } // Resolve address. grpc_resolved_addresses* resolved_addresses = NULL; error = grpc_blocking_resolve_address(conn->http_request.path, "80", @@ -436,7 +483,8 @@ static void thread_main(void* arg) { grpc_exec_ctx_finish(&exec_ctx); } -grpc_end2end_http_proxy* grpc_end2end_http_proxy_create(void) { +grpc_end2end_http_proxy* grpc_end2end_http_proxy_create( + grpc_channel_args* args) { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_end2end_http_proxy* proxy = (grpc_end2end_http_proxy*)gpr_malloc(sizeof(*proxy)); @@ -448,7 +496,7 @@ grpc_end2end_http_proxy* grpc_end2end_http_proxy_create(void) { gpr_join_host_port(&proxy->proxy_name, "localhost", proxy_port); gpr_log(GPR_INFO, "Proxy address: %s", proxy->proxy_name); // Create TCP server. - proxy->channel_args = grpc_channel_args_copy(NULL); + proxy->channel_args = grpc_channel_args_copy(args); grpc_error* error = grpc_tcp_server_create( &exec_ctx, NULL, proxy->channel_args, &proxy->server); GPR_ASSERT(error == GRPC_ERROR_NONE); diff --git a/test/core/end2end/fixtures/http_proxy_fixture.h b/test/core/end2end/fixtures/http_proxy_fixture.h index a72162e846..103bd08196 100644 --- a/test/core/end2end/fixtures/http_proxy_fixture.h +++ b/test/core/end2end/fixtures/http_proxy_fixture.h @@ -16,11 +16,28 @@ * */ +#ifndef GRPC_TEST_CORE_END2END_FIXTURES_HTTP_PROXY_FIXTURE_H +#define GRPC_TEST_CORE_END2END_FIXTURES_HTTP_PROXY_FIXTURE_H + +#include <grpc/grpc.h> + +/* The test credentials being used for HTTP Proxy Authorization */ +#define GRPC_TEST_HTTP_PROXY_AUTH_CREDS "aladdin:opensesame" + +/* A channel arg key used to indicate that the channel uses proxy authorization. + * The value (string) should be the proxy auth credentials that should be + * checked. + */ +#define GRPC_ARG_HTTP_PROXY_AUTH_CREDS "grpc.test.proxy_auth" + typedef struct grpc_end2end_http_proxy grpc_end2end_http_proxy; -grpc_end2end_http_proxy* grpc_end2end_http_proxy_create(); +grpc_end2end_http_proxy* grpc_end2end_http_proxy_create( + grpc_channel_args* args); void grpc_end2end_http_proxy_destroy(grpc_end2end_http_proxy* proxy); const char* grpc_end2end_http_proxy_get_proxy_name( grpc_end2end_http_proxy* proxy); + +#endif /* GRPC_TEST_CORE_END2END_FIXTURES_HTTP_PROXY_FIXTURE_H */ diff --git a/test/core/end2end/gen_build_yaml.py b/test/core/end2end/gen_build_yaml.py index 6878964c4f..18bae63a8a 100755 --- a/test/core/end2end/gen_build_yaml.py +++ b/test/core/end2end/gen_build_yaml.py @@ -24,9 +24,9 @@ import hashlib FixtureOptions = collections.namedtuple( 'FixtureOptions', - 'fullstack includes_proxy dns_resolver name_resolution secure platforms ci_mac tracing exclude_configs exclude_iomgrs large_writes enables_compression supports_compression is_inproc is_http2') + 'fullstack includes_proxy dns_resolver name_resolution secure platforms ci_mac tracing exclude_configs exclude_iomgrs large_writes enables_compression supports_compression is_inproc is_http2 supports_proxy_auth') default_unsecure_fixture_options = FixtureOptions( - True, False, True, True, False, ['windows', 'linux', 'mac', 'posix'], True, False, [], [], True, False, True, False, True) + True, False, True, True, False, ['windows', 'linux', 'mac', 'posix'], True, False, [], [], True, False, True, False, True, False) socketpair_unsecure_fixture_options = default_unsecure_fixture_options._replace(fullstack=False, dns_resolver=False) default_secure_fixture_options = default_unsecure_fixture_options._replace(secure=True) uds_fixture_options = default_unsecure_fixture_options._replace(dns_resolver=False, platforms=['linux', 'mac', 'posix'], exclude_iomgrs=['uv']) @@ -47,7 +47,7 @@ END2END_FIXTURES = { 'h2_full+trace': default_unsecure_fixture_options._replace(tracing=True), 'h2_full+workarounds': default_unsecure_fixture_options, 'h2_http_proxy': default_unsecure_fixture_options._replace( - ci_mac=False, exclude_iomgrs=['uv']), + ci_mac=False, exclude_iomgrs=['uv'], supports_proxy_auth=True), 'h2_oauth2': default_secure_fixture_options._replace( ci_mac=False, exclude_iomgrs=['uv']), 'h2_proxy': default_unsecure_fixture_options._replace( @@ -69,8 +69,8 @@ END2END_FIXTURES = { TestOptions = collections.namedtuple( 'TestOptions', - 'needs_fullstack needs_dns needs_names proxyable secure traceable cpu_cost exclude_iomgrs large_writes flaky allows_compression needs_compression exclude_inproc needs_http2') -default_test_options = TestOptions(False, False, False, True, False, True, 1.0, [], False, False, True, False, False, False) + 'needs_fullstack needs_dns needs_names proxyable secure traceable cpu_cost exclude_iomgrs large_writes flaky allows_compression needs_compression exclude_inproc needs_http2 needs_proxy_auth') +default_test_options = TestOptions(False, False, False, True, False, True, 1.0, [], False, False, True, False, False, False, False) connectivity_test_options = default_test_options._replace(needs_fullstack=True) LOWCPU = 0.1 @@ -128,6 +128,7 @@ END2END_TESTS = { 'load_reporting_hook': default_test_options, 'ping_pong_streaming': default_test_options._replace(cpu_cost=LOWCPU), 'ping': connectivity_test_options._replace(proxyable=False, cpu_cost=LOWCPU), + 'proxy_auth': default_test_options._replace(needs_proxy_auth=True), 'registered_call': default_test_options, 'request_with_flags': default_test_options._replace( proxyable=False, cpu_cost=LOWCPU), @@ -178,6 +179,9 @@ def compatible(f, t): if END2END_TESTS[t].needs_http2: if not END2END_FIXTURES[f].is_http2: return False + if END2END_TESTS[t].needs_proxy_auth: + if not END2END_FIXTURES[f].supports_proxy_auth: + return False return True diff --git a/test/core/end2end/generate_tests.bzl b/test/core/end2end/generate_tests.bzl index ea9ad03513..6d1917c0ff 100755 --- a/test/core/end2end/generate_tests.bzl +++ b/test/core/end2end/generate_tests.bzl @@ -21,7 +21,7 @@ load("//bazel:grpc_build_system.bzl", "grpc_sh_test", "grpc_cc_binary", "grpc_cc def fixture_options(fullstack=True, includes_proxy=False, dns_resolver=True, name_resolution=True, secure=True, tracing=False, platforms=['windows', 'linux', 'mac', 'posix'], - is_inproc=False, is_http2=True): + is_inproc=False, is_http2=True, supports_proxy_auth=False): return struct( fullstack=fullstack, includes_proxy=includes_proxy, @@ -30,7 +30,8 @@ def fixture_options(fullstack=True, includes_proxy=False, dns_resolver=True, secure=secure, tracing=tracing, is_inproc=is_inproc, - is_http2=is_http2 + is_http2=is_http2, + supports_proxy_auth=supports_proxy_auth #platforms=platforms ) @@ -47,7 +48,7 @@ END2END_FIXTURES = { 'h2_full+pipe': fixture_options(platforms=['linux']), 'h2_full+trace': fixture_options(tracing=True), 'h2_full+workarounds': fixture_options(), - 'h2_http_proxy': fixture_options(), + 'h2_http_proxy': fixture_options(supports_proxy_auth=True), 'h2_oauth2': fixture_options(), 'h2_proxy': fixture_options(includes_proxy=True), 'h2_sockpair_1byte': fixture_options(fullstack=False, dns_resolver=False), @@ -67,7 +68,8 @@ END2END_FIXTURES = { def test_options(needs_fullstack=False, needs_dns=False, needs_names=False, proxyable=True, secure=False, traceable=False, - exclude_inproc=False, needs_http2=False): + exclude_inproc=False, needs_http2=False, + needs_proxy_auth=False): return struct( needs_fullstack=needs_fullstack, needs_dns=needs_dns, @@ -76,7 +78,8 @@ def test_options(needs_fullstack=False, needs_dns=False, needs_names=False, secure=secure, traceable=traceable, exclude_inproc=exclude_inproc, - needs_http2=needs_http2 + needs_http2=needs_http2, + needs_proxy_auth=needs_proxy_auth ) @@ -123,6 +126,7 @@ END2END_TESTS = { 'load_reporting_hook': test_options(), 'ping_pong_streaming': test_options(), 'ping': test_options(needs_fullstack=True, proxyable=False), + 'proxy_auth': test_options(needs_proxy_auth=True), 'registered_call': test_options(), 'request_with_flags': test_options(proxyable=False), 'request_with_payload': test_options(), @@ -165,6 +169,9 @@ def compatible(fopt, topt): if topt.needs_http2: if not fopt.is_http2: return False + if topt.needs_proxy_auth: + if not fopt.supports_proxy_auth: + return False return True diff --git a/test/core/end2end/tests/proxy_auth.c b/test/core/end2end/tests/proxy_auth.c new file mode 100644 index 0000000000..d922049bcb --- /dev/null +++ b/test/core/end2end/tests/proxy_auth.c @@ -0,0 +1,235 @@ +/* + * + * 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 test is for checking whether proxy authentication is working with HTTP + * Connect. + */ +#include "test/core/end2end/end2end_tests.h" +#include "test/core/end2end/fixtures/http_proxy_fixture.h" + +#include <stdio.h> +#include <string.h> + +#include <grpc/byte_buffer.h> +#include <grpc/grpc.h> +#include <grpc/support/alloc.h> +#include <grpc/support/log.h> +#include <grpc/support/time.h> +#include <grpc/support/useful.h> +#include "src/core/lib/support/string.h" +#include "test/core/end2end/cq_verifier.h" + +static void *tag(intptr_t t) { return (void *)t; } + +static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config, + const char *test_name, + grpc_channel_args *client_args, + grpc_channel_args *server_args) { + grpc_end2end_test_fixture f; + gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name); + f = config.create_fixture(client_args, server_args); + config.init_server(&f, server_args); + config.init_client(&f, client_args); + return f; +} + +static gpr_timespec n_seconds_from_now(int n) { + return grpc_timeout_seconds_to_deadline(n); +} + +static gpr_timespec five_seconds_from_now(void) { + return n_seconds_from_now(5); +} + +static void drain_cq(grpc_completion_queue *cq) { + grpc_event ev; + do { + ev = grpc_completion_queue_next(cq, five_seconds_from_now(), NULL); + } while (ev.type != GRPC_QUEUE_SHUTDOWN); +} + +static void shutdown_server(grpc_end2end_test_fixture *f) { + if (!f->server) return; + grpc_server_shutdown_and_notify(f->server, f->shutdown_cq, tag(1000)); + GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_cq, tag(1000), + grpc_timeout_seconds_to_deadline(5), + NULL) + .type == GRPC_OP_COMPLETE); + grpc_server_destroy(f->server); + f->server = NULL; +} + +static void shutdown_client(grpc_end2end_test_fixture *f) { + if (!f->client) return; + grpc_channel_destroy(f->client); + f->client = NULL; +} + +static void end_test(grpc_end2end_test_fixture *f) { + shutdown_server(f); + shutdown_client(f); + + grpc_completion_queue_shutdown(f->cq); + drain_cq(f->cq); + grpc_completion_queue_destroy(f->cq); + grpc_completion_queue_destroy(f->shutdown_cq); +} + +static void simple_request_body(grpc_end2end_test_config config, + grpc_end2end_test_fixture f) { + grpc_call *c; + grpc_call *s; + cq_verifier *cqv = cq_verifier_create(f.cq); + grpc_op ops[6]; + grpc_op *op; + grpc_metadata_array initial_metadata_recv; + grpc_metadata_array trailing_metadata_recv; + grpc_metadata_array request_metadata_recv; + grpc_call_details call_details; + grpc_status_code status; + grpc_call_error error; + grpc_slice details; + int was_cancelled = 2; + char *peer; + + gpr_timespec deadline = five_seconds_from_now(); + c = grpc_channel_create_call( + f.client, NULL, GRPC_PROPAGATE_DEFAULTS, f.cq, + grpc_slice_from_static_string("/foo"), + get_host_override_slice("foo.test.google.fr:1234", config), deadline, + NULL); + GPR_ASSERT(c); + + peer = grpc_call_get_peer(c); + GPR_ASSERT(peer != NULL); + gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer); + gpr_free(peer); + + grpc_metadata_array_init(&initial_metadata_recv); + grpc_metadata_array_init(&trailing_metadata_recv); + grpc_metadata_array_init(&request_metadata_recv); + grpc_call_details_init(&call_details); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_INITIAL_METADATA; + op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_STATUS_ON_CLIENT; + op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv; + op->data.recv_status_on_client.status = &status; + op->data.recv_status_on_client.status_details = &details; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + error = + grpc_server_request_call(f.server, &s, &call_details, + &request_metadata_recv, f.cq, f.cq, tag(101)); + GPR_ASSERT(GRPC_CALL_OK == error); + CQ_EXPECT_COMPLETION(cqv, tag(101), 1); + cq_verify(cqv); + + peer = grpc_call_get_peer(s); + GPR_ASSERT(peer != NULL); + gpr_log(GPR_DEBUG, "server_peer=%s", peer); + gpr_free(peer); + peer = grpc_call_get_peer(c); + GPR_ASSERT(peer != NULL); + gpr_log(GPR_DEBUG, "client_peer=%s", peer); + gpr_free(peer); + + memset(ops, 0, sizeof(ops)); + op = ops; + op->op = GRPC_OP_SEND_INITIAL_METADATA; + op->data.send_initial_metadata.count = 0; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_SEND_STATUS_FROM_SERVER; + op->data.send_status_from_server.trailing_metadata_count = 0; + op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED; + grpc_slice status_details = grpc_slice_from_static_string("xyz"); + op->data.send_status_from_server.status_details = &status_details; + op->flags = 0; + op->reserved = NULL; + op++; + op->op = GRPC_OP_RECV_CLOSE_ON_SERVER; + op->data.recv_close_on_server.cancelled = &was_cancelled; + op->flags = 0; + op->reserved = NULL; + op++; + error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(102), NULL); + GPR_ASSERT(GRPC_CALL_OK == error); + + CQ_EXPECT_COMPLETION(cqv, tag(102), 1); + CQ_EXPECT_COMPLETION(cqv, tag(1), 1); + cq_verify(cqv); + + GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED); + GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz")); + GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo")); + validate_host_override_string("foo.test.google.fr:1234", call_details.host, + config); + GPR_ASSERT(0 == call_details.flags); + GPR_ASSERT(was_cancelled == 1); + + grpc_slice_unref(details); + grpc_metadata_array_destroy(&initial_metadata_recv); + grpc_metadata_array_destroy(&trailing_metadata_recv); + grpc_metadata_array_destroy(&request_metadata_recv); + grpc_call_details_destroy(&call_details); + + grpc_call_unref(c); + grpc_call_unref(s); + + cq_verifier_destroy(cqv); +} + +static void test_invoke_proxy_auth(grpc_end2end_test_config config) { + /* Indicate that the proxy requires user auth */ + grpc_arg client_arg = {.type = GRPC_ARG_STRING, + .key = GRPC_ARG_HTTP_PROXY_AUTH_CREDS, + .value.string = GRPC_TEST_HTTP_PROXY_AUTH_CREDS}; + grpc_channel_args client_args = {.num_args = 1, .args = &client_arg}; + grpc_end2end_test_fixture f = + begin_test(config, "test_invoke_proxy_auth", &client_args, NULL); + simple_request_body(config, f); + end_test(&f); + config.tear_down_data(&f); +} + +void proxy_auth(grpc_end2end_test_config config) { + test_invoke_proxy_auth(config); +} + +void proxy_auth_pre_init(void) {} |