122 lines
3.7 KiB
C
122 lines
3.7 KiB
C
/* SPDX-License-Identifier: GPL-3.0-or-later */
|
|
#include "probe.h"
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
typedef struct fake_probe {
|
|
size_t resolve_calls;
|
|
size_t close_calls;
|
|
size_t log_calls;
|
|
int fail_open;
|
|
int fail_lookup;
|
|
int fail_close;
|
|
int saw_address_text;
|
|
} fake_probe;
|
|
|
|
static int failures;
|
|
|
|
#define CHECK(expression) \
|
|
do { \
|
|
if (!(expression)) { \
|
|
(void)fprintf(stderr, "%s:%d: check failed: %s\n", __FILE__, \
|
|
__LINE__, #expression); \
|
|
failures += 1; \
|
|
} \
|
|
} while (0)
|
|
|
|
static int fake_open(void *userdata, const char *module_name) {
|
|
fake_probe *probe = (fake_probe *)userdata;
|
|
CHECK(strcmp(module_name, "libSceGnmDriver.sprx") == 0);
|
|
return probe->fail_open != 0 ? -1 : 0;
|
|
}
|
|
|
|
static int fake_resolve(void *userdata, const char *symbol_name, int *present) {
|
|
fake_probe *probe = (fake_probe *)userdata;
|
|
|
|
probe->resolve_calls += 1u;
|
|
if (probe->fail_lookup != 0) {
|
|
return -1;
|
|
}
|
|
*present = strcmp(symbol_name, "sceGnmSubmitCommandBuffers") != 0 ? 1 : 0;
|
|
return 0;
|
|
}
|
|
|
|
static int fake_close(void *userdata) {
|
|
fake_probe *probe = (fake_probe *)userdata;
|
|
probe->close_calls += 1u;
|
|
return probe->fail_close != 0 ? -1 : 0;
|
|
}
|
|
|
|
static void fake_log(void *userdata, const char *line) {
|
|
fake_probe *probe = (fake_probe *)userdata;
|
|
probe->log_calls += 1u;
|
|
if (strstr(line, "0x") != NULL) {
|
|
probe->saw_address_text = 1;
|
|
}
|
|
}
|
|
|
|
static chimera_gfx_probe_ops make_ops(fake_probe *probe) {
|
|
chimera_gfx_probe_ops ops;
|
|
ops.userdata = probe;
|
|
ops.open_module = fake_open;
|
|
ops.resolve_symbol = fake_resolve;
|
|
ops.close_module = fake_close;
|
|
ops.log_line = fake_log;
|
|
return ops;
|
|
}
|
|
|
|
static void test_partial_success(void) {
|
|
fake_probe probe = {0};
|
|
chimera_gfx_probe_ops ops = make_ops(&probe);
|
|
chimera_gfx_probe_report report;
|
|
|
|
CHECK(chimera_gfx_ps5_probe_symbols(&ops, &report) ==
|
|
CHIMERA_GFX_STATUS_OK);
|
|
CHECK(report.symbol_count == 21u);
|
|
CHECK(report.resolved_count == 20u);
|
|
CHECK(report.module_opened == 0);
|
|
CHECK(probe.resolve_calls == report.symbol_count);
|
|
CHECK(probe.close_calls == 1u);
|
|
CHECK(probe.log_calls == report.symbol_count + 3u);
|
|
CHECK(probe.saw_address_text == 0);
|
|
}
|
|
|
|
static void test_fail_closed_paths(void) {
|
|
fake_probe probe = {0};
|
|
chimera_gfx_probe_ops ops = make_ops(&probe);
|
|
chimera_gfx_probe_report report;
|
|
|
|
probe.fail_open = 1;
|
|
CHECK(chimera_gfx_ps5_probe_symbols(&ops, &report) ==
|
|
CHIMERA_GFX_STATUS_BACKEND_UNAVAILABLE);
|
|
CHECK(probe.resolve_calls == 0u);
|
|
CHECK(probe.close_calls == 0u);
|
|
|
|
probe = (fake_probe){0};
|
|
probe.fail_lookup = 1;
|
|
ops = make_ops(&probe);
|
|
CHECK(chimera_gfx_ps5_probe_symbols(&ops, &report) ==
|
|
CHIMERA_GFX_STATUS_INTERNAL_ERROR);
|
|
CHECK(probe.resolve_calls == 1u);
|
|
CHECK(probe.close_calls == 1u);
|
|
|
|
probe = (fake_probe){0};
|
|
probe.fail_close = 1;
|
|
ops = make_ops(&probe);
|
|
CHECK(chimera_gfx_ps5_probe_symbols(&ops, &report) ==
|
|
CHIMERA_GFX_STATUS_INTERNAL_ERROR);
|
|
CHECK(report.module_opened == 1);
|
|
CHECK(probe.resolve_calls == report.symbol_count);
|
|
CHECK(probe.close_calls == 1u);
|
|
|
|
CHECK(chimera_gfx_ps5_probe_symbols(NULL, &report) ==
|
|
CHIMERA_GFX_STATUS_INVALID_ARGUMENT);
|
|
}
|
|
|
|
int main(void) {
|
|
test_partial_success();
|
|
test_fail_closed_paths();
|
|
return failures == 0 ? 0 : 1;
|
|
}
|