tests: port remaining C unit tests to the C++ test harness

Convert acl, acl_literal, aead2022, base64, buffer, cache (legacy
reference), crypto, ipset, ipset_reference, json, netutils, ppbloom,
process, ref, ssurl and utils tests to test_helpers.hpp. ctest names are
unchanged; every assertion is kept. Build the ported sources with the
strict C++ warning set.
This commit is contained in:
Max Lv
2026-10-15 01:33:51 +08:00
parent d168986dc6
commit 678a891ef9
18 changed files with 1274 additions and 1169 deletions
+120 -66
View File
@@ -1,85 +1,139 @@
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// SPDX-License-Identifier: GPL-3.0-or-later
// Child process management (src/process.cpp): spawn failure, argument and
// environment passing, and exit detection. The test binary re-executes itself
// as the child via --child / --exit.
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include "ss_process.h"
#include "test_helpers.hpp"
#ifdef _WIN32
#include <windows.h>
static void pause_tick(void) { Sleep(10); }
#else
#include <time.h>
static void pause_tick(void) { struct timespec delay = {0, 10000000}; nanosleep(&delay, NULL); }
#endif
extern "C" {
int verbose = 0;
}
int
main(int argc, char **argv)
namespace {
void pause_tick()
{
if (argc > 1 && strcmp(argv[1], "--child") == 0) {
assert(argc == 5);
FILE *file = fopen(argv[2], "w");
assert(file != NULL);
assert(strcmp(argv[3], "spaces and \"quotes\" with \\") == 0);
assert(strcmp(argv[4], "") == 0);
assert(strcmp(getenv("SS_PROCESS_TEST"), "child value") == 0);
fputs("ready\n", file);
fclose(file);
for (unsigned i = 0; i < 1000; i++) pause_tick();
return 0;
}
if (argc > 1 && strcmp(argv[1], "--exit") == 0) return 17;
#ifdef _WIN32
Sleep(10);
#else
timespec delay = { 0, 10000000 };
nanosleep(&delay, nullptr);
#endif
}
struct ss_process *process = ss_process_new("ss-no-such-program-ef91ac");
ss_process_arg(process, "ss-no-such-program-ef91ac");
int started = ss_process_start(process, 0);
assert(started == -1 || started == 0);
/* POSIX permits exec failure to be reported by child exit (notably under
* Valgrind's spawn wrapper), rather than synchronously by posix_spawnp. */
if (started == 0) {
for (unsigned i = 0; i < 500 && ss_process_running(process); i++) pause_tick();
assert(!ss_process_running(process));
}
ss_process_free(process);
const char *const k_tricky_arg = "spaces and \"quotes\" with \\";
char path[4096];
assert(snprintf(path, sizeof(path), "%s.child-output", argv[0]) < (int)sizeof(path));
remove(path);
process = ss_process_new(argv[0]);
ss_process_arg(process, argv[0]);
ss_process_arg(process, "--child");
ss_process_arg(process, path);
ss_process_arg(process, "spaces and \"quotes\" with \\");
ss_process_arg(process, "");
ss_process_env(process, "SS_PROCESS_TEST", "child value");
const char *before = getenv("SS_PROCESS_TEST");
char *saved = before == NULL ? NULL : strdup(before);
assert(ss_process_start(process, 0) == 0);
bool ready = false;
for (unsigned i = 0; i < 500; i++) {
FILE *file = fopen(path, "r");
if (file != NULL) {
char line[16];
ready = fgets(line, sizeof(line), file) != NULL && strcmp(line, "ready\n") == 0;
fclose(file);
}
if (ready) break;
int run_child(int argc, char **argv)
{
SS_CHECK(argc == 5);
FILE *file = std::fopen(argv[2], "w");
SS_CHECK(file != nullptr);
SS_CHECK(std::strcmp(argv[3], k_tricky_arg) == 0);
SS_CHECK(std::strcmp(argv[4], "") == 0);
const char *env = std::getenv("SS_PROCESS_TEST");
SS_CHECK(env != nullptr && std::strcmp(env, "child value") == 0);
std::fputs("ready\n", file);
std::fclose(file);
for (unsigned i = 0; i < 1000; i++) {
pause_tick();
}
assert(ready);
assert(ss_process_running(process));
const char *after = getenv("SS_PROCESS_TEST");
assert(saved == NULL ? after == NULL : after != NULL && strcmp(after, saved) == 0);
free(saved);
return 0;
}
void test_missing_program()
{
ss_process *process = ss_process_new("ss-no-such-program-ef91ac");
ss_process_arg(process, "ss-no-such-program-ef91ac");
const int started = ss_process_start(process, 0);
SS_CHECK(started == -1 || started == 0);
// POSIX permits exec failure to be reported by child exit (notably under
// Valgrind's spawn wrapper), rather than synchronously by posix_spawnp.
if (started == 0) {
for (unsigned i = 0; i < 500 && ss_process_running(process); i++) {
pause_tick();
}
SS_CHECK(!ss_process_running(process));
}
ss_process_free(process);
}
void test_args_and_environment(const char *self)
{
const std::string path = std::string(self) + ".child-output";
std::remove(path.c_str());
ss_process *process = ss_process_new(self);
ss_process_arg(process, self);
ss_process_arg(process, "--child");
ss_process_arg(process, path.c_str());
ss_process_arg(process, k_tricky_arg);
ss_process_arg(process, "");
ss_process_env(process, "SS_PROCESS_TEST", "child value");
const char *before = std::getenv("SS_PROCESS_TEST");
const std::string saved(before == nullptr ? "" : before);
const bool had_value = before != nullptr;
SS_CHECK(ss_process_start(process, 0) == 0);
bool ready = false;
for (unsigned i = 0; i < 500; i++) {
FILE *file = std::fopen(path.c_str(), "r");
if (file != nullptr) {
char line[16];
ready = std::fgets(line, sizeof(line), file) != nullptr && std::strcmp(line, "ready\n") == 0;
std::fclose(file);
}
if (ready) {
break;
}
pause_tick();
}
SS_CHECK(ready);
SS_CHECK(ss_process_running(process));
// The parent's environment is left untouched.
const char *after = std::getenv("SS_PROCESS_TEST");
SS_CHECK(had_value ? after != nullptr && saved == after : after == nullptr);
ss_process_free(process);
remove(path);
std::remove(path.c_str());
}
process = ss_process_new(argv[0]);
ss_process_arg(process, argv[0]);
void test_exit_detection(const char *self)
{
ss_process *process = ss_process_new(self);
ss_process_arg(process, self);
ss_process_arg(process, "--exit");
assert(ss_process_start(process, 0) == 0);
for (unsigned i = 0; i < 500 && ss_process_running(process); i++) pause_tick();
assert(!ss_process_running(process));
SS_CHECK(ss_process_start(process, 0) == 0);
for (unsigned i = 0; i < 500 && ss_process_running(process); i++) {
pause_tick();
}
SS_CHECK(!ss_process_running(process));
ss_process_free(process);
ss_process_free(NULL);
ss_process_free(nullptr);
}
} // namespace
int main(int argc, char **argv)
{
if (argc > 1 && std::strcmp(argv[1], "--child") == 0) {
return run_child(argc, argv);
}
if (argc > 1 && std::strcmp(argv[1], "--exit") == 0) {
return 17;
}
SS_RUN(test_missing_program);
test_args_and_environment(argv[0]);
std::printf("ok test_args_and_environment\n");
test_exit_detection(argv[0]);
std::printf("ok test_exit_detection\n");
return 0;
}