Merge branch 'master' of github.com:grpc/grpc into qps_reporter_refactoring

pull/1649/head
David Garcia Quintas 10 years ago
commit f01ccb7ba3
  1. 3
      .travis.yml
  2. 172
      Makefile
  3. 69
      build.json
  4. 6
      include/grpc++/stream.h
  5. 5
      include/grpc/grpc.h
  6. 10
      include/grpc/support/subprocess.h
  7. 6
      src/core/support/subprocess_posix.c
  8. 56
      src/core/surface/call.c
  9. 4
      src/core/transport/chttp2/hpack_parser.c
  10. 2
      src/core/transport/chttp2/hpack_parser.h
  11. 2
      src/cpp/server/server.cc
  12. 56
      src/node/src/client.js
  13. 2
      src/objective-c/README.md
  14. 4
      test/core/fling/fling_test.c
  15. 165
      test/cpp/end2end/client_crash_test.cc
  16. 94
      test/cpp/end2end/client_crash_test_server.cc
  17. 12
      test/cpp/end2end/end2end_test.cc
  18. 166
      test/cpp/end2end/server_crash_test.cc
  19. 93
      test/cpp/end2end/server_crash_test_client.cc
  20. 10
      test/cpp/end2end/thread_stress_test.cc
  21. 43
      test/cpp/qps/client.h
  22. 89
      test/cpp/qps/client_async.cc
  23. 14
      test/cpp/qps/client_sync.cc
  24. 5
      test/cpp/qps/driver.cc
  25. 4
      test/cpp/qps/qps_driver.cc
  26. 24
      test/cpp/qps/qps_worker.cc
  27. 110
      test/cpp/qps/server_async.cc
  28. 16
      test/cpp/qps/server_sync.cc
  29. 7
      test/cpp/qps/worker.cc
  30. 59
      test/cpp/util/subprocess.cc
  31. 61
      test/cpp/util/subprocess.h
  32. 7
      tools/dockerfile/grpc_java_android/Dockerfile
  33. 1
      tools/run_tests/run_python.sh
  34. 18
      tools/run_tests/tests.json

@ -18,7 +18,8 @@ env:
- NUGET="mono nuget.exe"
matrix:
- CONFIG=opt TEST=sanity
- CONFIG=gcov TEST="c c++"
- CONFIG=gcov TEST=c
- CONFIG=gcov TEST=c++
- CONFIG=opt TEST="c c++"
- CONFIG=opt TEST=node
- CONFIG=opt TEST=ruby

File diff suppressed because one or more lines are too long

