Verify config updates preserve files and allocations under OOM

This commit is contained in:
evgeny committed 2026-10-21 19:03:39 +02:00
1 parent f7c8b95af6
commit bb87a0845b
2 files changed
+52 -1

No files matched your search

+2 -1
View File
@@ -301,7 +301,8 @@ test_mem_LDFLAGS = -Wl,--wrap=malloc
test_config_updater_SOURCES = test_config_updater.c
test_config_updater_LDADD = $(LIBUTUN) $(COMMON_LIBS)
test_config_updater_LDFLAGS = -Wl,--wrap=fopen -Wl,--wrap=fdopen -Wl,--wrap=fread -Wl,--wrap=ferror \
-Wl,--wrap=fwrite -Wl,--wrap=fflush -Wl,--wrap=fclose -Wl,--wrap=fsync -Wl,--wrap=fchmod -Wl,--wrap=rename -Wl,--wrap=open
-Wl,--wrap=fwrite -Wl,--wrap=fflush -Wl,--wrap=fclose -Wl,--wrap=fsync -Wl,--wrap=fchmod -Wl,--wrap=rename -Wl,--wrap=open \
-Wl,--wrap=u_malloc_impl -Wl,--wrap=u_calloc_impl -Wl,--wrap=u_realloc_impl -Wl,--wrap=u_strdup_impl
async_regression_sources = async_regression.c async_regression.h
async_regression_ldflags = -Wl,--wrap=u_malloc_impl -Wl,--wrap=u_calloc_impl -Wl,--wrap=u_realloc_impl \
+50
View File
@@ -5,6 +5,7 @@
#include "../src/transport_layer/secure_channel.h"
#include "../lib/platform_compat.h"
#include "../lib/debug_config.h"
#include "../lib/mem.h"
#include <assert.h>
#include <dirent.h>
#include <errno.h>
@@ -18,6 +19,7 @@ enum fault { NONE, READ_OPEN, READ_DATA, READ_CLOSE, TEMP_OPEN, WRITE_DATA, FLUS
static enum fault fault;
static int injected;
static FILE *input_stream, *output_stream;
static int allocation_fail_at, allocation_attempts;
static char directory[128], path[256];
static const char *private_hex = "abababababababababababababababababababababababababababababababab";
@@ -32,6 +34,32 @@ extern int __real_fsync(int);
extern int __real_fchmod(int, mode_t);
extern int __real_rename(const char *, const char *);
extern int __real_open(const char *, int, ...);
extern void *__real_u_malloc_impl(uint32_t, const char *);
extern void *__real_u_calloc_impl(uint32_t, uint32_t, const char *);
extern void *__real_u_realloc_impl(void *, uint32_t, const char *);
extern char *__real_u_strdup_impl(const char *, const char *);
static int allocation_fault(void) {
if (!allocation_fail_at || ++allocation_attempts != allocation_fail_at) return 0;
errno = ENOMEM;
return 1;
}
void *__wrap_u_malloc_impl(uint32_t size, const char *where) {
return allocation_fault() ? NULL : __real_u_malloc_impl(size, where);
}
void *__wrap_u_calloc_impl(uint32_t count, uint32_t size, const char *where) {
return allocation_fault() ? NULL : __real_u_calloc_impl(count, size, where);
}
void *__wrap_u_realloc_impl(void *ptr, uint32_t size, const char *where) {
return allocation_fault() ? NULL : __real_u_realloc_impl(ptr, size, where);
}
char *__wrap_u_strdup_impl(const char *text, const char *where) {
return allocation_fault() ? NULL : __real_u_strdup_impl(text, where);
}
static int inject(enum fault wanted) {
if (fault != wanted || injected) return 0;
@@ -291,6 +319,27 @@ static void test_failures(void) {
DEBUG_INFO(DEBUG_CATEGORY_CONFIG, "PASS links: rejected updates preserve names and original bytes");
}
/* Каждая аллокация на пути обновления может отказать: исходный файл и баланс памяти сохраняются. */
static void test_allocation_failures(void) {
const char *original = "[global]\n# sentinel\n";
size_t baseline = u_get_allocated_count();
int completed = 0;
for (int index = 1; index < 64; index++) {
write_text(original);
allocation_attempts = 0; allocation_fail_at = index;
int result = config_ensure_keys_and_node_id(path);
allocation_fail_at = 0;
assert(u_get_allocated_count() == baseline);
check_no_temporary();
if (allocation_attempts < index) { assert(result == 0); completed = 1; break; }
assert(result == -1);
char text[8192]; read_text(text, sizeof(text));
assert(!strcmp(text, original));
}
assert(completed);
DEBUG_INFO(DEBUG_CATEGORY_CONFIG, "PASS allocation failures: every allocation, original bytes and resource balance");
}
int main(void) {
debug_config_init();
debug_set_level(DEBUG_LEVEL_INFO);
@@ -301,6 +350,7 @@ int main(void) {
test_identity_and_text();
test_reality_and_validation();
test_failures();
test_allocation_failures();
assert(!unlink(path) && !rmdir(directory));
DEBUG_INFO(DEBUG_CATEGORY_CONFIG, "PASS config updater regression suite");
return 0;