Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ jobs:
repository: wolfssl/wolfssl
path: wolfssl

- name: Build and test refactor
run: cd test-refactor/posix && make clean && make -j WOLFSSL_DIR=../wolfssl && make run

# Build and test standard build
- name: Build and test
run: cd test && make clean && make -j WOLFSSL_DIR=../wolfssl && make run
Expand Down
134 changes: 134 additions & 0 deletions test-refactor/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# test-refactor

Prototype of the refactored wolfHSM test infrastructure.

## Key differences from test/

- **Runner** (`wh_test_runner.h/c`): generic suite executor.
Each suite is a name + NULL-terminated test array, run
either via `whTestRunner_Run` (suite owns its setup/cleanup)
or `whTestRunner_RunWithCtx` (caller provides the live
context). Group functions use the latter.
- **App-owned init**: the port's main() brings up the server
and client once at startup (mirroring real firmware boot)
and hands the live contexts to the group functions. Suites
no longer stand up their own fixtures.
- **Port helpers** (`wh_test_helpers_server_<port>.h/c`,
`wh_test_helpers_client_<port>.h/c`): per-port files that
stand in for what a real target does at boot -- configure
flash, init NVM/crypto, wire up a transport, bring up the
server or client context.
- **Groups** (`wh_test_groups.h/c`): three portable entry
points (Misc/Server/Client) that main invokes. Each runs
its gated suites and calls the caller-implemented reset
hook between them.
- **Transport shim**: in single-process mode, a Recv wrapper
pumps the server on `NOTREADY` so blocking client APIs work
without manual `HandleRequestMessage` calls or separate
threads. Lives in the client-side port helper.
- **Platform split**: platform-specific code is isolated in
`wh_test_helpers_server_<port>.c`,
`wh_test_helpers_client_<port>.c`, and
`wh_test_main_<port>.c`. Test modules and groups are
identical on all platforms.

## Suites implemented so far

| Suite | Group | Description |
|-------|-------|-------------|
| Flash RamSim | misc | Write-lock, erase, program, verify, blank-check |
| NVM Flash | misc | Flash unit ops, NVM add/overwrite/destroy/reclaim |
| Cert | server | Server-side cert add/verify/chain/erase |
| ClientServer | client-server | Echo round-trip, server info query |
| ThreadSafe Stress | client-server | Phased multi-thread contention (unchanged internals) |

## Remaining tests to port

| Suite | Group | Description |
|-------|-------|-------------|
| Comm | client-server | Transport layer (mem, TCP, SHM) |
| Crypto | client-server | AES, RSA, ECC, CMAC, curve25519, ed25519, etc. |
| Crypto Affinity | client-server | Device ID operation routing |
| SHE | client-server | Secure Hardware Extension key load, crypto, secure boot |
| Keywrap | client-server | Key wrap/unwrap operations |
| Log | misc | Logging frontend, ringbuf, POSIX file backends |
| Lock | misc | Lock primitives with POSIX backend |
| DMA | misc | DMA address translation and allow-list |
| Server Img Mgr | server | Image manager verify/install/erase |
| Timeout | client-server | POSIX timeout enforcement |
| wolfCrypt Test | client-server | wolfCrypt test suite via wolfHSM transport |
| MultiClient | client-server | 2 CS pairs, shared NVM, global/local key isolation |

## Platforms requiring update

Each platform with test infrastructure needs its own
`wh_test_helpers_server_<port>.c`,
`wh_test_helpers_client_<port>.c`, and
`wh_test_main_<port>.c` (see "Porting" below).

| Platform | Vendor | Test files |
|----------|--------|------------|
| POSIX | wolfSSL | `test-refactor/posix/` (done) |
| Bernina | STMicro | `bernina-server/src/bh_test.c` |
| SR6 | STMicro | (no test files found) |
| TC3xx | Infineon | `port/client/wolfhsm_tests.c`, `port/server/ccb_tests.c` |
| RH850 F1KM | Renesas | `rh850_test2_1/`, `rh850_test2_2/` |
| PIC32CZ | Microchip | `czhsm-client/tests/`, `czhsm-server/` |
| TDA4VH | TI | (no test files found) |
| New Eagle | Customer | (no test files found) |

