diff options
Diffstat (limited to 'test/core/echo')
-rw-r--r-- | test/core/echo/client.c | 139 | ||||
-rw-r--r-- | test/core/echo/echo_test.c | 106 | ||||
-rw-r--r-- | test/core/echo/server.c | 149 |
3 files changed, 394 insertions, 0 deletions
diff --git a/test/core/echo/client.c b/test/core/echo/client.c new file mode 100644 index 0000000000..1905863e11 --- /dev/null +++ b/test/core/echo/client.c @@ -0,0 +1,139 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include <grpc/grpc.h> + +#include <string.h> + +#include <grpc/support/log.h> +#include <grpc/support/time.h> +#include <grpc/byte_buffer.h> +#include "test/core/util/test_config.h" + +enum { WRITE_SLICE_LENGTH = 1024, TOTAL_BYTES = 102400 }; + +/* Start write the next slice, fill slice.data[0..length - 1] with first % 256, + (first + 1) % 256, ... (first + length - 1) % 256. + Produce a GRPC_WRITE_ACCEPTED event */ +static void start_write_next_slice(grpc_call *call, int first, int length) { + int i = 0; + grpc_byte_buffer *byte_buffer = NULL; + gpr_slice slice = gpr_slice_malloc(length); + for (i = 0; i < length; i++) + GPR_SLICE_START_PTR(slice)[i] = (first + i) % 256; + byte_buffer = grpc_byte_buffer_create(&slice, 1); + GPR_ASSERT(grpc_call_start_write(call, byte_buffer, (void *)1, 0) == + GRPC_CALL_OK); + gpr_slice_unref(slice); + grpc_byte_buffer_destroy(byte_buffer); +} + +int main(int argc, char **argv) { + grpc_channel *channel = NULL; + grpc_call *call = NULL; + grpc_event *ev = NULL; + grpc_byte_buffer_reader *bb_reader = NULL; + grpc_completion_queue *cq = NULL; + int bytes_written = 0; + int bytes_read = 0; + int i = 0; + int waiting_finishes; + gpr_slice read_slice; + + grpc_test_init(argc, argv); + + grpc_init(); + + cq = grpc_completion_queue_create(); + + GPR_ASSERT(argc == 2); + channel = grpc_channel_create(argv[1], NULL); + call = grpc_channel_create_call(channel, "/foo", "localhost", gpr_inf_future); + GPR_ASSERT(grpc_call_start_invoke(call, cq, (void *)1, (void *)1, (void *)1, + 0) == GRPC_CALL_OK); + ev = grpc_completion_queue_next(cq, gpr_inf_future); + GPR_ASSERT(ev->data.invoke_accepted == GRPC_OP_OK); + grpc_event_finish(ev); + + start_write_next_slice(call, bytes_written, WRITE_SLICE_LENGTH); + bytes_written += WRITE_SLICE_LENGTH; + GPR_ASSERT(grpc_call_start_read(call, (void *)1) == GRPC_CALL_OK); + waiting_finishes = 2; + while (waiting_finishes) { + ev = grpc_completion_queue_next(cq, gpr_inf_future); + switch (ev->type) { + case GRPC_WRITE_ACCEPTED: + if (bytes_written < TOTAL_BYTES) { + start_write_next_slice(call, bytes_written, WRITE_SLICE_LENGTH); + bytes_written += WRITE_SLICE_LENGTH; + } else { + GPR_ASSERT(grpc_call_writes_done(call, (void *)1) == GRPC_CALL_OK); + } + break; + case GRPC_CLIENT_METADATA_READ: + break; + case GRPC_READ: + bb_reader = grpc_byte_buffer_reader_create(ev->data.read); + while (grpc_byte_buffer_reader_next(bb_reader, &read_slice)) { + for (i = 0; i < GPR_SLICE_LENGTH(read_slice); i++) { + GPR_ASSERT(GPR_SLICE_START_PTR(read_slice)[i] == bytes_read % 256); + bytes_read++; + } + gpr_slice_unref(read_slice); + } + grpc_byte_buffer_reader_destroy(bb_reader); + if (bytes_read < TOTAL_BYTES) { + GPR_ASSERT(grpc_call_start_read(call, (void *)1) == GRPC_CALL_OK); + } + break; + case GRPC_FINISHED: + case GRPC_FINISH_ACCEPTED: + waiting_finishes--; + break; + default: + GPR_ASSERT(0 && "unexpected event"); + break; + } + grpc_event_finish(ev); + } + GPR_ASSERT(bytes_read == TOTAL_BYTES); + gpr_log(GPR_INFO, "All data have been successfully echoed"); + + grpc_call_destroy(call); + grpc_channel_destroy(channel); + grpc_completion_queue_destroy(cq); + + grpc_shutdown(); + + return 0; +} diff --git a/test/core/echo/echo_test.c b/test/core/echo/echo_test.c new file mode 100644 index 0000000000..c699f1e83e --- /dev/null +++ b/test/core/echo/echo_test.c @@ -0,0 +1,106 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#define _POSIX_SOURCE +#include <unistd.h> +#include <assert.h> +#include <stdio.h> +#include <string.h> +#include <signal.h> +#include <sys/types.h> +#include <sys/wait.h> + +#include <grpc/support/alloc.h> +#include <grpc/support/host_port.h> +#include <grpc/support/string.h> +#include "test/core/util/port.h" + +static const char *const kHosts[] = { + "127.0.0.1", "::1", "::ffff:127.0.0.1", "localhost", +}; + +int main(int argc, char **argv) { + char *me = argv[0]; + char *lslash = strrchr(me, '/'); + char root[1024]; + int port = grpc_pick_unused_port_or_die(); + char *args[3]; + int status; + pid_t svr, cli; + int i; + /* figure out where we are */ + if (lslash) { + memcpy(root, me, lslash - me); + root[lslash - me] = 0; + } else { + strcpy(root, "."); + } + /* start the server */ + svr = fork(); + if (svr == 0) { + gpr_asprintf(&args[0], "%s/echo_server", root); + gpr_join_host_port(&args[1], "::", port); + args[2] = 0; + execv(args[0], args); + + gpr_free(args[0]); + gpr_free(args[1]); + return 1; + } + /* wait a little */ + sleep(2); + /* start the clients */ + for (i = 0; i < sizeof(kHosts) / sizeof(*kHosts); i++) { + cli = fork(); + if (cli == 0) { + gpr_asprintf(&args[0], "%s/echo_client", root); + gpr_join_host_port(&args[1], kHosts[i], port); + args[2] = 0; + execv(args[0], args); + + gpr_free(args[0]); + gpr_free(args[1]); + return 1; + } + /* wait for client */ + printf("waiting for client: %s\n", kHosts[i]); + if (waitpid(cli, &status, 0) == -1) return 2; + if (!WIFEXITED(status)) return 4; + if (WEXITSTATUS(status)) return WEXITSTATUS(status); + } + /* wait for server */ + printf("checking server\n"); + if (waitpid(svr, &status, WNOHANG) != 0) return 2; + kill(svr, SIGKILL); + return 0; +} diff --git a/test/core/echo/server.c b/test/core/echo/server.c new file mode 100644 index 0000000000..77383f838e --- /dev/null +++ b/test/core/echo/server.c @@ -0,0 +1,149 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include <grpc/grpc.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#include "test/core/util/test_config.h" +#include <grpc/support/alloc.h> +#include <grpc/support/host_port.h> +#include <grpc/support/log.h> +#include <grpc/support/string.h> +#include <grpc/support/time.h> +#include "test/core/util/port.h" + +static grpc_completion_queue *cq; +static grpc_server *server; + +static const grpc_status status_ok = {GRPC_STATUS_OK, NULL}; + +typedef struct { + gpr_refcount pending_ops; + gpr_intmax bytes_read; +} call_state; + +static void request_call() { + call_state *tag = gpr_malloc(sizeof(*tag)); + gpr_ref_init(&tag->pending_ops, 2); + tag->bytes_read = 0; + grpc_server_request_call(server, tag); +} + +static void assert_read_ok(call_state *s, grpc_byte_buffer *b) { + grpc_byte_buffer_reader *bb_reader = NULL; + gpr_slice read_slice; + int i; + + bb_reader = grpc_byte_buffer_reader_create(b); + while (grpc_byte_buffer_reader_next(bb_reader, &read_slice)) { + for (i = 0; i < GPR_SLICE_LENGTH(read_slice); i++) { + GPR_ASSERT(GPR_SLICE_START_PTR(read_slice)[i] == s->bytes_read % 256); + s->bytes_read++; + } + gpr_slice_unref(read_slice); + } + grpc_byte_buffer_reader_destroy(bb_reader); +} + +int main(int argc, char **argv) { + grpc_event *ev; + char *addr; + call_state *s; + + grpc_test_init(argc, argv); + + grpc_init(); + srand(clock()); + + if (argc == 2) { + addr = gpr_strdup(argv[1]); + } else { + gpr_join_host_port(&addr, "::", grpc_pick_unused_port_or_die()); + } + gpr_log(GPR_INFO, "creating server on: %s", addr); + + cq = grpc_completion_queue_create(); + server = grpc_server_create(cq, NULL); + GPR_ASSERT(grpc_server_add_http2_port(server, addr)); + gpr_free(addr); + grpc_server_start(server); + + request_call(); + + for (;;) { + ev = grpc_completion_queue_next(cq, gpr_inf_future); + GPR_ASSERT(ev); + s = ev->tag; + switch (ev->type) { + case GRPC_SERVER_RPC_NEW: + /* initial ops are already started in request_call */ + grpc_call_accept(ev->call, cq, s, GRPC_WRITE_BUFFER_HINT); + GPR_ASSERT(grpc_call_start_read(ev->call, s) == GRPC_CALL_OK); + request_call(); + break; + case GRPC_WRITE_ACCEPTED: + GPR_ASSERT(ev->data.write_accepted == GRPC_OP_OK); + GPR_ASSERT(grpc_call_start_read(ev->call, s) == GRPC_CALL_OK); + break; + case GRPC_READ: + if (ev->data.read) { + assert_read_ok(ev->tag, ev->data.read); + GPR_ASSERT(grpc_call_start_write(ev->call, ev->data.read, s, + GRPC_WRITE_BUFFER_HINT) == + GRPC_CALL_OK); + } else { + GPR_ASSERT(grpc_call_start_write_status(ev->call, status_ok, s) == + GRPC_CALL_OK); + } + break; + case GRPC_FINISH_ACCEPTED: + case GRPC_FINISHED: + if (gpr_unref(&s->pending_ops)) { + grpc_call_destroy(ev->call); + gpr_free(s); + } + break; + default: + abort(); + } + grpc_event_finish(ev); + } + + grpc_shutdown(); + + return 0; +} |