summaryrefslogtreecommitdiff
path: root/p11-kit/tests
diff options
context:
space:
mode:
authorStef Walter <stefw@gnome.org>2013-02-20 12:24:03 +0100
committerStef Walter <stef@thewalter.net>2014-07-08 08:57:31 +0200
commit7ec80ff13adb167705a999b7d082c76219adc909 (patch)
tree2c9872e6154466209e14e1b08e1fa14a548f0aae /p11-kit/tests
parent5ecfe2c8aa58a170aac2d9a9c22d7ffb3cc9442a (diff)
rpc: Implement execution of another tool to transport PKCS#11 RPC
Diffstat (limited to 'p11-kit/tests')
-rw-r--r--p11-kit/tests/Makefile.am19
-rw-r--r--p11-kit/tests/frob-server.c173
-rw-r--r--p11-kit/tests/mock-module-ep2.c56
-rw-r--r--p11-kit/tests/test-rpc.c156
-rw-r--r--p11-kit/tests/test-transport.c281
5 files changed, 662 insertions, 23 deletions
diff --git a/p11-kit/tests/Makefile.am b/p11-kit/tests/Makefile.am
index 2192fed..0672d62 100644
--- a/p11-kit/tests/Makefile.am
+++ b/p11-kit/tests/Makefile.am
@@ -29,20 +29,24 @@ CHECK_PROGS = \
test-rpc \
$(NULL)
+noinst_PROGRAMS = \
+ print-messages \
+ frob-setuid \
+ $(CHECK_PROGS)
+
if WITH_FFI
CHECK_PROGS += \
test-virtual \
test-managed \
test-log \
+ test-transport \
$(NULL)
-endif
+noinst_PROGRAMS += \
+ frob-server
-noinst_PROGRAMS = \
- print-messages \
- frob-setuid \
- $(CHECK_PROGS)
+endif
TESTS = $(CHECK_PROGS)
@@ -67,7 +71,9 @@ mock_one_la_LDFLAGS = \
-module -avoid-version -rpath /nowhere \
-no-undefined -export-symbols-regex 'C_GetFunctionList'
-mock_two_la_SOURCES = $(mock_one_la_SOURCES)
+mock_two_la_SOURCES = \
+ mock-module-ep2.c
+
mock_two_la_CFLAGS = $(mock_one_la_CFLAGS)
mock_two_la_LDFLAGS = $(mock_one_la_LDFLAGS)
mock_two_la_LIBADD = $(mock_one_la_LIBADD)
@@ -78,6 +84,7 @@ mock_three_la_LDFLAGS = $(mock_one_la_LDFLAGS)
mock_three_la_LIBADD = $(mock_one_la_LIBADD)
mock_four_la_SOURCES = $(mock_one_la_SOURCES)
+mock_four_la_CFLAGS = $(mock_one_la_CFLAGS)
mock_four_la_LDFLAGS = $(mock_one_la_LDFLAGS)
mock_four_la_LIBADD = $(mock_one_la_LIBADD)
diff --git a/p11-kit/tests/frob-server.c b/p11-kit/tests/frob-server.c
new file mode 100644
index 0000000..e0e7020
--- /dev/null
+++ b/p11-kit/tests/frob-server.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2013 Red Hat Inc.
+ *
+ * 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.
+ * * The names of contributors to this software may not 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.
+ *
+ * Author: Stef Walter <stefw@redhat.com>
+ */
+
+#include "config.h"
+
+#include "buffer.h"
+#include "compat.h"
+#include "debug.h"
+#include "p11-kit.h"
+#include "rpc.h"
+#include "virtual.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int
+main (int argc,
+ char *argv[])
+{
+ CK_FUNCTION_LIST *funcs;
+ CK_C_GetFunctionList gfl;
+ p11_rpc_status status;
+ unsigned char version;
+ p11_virtual virt;
+ p11_buffer options;
+ p11_buffer buffer;
+ dl_module_t dl;
+ size_t state;
+ int code;
+ CK_RV rv;
+
+ p11_debug_init ();
+
+ if (argc != 2) {
+ fprintf (stderr, "usage: frob-server module\n");
+ exit (2);
+ }
+
+ dl = p11_dl_open (argv[1]);
+ if (dl == NULL) {
+ fprintf (stderr, "couldn't load module: %s: %s\n",
+ argv[1], p11_dl_error ());
+ exit (1);
+ }
+
+ gfl = p11_dl_symbol (dl, "C_GetFunctionList");
+ if (!gfl) {
+ fprintf (stderr, "couldn't find C_GetFunctionList entry point in module: %s: %s\n",
+ argv[1], p11_dl_error ());
+ exit (1);
+ }
+
+ rv = gfl (&funcs);
+ if (rv != CKR_OK) {
+ fprintf (stderr, "call to C_GetFunctiontList failed in module: %s: %s\n",
+ argv[1], p11_kit_strerror (rv));
+ exit (1);
+ }
+
+ p11_virtual_init (&virt, &p11_virtual_base, funcs, NULL);
+ p11_buffer_init (&options, 0);
+ p11_buffer_init (&buffer, 0);
+
+ switch (read (0, &version, 1)) {
+ case 0:
+ status = P11_RPC_EOF;
+ break;
+ case 1:
+ if (version != 0) {
+ fprintf (stderr, "unspported version received: %d", (int)version);
+ exit (1);
+ }
+ break;
+ default:
+ fprintf (stderr, "couldn't read creds: %s", strerror (errno));
+ exit (1);
+ }
+
+ version = 0;
+ switch (write (1, &version, 1)) {
+ case 1:
+ break;
+ default:
+ fprintf (stderr, "couldn't read creds: %s", strerror (errno));
+ exit (1);
+ }
+
+ status = P11_RPC_OK;
+ while (status == P11_RPC_OK) {
+ state = 0;
+ code = 0;
+
+ do {
+ status = p11_rpc_transport_read (0, &state, &code,
+ &options, &buffer);
+ } while (status == P11_RPC_AGAIN);
+
+ switch (status) {
+ case P11_RPC_OK:
+ break;
+ case P11_RPC_EOF:
+ continue;
+ case P11_RPC_AGAIN:
+ assert_not_reached ();
+ case P11_RPC_ERROR:
+ fprintf (stderr, "failed to read rpc message: %s\n", strerror (errno));
+ exit (1);
+ }
+
+ if (!p11_rpc_server_handle (&virt.funcs, &buffer, &buffer)) {
+ fprintf (stderr, "unexpected error handling rpc message\n");
+ exit (1);
+ }
+
+ state = 0;
+ options.len = 0;
+ do {
+ status = p11_rpc_transport_write (1, &state, code,
+ &options, &buffer);
+ } while (status == P11_RPC_AGAIN);
+
+ switch (status) {
+ case P11_RPC_OK:
+ break;
+ case P11_RPC_EOF:
+ case P11_RPC_AGAIN:
+ assert_not_reached ();
+ case P11_RPC_ERROR:
+ fprintf (stderr, "failed to write rpc message: %s\n", strerror (errno));
+ exit (1);
+ }
+ }
+
+ p11_buffer_uninit (&buffer);
+ p11_buffer_uninit (&options);
+ p11_dl_close (dl);
+
+ return 0;
+}
diff --git a/p11-kit/tests/mock-module-ep2.c b/p11-kit/tests/mock-module-ep2.c
new file mode 100644
index 0000000..ee71711
--- /dev/null
+++ b/p11-kit/tests/mock-module-ep2.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2012 Stefan Walter
+ *
+ * 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.
+ * * The names of contributors to this software may not 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.
+ *
+ * Author: Stef Walter <stef@thewalter.net>
+ */
+
+#include "config.h"
+
+#define CRYPTOKI_EXPORTS 1
+#include "pkcs11.h"
+
+#include "mock.h"
+
+#include <stdio.h>
+
+#ifdef OS_WIN32
+__declspec(dllexport)
+#endif
+CK_RV
+C_GetFunctionList (CK_FUNCTION_LIST_PTR_PTR list)
+{
+ mock_module_init ();
+ mock_module.C_GetFunctionList = C_GetFunctionList;
+ if (list == NULL)
+ return CKR_ARGUMENTS_BAD;
+ *list = &mock_module;
+ return CKR_OK;
+}
diff --git a/p11-kit/tests/test-rpc.c b/p11-kit/tests/test-rpc.c
index d945efd..0ce2c55 100644
--- a/p11-kit/tests/test-rpc.c
+++ b/p11-kit/tests/test-rpc.c
@@ -47,6 +47,7 @@
#include "virtual.h"
#include <sys/types.h>
+#include <sys/wait.h>
#include <assert.h>
#include <string.h>
#include <stdio.h>
@@ -350,15 +351,17 @@ test_byte_array_static (void)
}
static p11_virtual base;
-static bool rpc_initialized = false;
+static pid_t rpc_initialized = 0;
static CK_RV
rpc_initialize (p11_rpc_client_vtable *vtable,
void *init_reserved)
{
+ pid_t pid = getpid ();
+
assert_str_eq (vtable->data, "vtable-data");
- assert_num_eq (false, rpc_initialized);
- rpc_initialized = true;
+ assert_num_cmp (pid, !=, rpc_initialized);
+ rpc_initialized = pid;
return CKR_OK;
}
@@ -367,8 +370,10 @@ static CK_RV
rpc_initialize_fails (p11_rpc_client_vtable *vtable,
void *init_reserved)
{
+ pid_t pid = getpid ();
+
assert_str_eq (vtable->data, "vtable-data");
- assert_num_eq (false, rpc_initialized);
+ assert_num_cmp (pid, !=, rpc_initialized);
return CKR_FUNCTION_FAILED;
}
@@ -376,8 +381,10 @@ static CK_RV
rpc_initialize_device_removed (p11_rpc_client_vtable *vtable,
void *init_reserved)
{
+ pid_t pid = getpid ();
+
assert_str_eq (vtable->data, "vtable-data");
- assert_num_eq (false, rpc_initialized);
+ assert_num_cmp (pid, !=, rpc_initialized);
return CKR_DEVICE_REMOVED;
}
@@ -401,21 +408,24 @@ static void
rpc_finalize (p11_rpc_client_vtable *vtable,
void *fini_reserved)
{
+ pid_t pid = getpid ();
+
assert_str_eq (vtable->data, "vtable-data");
- assert_num_eq (true, rpc_initialized);
- rpc_initialized = false;
+ assert_num_cmp (pid, ==, rpc_initialized);
+ rpc_initialized = 0;
}
static void
test_initialize (void)
{
p11_rpc_client_vtable vtable = { "vtable-data", rpc_initialize, rpc_transport, rpc_finalize };
+ pid_t pid = getpid ();
p11_virtual mixin;
bool ret;
CK_RV rv;
/* Build up our own function list */
- rpc_initialized = false;
+ rpc_initialized = 0;
p11_virtual_init (&base, &p11_virtual_base, &mock_module_no_slots, NULL);
ret = p11_rpc_client_init (&mixin, &vtable);
@@ -423,11 +433,11 @@ test_initialize (void)
rv = mixin.funcs.C_Initialize (&mixin.funcs, NULL);
assert (rv == CKR_OK);
- assert_num_eq (true, rpc_initialized);
+ assert_num_eq (pid, rpc_initialized);
rv = mixin.funcs.C_Finalize (&mixin.funcs, NULL);
assert (rv == CKR_OK);
- assert_num_eq (false, rpc_initialized);
+ assert_num_cmp (pid, !=, rpc_initialized);
p11_virtual_uninit (&mixin);
}
@@ -442,7 +452,7 @@ test_not_initialized (void)
CK_RV rv;
/* Build up our own function list */
- rpc_initialized = false;
+ rpc_initialized = 0;
p11_virtual_init (&base, &p11_virtual_base, &mock_module_no_slots, NULL);
ret = p11_rpc_client_init (&mixin, &vtable);
@@ -463,7 +473,7 @@ test_initialize_fails_on_client (void)
CK_RV rv;
/* Build up our own function list */
- rpc_initialized = false;
+ rpc_initialized = 0;
p11_virtual_init (&base, &p11_virtual_base, &mock_module_no_slots, NULL);
ret = p11_rpc_client_init (&mixin, &vtable);
@@ -471,7 +481,7 @@ test_initialize_fails_on_client (void)
rv = (mixin.funcs.C_Initialize) (&mixin.funcs, NULL);
assert (rv == CKR_FUNCTION_FAILED);
- assert_num_eq (false, rpc_initialized);
+ assert_num_eq (0, rpc_initialized);
p11_virtual_uninit (&mixin);
}
@@ -493,7 +503,7 @@ test_transport_fails (void)
CK_RV rv;
/* Build up our own function list */
- rpc_initialized = false;
+ rpc_initialized = 0;
p11_virtual_init (&base, &p11_virtual_base, &mock_module_no_slots, NULL);
ret = p11_rpc_client_init (&mixin, &vtable);
@@ -501,7 +511,7 @@ test_transport_fails (void)
rv = (mixin.funcs.C_Initialize) (&mixin.funcs, NULL);
assert (rv == CKR_FUNCTION_REJECTED);
- assert_num_eq (false, rpc_initialized);
+ assert_num_eq (0, rpc_initialized);
p11_virtual_uninit (&mixin);
}
@@ -523,7 +533,7 @@ test_initialize_fails_on_server (void)
rv = (mixin.funcs.C_Initialize) (&mixin.funcs, NULL);
assert (rv == CKR_FUNCTION_FAILED);
- assert_num_eq (false, rpc_initialized);
+ assert_num_eq (0, rpc_initialized);
p11_virtual_uninit (&mixin);
}
@@ -555,7 +565,7 @@ test_transport_bad_parse (void)
CK_RV rv;
/* Build up our own function list */
- rpc_initialized = false;
+ rpc_initialized = 0;
p11_virtual_init (&base, &p11_virtual_base, &mock_module_no_slots, NULL);
ret = p11_rpc_client_init (&mixin, &vtable);
@@ -886,6 +896,116 @@ test_get_slot_list_no_device (void)
teardown_mock_module (rpc_module);
}
+static void *
+invoke_in_thread (void *arg)
+{
+ CK_FUNCTION_LIST *rpc_module = arg;
+ CK_INFO info;
+ CK_RV rv;
+
+ rv = (rpc_module->C_GetInfo) (&info);
+ assert_num_eq (rv, CKR_OK);
+
+ assert (memcmp (info.manufacturerID, MOCK_INFO.manufacturerID,
+ sizeof (info.manufacturerID)) == 0);
+
+ return NULL;
+}
+
+static p11_mutex_t delay_mutex;
+
+static CK_RV
+delayed_C_GetInfo (CK_INFO_PTR info)
+{
+ CK_RV rv;
+
+ p11_sleep_ms (rand () % 100);
+
+ p11_mutex_lock (&delay_mutex);
+ rv = mock_C_GetInfo (info);
+ p11_mutex_unlock (&delay_mutex);
+
+ return rv;
+}
+
+static void
+test_simultaneous_functions (void)
+{
+ CK_FUNCTION_LIST real_module;
+ CK_FUNCTION_LIST *rpc_module;
+ const int num_threads = 128;
+ p11_thread_t threads[num_threads];
+ int i, ret;
+
+ p11_mutex_init (&delay_mutex);
+
+ memcpy (&real_module, &mock_module_no_slots, sizeof (CK_FUNCTION_LIST));
+ real_module.C_GetInfo = delayed_C_GetInfo;
+
+ rpc_module = setup_test_rpc_module (&test_normal_vtable,
+ &real_module, NULL);
+
+ /* Make the invoked function (above) wait */
+ p11_mutex_lock (&delay_mutex);
+
+ for (i = 0; i < num_threads; i++) {
+ ret = p11_thread_create (threads + i, invoke_in_thread, rpc_module);
+ assert_num_eq (0, ret);
+ }
+
+ /* Let the invoked functions return */
+ p11_mutex_unlock (&delay_mutex);
+
+ for (i = 0; i < num_threads; i++)
+ p11_thread_join (threads[i]);
+
+ teardown_mock_module (rpc_module);
+ p11_mutex_uninit (&delay_mutex);
+}
+
+static void
+test_fork_and_reinitialize (void)
+{
+ CK_FUNCTION_LIST *rpc_module;
+ CK_INFO info;
+ int status;
+ CK_RV rv;
+ pid_t pid;
+ int i;
+
+ rpc_module = setup_test_rpc_module (&test_normal_vtable,
+ &mock_module_no_slots, NULL);
+
+ pid = fork ();
+ assert_num_cmp (pid, >=, 0);
+
+ /* The child */
+ if (pid == 0) {
+ rv = (rpc_module->C_Initialize) (NULL);
+ assert_num_eq (CKR_OK, rv);
+
+ for (i = 0; i < 32; i++) {
+ rv = (rpc_module->C_GetInfo) (&info);
+ assert_num_eq (CKR_OK, rv);
+ }
+
+ rv = (rpc_module->C_Finalize) (NULL);
+ assert_num_eq (CKR_OK, rv);
+
+ _exit (66);
+ }
+
+ for (i = 0; i < 128; i++) {
+ rv = (rpc_module->C_GetInfo) (&info);
+ assert_num_eq (CKR_OK, rv);
+ }
+
+ assert_num_eq (waitpid (pid, &status, 0), pid);
+ assert_num_eq (WEXITSTATUS (status), 66);
+
+ teardown_mock_module (rpc_module);
+}
+
#include "test-mock.c"
int
@@ -932,6 +1052,8 @@ main (int argc,
p11_test (test_transport_bad_contents, "/rpc/transport-bad-contents");
p11_test (test_get_info_stand_in, "/rpc/get-info-stand-in");
p11_test (test_get_slot_list_no_device, "/rpc/get-slot-list-no-device");
+ p11_test (test_simultaneous_functions, "/rpc/simultaneous-functions");
+ p11_test (test_fork_and_reinitialize, "/rpc/fork-and-reinitialize");
test_mock_add_tests ("/rpc");
diff --git a/p11-kit/tests/test-transport.c b/p11-kit/tests/test-transport.c
new file mode 100644
index 0000000..32ec02a
--- /dev/null
+++ b/p11-kit/tests/test-transport.c
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 2012 Stefan Walter
+ * Copyright (c) 2012 Red Hat Inc.
+ *
+ * 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.
+ * * The names of contributors to this software may not 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.
+ *
+ * Author: Stef Walter <stef@thewalter.net>
+ */
+
+#include "config.h"
+#include "test.h"
+
+#include "library.h"
+#include "mock.h"
+#include "path.h"
+#include "private.h"
+#include "p11-kit.h"
+#include "rpc.h"
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+struct {
+ char *directory;
+ char *user_config;
+ char *user_modules;
+} test;
+
+static void
+setup_remote (void *unused)
+{
+ const char *data;
+
+ test.directory = p11_test_directory ("p11-test-config");
+ test.user_modules = p11_path_build (test.directory, "modules", NULL);
+ if (mkdir (test.user_modules, 0700) < 0)
+ assert_not_reached ();
+
+ data = "user-config: only\n";
+ test.user_config = p11_path_build (test.directory, "pkcs11.conf", NULL);
+ p11_test_file_write (NULL, test.user_config, data, strlen (data));
+
+ data = "remote: " BUILDDIR "/frob-server " BUILDDIR "/.libs/mock-two.so\n";
+ p11_test_file_write (test.user_modules, "remote.module", data, strlen (data));
+
+ p11_config_user_modules = test.user_modules;
+ p11_config_user_file = test.user_config;
+}
+
+static void
+teardown_remote (void *unused)
+{
+ p11_test_directory_delete (test.user_modules);
+ p11_test_directory_delete (test.directory);
+
+ free (test.directory);
+ free (test.user_config);
+ free (test.user_modules);
+}
+
+static CK_FUNCTION_LIST *
+setup_mock_module (CK_SESSION_HANDLE *session)
+{
+ CK_FUNCTION_LIST **modules;
+ CK_FUNCTION_LIST *module;
+ CK_RV rv;
+ int i;
+
+ setup_remote (NULL);
+
+ modules = p11_kit_modules_load (NULL, 0);
+
+ module = p11_kit_module_for_name (modules, "remote");
+ assert (module != NULL);
+
+ rv = p11_kit_module_initialize (module);
+ assert_num_eq (rv, CKR_OK);
+
+ if (session) {
+ rv = (module->C_OpenSession) (MOCK_SLOT_ONE_ID, CKF_RW_SESSION | CKF_SERIAL_SESSION,
+ NULL, NULL, session);
+ assert (rv == CKR_OK);
+ }
+
+ /* Release all the other modules */
+ for (i = 0; modules[i] != NULL; i++) {
+ if (modules[i] != module)
+ p11_kit_module_release (modules[i]);
+ }
+
+ free (modules);
+ return module;
+}
+
+static void
+teardown_mock_module (CK_FUNCTION_LIST *module)
+{
+ p11_kit_module_finalize (module);
+ teardown_remote (NULL);
+}
+
+static void
+test_basic_exec (void)
+{
+ CK_FUNCTION_LIST **modules;
+ CK_FUNCTION_LIST *module;
+ CK_RV rv;
+
+ modules = p11_kit_modules_load (NULL, 0);
+
+ module = p11_kit_module_for_name (modules, "remote");
+ assert (module != NULL);
+
+ rv = p11_kit_module_initialize (module);
+ assert_num_eq (rv, CKR_OK);
+
+ rv = p11_kit_module_finalize (module);
+ assert_num_eq (rv, CKR_OK);
+
+ p11_kit_modules_release (modules);
+}
+
+static void *
+invoke_in_thread (void *arg)
+{
+ CK_FUNCTION_LIST *rpc_module = arg;
+ CK_INFO info;
+ CK_RV rv;
+
+ rv = (rpc_module->C_GetInfo) (&info);
+ assert_num_eq (rv, CKR_OK);
+
+ assert (memcmp (info.manufacturerID, MOCK_INFO.manufacturerID,
+ sizeof (info.manufacturerID)) == 0);
+
+ return NULL;
+}
+
+static void
+test_simultaneous_functions (void)
+{
+ CK_FUNCTION_LIST **modules;
+ CK_FUNCTION_LIST *module;
+ const int num_threads = 128;
+ p11_thread_t threads[num_threads];
+ int i, ret;
+ CK_RV rv;
+
+ modules = p11_kit_modules_load (NULL, 0);
+
+ module = p11_kit_module_for_name (modules, "remote");
+ assert (module != NULL);
+
+ rv = p11_kit_module_initialize (module);
+ assert_num_eq (rv, CKR_OK);
+
+ for (i = 0; i < num_threads; i++) {
+ ret = p11_thread_create (threads + i, invoke_in_thread, module);
+ assert_num_eq (0, ret);
+ }
+
+ for (i = 0; i < num_threads; i++)
+ p11_thread_join (threads[i]);
+
+ rv = p11_kit_module_finalize (module);
+ assert_num_eq (rv, CKR_OK);
+
+ p11_kit_modules_release (modules);
+}
+
+static void
+test_fork_and_reinitialize (void)
+{
+ CK_FUNCTION_LIST **modules;
+ CK_FUNCTION_LIST *module;
+ CK_INFO info;
+ int status;
+ CK_RV rv;
+ pid_t pid;
+ int i;
+
+ modules = p11_kit_modules_load (NULL, 0);
+
+ module = p11_kit_module_for_name (modules, "remote");
+ assert (module != NULL);
+
+ rv = p11_kit_module_initialize (module);
+ assert_num_eq (rv, CKR_OK);
+
+ pid = fork ();
+ assert_num_cmp (pid, >=, 0);
+
+ /* The child */
+ if (pid == 0) {
+ rv = (module->C_Initialize) (NULL);
+ assert_num_eq (CKR_OK, rv);
+
+ for (i = 0; i < 32; i++) {
+ rv = (module->C_GetInfo) (&info);
+ assert_num_eq (CKR_OK, rv);
+ }
+
+ rv = (module->C_Finalize) (NULL);
+ assert_num_eq (CKR_OK, rv);
+
+ _exit (66);
+ }
+
+ for (i = 0; i < 128; i++) {
+ rv = (module->C_GetInfo) (&info);
+ assert_num_eq (CKR_OK, rv);
+ }
+
+ assert_num_eq (waitpid (pid, &status, 0), pid);
+ assert_num_eq (WEXITSTATUS (status), 66);
+
+ rv = p11_kit_module_finalize (module);
+ assert_num_eq (rv, CKR_OK);
+
+ p11_kit_modules_release (modules);
+}
+
+
+#include "test-mock.c"
+
+int
+main (int argc,
+ char *argv[])
+{
+ CK_MECHANISM_TYPE mechanisms[] = {
+ CKM_MOCK_CAPITALIZE,
+ CKM_MOCK_PREFIX,
+ CKM_MOCK_GENERATE,
+ CKM_MOCK_WRAP,
+ CKM_MOCK_DERIVE,
+ CKM_MOCK_COUNT,
+ 0,
+ };
+
+ p11_library_init ();
+
+ /* Override the mechanisms that the RPC mechanism will handle */
+ p11_rpc_mechanisms_override_supported = mechanisms;
+
+ p11_fixture (setup_remote, teardown_remote);
+ p11_test (test_basic_exec, "/transport/basic");
+ p11_test (test_simultaneous_functions, "/transport/simultaneous-functions");
+ p11_test (test_fork_and_reinitialize, "/transport/fork-and-reinitialize");
+
+ test_mock_add_tests ("/transport");
+
+ return p11_test_run (argc, argv);
+}