## File layout

```
Portable (ships in wolfHSM):
wh_test_runner.h/c - suite runner
wh_test_groups.h/c - Misc/Server/Client entry points
server/wh_test_*.c/h - server-only test modules
client-server/wh_test_*.c/h - client-server test modules
misc/wh_test_*.c/h - standalone test modules

Platform-specific (one directory per platform, e.g. posix/):
<port>/wh_test_helpers_misc_<port>.h/c - misc fixtures
<port>/wh_test_helpers_server_<port>.h/c - server bringup
<port>/wh_test_helpers_client_<port>.h/c - client bringup
<port>/wh_test_main_<port>.c - init, group
dispatch, reset
hooks
<port>/Makefile - build rules
```

## Porting to other platforms

1. Implement the init helpers for the side(s) the target
needs. These stand in for what your firmware's normal
boot flow already does -- if it's simpler to call your
existing init code directly from main, that works too:
- `whTestHelperPosix_Server_Init/Cleanup` (reference):
bring up flash/NVM/crypto/transport/server.
- `whTestHelperPosix_Client_Init/Cleanup` (reference):
bring up client comm + handshake. On single-process
targets, wrap the client Recv to pump the in-process
server on `NOTREADY`.
2. Provide a `main()` that:
- Calls `whTestGroup_Misc()` for standalone tests.
- Brings up the server/client contexts once.
- Calls `whTestGroup_Server(&server)` and/or
`whTestGroup_Client(&client)` with the live handles.
- Tears the contexts down.
- Implements `whTestGroup_ResetServer` and/or
`whTestGroup_ResetClient` -- called between suites to
scrub persistent state.
3. Add the portable `.c` files and your port files to your
build system.

See `wh_test_main_posix.c` and the two `*_posix.c` helpers as
a reference implementation.

## Build and run (POSIX)

```
cd posix
make run
make run DEBUG=1
make run THREADSAFE=1 # enables stress test gate
```
129 changes: 129 additions & 0 deletions test-refactor/client-server/wh_test_clientserver.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/*
* Copyright (C) 2026 wolfSSL Inc.
*
* This file is part of wolfHSM.
*
* wolfHSM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfHSM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with wolfHSM. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* test-refactor/wh_test_clientserver.c
*
* Basic client-server test suite. Exercises echo and
* server info queries using the CS helper for setup.
* All tests use blocking client APIs -- the transport
* shim handles server dispatch automatically.
*/

#include <stdio.h>
#include <string.h>

#include "wolfhsm/wh_settings.h"
#include "wolfhsm/wh_error.h"
#include "wolfhsm/wh_client.h"
#include "wolfhsm/wh_message_comm.h"

#include "wh_test_common.h"
#include "wh_test_runner.h"
#include "wh_test_clientserver.h"

#define REPEAT_COUNT 10


/*
* Echo a message to the server and verify the response
* matches. Repeats several times with different payloads.
*/
static int test_echo(void* ctx)
{
whClientContext* client = (whClientContext*)ctx;
char send_buf[WOLFHSM_CFG_COMM_DATA_LEN];
char recv_buf[WOLFHSM_CFG_COMM_DATA_LEN];
uint16_t send_len = 0;
uint16_t recv_len = 0;
int i;

for (i = 0; i < REPEAT_COUNT; i++) {
send_len = snprintf(send_buf, sizeof(send_buf),
"Echo test %d", i);

recv_len = 0;
memset(recv_buf, 0, sizeof(recv_buf));

WH_TEST_RETURN_ON_FAIL(
wh_Client_Echo(client,
send_len, send_buf,
&recv_len, recv_buf));

WH_TEST_ASSERT_RETURN(recv_len == send_len);
WH_TEST_ASSERT_RETURN(
memcmp(recv_buf, send_buf, recv_len) == 0);
}

return 0;
}


