mirror of
https://github.com/itsPLK/ps5-payload-manager.git
synced 2026-10-22 03:42:51 -05:00
138 lines
6.9 KiB
C
138 lines
6.9 KiB
C
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include "repository.h"
|
|
#include "slot.h"
|
|
#include "payload_mgr.h"
|
|
#include "collection_helpers.h"
|
|
#include "sources.h"
|
|
|
|
static size_t malloc_calls, realloc_calls, strdup_calls;
|
|
static size_t fail_malloc, fail_realloc, fail_strdup;
|
|
static int checks, failures;
|
|
|
|
void *allocation_test_malloc(size_t size) {
|
|
if (++malloc_calls == fail_malloc) { errno = ENOMEM; return NULL; }
|
|
return malloc(size);
|
|
}
|
|
void *allocation_test_realloc(void *pointer, size_t size) {
|
|
if (++realloc_calls == fail_realloc) { errno = ENOMEM; return NULL; }
|
|
return realloc(pointer, size);
|
|
}
|
|
char *allocation_test_strdup(const char *string) {
|
|
if (++strdup_calls == fail_strdup) { errno = ENOMEM; return NULL; }
|
|
return strdup(string);
|
|
}
|
|
static void reset(void) { malloc_calls = realloc_calls = strdup_calls = 0; fail_malloc = fail_realloc = fail_strdup = 0; }
|
|
static void expect(int condition, const char *message) {
|
|
checks++;
|
|
if (!condition) { failures++; fprintf(stderr, "FAIL %s\n", message); }
|
|
}
|
|
/* No test may download or launch anything. Fresh cache tests use other suites. */
|
|
int download_to_file(const char *url, const char *path) { (void)url; (void)path; abort(); }
|
|
void pldmgr_log(const char *fmt, ...) { (void)fmt; }
|
|
|
|
static char *manifest(size_t count) {
|
|
char *json = malloc(count * 128 + 4);
|
|
if (!json) exit(2);
|
|
size_t pos = 0;
|
|
json[pos++] = '[';
|
|
for (size_t i = 0; i < count; i++)
|
|
pos += (size_t)sprintf(json + pos, "%s{\"name\":\"item-%zu\",\"filename\":\"safe.elf\",\"url\":\"https://example.invalid\"}", i ? "," : "", i);
|
|
strcpy(json + pos, "]");
|
|
return json;
|
|
}
|
|
|
|
int main(int argc, char **argv) {
|
|
if (argc != 2) return 2;
|
|
if (strcmp(argv[1], "repository") == 0) {
|
|
char *json = manifest(500);
|
|
RepoPayload *items; size_t count;
|
|
reset();
|
|
expect(parse_repository_payloads(json, &items, &count) == 0 && count == 500, "complete repository");
|
|
size_t growths = realloc_calls, allocations = malloc_calls;
|
|
expect(growths <= 6 && allocations == 0, "geometric parser growth without per-item malloc");
|
|
free(items);
|
|
#ifdef LEGACY_ALLOCATION
|
|
if (growths > 8) growths = 8;
|
|
#endif
|
|
for (size_t failure = 1; failure <= growths; failure++) {
|
|
reset(); fail_realloc = failure;
|
|
items = NULL; count = 0;
|
|
int result = parse_repository_payloads(json, &items, &count);
|
|
expect(result != 0 && !items && !count, "each parser growth failure returns no partial collection");
|
|
free(items);
|
|
}
|
|
free(json);
|
|
reset(); json = manifest(collection_limit(sizeof(RepoPayload)) + 1);
|
|
int result = parse_repository_payloads(json, &items, &count);
|
|
expect(result != 0 && !items && !count, "repository item/byte limit rejects partial output"); free(items); free(json);
|
|
reset(); json = malloc(16 * 1024 * 1024 + 2); memset(json, ' ', 16 * 1024 * 1024 + 1); json[16 * 1024 * 1024 + 1] = 0;
|
|
result = parse_repository_payloads(json, &items, &count);
|
|
expect(result != 0 && !items && !count, "repository input size bounded"); free(items); free(json);
|
|
result = parse_repository_payloads("[{\"name\":\"valid\",\"filename\":\"safe.elf\",\"url\":\"https://example.invalid\"},{\"name\":\"unfinished", &items, &count);
|
|
expect(result != 0 && !items && !count, "unterminated trailing object does not publish earlier items"); free(items);
|
|
size_t capacity = 16;
|
|
char *owned = malloc(16); memset(owned, 'x', 16);
|
|
expect(collection_reserve(owned, &capacity, COLLECTION_MAX_ITEMS + 1, 1) == NULL && capacity == 16 && owned[0] == 'x',
|
|
"item limit leaves ownership/capacity intact");
|
|
expect(collection_reserve(owned, &capacity, 1, SIZE_MAX) == NULL && capacity == 16 && owned[0] == 'x',
|
|
"byte/multiplication limit leaves ownership intact");
|
|
free(owned);
|
|
} else if (strcmp(argv[1], "slots") == 0) {
|
|
SlotMeta *items; size_t count;
|
|
reset(); expect(slot_list_all(&items, &count) == 0 && count == 70, "complete slot scan");
|
|
size_t growths = realloc_calls, reads = malloc_calls;
|
|
expect(growths == 3, "slot array grows geometrically"); free(items);
|
|
for (size_t failure = 1; failure <= growths; failure++) {
|
|
reset(); fail_realloc = failure;
|
|
int result = slot_list_all(&items, &count);
|
|
expect(result != 0 && !items && !count, "slot growth failure is not partial success"); free(items);
|
|
}
|
|
for (size_t failure = 1; failure <= reads; failure++) {
|
|
reset(); fail_malloc = failure;
|
|
int result = slot_list_all(&items, &count);
|
|
expect(result != 0 && !items && !count, "metadata allocation failure aborts slot scan"); free(items);
|
|
}
|
|
} else if (strcmp(argv[1], "source_listing") == 0) {
|
|
char *output = malloc(4194304); if (!output) return 2;
|
|
reset(); expect(sources_multi_repository_list_json(output, 4194304, 0) != 0, "cached source listing complete");
|
|
size_t growths = realloc_calls, allocations = malloc_calls;
|
|
#ifdef LEGACY_ALLOCATION
|
|
if (growths > 8) growths = 8;
|
|
if (allocations > 8) allocations = 8;
|
|
#endif
|
|
for (size_t failure = 1; failure <= growths; failure++) {
|
|
reset(); fail_realloc = failure;
|
|
expect(sources_multi_repository_list_json(output, 4194304, 0) == 0 && output[0] == 0,
|
|
"parser allocation failure propagates through source listing");
|
|
}
|
|
for (size_t failure = 1; failure <= allocations; failure++) {
|
|
reset(); fail_malloc = failure;
|
|
expect(sources_multi_repository_list_json(output, 4194304, 0) == 0 && output[0] == 0,
|
|
"cache/icon allocation failure is not an empty successful source");
|
|
}
|
|
free(output);
|
|
} else if (strcmp(argv[1], "usb") == 0) {
|
|
char *output = malloc(4194304); if (!output) return 2;
|
|
reset(); expect(payload_mgr_list_json(output, 4194304) != 0 && strdup_calls == 70, "all three USB scan paths collected");
|
|
size_t growths = realloc_calls, copies = strdup_calls;
|
|
for (size_t failure = 1; failure <= growths; failure++) {
|
|
reset(); fail_realloc = failure;
|
|
expect(payload_mgr_list_json(output, 4194304) == 0 && output[0] == 0, "USB growth failure cleans complete scan");
|
|
}
|
|
for (size_t failure = 1; failure <= copies; failure++) {
|
|
reset(); fail_strdup = failure;
|
|
expect(payload_mgr_list_json(output, 4194304) == 0 && output[0] == 0, "USB strdup failure cleans complete scan");
|
|
}
|
|
free(output);
|
|
} else return 2;
|
|
printf("Allocation tests (%s): %d checks, %d failures\n", argv[1], checks, failures);
|
|
return failures ? 1 : 0;
|
|
}
|
|
|
|
int download_to_file_limited(const char *url, const char *path, size_t limit) {
|
|
(void)limit; return download_to_file(url, path);
|
|
}
|