// // Copyright 2024 Staysail Systems, Inc. // Copyright 2018 Capitar IT Group BV // // This software is supplied under the terms of the MIT License, a // copy of which should be located in the distribution where this // file was obtained (LICENSE.txt). A copy of the license may also be // found online at https://opensource.org/licenses/MIT. // #include "core/nng_impl.h" #include #include #include #ifdef NNG_PLATFORM_POSIX #include #include #endif static void test_permissions(void) { #ifdef NNG_PLATFORM_POSIX char *temp; char *file; void *data; size_t n; if (geteuid() == 0) { NUTS_SKIP("Cannot test permissions as root"); return; } temp = nni_plat_temp_dir(); NUTS_TRUE(temp != NULL); file = nni_file_join(temp, "nng_files_perms_test"); NUTS_PASS(nni_file_put(file, "abc", 4)); chmod(file, 0); NUTS_FAIL(nni_file_get(file, &data, &n), NNG_EPERM); NUTS_FAIL(nni_file_put(file, "def", 4), NNG_EPERM); nni_file_delete(file); nni_strfree(file); nni_strfree(temp); #else NUTS_SKIP("Not a POSIX platform"); #endif } struct walkarg { int a; int b; int c; int d; int seen; }; static int walker(const char *name, void *arg) { struct walkarg *wa = arg; const char *bn; bn = nni_file_basename(name); if (wa != NULL) { wa->seen++; if (strcmp(bn, "a") == 0) { wa->a++; } else if (strcmp(bn, "b") == 0) { wa->b++; } else if (strcmp(bn, "c") == 0) { wa->c++; } else if (strcmp(bn, "d") == 0) { wa->d++; } } if (strcmp(bn, "stop") == 0) { return (NNI_FILE_WALK_STOP); } if (strcmp(bn, "prunechild") == 0) { return (NNI_FILE_WALK_PRUNE_CHILD); } if (strcmp(bn, "prunesib") == 0) { return (NNI_FILE_WALK_PRUNE_SIB); } return (NNI_FILE_WALK_CONTINUE); } static void test_directory_names(void) { char *d; NUTS_TRUE((d = nni_plat_temp_dir()) != NULL); nni_strfree(d); NUTS_TRUE((d = nni_file_join("a", "b")) != NULL); NUTS_TRUE(d[0] == 'a'); NUTS_TRUE(d[2] == 'b'); NUTS_TRUE(d[3] == '\0'); NUTS_TRUE((d[1] == '/') || (d[1] == '\\')); nni_strfree(d); } static void test_create_file_in_absent_dir(void) { int rv; char *tmp; char *d1; char *d2; NUTS_TRUE((tmp = nni_plat_temp_dir()) != NULL); NUTS_TRUE((d1 = nni_file_join(tmp, "bogusdir")) != NULL); NUTS_TRUE((d2 = nni_file_join(d1, "a")) != NULL); NUTS_TRUE((rv = nni_plat_file_put(d2, "", 0)) == 0); NUTS_PASS(nni_file_delete(d2)); NUTS_PASS(nni_file_delete(d1)); nni_strfree(d2); nni_strfree(d1); nni_strfree(tmp); } static void test_cannot_read_missing_file(void) { void *data; size_t n; NUTS_FAIL(nni_file_get("/bogus/dir/a", &data, &n), NNG_ENOENT); } static void test_delete_missing_file(void) { NUTS_PASS(nni_file_delete("/bogus/dir/a")); } static void test_walk_missing_dir(void) { NUTS_FAIL(nni_file_walk("/bogus/dir/a", walker, NULL, 0), NNG_ENOENT); } struct scratch { char *temp; char *mydir; char *a; char *b; char *c; char *d; }; static void make_scratch(struct scratch *s) { s->temp = nni_plat_temp_dir(); NUTS_TRUE(s->temp != NULL); s->mydir = nni_file_join(s->temp, "nng_files_test"); NUTS_TRUE(s->mydir != NULL); s->a = nni_file_join(s->mydir, "a"); NUTS_TRUE(s->a != NULL); s->b = nni_file_join(s->mydir, "b"); NUTS_TRUE(s->b != NULL); s->c = nni_file_join(s->mydir, "c"); NUTS_TRUE(s->c != NULL); s->d = nni_file_join(s->c, "d"); NUTS_TRUE(s->d != NULL); NUTS_PASS(nni_file_put(s->a, "alpha", 6)); NUTS_PASS(nni_file_put(s->b, "bravo", 6)); NUTS_PASS(nni_file_put(s->d, "delta", 6)); } static void clean_scratch(struct scratch *s) { nni_strfree(s->temp); nni_file_delete(s->a); nni_file_delete(s->b); nni_file_delete(s->d); nni_file_delete(s->c); nni_file_delete(s->mydir); nni_strfree(s->a); nni_strfree(s->b); nni_strfree(s->c); nni_strfree(s->d); nni_strfree(s->mydir); } static void test_directory_walk(void) { struct scratch s = { 0 }; struct walkarg wa = { 0 }; make_scratch(&s); memset(&wa, 0, sizeof(wa)); NUTS_PASS(nni_file_walk(s.mydir, walker, &wa, 0)); NUTS_TRUE(wa.a == 1); NUTS_TRUE(wa.b == 1); NUTS_TRUE(wa.c == 1); NUTS_TRUE(wa.d == 1); NUTS_TRUE(wa.seen == 4); memset(&wa, 0, sizeof(wa)); NUTS_PASS( nni_file_walk(s.mydir, walker, &wa, NNI_FILE_WALK_FILES_ONLY)); NUTS_TRUE(wa.a == 1); NUTS_TRUE(wa.b == 1); NUTS_TRUE(wa.c == 0); NUTS_TRUE(wa.d == 1); NUTS_TRUE(wa.seen == 3); memset(&wa, 0, sizeof(wa)); NUTS_PASS(nni_file_walk(s.mydir, walker, &wa, NNI_FILE_WALK_SHALLOW)); NUTS_TRUE(wa.a == 1); NUTS_TRUE(wa.b == 1); NUTS_TRUE(wa.c == 1); NUTS_TRUE(wa.d == 0); NUTS_TRUE(wa.seen == 3); memset(&wa, 0, sizeof(wa)); NUTS_PASS(nni_file_walk(s.mydir, walker, &wa, NNI_FILE_WALK_SHALLOW | NNI_FILE_WALK_FILES_ONLY)); NUTS_TRUE(wa.a == 1); NUTS_TRUE(wa.b == 1); NUTS_TRUE(wa.c == 0); NUTS_TRUE(wa.d == 0); NUTS_TRUE(wa.seen == 2); clean_scratch(&s); } static void test_file_contents(void) { void *data; size_t len; struct scratch s = { 0 }; make_scratch(&s); NUTS_PASS(nni_file_get(s.a, &data, &len)); NUTS_TRUE(len == 6); NUTS_MATCH(data, "alpha"); nni_free(data, len); clean_scratch(&s); } static void test_empty_files(void) { char *temp; char *empty; void *data; size_t n; temp = nni_plat_temp_dir(); NUTS_TRUE(temp != NULL); empty = nni_file_join(temp, "nng_files_test1"); NUTS_TRUE(empty != NULL); NUTS_PASS(nni_file_put(empty, "", 0)); NUTS_PASS(nni_file_get(empty, &data, &n)); nni_free(data, n); NUTS_TRUE(n == 0); nni_file_delete(empty); nni_strfree(empty); nni_strfree(temp); } NUTS_TESTS = { { "permissions", test_permissions }, { "directory names", test_directory_names }, { "create file absent dir", test_create_file_in_absent_dir }, { "cannot read missing file", test_cannot_read_missing_file }, { "delete missing file", test_delete_missing_file }, { "walk missing dir", test_walk_missing_dir }, { "walk directory", test_directory_walk }, { "file contents", test_file_contents }, { "empty files", test_empty_files }, { NULL, NULL }, };