/*
* Query server info and verify the response contains
* valid data.
*/
static int test_server_info(void* ctx)
{
whClientContext* client = (whClientContext*)ctx;
uint8_t version[WH_INFO_VERSION_LEN + 1] = {0};
uint8_t build[WH_INFO_VERSION_LEN + 1] = {0};
uint32_t comm_data_len = 0;
uint32_t nvm_object_count = 0;
uint32_t keycache_count = 0;
uint32_t keycache_bufsize = 0;
uint32_t keycache_bigcount = 0;
uint32_t keycache_bigbufsz = 0;
uint32_t customcb_count = 0;
uint32_t dmaaddr_count = 0;
uint32_t debug_state = 0;
uint32_t boot_state = 0;
uint32_t lifecycle_state = 0;
uint32_t nvm_state = 0;

WH_TEST_RETURN_ON_FAIL(
wh_Client_CommInfo(client,
version, build,
&comm_data_len,
&nvm_object_count,
&keycache_count,
&keycache_bufsize,
&keycache_bigcount,
&keycache_bigbufsz,
&customcb_count,
&dmaaddr_count,
&debug_state,
&boot_state,
&lifecycle_state,
&nvm_state));

/* Comm data length must be nonzero */
WH_TEST_ASSERT_RETURN(comm_data_len > 0);

return 0;
}


static whTestFn _tests[] = {
test_echo,
test_server_info,
NULL
};

whTestSuite whTestSuite_ClientServer =
WH_TEST_SUITE("ClientServer", _tests);
32 changes: 32 additions & 0 deletions test-refactor/client-server/wh_test_clientserver.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright (C) 2026 wolfSSL Inc.
*
* This file is part of wolfHSM.
*
* wolfHSM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfHSM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with wolfHSM. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* test-refactor/wh_test_clientserver.h
*
* Basic client-server test suite (echo, info).
*/

#ifndef WH_TEST_CLIENTSERVER_REFACTOR_H_
#define WH_TEST_CLIENTSERVER_REFACTOR_H_

#include "wh_test_runner.h"

extern whTestSuite whTestSuite_ClientServer;

#endif /* WH_TEST_CLIENTSERVER_REFACTOR_H_ */
57 changes: 57 additions & 0 deletions test-refactor/client-server/wh_test_stress.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright (C) 2026 wolfSSL Inc.
*
* This file is part of wolfHSM.
*
* wolfHSM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfHSM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with wolfHSM. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* test-refactor/wh_test_stress.c
*
* Thread-safety stress test suite. Thin wrapper around the
* existing whTest_ThreadSafeStress() -- no changes to the
* stress test internals, just runner integration.
*/

#include "wolfhsm/wh_settings.h"

#if defined(WOLFHSM_CFG_THREADSAFE) \
&& defined(WOLFHSM_CFG_TEST_POSIX) \
&& defined(WOLFHSM_CFG_GLOBAL_KEYS) \
&& defined(WOLFHSM_CFG_ENABLE_CLIENT) \
&& defined(WOLFHSM_CFG_ENABLE_SERVER) \
&& !defined(WOLFHSM_CFG_NO_CRYPTO)

#include "wh_test_posix_threadsafe_stress.h"
#include "wh_test_stress.h"

static int test_stress(void* ctx)
{
(void)ctx;
return whTest_ThreadSafeStress();
}

static whTestFn _tests[] = {
test_stress,
NULL
};

whTestSuite whTestSuite_Stress = {
.name = "ThreadSafe Stress",
.tests = _tests,
.setup = NULL,
.cleanup = NULL,
};

#endif
Loading
Loading