blob: 797f06686e5aabbca95ebea2162a79b2e43d0852 [file]
/*
* Copyright (c) 2012 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.
*/
/*
* Interface test for simple rpc (SRPC). Tests passing of all supported
* parameter and return types.
*
* It really only makes sense to run this test from within either sel_universal
* or the browser, as it is intended to test marshalling and serialization
* of parameters.
*/
#include <stdio.h>
#include <string.h>
#include "native_client/src/shared/srpc/nacl_srpc.h"
/*
* When running embedded, sel_ldr instances are invoked with the -X option.
* This creates a bound socket on descriptor 3 and its address on descriptor 4.
* The SRPC system accepts connections on descriptor 3, and creates an SRPC
* channel with a listener thread for each connection.
* 4 is a convenient transferrable descriptor for the "handle" parameter type.
* TODO(sehr): this should move to an SRPC header file.
*/
static const int kSrpcSocketAddressDescriptorNumber = 4;
static const int kInvalidDescriptorNumber = -1;
/*
* First, tests for scalar argument passing and return.
*/
/*
* The test for bool inverts the input and returns it.
*/
void BoolMethod(NaClSrpcRpc *rpc,
NaClSrpcArg **in_args,
NaClSrpcArg **out_args,
NaClSrpcClosure *done) {
out_args[0]->u.bval = !in_args[0]->u.bval;
rpc->result = NACL_SRPC_RESULT_OK;
done->Run(done);
}
/*
* The test for double negates the input and returns it.
*/
void DoubleMethod(NaClSrpcRpc *rpc,
NaClSrpcArg **in_args,
NaClSrpcArg **out_args,
NaClSrpcClosure *done) {
out_args[0]->u.dval = -in_args[0]->u.dval;
rpc->result = NACL_SRPC_RESULT_OK;
done->Run(done);
}
/*
* The test for returning signalling NaNs takes no input.
*/
void NaNMethod(NaClSrpcRpc *rpc,
NaClSrpcArg **in_args,
NaClSrpcArg **out_args,
NaClSrpcClosure *done) {
union IntDouble {
double d;
int i[2];
} u;
u.i[0] = 0x4007ffff;
u.i[1] = 0xffffffff;
*((union IntDouble*) (&out_args[0]->u.dval)) = u;
rpc->result = NACL_SRPC_RESULT_OK;
done->Run(done);
}
/*
* The test for int negates the input and returns it.
*/
void IntMethod(NaClSrpcRpc *rpc,
NaClSrpcArg **in_args,
NaClSrpcArg **out_args,
NaClSrpcClosure *done) {
out_args[0]->u.ival = -in_args[0]->u.ival;
rpc->result = NACL_SRPC_RESULT_OK;
done->Run(done);
}
/*
* The test for long negates the input and returns it.
*/
void LongMethod(NaClSrpcRpc *rpc,
NaClSrpcArg **in_args,
NaClSrpcArg **out_args,
NaClSrpcClosure *done) {
out_args[0]->u.lval = -in_args[0]->u.lval;
rpc->result = NACL_SRPC_RESULT_OK;
done->Run(done);
}
/*
* The test for string returns the length of the string.
*/
void StringMethod(NaClSrpcRpc *rpc,
NaClSrpcArg **in_args,
NaClSrpcArg **out_args,
NaClSrpcClosure *done) {
out_args[0]->u.ival = strlen(in_args[0]->arrays.str);
rpc->result = NACL_SRPC_RESULT_OK;
done->Run(done);
}
/*
* Second, tests for array argument passing and return.
* All the array methods reverse their input arrays and return them.
* If the counts don't match, return an error.
*/
void CharArrayMethod(NaClSrpcRpc *rpc,
NaClSrpcArg **in_args,
NaClSrpcArg **out_args,
NaClSrpcClosure *done) {
int i, length;
if (out_args[0]->u.count != in_args[0]->u.count) {
printf("CharArrayMethod: count mismatch: in=%d out=%d\n",
(int) in_args[0]->u.count, (int) out_args[0]->u.count);
rpc->result = NACL_SRPC_RESULT_APP_ERROR;
done->Run(done);
}
length = in_args[0]->u.count;
for (i = 0; i < length; i++) {
out_args[0]->arrays.carr[length - i - 1] = in_args[0]->arrays.carr[i];
}
rpc->result = NACL_SRPC_RESULT_OK;
done->Run(done);
}
void DoubleArrayMethod(NaClSrpcRpc *rpc,
NaClSrpcArg **in_args,
NaClSrpcArg **out_args,
NaClSrpcClosure *done) {
int i, length;
if (out_args[0]->u.count != in_args[0]->u.count) {
rpc->result = NACL_SRPC_RESULT_APP_ERROR;
done->Run(done);
}
length = in_args[0]->u.count;
for (i = 0; i < length; i++) {
out_args[0]->arrays.darr[length - i - 1] = in_args[0]->arrays.darr[i];
}
rpc->result = NACL_SRPC_RESULT_OK;
done->Run(done);
}
void IntArrayMethod(NaClSrpcRpc *rpc,
NaClSrpcArg **in_args,
NaClSrpcArg **out_args,
NaClSrpcClosure *done) {
int i, length;
if (out_args[0]->u.count != in_args[0]->u.count) {
rpc->result = NACL_SRPC_RESULT_APP_ERROR;
done->Run(done);
}
length = in_args[0]->u.count;
for (i = 0; i < length; i++) {
out_args[0]->arrays.iarr[length - i - 1] = in_args[0]->arrays.iarr[i];
}
rpc->result = NACL_SRPC_RESULT_OK;
done->Run(done);
}
void LongArrayMethod(NaClSrpcRpc *rpc,
NaClSrpcArg **in_args,
NaClSrpcArg **out_args,
NaClSrpcClosure *done) {
int i, length;
if (out_args[0]->u.count != in_args[0]->u.count) {
rpc->result = NACL_SRPC_RESULT_APP_ERROR;
done->Run(done);
}
length = in_args[0]->u.count;
for (i = 0; i < length; i++) {
out_args[0]->arrays.larr[length - i - 1] = in_args[0]->arrays.larr[i];
}
rpc->result = NACL_SRPC_RESULT_OK;
done->Run(done);
}
/*
* A null RPC to test throughput and latency.
*/
void NullMethod(NaClSrpcRpc *rpc,
NaClSrpcArg **in_args,
NaClSrpcArg **out_args,
NaClSrpcClosure *done) {
rpc->result = NACL_SRPC_RESULT_OK;
done->Run(done);
}
/*
* A method to return a string.
*/
void ReturnStringMethod(NaClSrpcRpc *rpc,
NaClSrpcArg **in_args,
NaClSrpcArg **out_args,
NaClSrpcClosure *done) {
static char string[] = "Ich weiss nicht, was soll es bedeuten"
"Dass ich so traurig bin,"
"Ein Maerchen aus uralten Zeiten,"
"Das kommt mir nicht aus dem Sinn."
"Die Luft ist kuehl und es dunkelt,"
"Und ruhig fliesst der Rhein;"
"Der Gipfel des Berges funkelt,"
"Im Abendsonnenschein."
"Die schoenste Jungfrau sitzet"
"Dort oben wunderbar,"
"Ihr gold'nes Geschmeide blitzet,"
"Sie kaemmt ihr goldenes Haar,"
"Sie kaemmt es mit goldenem Kamme,"
"Und singt ein Lied dabei;"
"Das hat eine wundersame,"
"Gewalt'ge Melodei.";
out_args[0]->arrays.str = strdup(string + in_args[0]->u.ival);
rpc->result = NACL_SRPC_RESULT_OK;
done->Run(done);
}
/*
* A method to receive a handle (descriptor).
*/
void HandleMethod(NaClSrpcRpc *rpc,
NaClSrpcArg **in_args,
NaClSrpcArg **out_args,
NaClSrpcClosure *done) {
/* If we got this far, things succeeded */
rpc->result = NACL_SRPC_RESULT_OK;
done->Run(done);
}
/*
* A method to return a handle (descriptor).
*/
void ReturnHandleMethod(NaClSrpcRpc *rpc,
NaClSrpcArg **in_args,
NaClSrpcArg **out_args,
NaClSrpcClosure *done) {
out_args[0]->u.hval = kSrpcSocketAddressDescriptorNumber;
rpc->result = NACL_SRPC_RESULT_OK;
done->Run(done);
}
/*
* A method to accept an invalid handle (descriptor).
*/
void InvalidHandleMethod(NaClSrpcRpc *rpc,
NaClSrpcArg **in_args,
NaClSrpcArg **out_args,
NaClSrpcClosure *done) {
if (kInvalidDescriptorNumber == in_args[0]->u.hval) {
rpc->result = NACL_SRPC_RESULT_OK;
} else {
rpc->result = NACL_SRPC_RESULT_APP_ERROR;
}
done->Run(done);
}
/*
* A method to return an invalid handle (descriptor).
*/
void ReturnInvalidHandleMethod(NaClSrpcRpc *rpc,
NaClSrpcArg **in_args,
NaClSrpcArg **out_args,
NaClSrpcClosure *done) {
out_args[0]->u.hval = kInvalidDescriptorNumber;
rpc->result = NACL_SRPC_RESULT_OK;
done->Run(done);
}
const struct NaClSrpcHandlerDesc srpc_methods[] = {
{ "bool:b:b", BoolMethod },
{ "double:d:d", DoubleMethod },
{ "nan::d", NaNMethod },
{ "int:i:i", IntMethod },
{ "long:l:l", LongMethod },
{ "string:s:i", StringMethod },
{ "char_array:C:C", CharArrayMethod },
{ "double_array:D:D", DoubleArrayMethod },
{ "int_array:I:I", IntArrayMethod },
{ "long_array:L:L", LongArrayMethod },
{ "null_method::", NullMethod },
{ "stringret:i:s", ReturnStringMethod },
{ "handle:h:", HandleMethod },
{ "handleret::h", ReturnHandleMethod },
{ "invalid_handle:h:", InvalidHandleMethod },
{ "invalid_handle_ret::h", ReturnInvalidHandleMethod },
{ NULL, NULL },
};
int main(void) {
if (!NaClSrpcModuleInit()) {
return 1;
}
if (!NaClSrpcAcceptClientConnection(srpc_methods)) {
return 1;
}
NaClSrpcModuleFini();
return 0;
}