Chromium Code Reviews| Index: tests/nameservice/srpc_nameservice_test.c |
| =================================================================== |
| --- tests/nameservice/srpc_nameservice_test.c (revision 0) |
| +++ tests/nameservice/srpc_nameservice_test.c (revision 0) |
| @@ -0,0 +1,294 @@ |
| +/* |
| + * Copyright (c) 2011 The Native Client Authors. All rights reserved. |
| + * Use of this source code is governed by a BSD-style license that can be |
| + * found in the LICENSE file. |
| + */ |
| + |
| +/* |
| + * Test for simple rpc based access to name services. |
| + */ |
| + |
| +#include <assert.h> |
| +#include <stdio.h> |
| +#include <stdlib.h> |
| +#include <inttypes.h> |
| +#include <sys/fcntl.h> |
| +#include <string.h> |
| +#include <unistd.h> |
| +#include <sys/nacl_syscalls.h> |
| +#if 0 /* swap after SDK update */ |
| +#include <sys/nacl_name_service.h> |
| +#else |
| +#include "native_client/src/trusted/service_runtime/include/sys/nacl_name_service.h" |
| +#endif |
| +#include <nacl/nacl_srpc.h> |
| + |
| +#define RNG_OUTPUT_BYTES 1024 |
| + |
| +#define BYTES_PER_LINE 32 |
| +#define BYTE_SPACING 4 |
| + |
| +struct StringBuffer { |
| + size_t nbytes; |
| + size_t insert; |
| + char *buffer; |
| +}; |
| + |
| +NaClSrpcChannel ns_channel; |
| + |
| +void StringBufferCtor(struct StringBuffer *sb) { |
| + sb->nbytes = 1024; |
| + sb->insert = 0; |
| + sb->buffer = malloc(sb->nbytes); |
| + if (NULL == sb->buffer) { |
| + perror("StringBufferInit::malloc"); |
| + abort(); |
| + } |
| + sb->buffer[0] = '\0'; |
| +} |
| + |
| +void StringBufferDiscardOutput(struct StringBuffer *sb) { |
| + sb->insert = 0; |
| +} |
| + |
| +void StringBufferDtor(struct StringBuffer *sb) { |
| + sb->nbytes = 0; |
| + sb->insert = 0; |
| + free(sb->buffer); |
| + sb->buffer = NULL; |
| +} |
| + |
| +void StringBufferPrintf(struct StringBuffer *sb, |
| + char const *fmt, ...) |
| + __attribute__((format(printf, 2, 3))); |
| + |
| +void StringBufferPrintf(struct StringBuffer *sb, |
| + char const *fmt, ...) { |
| + size_t space; |
| + char *insert_pt; |
| + va_list ap; |
| + int written = 0; |
| + char *new_buffer; |
| + |
| + va_start(ap, fmt); |
| + vfprintf(stderr, fmt, ap); |
| + va_end(ap); |
| + |
| + for (;;) { |
| + space = sb->nbytes - sb->insert; |
| + insert_pt = sb->buffer + sb->insert; |
| + va_start(ap, fmt); |
| + written = vsnprintf(insert_pt, space, fmt, ap); |
| + va_end(ap); |
| + if (written < space) { |
| + sb->insert += written; |
| + break; |
| + } |
| + /* insufficient space -- grow the buffer */ |
| + new_buffer = realloc(sb->buffer, 2 * sb->nbytes); |
| + if (NULL == new_buffer) { |
| + /* give up */ |
| + fprintf(stderr, "StringBufferPrintf: no memory\n"); |
| + break; |
| + } |
| + sb->nbytes *= 2; |
| + sb->buffer = new_buffer; |
| + } |
| +} |
| + |
| +void dump_output(struct StringBuffer *sb, int d, size_t nbytes) { |
| + uint8_t *bytes; |
| + int got; |
| + int copied; |
| + int ix; |
| + |
| + bytes = malloc(nbytes); |
| + if (!bytes) { |
| + perror("dump_output"); |
| + fprintf(stderr, "No memory\n"); |
| + return; |
| + } |
| + /* read output */ |
| + for (got = 0; got < nbytes; got += copied) { |
| + copied = read(d, bytes + got, nbytes - got); |
| + if (-1 == copied) { |
| + perror("dump_output:read"); |
| + fprintf(stderr, "read failure\n"); |
| + break; |
| + } |
| + printf("read(%d, ..., %zd) -> %d\n", d, nbytes - got, copied); |
| + } |
| + /* hex dump it */ |
| + for (ix = 0; ix < got; ++ix) { |
| + if (0 == (ix & (BYTES_PER_LINE-1))) { |
| + StringBufferPrintf(sb, "\n%04x:", ix); |
| + } else if (0 == (ix & (BYTE_SPACING-1))) { |
| + StringBufferPrintf(sb, " "); |
| + } |
| + StringBufferPrintf(sb, "%02x", bytes[ix]); |
| + } |
| + StringBufferPrintf(sb, "\n"); |
| + |
| + free(bytes); |
| +} |
| + |
| +int EnumerateNames(struct StringBuffer *sb, NaClSrpcChannel *nschan) { |
| + char buffer[1024]; |
| + uint32_t nbytes = sizeof buffer; |
| + char *p; |
| + size_t name_len; |
| + |
| + if (NACL_SRPC_RESULT_OK != NaClSrpcInvokeBySignature(nschan, |
| + NACL_NAME_SERVICE_LIST, |
| + &nbytes, buffer)) { |
| + return 0; |
| + } |
| + StringBufferPrintf(sb, "nbytes = %zu\n", (size_t) nbytes); |
| + if (nbytes == sizeof buffer) { |
| + fprintf(stderr, "Insufficent space for namespace enumeration\n"); |
| + return 0; |
| + } |
| + for (p = buffer; p - buffer < nbytes; p += name_len) { |
| + name_len = strlen(p) + 1; |
| + StringBufferPrintf(sb, "%s\n", p); |
| + } |
| + return 1; |
| +} |
| + |
| +/* |
| + * Return name service output |
| + */ |
| +void NameServiceDump(NaClSrpcRpc *rpc, |
| + NaClSrpcArg **in_args, |
| + NaClSrpcArg **out_args, |
| + NaClSrpcClosure *done) { |
| + struct StringBuffer sb; |
| + StringBufferCtor(&sb); |
| + |
| + if (EnumerateNames(&sb, &ns_channel)) { |
| + out_args[0]->arrays.str = strdup(sb.buffer); |
| + rpc->result = NACL_SRPC_RESULT_OK; |
| + } else { |
| + rpc->result = NACL_SRPC_RESULT_APP_ERROR; |
| + } |
| + done->Run(done); |
| + StringBufferDtor(&sb); |
| +} |
| + |
| +/* |
| + * Dump RNG output into a string. |
| + */ |
| +void RngDump(NaClSrpcRpc *rpc, |
| + NaClSrpcArg **in_args, |
| + NaClSrpcArg **out_args, |
| + NaClSrpcClosure *done) { |
| + struct StringBuffer sb; |
| + int status; |
| + int rng; |
| + |
| + StringBufferCtor(&sb); |
| + if (NACL_SRPC_RESULT_OK != |
| + NaClSrpcInvokeBySignature(&ns_channel, NACL_NAME_SERVICE_LOOKUP, |
| + "SecureRandom", O_RDONLY, &status, &rng)) { |
| + } |
|
noelallen_use_chromium
2011/06/14 22:08:14
Missing an error case? If you are assuming status
bsy
2011/06/15 00:21:03
oops. missing body to the error check. i've chan
|
| + printf("rpc status %d\n", status); |
| + assert(NACL_NAME_SERVICE_SUCCESS == status); |
| + printf("rng descriptor %d\n", rng); |
| + |
| + dump_output(&sb, rng, RNG_OUTPUT_BYTES); |
| + out_args[0]->arrays.str = strdup(sb.buffer); |
| + rpc->result = NACL_SRPC_RESULT_OK; |
| + done->Run(done); |
| + close(rng); |
| + StringBufferDtor(&sb); |
| +} |
| + |
| +void ManifestTest(NaClSrpcRpc *rpc, |
| + NaClSrpcArg **in_args, |
| + NaClSrpcArg **out_args, |
| + NaClSrpcClosure *done) { |
| + struct StringBuffer sb; |
| + int status; |
| + int manifest; |
| + char buffer[1024]; |
| + uint32_t nbytes = sizeof buffer; |
| + |
| + /* just get the descriptor for now */ |
| + StringBufferCtor(&sb); |
| + if (NACL_SRPC_RESULT_OK != |
| + NaClSrpcInvokeBySignature(&ns_channel, NACL_NAME_SERVICE_LOOKUP, |
| + "manifest_proxy", O_RDWR, &status, &manifest)) { |
| + fprintf(stderr, "nameservice lookup failed, status %d\n", status); |
| + } |
| + StringBufferPrintf(&sb, "Got manifest descriptor %d\n", manifest); |
| + if (-1 != manifest) { |
| + /* connect to manifest name server */ |
| + int manifest_conn; |
| + struct NaClSrpcChannel manifest_channel; |
| + |
| + manifest_conn = imc_connect(manifest); |
| + StringBufferPrintf(&sb, "got manifest connection %d\n", manifest_conn); |
| + if (-1 == manifest_conn) { |
| + StringBufferPrintf(&sb, "could not connect\n"); |
| + goto done; |
| + } |
| + close(manifest); |
| + if (!NaClSrpcClientCtor(&manifest_channel, manifest_conn)) { |
| + StringBufferPrintf(&sb, "could not build srpc client\n"); |
| + goto done; |
| + } |
| + if (NACL_SRPC_RESULT_OK != |
| + NaClSrpcInvokeBySignature(&manifest_channel, NACL_NAME_SERVICE_LIST, |
| + &nbytes, buffer)) { |
| + StringBufferPrintf(&sb, "manifest list failed\n"); |
| + goto done; |
| + } |
| + StringBufferDiscardOutput(&sb); |
| + StringBufferPrintf(&sb, "ManifestList: %.*s\n", (int) nbytes, buffer); |
| + } |
| + done: |
| + out_args[0]->arrays.str = strdup(sb.buffer); |
| + rpc->result = NACL_SRPC_RESULT_OK; |
| + done->Run(done); |
| + StringBufferDtor(&sb); |
| +} |
| + |
| +const struct NaClSrpcHandlerDesc srpc_methods[] = { |
| + /* Export the methods as taking no arguments and returning a string. */ |
| + { "namedump::s", NameServiceDump }, |
| + { "rngdump::s", RngDump }, |
| + { "manifest_test::s", ManifestTest }, |
| + { NULL, NULL }, |
| +}; |
| + |
| +int main() { |
| + int ns; |
| + int connected_socket; |
| + |
| + if (!NaClSrpcModuleInit()) { |
| + return 1; |
| + } |
| + /* |
| + * BEGIN HACK -- test code should move to RPC handlers |
| + */ |
| + ns = -1; |
| + nacl_nameservice(&ns); |
| + printf("ns = %d\n", ns); |
| + assert(-1 != ns); |
| + |
| + connected_socket = imc_connect(ns); |
| + assert(-1 != connected_socket); |
| + if (!NaClSrpcClientCtor(&ns_channel, connected_socket)) { |
| + fprintf(stderr, "Srpc client channel ctor failed\n"); |
| + return 1; |
| + } |
| + printf("NaClSrpcClientCtor succeeded\n"); |
| + /* |
| + * END HACK |
| + */ |
| + if (!NaClSrpcAcceptClientConnection(srpc_methods)) { |
| + return 1; |
| + } |
|
noelallen_use_chromium
2011/06/14 22:08:14
Why not close NS?
bsy
2011/06/15 00:21:03
Done.
|
| + NaClSrpcModuleFini(); |
| + return 0; |
| +} |
| Property changes on: tests/nameservice/srpc_nameservice_test.c |
| ___________________________________________________________________ |
| Added: svn:eol-style |
| + LF |