@ -553,7 +553,8 @@
"test/cpp/util/echo_duplicate.proto",
"test/cpp/util/cli_call.cc",
"test/cpp/util/create_test_channel.cc",
"test/cpp/util/fake_credentials.cc"
"test/cpp/util/fake_credentials.cc",
"test/cpp/util/subprocess.cc"
]
},
{
@ -1884,6 +1885,39 @@
"gpr"
]
},
{
"name": "client_crash_test",
"build": "test",
"language": "c++",
"src": [
"test/cpp/end2end/client_crash_test.cc"
],
"deps": [
"grpc++_test_util",
"grpc_test_util",
"grpc++",
"grpc",
"gpr_test_util",
"gpr"
]
},
{
"name": "client_crash_test_server",
"build": "test",
"run": false,
"language": "c++",
"src": [
"test/cpp/end2end/client_crash_test_server.cc"
],
"deps": [
"grpc++_test_util",
"grpc_test_util",
"grpc++",
"grpc",
"gpr_test_util",
"gpr"
]
},
{
"name": "credentials_test",
"build": "test",
@ -2200,6 +2234,39 @@
"grpc++_test_config"
]
},
{
"name": "server_crash_test",
"build": "test",
"language": "c++",
"src": [
"test/cpp/end2end/server_crash_test.cc"
],
"deps": [
"grpc++_test_util",
"grpc_test_util",
"grpc++",
"grpc",
"gpr_test_util",
"gpr"
]
},
{
"name": "server_crash_test_client",
"build": "test",
"run": false,
"language": "c++",
"src": [
"test/cpp/end2end/server_crash_test_client.cc"
],
"deps": [
"grpc++_test_util",
"grpc_test_util",
"grpc++",
"grpc",
"gpr_test_util",
"gpr"
]
},
{
"name": "status_test",
"build": "test",

@ -114,7 +114,7 @@ class ClientReader GRPC_FINAL : public ClientReaderInterface<R> {
CallOpBuffer buf;
buf.AddRecvInitialMetadata(context_);
call_.PerformOps(&buf);
GPR_ASSERT(cq_.Pluck(&buf));
cq_.Pluck(&buf); // status ignored
}
bool Read(R* msg) GRPC_OVERRIDE {
@ -216,7 +216,7 @@ class ClientReaderWriter GRPC_FINAL : public ClientReaderWriterInterface<W, R> {
CallOpBuffer buf;
buf.AddSendInitialMetadata(&context->send_initial_metadata_);
call_.PerformOps(&buf);
GPR_ASSERT(cq_.Pluck(&buf));
cq_.Pluck(&buf);
}
// Blocking wait for initial metadata from server. The received metadata
@ -229,7 +229,7 @@ class ClientReaderWriter GRPC_FINAL : public ClientReaderWriterInterface<W, R> {
CallOpBuffer buf;
buf.AddRecvInitialMetadata(context_);
call_.PerformOps(&buf);
GPR_ASSERT(cq_.Pluck(&buf));
cq_.Pluck(&buf); // status ignored
}
bool Read(R* msg) GRPC_OVERRIDE {

@ -244,7 +244,10 @@ typedef enum {
GRPC_OP_RECV_INITIAL_METADATA,
/* Receive a message: 0 or more of these operations can occur for each call */
GRPC_OP_RECV_MESSAGE,
/* Receive status on the client: one and only one must be made on the client
/* Receive status on the client: one and only one must be made on the client.
This operation always succeeds, meaning ops paired with this operation
will also appear to succeed, even though they may not have. In that case
the status will indicate some failure.
*/
GRPC_OP_RECV_STATUS_ON_CLIENT,
/* Receive status on the server: one and only one must be made on the server

@ -34,16 +34,24 @@
#ifndef GRPC_SUPPORT_SUBPROCESS_H
#define GRPC_SUPPORT_SUBPROCESS_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct gpr_subprocess gpr_subprocess;
/* .exe on windows, empty on unices */
const char *gpr_subprocess_binary_extension();
gpr_subprocess *gpr_subprocess_create(int argc, char **argv);
gpr_subprocess *gpr_subprocess_create(int argc, const char **argv);
/* if subprocess has not been joined, kill it */
void gpr_subprocess_destroy(gpr_subprocess *p);
/* returns exit status; can be called at most once */
int gpr_subprocess_join(gpr_subprocess *p);
void gpr_subprocess_interrupt(gpr_subprocess *p);
#ifdef __cplusplus
} // extern "C"
#endif
#endif

@ -57,7 +57,7 @@ struct gpr_subprocess {
const char *gpr_subprocess_binary_extension() { return ""; }
gpr_subprocess *gpr_subprocess_create(int argc, char **argv) {
gpr_subprocess *gpr_subprocess_create(int argc, const char **argv) {
gpr_subprocess *r;
int pid;
char **exec_args;
@ -92,7 +92,11 @@ void gpr_subprocess_destroy(gpr_subprocess *p) {
int gpr_subprocess_join(gpr_subprocess *p) {
int status;
retry:
if (waitpid(p->pid, &status, 0) == -1) {
if (errno == EINTR) {
goto retry;
}
gpr_log(GPR_ERROR, "waitpid failed: %s", strerror(errno));
return -1;
}

@ -536,9 +536,8 @@ static void finish_live_ioreq_op(grpc_call *call, grpc_ioreq_op op,
switch ((grpc_ioreq_op)i) {
case GRPC_IOREQ_RECV_MESSAGE:
case GRPC_IOREQ_SEND_MESSAGE:
if (master->success) {
call->request_set[i] = REQSET_EMPTY;
} else {
call->request_set[i] = REQSET_EMPTY;
if (!master->success) {
call->write_state = WRITE_STATE_WRITE_CLOSED;
}
break;
@ -583,11 +582,29 @@ static void finish_ioreq_op(grpc_call *call, grpc_ioreq_op op, int success) {
}
}
static void early_out_write_ops(grpc_call *call) {
switch (call->write_state) {
case WRITE_STATE_WRITE_CLOSED:
finish_ioreq_op(call, GRPC_IOREQ_SEND_MESSAGE, 0);
finish_ioreq_op(call, GRPC_IOREQ_SEND_STATUS, 0);
finish_ioreq_op(call, GRPC_IOREQ_SEND_TRAILING_METADATA, 0);
finish_ioreq_op(call, GRPC_IOREQ_SEND_CLOSE, 1);
/* fallthrough */
case WRITE_STATE_STARTED:
finish_ioreq_op(call, GRPC_IOREQ_SEND_INITIAL_METADATA, 0);
/* fallthrough */
case WRITE_STATE_INITIAL:
/* do nothing */
break;
}
}
static void call_on_done_send(void *pc, int success) {
grpc_call *call = pc;
lock(call);
if (call->last_send_contains & (1 << GRPC_IOREQ_SEND_INITIAL_METADATA)) {
finish_ioreq_op(call, GRPC_IOREQ_SEND_INITIAL_METADATA, success);
call->write_state = WRITE_STATE_STARTED;
}
if (call->last_send_contains & (1 << GRPC_IOREQ_SEND_MESSAGE)) {
finish_ioreq_op(call, GRPC_IOREQ_SEND_MESSAGE, success);
@ -596,6 +613,11 @@ static void call_on_done_send(void *pc, int success) {
finish_ioreq_op(call, GRPC_IOREQ_SEND_TRAILING_METADATA, success);
finish_ioreq_op(call, GRPC_IOREQ_SEND_STATUS, success);
finish_ioreq_op(call, GRPC_IOREQ_SEND_CLOSE, 1);
call->write_state = WRITE_STATE_WRITE_CLOSED;
}
if (!success) {
call->write_state = WRITE_STATE_WRITE_CLOSED;
early_out_write_ops(call);
}
call->send_ops.nops = 0;
call->last_send_contains = 0;
@ -811,7 +833,6 @@ static int fill_send_ops(grpc_call *call, grpc_transport_op *op) {
op->send_ops = &call->send_ops;
op->bind_pollset = grpc_cq_pollset(call->cq);
call->last_send_contains |= 1 << GRPC_IOREQ_SEND_INITIAL_METADATA;
call->write_state = WRITE_STATE_STARTED;
call->send_initial_metadata_count = 0;
/* fall through intended */
case WRITE_STATE_STARTED:
@ -827,7 +848,6 @@ static int fill_send_ops(grpc_call *call, grpc_transport_op *op) {
op->is_last_send = 1;
op->send_ops = &call->send_ops;
call->last_send_contains |= 1 << GRPC_IOREQ_SEND_CLOSE;
call->write_state = WRITE_STATE_WRITE_CLOSED;
if (!call->is_client) {
/* send trailing metadata */
data = call->request_data[GRPC_IOREQ_SEND_TRAILING_METADATA];
@ -919,23 +939,6 @@ static void finish_read_ops(grpc_call *call) {
}
}
static void early_out_write_ops(grpc_call *call) {
switch (call->write_state) {
case WRITE_STATE_WRITE_CLOSED:
finish_ioreq_op(call, GRPC_IOREQ_SEND_MESSAGE, 0);
finish_ioreq_op(call, GRPC_IOREQ_SEND_STATUS, 0);
finish_ioreq_op(call, GRPC_IOREQ_SEND_TRAILING_METADATA, 0);
finish_ioreq_op(call, GRPC_IOREQ_SEND_CLOSE, 1);
/* fallthrough */
case WRITE_STATE_STARTED:
finish_ioreq_op(call, GRPC_IOREQ_SEND_INITIAL_METADATA, 0);
/* fallthrough */
case WRITE_STATE_INITIAL:
/* do nothing */
break;
}
}
static grpc_call_error start_ioreq(grpc_call *call, const grpc_ioreq *reqs,
size_t nreqs,
grpc_ioreq_completion_func completion,
@ -1176,6 +1179,10 @@ static void set_cancelled_value(grpc_status_code status, void *dest) {
}
static void finish_batch(grpc_call *call, int success, void *tag) {
grpc_cq_end_op(call->cq, tag, call, success);
}
static void finish_batch_with_close(grpc_call *call, int success, void *tag) {
grpc_cq_end_op(call->cq, tag, call, 1);
}
@ -1186,6 +1193,7 @@ grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops,
size_t out;
const grpc_op *op;
grpc_ioreq *req;
void (*finish_func)(grpc_call *, int, void *) = finish_batch;
GRPC_CALL_LOG_BATCH(GPR_INFO, call, ops, nops, tag);
@ -1269,6 +1277,7 @@ grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops,
op->data.recv_status_on_client.trailing_metadata;
req = &reqs[out++];
req->op = GRPC_IOREQ_RECV_CLOSE;
finish_func = finish_batch_with_close;
break;
case GRPC_OP_RECV_CLOSE_ON_SERVER:
req = &reqs[out++];
@ -1278,13 +1287,14 @@ grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops,
op->data.recv_close_on_server.cancelled;
req = &reqs[out++];
req->op = GRPC_IOREQ_RECV_CLOSE;
finish_func = finish_batch_with_close;
break;
}
}
grpc_cq_begin_op(call->cq, call);
return grpc_call_start_ioreq_and_call_back(call, reqs, out, finish_batch,
return grpc_call_start_ioreq_and_call_back(call, reqs, out, finish_func,
tag);
}

@ -654,7 +654,7 @@ static int parse_stream_weight(grpc_chttp2_hpack_parser *p,
return 1;
}
return parse_begin(p, cur + 1, end);
return p->after_prioritization(p, cur + 1, end);
}
static int parse_stream_dep3(grpc_chttp2_hpack_parser *p, const gpr_uint8 *cur,
@ -1349,7 +1349,7 @@ void grpc_chttp2_hpack_parser_init(grpc_chttp2_hpack_parser *p,
}
void grpc_chttp2_hpack_parser_set_has_priority(grpc_chttp2_hpack_parser *p) {
GPR_ASSERT(p->state == parse_begin);
p->after_prioritization = p->state;
p->state = parse_stream_dep0;
}

@ -62,6 +62,8 @@ struct grpc_chttp2_hpack_parser {
grpc_chttp2_hpack_parser_state state;
/* future states dependent on the opening op code */
const grpc_chttp2_hpack_parser_state *next_state;
/* what to do after skipping prioritization data */
grpc_chttp2_hpack_parser_state after_prioritization;
/* the value we're currently parsing */
union {
gpr_uint32 *value;

@ -149,7 +149,7 @@ class Server::SyncRequest GRPC_FINAL : public CompletionQueueTag {
}
buf.AddServerSendStatus(&ctx_.trailing_metadata_, status);
call_.PerformOps(&buf);
GPR_ASSERT(cq_.Pluck(&buf));
cq_.Pluck(&buf); /* status ignored */
void* ignored_tag;
bool ignored_ok;
cq_.Shutdown();

@ -81,7 +81,8 @@ function _write(chunk, encoding, callback) {
batch[grpc.opType.SEND_MESSAGE] = this.serialize(chunk);
this.call.startBatch(batch, function(err, event) {
if (err) {
throw err;
// Something has gone wrong. Stop writing by failing to call callback
return;
}
callback();
});
@ -120,7 +121,9 @@ function _read(size) {
*/
function readCallback(err, event) {
if (err) {
throw err;
// Something has gone wrong. Stop reading and wait for status
self.finished = true;
return;
}
if (self.finished) {
self.push(null);
@ -237,10 +240,6 @@ function makeUnaryRequestFunction(method, serialize, deserialize) {
client_batch[grpc.opType.RECV_MESSAGE] = true;
client_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true;
call.startBatch(client_batch, function(err, response) {
if (err) {
callback(err);
return;
}
emitter.emit('status', response.status);
if (response.status.code !== grpc.status.OK) {
var error = new Error(response.status.details);
@ -248,6 +247,12 @@ function makeUnaryRequestFunction(method, serialize, deserialize) {
error.metadata = response.status.metadata;
callback(error);
return;
} else {
if (err) {
// Got a batch error, but OK status. Something went wrong
callback(err);
return;
}
}
emitter.emit('metadata', response.metadata);
callback(null, deserialize(response.read));
@ -300,7 +305,8 @@ function makeClientStreamRequestFunction(method, serialize, deserialize) {
metadata_batch[grpc.opType.RECV_INITIAL_METADATA] = true;
call.startBatch(metadata_batch, function(err, response) {
if (err) {
callback(err);
// The call has stopped for some reason. A non-OK status will arrive
// in the other batch.
return;
}
stream.emit('metadata', response.metadata);
@ -309,10 +315,6 @@ function makeClientStreamRequestFunction(method, serialize, deserialize) {
client_batch[grpc.opType.RECV_MESSAGE] = true;
client_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true;
call.startBatch(client_batch, function(err, response) {
if (err) {
callback(err);
return;
}
stream.emit('status', response.status);
if (response.status.code !== grpc.status.OK) {
var error = new Error(response.status.details);
@ -320,6 +322,12 @@ function makeClientStreamRequestFunction(method, serialize, deserialize) {
error.metadata = response.status.metadata;
callback(error);
return;
} else {
if (err) {
// Got a batch error, but OK status. Something went wrong
callback(err);
return;
}
}
callback(null, deserialize(response.read));
});
@ -373,16 +381,15 @@ function makeServerStreamRequestFunction(method, serialize, deserialize) {
start_batch[grpc.opType.SEND_CLOSE_FROM_CLIENT] = true;
call.startBatch(start_batch, function(err, response) {
if (err) {
throw err;
// The call has stopped for some reason. A non-OK status will arrive
// in the other batch.
return;
}
stream.emit('metadata', response.metadata);
});
var status_batch = {};
status_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true;
call.startBatch(status_batch, function(err, response) {
if (err) {
throw err;
}
stream.emit('status', response.status);
if (response.status.code !== grpc.status.OK) {
var error = new Error(response.status.details);
@ -390,6 +397,12 @@ function makeServerStreamRequestFunction(method, serialize, deserialize) {
error.metadata = response.status.metadata;
stream.emit('error', error);
return;
} else {
if (err) {
// Got a batch error, but OK status. Something went wrong
stream.emit('error', err);
return;
}
}
});
});
@ -438,16 +451,15 @@ function makeBidiStreamRequestFunction(method, serialize, deserialize) {
start_batch[grpc.opType.RECV_INITIAL_METADATA] = true;
call.startBatch(start_batch, function(err, response) {
if (err) {
throw err;
// The call has stopped for some reason. A non-OK status will arrive
// in the other batch.
return;
}
stream.emit('metadata', response.metadata);
});
var status_batch = {};
status_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true;
call.startBatch(status_batch, function(err, response) {
if (err) {
throw err;
}
stream.emit('status', response.status);
if (response.status.code !== grpc.status.OK) {
var error = new Error(response.status.details);
@ -455,6 +467,12 @@ function makeBidiStreamRequestFunction(method, serialize, deserialize) {
error.metadata = response.status.metadata;
stream.emit('error', error);
return;
} else {
if (err) {
// Got a batch error, but OK status. Something went wrong
stream.emit('error', err);
return;
}
}
});
});

@ -22,7 +22,7 @@ If you don't want to create the symbolic link, you can alternatively copy the bi
Finally, run _protoc_ with the following flags to generate the client library for your `.proto` files:
```sh
protoc --objc_out=. --objcrpc_out=. *.proto
protoc --objc_out=. --objcgrpc_out=. *.proto
```
This will generate a pair of `.pbobjc.h`/`.pbobjc.m` files for each `.proto` file, with the messages and enums defined in them. And a pair of `.pbrpc.h`/`.pbrpc.m` files for each `.proto` file with services defined. The latter contains the code to make remote calls to the specified API.

@ -60,7 +60,7 @@ int main(int argc, char **argv) {
args[1] = "--bind";
gpr_join_host_port(&args[2], "::", port);
args[3] = "--no-secure";
svr = gpr_subprocess_create(4, args);
svr = gpr_subprocess_create(4, (const char**)args);
gpr_free(args[0]);
gpr_free(args[2]);
@ -71,7 +71,7 @@ int main(int argc, char **argv) {
args[3] = "--scenario=ping-pong-request";
args[4] = "--no-secure";
args[5] = 0;
cli = gpr_subprocess_create(6, args);
cli = gpr_subprocess_create(6, (const char**)args);
gpr_free(args[0]);
gpr_free(args[2]);

@ -0,0 +1,165 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <thread>
#include "test/core/util/port.h"
#include "test/core/util/test_config.h"
#include "test/cpp/util/echo_duplicate.grpc.pb.h"
#include "test/cpp/util/echo.grpc.pb.h"
#include "src/cpp/server/thread_pool.h"
#include <grpc++/channel_arguments.h>
#include <grpc++/channel_interface.h>
#include <grpc++/client_context.h>
#include <grpc++/create_channel.h>
#include <grpc++/credentials.h>
#include <grpc++/server.h>
#include <grpc++/server_builder.h>
#include <grpc++/server_context.h>
#include <grpc++/server_credentials.h>
#include <grpc++/status.h>
#include <grpc++/stream.h>
#include <grpc++/time.h>
#include <gtest/gtest.h>
#include <grpc/grpc.h>
#include <grpc/support/thd.h>
#include <grpc/support/time.h>
#include "test/cpp/util/subprocess.h"
using grpc::cpp::test::util::EchoRequest;
using grpc::cpp::test::util::EchoResponse;
using std::chrono::system_clock;
static std::string g_root;
namespace grpc {
namespace testing {
namespace {
class CrashTest : public ::testing::Test {
protected:
CrashTest() {}
std::unique_ptr<grpc::cpp::test::util::TestService::Stub>
CreateServerAndStub() {
auto port = grpc_pick_unused_port_or_die();
std::ostringstream addr_stream;
addr_stream << "localhost:" << port;
auto addr = addr_stream.str();
server_.reset(new SubProcess({
g_root + "/client_crash_test_server",
"--address=" + addr,
}));
GPR_ASSERT(server_);
return grpc::cpp::test::util::TestService::NewStub(
CreateChannel(addr, InsecureCredentials(), ChannelArguments()));
}
void KillServer() {
server_.reset();
// give some time for the TCP connection to drop
gpr_sleep_until(gpr_time_add(gpr_now(), gpr_time_from_seconds(1)));
}
private:
std::unique_ptr<SubProcess> server_;
};
TEST_F(CrashTest, KillAfterWrite) {
auto stub = CreateServerAndStub();
EchoRequest request;
EchoResponse response;
ClientContext context;
auto stream = stub->BidiStream(&context);
request.set_message("Hello");
EXPECT_TRUE(stream->Write(request));
EXPECT_TRUE(stream->Read(&response));
EXPECT_EQ(response.message(), request.message());
request.set_message("I'm going to kill you");
EXPECT_TRUE(stream->Write(request));
KillServer();
EXPECT_FALSE(stream->Read(&response));
EXPECT_FALSE(stream->Finish().IsOk());
}
TEST_F(CrashTest, KillBeforeWrite) {
auto stub = CreateServerAndStub();
EchoRequest request;
EchoResponse response;
ClientContext context;
auto stream = stub->BidiStream(&context);
request.set_message("Hello");
EXPECT_TRUE(stream->Write(request));
EXPECT_TRUE(stream->Read(&response));
EXPECT_EQ(response.message(), request.message());
KillServer();
request.set_message("You should be dead");
EXPECT_FALSE(stream->Write(request));
EXPECT_FALSE(stream->Read(&response));
EXPECT_FALSE(stream->Finish().IsOk());
}
} // namespace
} // namespace testing
} // namespace grpc
int main(int argc, char** argv) {
std::string me = argv[0];
auto lslash = me.rfind('/');
if (lslash != std::string::npos) {
g_root = me.substr(0, lslash);
} else {
g_root = ".";
}
grpc_test_init(argc, argv);
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

@ -0,0 +1,94 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <iostream>
#include <memory>
#include <string>
#include <gflags/gflags.h>
#include <grpc++/server.h>
#include <grpc++/server_builder.h>
#include <grpc++/server_context.h>
#include <grpc++/server_credentials.h>
#include <grpc++/status.h>
#include "test/cpp/util/echo.grpc.pb.h"
DEFINE_string(address, "", "Address to bind to");
using grpc::cpp::test::util::EchoRequest;
using grpc::cpp::test::util::EchoResponse;
// In some distros, gflags is in the namespace google, and in some others,
// in gflags. This hack is enabling us to find both.
namespace google {}
namespace gflags {}
using namespace google;
using namespace gflags;
namespace grpc {
namespace testing {
class ServiceImpl GRPC_FINAL : public ::grpc::cpp::test::util::TestService::Service {
Status BidiStream(ServerContext* context,
ServerReaderWriter<EchoResponse, EchoRequest>* stream)
GRPC_OVERRIDE {
EchoRequest request;
EchoResponse response;
while (stream->Read(&request)) {
gpr_log(GPR_INFO, "recv msg %s", request.message().c_str());
response.set_message(request.message());
stream->Write(response);
}
return Status::OK;
}
};
void RunServer() {
ServiceImpl service;
ServerBuilder builder;
builder.AddListeningPort(FLAGS_address, grpc::InsecureServerCredentials());
builder.RegisterService(&service);
std::unique_ptr<Server> server(builder.BuildAndStart());
std::cout << "Server listening on " << FLAGS_address << std::endl;
server->Wait();
}
}
}
int main(int argc, char** argv) {
ParseCommandLineFlags(&argc, &argv, true);
grpc::testing::RunServer();
return 0;
}

@ -96,14 +96,16 @@ class TestServiceImpl : public ::grpc::cpp::test::util::TestService::Service {
signal_client_ = true;
}
while (!context->IsCancelled()) {
std::this_thread::sleep_for(std::chrono::microseconds(
request->param().client_cancel_after_us()));
gpr_sleep_until(gpr_time_add(
gpr_now(),
gpr_time_from_micros(request->param().client_cancel_after_us())));
}
return Status::Cancelled;
} else if (request->has_param() &&
request->param().server_cancel_after_us()) {
std::this_thread::sleep_for(
std::chrono::microseconds(request->param().server_cancel_after_us()));
gpr_sleep_until(gpr_time_add(
gpr_now(),
gpr_time_from_micros(request->param().server_cancel_after_us())));
return Status::Cancelled;
} else {
EXPECT_FALSE(context->IsCancelled());
@ -469,7 +471,7 @@ TEST_F(End2endTest, BadCredentials) {
}
void CancelRpc(ClientContext* context, int delay_us, TestServiceImpl* service) {
std::this_thread::sleep_for(std::chrono::microseconds(delay_us));
gpr_sleep_until(gpr_time_add(gpr_now(), gpr_time_from_micros(delay_us)));
while (!service->signal_client()) {
}
context->TryCancel();

@ -0,0 +1,166 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <thread>
#include "test/core/util/port.h"
#include "test/core/util/test_config.h"
#include "test/cpp/util/echo_duplicate.grpc.pb.h"
#include "test/cpp/util/echo.grpc.pb.h"
#include "src/cpp/server/thread_pool.h"
#include <grpc++/channel_arguments.h>
#include <grpc++/channel_interface.h>
#include <grpc++/client_context.h>
#include <grpc++/create_channel.h>
#include <grpc++/credentials.h>
#include <grpc++/server.h>
#include <grpc++/server_builder.h>
#include <grpc++/server_context.h>
#include <grpc++/server_credentials.h>
#include <grpc++/status.h>
#include <grpc++/stream.h>
#include <grpc++/time.h>
#include <gtest/gtest.h>
#include <grpc/grpc.h>
#include <grpc/support/thd.h>
#include <grpc/support/time.h>
#include "test/cpp/util/subprocess.h"
using grpc::cpp::test::util::EchoRequest;
using grpc::cpp::test::util::EchoResponse;
using std::chrono::system_clock;
static std::string g_root;
namespace grpc {
namespace testing {
namespace {
class ServiceImpl GRPC_FINAL : public ::grpc::cpp::test::util::TestService::Service {
Status BidiStream(ServerContext* context,
ServerReaderWriter<EchoResponse, EchoRequest>* stream)
GRPC_OVERRIDE {
EchoRequest request;
EchoResponse response;
while (stream->Read(&request)) {
gpr_log(GPR_INFO, "recv msg %s", request.message().c_str());
response.set_message(request.message());
stream->Write(response);
gpr_sleep_until(gpr_time_add(gpr_now(), gpr_time_from_seconds(1)));
}
return Status::OK;
}
Status ResponseStream(ServerContext* context, const EchoRequest* request,
ServerWriter<EchoResponse>* writer) GRPC_OVERRIDE {
EchoResponse response;
for (int i = 0;; i++) {
std::ostringstream msg;
msg << "Hello " << i;
response.set_message(msg.str());
if (!writer->Write(response)) break;
gpr_sleep_until(gpr_time_add(gpr_now(), gpr_time_from_seconds(1)));
}
return Status::OK;
}
};
class CrashTest : public ::testing::Test {
protected:
CrashTest() {}
std::unique_ptr<Server>
CreateServerAndClient(const std::string& mode) {
auto port = grpc_pick_unused_port_or_die();
std::ostringstream addr_stream;
addr_stream << "localhost:" << port;
auto addr = addr_stream.str();
client_.reset(new SubProcess({
g_root + "/server_crash_test_client",
"--address=" + addr,
"--mode=" + mode
}));
GPR_ASSERT(client_);
ServerBuilder builder;
builder.AddListeningPort(addr, grpc::InsecureServerCredentials());
builder.RegisterService(&service_);
return builder.BuildAndStart();
}
void KillClient() {
client_.reset();
}
private:
std::unique_ptr<SubProcess> client_;
ServiceImpl service_;
};
TEST_F(CrashTest, ResponseStream) {
auto server = CreateServerAndClient("response");
gpr_sleep_until(gpr_time_add(gpr_now(), gpr_time_from_seconds(5)));
KillClient();
server->Shutdown();
}
TEST_F(CrashTest, BidiStream) {
auto server = CreateServerAndClient("bidi");
gpr_sleep_until(gpr_time_add(gpr_now(), gpr_time_from_seconds(5)));
KillClient();
server->Shutdown();
}
} // namespace
} // namespace testing
} // namespace grpc
int main(int argc, char** argv) {
std::string me = argv[0];
auto lslash = me.rfind('/');
if (lslash != std::string::npos) {
g_root = me.substr(0, lslash);
} else {
g_root = ".";
}
grpc_test_init(argc, argv);
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

@ -0,0 +1,93 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <iostream>
#include <memory>
#include <sstream>
#include <string>
#include <gflags/gflags.h>
#include <grpc++/channel_arguments.h>
#include <grpc++/channel_interface.h>
#include <grpc++/client_context.h>
#include <grpc++/create_channel.h>
#include <grpc++/credentials.h>
#include <grpc++/status.h>
#include "test/cpp/util/echo.grpc.pb.h"
DEFINE_string(address, "", "Address to connect to");
DEFINE_string(mode, "", "Test mode to use");
using grpc::cpp::test::util::EchoRequest;
using grpc::cpp::test::util::EchoResponse;
// In some distros, gflags is in the namespace google, and in some others,
// in gflags. This hack is enabling us to find both.
namespace google {}
namespace gflags {}
using namespace google;
using namespace gflags;
int main(int argc, char** argv) {
ParseCommandLineFlags(&argc, &argv, true);
auto stub = grpc::cpp::test::util::TestService::NewStub(
grpc::CreateChannel(FLAGS_address, grpc::InsecureCredentials(), grpc::ChannelArguments()));
EchoRequest request;
EchoResponse response;
grpc::ClientContext context;
if (FLAGS_mode == "bidi") {
auto stream = stub->BidiStream(&context);
for (int i = 0;; i++) {
std::ostringstream msg;
msg << "Hello " << i;
request.set_message(msg.str());
GPR_ASSERT(stream->Write(request));
GPR_ASSERT(stream->Read(&response));
GPR_ASSERT(response.message() == request.message());
}
} else if (FLAGS_mode == "response") {
EchoRequest request;
request.set_message("Hello");
auto stream = stub->ResponseStream(&context, request);
for (;;) {
GPR_ASSERT(stream->Read(&response));
}
} else {
gpr_log(GPR_ERROR, "invalid test mode '%s'", FLAGS_mode.c_str());
return 1;
}
return 0;
}

@ -94,14 +94,16 @@ class TestServiceImpl : public ::grpc::cpp::test::util::TestService::Service {
signal_client_ = true;
}
while (!context->IsCancelled()) {
std::this_thread::sleep_for(std::chrono::microseconds(
request->param().client_cancel_after_us()));
gpr_sleep_until(gpr_time_add(
gpr_now(),
gpr_time_from_micros(request->param().client_cancel_after_us())));
}
return Status::Cancelled;
} else if (request->has_param() &&
request->param().server_cancel_after_us()) {
std::this_thread::sleep_for(
std::chrono::microseconds(request->param().server_cancel_after_us()));
gpr_sleep_until(gpr_time_add(
gpr_now(),
gpr_time_from_micros(request->param().server_cancel_after_us())));
return Status::Cancelled;
} else {
EXPECT_FALSE(context->IsCancelled());

@ -113,24 +113,26 @@ class Client {
: done_(false),
new_(nullptr),
impl_([this, idx, client]() {
for (;;) {
// run the loop body
bool thread_still_ok = client->ThreadFunc(&histogram_, idx);
// lock, see if we're done
std::lock_guard<std::mutex> g(mu_);
if (!thread_still_ok) {
gpr_log(GPR_ERROR, "Finishing client thread due to RPC error");
done_ = true;
}
if (done_) {return;}
// check if we're marking, swap out the histogram if so
if (new_) {
new_->Swap(&histogram_);
new_ = nullptr;
cv_.notify_one();
}
for (;;) {
// run the loop body
bool thread_still_ok = client->ThreadFunc(&histogram_, idx);
// lock, see if we're done
std::lock_guard<std::mutex> g(mu_);
if (!thread_still_ok) {
gpr_log(GPR_ERROR, "Finishing client thread due to RPC error");
done_ = true;
}
}) {}
if (done_) {
return;
}
// check if we're marking, swap out the histogram if so
if (new_) {
new_->Swap(&histogram_);
new_ = nullptr;
cv_.notify_one();
}
}
}) {}
~Thread() {
{
@ -168,10 +170,9 @@ class Client {
std::unique_ptr<Timer> timer_;
};
std::unique_ptr<Client>
CreateSynchronousUnaryClient(const ClientConfig& args);
std::unique_ptr<Client>
CreateSynchronousStreamingClient(const ClientConfig& args);
std::unique_ptr<Client> CreateSynchronousUnaryClient(const ClientConfig& args);
std::unique_ptr<Client> CreateSynchronousStreamingClient(
const ClientConfig& args);
std::unique_ptr<Client> CreateAsyncUnaryClient(const ClientConfig& args);
std::unique_ptr<Client> CreateAsyncStreamingClient(const ClientConfig& args);

@ -128,16 +128,16 @@ class ClientRpcContextUnaryImpl : public ClientRpcContext {
class AsyncClient : public Client {
public:
explicit AsyncClient(const ClientConfig& config,
std::function<void(CompletionQueue*, TestService::Stub*,
const SimpleRequest&)> setup_ctx) :
Client(config) {
std::function<void(CompletionQueue*, TestService::Stub*,
const SimpleRequest&)> setup_ctx)
: Client(config) {
for (int i = 0; i < config.async_client_threads(); i++) {
cli_cqs_.emplace_back(new CompletionQueue);
}
int t = 0;
for (int i = 0; i < config.outstanding_rpcs_per_channel(); i++) {
for (auto channel = channels_.begin(); channel != channels_.end();
channel++) {
channel++) {
auto* cq = cli_cqs_[t].get();
t = (t + 1) % cli_cqs_.size();
setup_ctx(cq, channel->get_stub(), request_);
@ -155,16 +155,19 @@ class AsyncClient : public Client {
}
}
bool ThreadFunc(Histogram* histogram, size_t thread_idx)
GRPC_OVERRIDE GRPC_FINAL {
bool ThreadFunc(Histogram* histogram,
size_t thread_idx) GRPC_OVERRIDE GRPC_FINAL {
void* got_tag;
bool ok;
switch (cli_cqs_[thread_idx]->AsyncNext(&got_tag, &ok,
std::chrono::system_clock::now() +
std::chrono::seconds(1))) {
case CompletionQueue::SHUTDOWN: return false;
case CompletionQueue::TIMEOUT: return true;
case CompletionQueue::GOT_EVENT: break;
switch (cli_cqs_[thread_idx]->AsyncNext(
&got_tag, &ok,
std::chrono::system_clock::now() + std::chrono::seconds(1))) {
case CompletionQueue::SHUTDOWN:
return false;
case CompletionQueue::TIMEOUT:
return true;
case CompletionQueue::GOT_EVENT:
break;
}
ClientRpcContext* ctx = ClientRpcContext::detag(got_tag);
@ -177,18 +180,20 @@ class AsyncClient : public Client {
return true;
}
private:
std::vector<std::unique_ptr<CompletionQueue>> cli_cqs_;
};
class AsyncUnaryClient GRPC_FINAL : public AsyncClient {
public:
explicit AsyncUnaryClient(const ClientConfig& config) :
AsyncClient(config, SetupCtx) {
explicit AsyncUnaryClient(const ClientConfig& config)
: AsyncClient(config, SetupCtx) {
StartThreads(config.async_client_threads());
}
~AsyncUnaryClient() GRPC_OVERRIDE { EndThreads(); }
private:
private:
static void SetupCtx(CompletionQueue* cq, TestService::Stub* stub,
const SimpleRequest& req) {
auto check_done = [](grpc::Status s, SimpleResponse* response) {};
@ -205,12 +210,11 @@ template <class RequestType, class ResponseType>
class ClientRpcContextStreamingImpl : public ClientRpcContext {
public:
ClientRpcContextStreamingImpl(
TestService::Stub *stub, const RequestType &req,
std::function<
std::unique_ptr<grpc::ClientAsyncReaderWriter<
RequestType,ResponseType>>(
TestService::Stub *, grpc::ClientContext *, void *)> start_req,
std::function<void(grpc::Status, ResponseType *)> on_done)
TestService::Stub* stub, const RequestType& req,
std::function<std::unique_ptr<
grpc::ClientAsyncReaderWriter<RequestType, ResponseType>>(
TestService::Stub*, grpc::ClientContext*, void*)> start_req,
std::function<void(grpc::Status, ResponseType*)> on_done)
: context_(),
stub_(stub),
req_(req),
@ -221,7 +225,7 @@ class ClientRpcContextStreamingImpl : public ClientRpcContext {
start_(Timer::Now()),
stream_(start_req_(stub_, &context_, ClientRpcContext::tag(this))) {}
~ClientRpcContextStreamingImpl() GRPC_OVERRIDE {}
bool RunNextState(bool ok, Histogram *hist) GRPC_OVERRIDE {
bool RunNextState(bool ok, Histogram* hist) GRPC_OVERRIDE {
return (this->*next_state_)(ok, hist);
}
void StartNewClone() GRPC_OVERRIDE {
@ -229,59 +233,58 @@ class ClientRpcContextStreamingImpl : public ClientRpcContext {
}
private:
bool ReqSent(bool ok, Histogram *) {
return StartWrite(ok);
}
bool ReqSent(bool ok, Histogram*) { return StartWrite(ok); }
bool StartWrite(bool ok) {
if (!ok) {
return(false);
return (false);
}
start_ = Timer::Now();
next_state_ = &ClientRpcContextStreamingImpl::WriteDone;
stream_->Write(req_, ClientRpcContext::tag(this));
return true;
}
bool WriteDone(bool ok, Histogram *) {
bool WriteDone(bool ok, Histogram*) {
if (!ok) {
return(false);
return (false);
}
next_state_ = &ClientRpcContextStreamingImpl::ReadDone;
stream_->Read(&response_, ClientRpcContext::tag(this));
return true;
}
bool ReadDone(bool ok, Histogram *hist) {
bool ReadDone(bool ok, Histogram* hist) {
hist->Add((Timer::Now() - start_) * 1e9);
return StartWrite(ok);
}
grpc::ClientContext context_;
TestService::Stub *stub_;
TestService::Stub* stub_;
RequestType req_;
ResponseType response_;
bool (ClientRpcContextStreamingImpl::*next_state_)(bool, Histogram *);
std::function<void(grpc::Status, ResponseType *)> callback_;
std::function<std::unique_ptr<grpc::ClientAsyncReaderWriter<
RequestType,ResponseType>>(
TestService::Stub *, grpc::ClientContext *, void *)> start_req_;
bool (ClientRpcContextStreamingImpl::*next_state_)(bool, Histogram*);
std::function<void(grpc::Status, ResponseType*)> callback_;
std::function<
std::unique_ptr<grpc::ClientAsyncReaderWriter<RequestType, ResponseType>>(
TestService::Stub*, grpc::ClientContext*, void*)> start_req_;
grpc::Status status_;
double start_;
std::unique_ptr<grpc::ClientAsyncReaderWriter<RequestType,ResponseType>>
stream_;
std::unique_ptr<grpc::ClientAsyncReaderWriter<RequestType, ResponseType>>
stream_;
};
class AsyncStreamingClient GRPC_FINAL : public AsyncClient {
public:
explicit AsyncStreamingClient(const ClientConfig &config) :
AsyncClient(config, SetupCtx) {
explicit AsyncStreamingClient(const ClientConfig& config)
: AsyncClient(config, SetupCtx) {
StartThreads(config.async_client_threads());
}
~AsyncStreamingClient() GRPC_OVERRIDE { EndThreads(); }
private:
private:
static void SetupCtx(CompletionQueue* cq, TestService::Stub* stub,
const SimpleRequest& req) {
const SimpleRequest& req) {
auto check_done = [](grpc::Status s, SimpleResponse* response) {};
auto start_req = [cq](TestService::Stub *stub, grpc::ClientContext *ctx,
void *tag) {
auto start_req = [cq](TestService::Stub* stub, grpc::ClientContext* ctx,
void* tag) {
auto stream = stub->AsyncStreamingCall(ctx, cq, tag);
return stream;
};

@ -99,7 +99,9 @@ class SynchronousUnaryClient GRPC_FINAL : public SynchronousClient {
class SynchronousStreamingClient GRPC_FINAL : public SynchronousClient {
public:
SynchronousStreamingClient(const ClientConfig& config)
: SynchronousClient(config), context_(num_threads_), stream_(num_threads_) {
: SynchronousClient(config),
context_(num_threads_),
stream_(num_threads_) {
for (size_t thread_idx = 0; thread_idx < num_threads_; thread_idx++) {
auto* stub = channels_[thread_idx % channels_.size()].get_stub();
stream_[thread_idx] = stub->StreamingCall(&context_[thread_idx]);
@ -110,8 +112,8 @@ class SynchronousStreamingClient GRPC_FINAL : public SynchronousClient {
EndThreads();
for (auto stream = stream_.begin(); stream != stream_.end(); stream++) {
if (*stream) {
(*stream)->WritesDone();
EXPECT_TRUE((*stream)->Finish().IsOk());
(*stream)->WritesDone();
EXPECT_TRUE((*stream)->Finish().IsOk());
}
}
}
@ -119,7 +121,7 @@ class SynchronousStreamingClient GRPC_FINAL : public SynchronousClient {
bool ThreadFunc(Histogram* histogram, size_t thread_idx) GRPC_OVERRIDE {
double start = Timer::Now();
if (stream_[thread_idx]->Write(request_) &&
stream_[thread_idx]->Read(&responses_[thread_idx])) {
stream_[thread_idx]->Read(&responses_[thread_idx])) {
histogram->Add((Timer::Now() - start) * 1e9);
return true;
}
@ -128,8 +130,8 @@ class SynchronousStreamingClient GRPC_FINAL : public SynchronousClient {
private:
std::vector<grpc::ClientContext> context_;
std::vector<std::unique_ptr<grpc::ClientReaderWriter<
SimpleRequest, SimpleResponse>>> stream_;
std::vector<std::unique_ptr<
grpc::ClientReaderWriter<SimpleRequest, SimpleResponse>>> stream_;
};
std::unique_ptr<Client> CreateSynchronousUnaryClient(

@ -105,7 +105,7 @@ std::unique_ptr<ScenarioResult> RunScenario(
if (!called_init) {
char args_buf[100];
strcpy(args_buf, "some-benchmark");
char *args[] = {args_buf};
char* args[] = {args_buf};
grpc_test_init(1, args);
called_init = true;
}
@ -211,7 +211,8 @@ std::unique_ptr<ScenarioResult> RunScenario(
// Wait some time
gpr_log(GPR_INFO, "Running");
gpr_sleep_until(gpr_time_add(start, gpr_time_from_seconds(benchmark_seconds)));
gpr_sleep_until(
gpr_time_add(start, gpr_time_from_seconds(benchmark_seconds)));
// Finish a run
std::unique_ptr<ScenarioResult> result(new ScenarioResult);

@ -104,8 +104,8 @@ static void QpsDriver() {
// client will deadlock on a timer.
GPR_ASSERT(!(server_type == grpc::testing::SYNCHRONOUS_SERVER &&
rpc_type == grpc::testing::STREAMING &&
FLAGS_server_threads < FLAGS_client_channels *
FLAGS_outstanding_rpcs_per_channel));
FLAGS_server_threads <
FLAGS_client_channels * FLAGS_outstanding_rpcs_per_channel));
const auto result = RunScenario(
client_config, FLAGS_num_clients, server_config, FLAGS_num_servers,

@ -64,17 +64,19 @@ namespace testing {
std::unique_ptr<Client> CreateClient(const ClientConfig& config) {
switch (config.client_type()) {
case ClientType::SYNCHRONOUS_CLIENT:
return (config.rpc_type() == RpcType::UNARY) ?
CreateSynchronousUnaryClient(config) :
CreateSynchronousStreamingClient(config);
return (config.rpc_type() == RpcType::UNARY)
? CreateSynchronousUnaryClient(config)
: CreateSynchronousStreamingClient(config);
case ClientType::ASYNC_CLIENT:
return (config.rpc_type() == RpcType::UNARY) ?
CreateAsyncUnaryClient(config) : CreateAsyncStreamingClient(config);
return (config.rpc_type() == RpcType::UNARY)
? CreateAsyncUnaryClient(config)
: CreateAsyncStreamingClient(config);
}
abort();
}
std::unique_ptr<Server> CreateServer(const ServerConfig& config, int server_port) {
std::unique_ptr<Server> CreateServer(const ServerConfig& config,
int server_port) {
switch (config.server_type()) {
case ServerType::SYNCHRONOUS_SERVER:
return CreateSynchronousServer(config, server_port);
@ -86,7 +88,8 @@ std::unique_ptr<Server> CreateServer(const ServerConfig& config, int server_port
class WorkerImpl GRPC_FINAL : public Worker::Service {
public:
explicit WorkerImpl(int server_port) : server_port_(server_port), acquired_(false) {}
explicit WorkerImpl(int server_port)
: server_port_(server_port), acquired_(false) {}
Status RunTest(ServerContext* ctx,
ServerReaderWriter<ClientStatus, ClientArgs>* stream)
@ -97,7 +100,7 @@ class WorkerImpl GRPC_FINAL : public Worker::Service {
}
grpc_profiler_start("qps_client.prof");
Status ret = RunTestBody(ctx,stream);
Status ret = RunTestBody(ctx, stream);
grpc_profiler_stop();
return ret;
}
@ -111,7 +114,7 @@ class WorkerImpl GRPC_FINAL : public Worker::Service {
}
grpc_profiler_start("qps_server.prof");
Status ret = RunServerBody(ctx,stream);
Status ret = RunServerBody(ctx, stream);
grpc_profiler_stop();
return ret;
}
@ -226,8 +229,7 @@ QpsWorker::QpsWorker(int driver_port, int server_port) {
server_ = std::move(builder.BuildAndStart());
}
QpsWorker::~QpsWorker() {
}
QpsWorker::~QpsWorker() {}
} // namespace testing
} // namespace grpc

@ -64,7 +64,7 @@ namespace testing {
class AsyncQpsServerTest : public Server {
public:
AsyncQpsServerTest(const ServerConfig &config, int port) : shutdown_(false) {
char* server_address = NULL;
char *server_address = NULL;
gpr_join_host_port(&server_address, "::", port);
ServerBuilder builder;
@ -95,9 +95,9 @@ class AsyncQpsServerTest : public Server {
threads_.push_back(std::thread([=]() {
// Wait until work is available or we are shutting down
bool ok;
void* got_tag;
void *got_tag;
while (srv_cq_->Next(&got_tag, &ok)) {
ServerRpcContext* ctx = detag(got_tag);
ServerRpcContext *ctx = detag(got_tag);
// The tag is a pointer to an RPC context to invoke
if (ctx->RunNextState(ok) == false) {
// this RPC context is done, so refresh it
@ -133,23 +133,23 @@ class AsyncQpsServerTest : public Server {
ServerRpcContext() {}
virtual ~ServerRpcContext(){};
virtual bool RunNextState(bool) = 0; // next state, return false if done
virtual void Reset() = 0; // start this back at a clean state
virtual void Reset() = 0; // start this back at a clean state
};
static void* tag(ServerRpcContext* func) {
return reinterpret_cast<void*>(func);
static void *tag(ServerRpcContext *func) {
return reinterpret_cast<void *>(func);
}
static ServerRpcContext* detag(void* tag) {
return reinterpret_cast<ServerRpcContext*>(tag);
static ServerRpcContext *detag(void *tag) {
return reinterpret_cast<ServerRpcContext *>(tag);
}
template <class RequestType, class ResponseType>
class ServerRpcContextUnaryImpl GRPC_FINAL : public ServerRpcContext {
public:
ServerRpcContextUnaryImpl(
std::function<void(ServerContext*, RequestType*,
grpc::ServerAsyncResponseWriter<ResponseType>*,
void*)> request_method,
std::function<grpc::Status(const RequestType*, ResponseType*)>
std::function<void(ServerContext *, RequestType *,
grpc::ServerAsyncResponseWriter<ResponseType> *,
void *)> request_method,
std::function<grpc::Status(const RequestType *, ResponseType *)>
invoke_method)
: next_state_(&ServerRpcContextUnaryImpl::invoker),
request_method_(request_method),
@ -159,7 +159,9 @@ class AsyncQpsServerTest : public Server {
AsyncQpsServerTest::tag(this));
}
~ServerRpcContextUnaryImpl() GRPC_OVERRIDE {}
bool RunNextState(bool ok) GRPC_OVERRIDE {return (this->*next_state_)(ok);}
bool RunNextState(bool ok) GRPC_OVERRIDE {
return (this->*next_state_)(ok);
}
void Reset() GRPC_OVERRIDE {
srv_ctx_ = ServerContext();
req_ = RequestType();
@ -192,10 +194,10 @@ class AsyncQpsServerTest : public Server {
ServerContext srv_ctx_;
RequestType req_;
bool (ServerRpcContextUnaryImpl::*next_state_)(bool);
std::function<void(ServerContext*, RequestType*,
grpc::ServerAsyncResponseWriter<ResponseType>*, void*)>
std::function<void(ServerContext *, RequestType *,
grpc::ServerAsyncResponseWriter<ResponseType> *, void *)>
request_method_;
std::function<grpc::Status(const RequestType*, ResponseType*)>
std::function<grpc::Status(const RequestType *, ResponseType *)>
invoke_method_;
grpc::ServerAsyncResponseWriter<ResponseType> response_writer_;
};
@ -204,9 +206,9 @@ class AsyncQpsServerTest : public Server {
class ServerRpcContextStreamingImpl GRPC_FINAL : public ServerRpcContext {
public:
ServerRpcContextStreamingImpl(
std::function<void(ServerContext *,
grpc::ServerAsyncReaderWriter<ResponseType,
RequestType> *, void *)> request_method,
std::function<void(ServerContext *, grpc::ServerAsyncReaderWriter<
ResponseType, RequestType> *,
void *)> request_method,
std::function<grpc::Status(const RequestType *, ResponseType *)>
invoke_method)
: next_state_(&ServerRpcContextStreamingImpl::request_done),
@ -215,14 +217,15 @@ class AsyncQpsServerTest : public Server {
stream_(&srv_ctx_) {
request_method_(&srv_ctx_, &stream_, AsyncQpsServerTest::tag(this));
}
~ServerRpcContextStreamingImpl() GRPC_OVERRIDE {
~ServerRpcContextStreamingImpl() GRPC_OVERRIDE {}
bool RunNextState(bool ok) GRPC_OVERRIDE {
return (this->*next_state_)(ok);
}
bool RunNextState(bool ok) GRPC_OVERRIDE {return (this->*next_state_)(ok);}
void Reset() GRPC_OVERRIDE {
srv_ctx_ = ServerContext();
req_ = RequestType();
stream_ = grpc::ServerAsyncReaderWriter<ResponseType,
RequestType>(&srv_ctx_);
stream_ =
grpc::ServerAsyncReaderWriter<ResponseType, RequestType>(&srv_ctx_);
// Then request the method
next_state_ = &ServerRpcContextStreamingImpl::request_done;
@ -241,47 +244,47 @@ class AsyncQpsServerTest : public Server {
bool read_done(bool ok) {
if (ok) {
// invoke the method
ResponseType response;
// Call the RPC processing function
grpc::Status status = invoke_method_(&req_, &response);
// initiate the write
stream_.Write(response, AsyncQpsServerTest::tag(this));
next_state_ = &ServerRpcContextStreamingImpl::write_done;
} else { // client has sent writes done
// finish the stream
stream_.Finish(Status::OK, AsyncQpsServerTest::tag(this));
next_state_ = &ServerRpcContextStreamingImpl::finish_done;
// invoke the method
ResponseType response;
// Call the RPC processing function
grpc::Status status = invoke_method_(&req_, &response);
// initiate the write
stream_.Write(response, AsyncQpsServerTest::tag(this));
next_state_ = &ServerRpcContextStreamingImpl::write_done;
} else { // client has sent writes done
// finish the stream
stream_.Finish(Status::OK, AsyncQpsServerTest::tag(this));
next_state_ = &ServerRpcContextStreamingImpl::finish_done;
}
return true;
}
bool write_done(bool ok) {
// now go back and get another streaming read!
if (ok) {
stream_.Read(&req_, AsyncQpsServerTest::tag(this));
next_state_ = &ServerRpcContextStreamingImpl::read_done;
}
else {
stream_.Finish(Status::OK, AsyncQpsServerTest::tag(this));
next_state_ = &ServerRpcContextStreamingImpl::finish_done;
stream_.Read(&req_, AsyncQpsServerTest::tag(this));
next_state_ = &ServerRpcContextStreamingImpl::read_done;
} else {
stream_.Finish(Status::OK, AsyncQpsServerTest::tag(this));
next_state_ = &ServerRpcContextStreamingImpl::finish_done;
}
return true;
}
bool finish_done(bool ok) {return false; /* reset the context */ }
bool finish_done(bool ok) { return false; /* reset the context */ }
ServerContext srv_ctx_;
RequestType req_;
bool (ServerRpcContextStreamingImpl::*next_state_)(bool);
std::function<void(ServerContext *,
grpc::ServerAsyncReaderWriter<ResponseType,
RequestType> *, void *)> request_method_;
std::function<void(
ServerContext *,
grpc::ServerAsyncReaderWriter<ResponseType, RequestType> *, void *)>
request_method_;
std::function<grpc::Status(const RequestType *, ResponseType *)>
invoke_method_;
grpc::ServerAsyncReaderWriter<ResponseType,RequestType> stream_;
grpc::ServerAsyncReaderWriter<ResponseType, RequestType> stream_;
};
static Status ProcessRPC(const SimpleRequest* request,
SimpleResponse* response) {
static Status ProcessRPC(const SimpleRequest *request,
SimpleResponse *response) {
if (request->response_size() > 0) {
if (!SetPayload(request->response_type(), request->response_size(),
response->mutable_payload())) {
@ -294,19 +297,20 @@ class AsyncQpsServerTest : public Server {
std::unique_ptr<grpc::Server> server_;
std::unique_ptr<grpc::ServerCompletionQueue> srv_cq_;
TestService::AsyncService async_service_;
std::function<void(ServerContext*, SimpleRequest*,
grpc::ServerAsyncResponseWriter<SimpleResponse>*, void*)>
std::function<void(ServerContext *, SimpleRequest *,
grpc::ServerAsyncResponseWriter<SimpleResponse> *, void *)>
request_unary_;
std::function<void(ServerContext*, grpc::ServerAsyncReaderWriter<
SimpleResponse,SimpleRequest>*, void*)>
std::function<void(
ServerContext *,
grpc::ServerAsyncReaderWriter<SimpleResponse, SimpleRequest> *, void *)>
request_streaming_;
std::forward_list<ServerRpcContext*> contexts_;
std::forward_list<ServerRpcContext *> contexts_;
std::mutex shutdown_mutex_;
bool shutdown_;
};
std::unique_ptr<Server> CreateAsyncServer(const ServerConfig& config,
std::unique_ptr<Server> CreateAsyncServer(const ServerConfig &config,
int port) {
return std::unique_ptr<Server>(new AsyncQpsServerTest(config, port));
}

@ -70,18 +70,18 @@ class TestServiceImpl GRPC_FINAL : public TestService::Service {
}
return Status::OK;
}
Status StreamingCall(ServerContext *context,
ServerReaderWriter<SimpleResponse, SimpleRequest>*
stream) GRPC_OVERRIDE {
Status StreamingCall(
ServerContext* context,
ServerReaderWriter<SimpleResponse, SimpleRequest>* stream) GRPC_OVERRIDE {
SimpleRequest request;
while (stream->Read(&request)) {
SimpleResponse response;
if (request.response_size() > 0) {
if (!Server::SetPayload(request.response_type(),
request.response_size(),
response.mutable_payload())) {
return Status(grpc::StatusCode::INTERNAL, "Error creating payload.");
}
if (!Server::SetPayload(request.response_type(),
request.response_size(),
response.mutable_payload())) {
return Status(grpc::StatusCode::INTERNAL, "Error creating payload.");
}
}
stream->Write(response);
}

@ -37,6 +37,7 @@
#include <thread>
#include <grpc/grpc.h>
#include <grpc/support/time.h>
#include <gflags/gflags.h>
#include "qps_worker.h"
@ -47,7 +48,7 @@ DEFINE_int32(server_port, 0, "Spawned server port.");
static bool got_sigint = false;
static void sigint_handler(int x) {got_sigint = true;}
static void sigint_handler(int x) { got_sigint = true; }
namespace grpc {
namespace testing {
@ -56,7 +57,7 @@ static void RunServer() {
QpsWorker worker(FLAGS_driver_port, FLAGS_server_port);
while (!got_sigint) {
std::this_thread::sleep_for(std::chrono::seconds(5));
gpr_sleep_until(gpr_time_add(gpr_now(), gpr_time_from_seconds(5)));
}
}
@ -69,6 +70,6 @@ int main(int argc, char** argv) {
signal(SIGINT, sigint_handler);
grpc::testing::RunServer();
return 0;
}

@ -0,0 +1,59 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "test/cpp/util/subprocess.h"
#include <vector>
#include <grpc/support/subprocess.h>
namespace grpc {
static gpr_subprocess *MakeProcess(std::initializer_list<std::string> args) {
std::vector<const char *> vargs;
for (auto it = args.begin(); it != args.end(); ++it) {
vargs.push_back(it->c_str());
}
return gpr_subprocess_create(vargs.size(), &vargs[0]);
}
SubProcess::SubProcess(std::initializer_list<std::string> args)
: subprocess_(MakeProcess(args)) {}
SubProcess::~SubProcess() { gpr_subprocess_destroy(subprocess_); }
int SubProcess::Join() { return gpr_subprocess_join(subprocess_); }
void SubProcess::Interrupt() { gpr_subprocess_interrupt(subprocess_); }
} // namespace grpc

@ -0,0 +1,61 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPC_TEST_CPP_UTIL_SUBPROCESS_H
#define GRPC_TEST_CPP_UTIL_SUBPROCESS_H
#include <initializer_list>
#include <string>
struct gpr_subprocess;
namespace grpc {
class SubProcess {
public:
SubProcess(std::initializer_list<std::string> args);
~SubProcess();
int Join();
void Interrupt();
private:
SubProcess(const SubProcess& other);
SubProcess& operator=(const SubProcess& other);
gpr_subprocess* const subprocess_;
};
} // namespace grpc
#endif // GRPC_TEST_CPP_UTIL_SUBPROCESS_H

@ -44,10 +44,13 @@ ENV PATH $PATH:$ANDROID_HOME/platform-tools
ENV HOME /root
# Update sdk for android 5.1 (API level 22)
RUN echo y | android update sdk --all --filter platform-tools,build-tools-22.0.1,sys-img-armeabi-v7a-android-22,android-22,extra-android-m2repository,extra-google-m2repository --no-ui --force
RUN echo y | android update sdk --all --filter platform-tools,build-tools-22.0.1,sys-img-armeabi-v7a-addon-google_apis-google-22,sys-img-armeabi-v7a-addon-google_apis-google-21,sys-img-armeabi-v7a-android-19,addon-google_apis-google-22,addon-google_apis-google-21,addon-google_apis-google-19,extra-android-m2repository,extra-google-m2repository --no-ui --force
# Create an AVD with API level 22
RUN echo no | android create avd --force -n avd-api-22 -t android-22
RUN echo no | android create avd --force -n avd-google-api-22 -t "Google Inc.:Google APIs:22" --abi google_apis/armeabi-v7a
RUN echo no | android create avd --force -n avd-google-api-21 -t "Google Inc.:Google APIs:21" --abi google_apis/armeabi-v7a
RUN echo no | android create avd --force -n avd-google-api-19 -t "Google Inc.:Google APIs:19" --abi default/armeabi-v7a
# Pull gRPC Java and trigger download of needed Maven and Gradle artifacts.
RUN git clone --depth 1 https://github.com/grpc/grpc-java.git /var/local/git/grpc-java && \

@ -35,5 +35,6 @@ cd $(dirname $0)/../..
root=`pwd`
export LD_LIBRARY_PATH=$root/libs/$CONFIG
export DYLD_LIBRARY_PATH=$root/libs/$CONFIG
source python2.7_virtual_environment/bin/activate
python2.7 -B $*

@ -632,6 +632,15 @@
"posix"
]
},
{
"flaky": false,
"language": "c++",
"name": "client_crash_test",
"platforms": [
"windows",
"posix"
]
},
{
"flaky": false,
"language": "c++",
@ -686,6 +695,15 @@
"posix"
]
},
{
"flaky": false,
"language": "c++",
"name": "server_crash_test",
"platforms": [
"windows",
"posix"
]
},
{
"flaky": false,
"language": "c++",

Loading…
Cancel
Save