From ad633260bae6d4a36f48133a186b55ab9102e5b5 Mon Sep 17 00:00:00 2001 From: KArkadiusz Date: Fri, 26 Jan 2024 21:01:18 +0100 Subject: [PATCH] Libc: add dirent tests JIRA: CI-359 --- libc/dirent/closedir.c | 95 +++++++- libc/dirent/dirent_helper_functions.c | 81 ------- libc/dirent/dirent_helper_functions.h | 17 +- libc/dirent/opendir.c | 297 ++++++++++++-------------- libc/dirent/readdir.c | 147 +++++++------ libc/dirent/rewinddir.c | 77 ++++--- 6 files changed, 361 insertions(+), 353 deletions(-) delete mode 100644 libc/dirent/dirent_helper_functions.c diff --git a/libc/dirent/closedir.c b/libc/dirent/closedir.c index 3ef8755b..ea950a26 100644 --- a/libc/dirent/closedir.c +++ b/libc/dirent/closedir.c @@ -15,29 +15,27 @@ * %LICENSE% */ - #include -#include #include #include #include -#include #include #include #include "common.h" +#include "dirent_helper_functions.h" #define MAIN_DIR "test_closedir" - TEST_GROUP(dirent_closedir); TEST_SETUP(dirent_closedir) { errno = 0; - TEST_ASSERT_TRUE(mkdir(MAIN_DIR, 0777) != -1 || errno == EEXIST); - TEST_ASSERT_TRUE(mkdir(MAIN_DIR "/dir1", 0777) != -1 || errno == EEXIST); + TEST_MKDIR_ASSERTED(MAIN_DIR, S_IRWXU); + errno = 0; + TEST_MKDIR_ASSERTED(MAIN_DIR "/dir1", S_IRUSR); } @@ -53,7 +51,7 @@ TEST(dirent_closedir, closing_empty_dir) DIR *dp = opendir(MAIN_DIR "/dir1"); TEST_ASSERT_NOT_NULL(dp); - TEST_ASSERT_EQUAL(0, closedir(dp)); + TEST_ASSERT_EQUAL_INT(0, closedir(dp)); } @@ -66,8 +64,91 @@ TEST(dirent_closedir, closing_non_empty_dir) } +TEST(dirent_closedir, preserving_content_after_closedir) +{ + char dirNames[7][10]; + ino_t inodes[7]; + struct dirent *info; + DIR *dp1; + int result = 0; + errno = 0; + + + TEST_MKDIR_ASSERTED(MAIN_DIR "/test_preserve", S_IRWXU); + TEST_MKDIR_ASSERTED(MAIN_DIR "/test_preserve/B", S_IRUSR); + TEST_MKDIR_ASSERTED(MAIN_DIR "/test_preserve/CC", S_IRUSR); + TEST_MKDIR_ASSERTED(MAIN_DIR "/test_preserve/DDDD", S_IRUSR); + TEST_MKDIR_ASSERTED(MAIN_DIR "/test_preserve/EEEEEE", S_IRUSR); + + + dp1 = opendir(MAIN_DIR "/test_preserve"); + TEST_ASSERT_NOT_NULL(dp1); + + /* + *Create an array with names of dirs. + *Indexes will be used to associate name of each directory with a bit + */ + + { + int i = 0; + while ((info = readdir(dp1)) != NULL) { + inodes[i] = info->d_ino; + strcpy(dirNames[i++], info->d_name); + } + } + + TEST_ASSERT_EQUAL_INT(0, closedir(dp1)); + DIR *dp2 = opendir(MAIN_DIR "/test_preserve"); + TEST_ASSERT_NOT_NULL(dp2); + rewinddir(dp2); + + /* + * Map each directory to a bit. + * In case of fail set most left bit to 1. + * Assert every bit is high except the first two. + */ + + /* Go through each entry */ + + while ((info = readdir(dp2)) != NULL) { + int found = 0; + char name[10]; + strcpy(name, info->d_name); + + /* determine the index of given name */ + for (int i = 0; i < 7; ++i) { + if (!strcmp(name, dirNames[i])) { + TEST_ASSERT_EQUAL_INT64(inodes[i], info->d_ino); + /* Set the index bit of found name */ + result |= 1 << i; + + found = 1; + } + } + /* Name found, time to search for another name */ + if (found) { + continue; + } + + TEST_FAIL(); + } + + /* result variable should be 0b0011 1111, which is 63, or 3f */ + TEST_ASSERT_EQUAL_INT(0x3f, result); + + closedir(dp2); + + rmdir(MAIN_DIR "/test_preserve/B"); + rmdir(MAIN_DIR "/test_preserve/CC"); + rmdir(MAIN_DIR "/test_preserve/DDDD"); + rmdir(MAIN_DIR "/test_preserve/EEEEEE"); + rmdir(MAIN_DIR "/test_preserve"); +} + + TEST_GROUP_RUNNER(dirent_closedir) { RUN_TEST_CASE(dirent_closedir, closing_empty_dir); RUN_TEST_CASE(dirent_closedir, closing_non_empty_dir); + RUN_TEST_CASE(dirent_closedir, preserving_content_after_closedir); } diff --git a/libc/dirent/dirent_helper_functions.c b/libc/dirent/dirent_helper_functions.c deleted file mode 100644 index 88a5d66e..00000000 --- a/libc/dirent/dirent_helper_functions.c +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include -#include - -#include "unity_fixture.h" -#include "common.h" - -#include "dirent_helper_functions.h" - -#define INO_T_TEST_MAX_DIRS 10 - - -void test_mkdir_asserted(char *path, mode_t mode) -{ - TEST_ASSERT_TRUE_MESSAGE(mkdir(path, mode) != -1 || errno == EEXIST, strerror(errno)); -} - - -int test_create_directories(int num_of_dirs) -{ - - char dirPath[40]; - DIR *dirs[num_of_dirs]; - int opened_dirs = 0; - int result = 0; - - - /* Create directories in batch */ - for (int i = 0; i < num_of_dirs; ++i) { - - sprintf(dirPath, "test_opendir/%d", i); - - test_mkdir_asserted(dirPath, 0777); - } - - /* Open directories one by one, until one of them fails */ - for (int i = 0; i < num_of_dirs; ++i) { - - sprintf(dirPath, "test_opendir/%d", i); - - /* - * Guard clause that skips current take if dir was opened, - * Upon failing it proceeds to cleanup - */ - if ((dirs[i] = opendir(dirPath)) != NULL) { - opened_dirs = i; - continue; - } - - result = -1; - break; - } - - for (int i = 0; i <= opened_dirs; ++i) { - TEST_ASSERT_EQUAL(0, closedir(dirs[i])); - } - - for (int i = 0; i < num_of_dirs; ++i) { - sprintf(dirPath, "test_opendir/%d", i); - rmdir(dirPath); - } - - return result; -} - - -int d_ino_in(ino_t arg, ino_t *arr) -{ - for (int i = 0; i < INO_T_TEST_MAX_DIRS; ++i) - if (arg == arr[i]) - return i; - return -1; -} - - -DIR *test_opendir_asserted(const char *path) -{ - DIR *dp = opendir(path); - TEST_ASSERT_NOT_NULL(dp); - return dp; -} diff --git a/libc/dirent/dirent_helper_functions.h b/libc/dirent/dirent_helper_functions.h index 730e7d17..fe0bb3d5 100644 --- a/libc/dirent/dirent_helper_functions.h +++ b/libc/dirent/dirent_helper_functions.h @@ -5,16 +5,15 @@ #include #include -#define INO_T_TEST_MAX_DIRS 10 +#define TEST_MKDIR_ASSERTED(path, mode) TEST_ASSERT_TRUE_MESSAGE(mkdir(path, mode) != -1 || errno == EEXIST, strerror(errno)) -void test_mkdir_asserted(char *path, mode_t mode); +#define TEST_OPENDIR_ASSERTED(path) \ + ({ \ + DIR *dp = opendir(path); \ + TEST_ASSERT_NOT_NULL(dp); \ + dp; \ + }) -int test_create_directories(int num_of_dirs); -int d_ino_in(ino_t arg, ino_t *arr); - -DIR *test_opendir_asserted(const char *path); - - -#endif \ No newline at end of file +#endif diff --git a/libc/dirent/opendir.c b/libc/dirent/opendir.c index f157d133..7c009194 100644 --- a/libc/dirent/opendir.c +++ b/libc/dirent/opendir.c @@ -1,8 +1,6 @@ /* * Phoenix-RTOS * - * libphoenix - * * POSIX.1-2017 standard library functions tests * HEADER: * - dirent.h @@ -17,14 +15,12 @@ * %LICENSE% */ - #include #include #include #include -#include -#include #include +#include #include @@ -33,28 +29,65 @@ #define MAIN_DIR "test_opendir" +static int test_create_directories(int num_of_dirs) +{ + + char dirPath[40]; + DIR *dirs[num_of_dirs]; + int opened_dirs = 0; + int result = 0; + + /* Create directories in batch */ + for (int i = 0; i < num_of_dirs; ++i) { + + sprintf(dirPath, MAIN_DIR "/%d", i); + + TEST_MKDIR_ASSERTED(dirPath, S_IRUSR); + } + + /* Open directories one by one, until one of them fails */ + for (int i = 0; i < num_of_dirs; ++i) { + + sprintf(dirPath, MAIN_DIR "/%d", i); + + /* + * Guard clause that skips current take if dir was opened, + * Upon failing it proceeds to cleanup + */ + if ((dirs[i] = opendir(dirPath)) != NULL) { + opened_dirs = i; + continue; + } + + result = -1; + break; + } + + for (int i = 0; i <= opened_dirs; ++i) { + TEST_ASSERT_EQUAL_INT(0, closedir(dirs[i])); + } + + + for (int i = 0; i < num_of_dirs; ++i) { + sprintf(dirPath, MAIN_DIR "/%d", i); + rmdir(dirPath); + } + + return result; +} + TEST_GROUP(dirent_opendir); TEST_SETUP(dirent_opendir) { - - test_mkdir_asserted(MAIN_DIR, 0777); - test_mkdir_asserted(MAIN_DIR "/dir_without_read_perm", 0000); - FILE *fptr; - if ((fptr = fopen(MAIN_DIR "/notadir.txt", "w")) != NULL) { - fprintf(fptr, "Some file contents"); - fclose(fptr); - } + TEST_MKDIR_ASSERTED(MAIN_DIR, S_IRWXU); } TEST_TEAR_DOWN(dirent_opendir) { - remove(MAIN_DIR "/notadir.txt"); - chmod(MAIN_DIR "/dir_without_read_perm", 0777); - rmdir(MAIN_DIR "/dir_without_read_perm"); rmdir(MAIN_DIR); } @@ -62,7 +95,7 @@ TEST_TEAR_DOWN(dirent_opendir) TEST(dirent_opendir, opening_empty_directory) { DIR *dp; - test_mkdir_asserted(MAIN_DIR "/empty_dir", 0777); + TEST_MKDIR_ASSERTED(MAIN_DIR "/empty_dir", S_IRUSR); dp = opendir(MAIN_DIR "/empty_dir"); TEST_ASSERT_NOT_NULL(dp); closedir(dp); @@ -81,19 +114,17 @@ TEST(dirent_opendir, opening_not_empty_directory) TEST(dirent_opendir, no_read_permission) { + TEST_IGNORE_MESSAGE("#937 issue"); + char unreadable[] = MAIN_DIR "/dir_without_read_perm"; char readable[] = MAIN_DIR "/dir_without_read_perm/readable_dir"; DIR *dirPtr; - chmod(unreadable, 0700); - test_mkdir_asserted(readable, 0777); - chmod(unreadable, 0000); + TEST_MKDIR_ASSERTED(unreadable, 0000); - if ((dirPtr = opendir(unreadable)) != NULL) { - closedir(dirPtr); - rmdir(readable); - TEST_IGNORE_MESSAGE("Opened a file without any permissions"); - } + chmod(unreadable, S_IRWXU); + TEST_MKDIR_ASSERTED(readable, S_IRUSR | S_IWUSR); + chmod(unreadable, 0000); /* Try to read from locked directory */ errno = 0; @@ -107,15 +138,15 @@ TEST(dirent_opendir, no_read_permission) TEST_ASSERT_EQUAL_INT(EACCES, errno); TEST_ASSERT_NULL(dirPtr); - /* No execute permission */ - chmod(unreadable, 0600); + /* No execute permission in parent*/ + chmod(unreadable, S_IRUSR | S_IWUSR); errno = 0; dirPtr = opendir(readable); TEST_ASSERT_EQUAL_INT(EACCES, errno); TEST_ASSERT_NULL(dirPtr); /* No read permission */ - chmod(unreadable, 0300); + chmod(unreadable, S_IWUSR | S_IXUSR); errno = 0; dirPtr = opendir(unreadable); TEST_ASSERT_EQUAL_INT(EACCES, errno); @@ -123,9 +154,9 @@ TEST(dirent_opendir, no_read_permission) errno = 0; - chmod(unreadable, 0700); + chmod(unreadable, S_IRWXU); rmdir(readable); - chmod(unreadable, 0000); + rmdir(unreadable); } @@ -145,10 +176,12 @@ TEST(dirent_opendir, wrong_directory_name) TEST(dirent_opendir, not_a_directory) { + close(creat(MAIN_DIR "/notadir.txt", S_IRUSR)); errno = 0; DIR *dirPtr = opendir(MAIN_DIR "/notadir.txt"); TEST_ASSERT_EQUAL_INT(ENOTDIR, errno); TEST_ASSERT_NULL(dirPtr); + remove(MAIN_DIR "/notadir.txt"); } @@ -156,26 +189,35 @@ TEST(dirent_opendir, creating_dirs_in_closed_and_open_directories) { /* Create dir in closed directory */ DIR *dirs[4]; - test_mkdir_asserted(MAIN_DIR "/formerDir", 0777); + TEST_MKDIR_ASSERTED(MAIN_DIR "/formerDir", S_IRUSR); /* Create dir in opened directory, then close opened one */ - DIR *dp = opendir(MAIN_DIR); + DIR *dp = TEST_OPENDIR_ASSERTED(MAIN_DIR); TEST_ASSERT_NOT_NULL(dirs[0] = opendir(MAIN_DIR "/formerDir")); - test_mkdir_asserted(MAIN_DIR "/latterDir", 0777); + TEST_MKDIR_ASSERTED(MAIN_DIR "/latterDir", S_IRUSR); closedir(dp); /* Assure that both dirs can be opened without problems */ TEST_ASSERT_NOT_NULL(dirs[1] = opendir(MAIN_DIR "/formerDir")); TEST_ASSERT_NOT_NULL(dirs[2] = opendir(MAIN_DIR "/latterDir")); + dp = opendir(MAIN_DIR); - closedir(dp); - test_mkdir_asserted(MAIN_DIR "/evenLatterDir", 0777); + TEST_ASSERT_NOT_NULL(dp); + + TEST_MKDIR_ASSERTED("ToBeDeleted", S_IRUSR); + TEST_ASSERT_EQUAL_INT(0, rmdir("ToBeDeleted")); + TEST_ASSERT_EQUAL_INT(0, closedir(dp)); + + TEST_ASSERT_NULL(opendir("ToBeDeleted")); + TEST_MKDIR_ASSERTED(MAIN_DIR "/evenLatterDir", S_IRUSR); TEST_ASSERT_NOT_NULL(dirs[3] = opendir(MAIN_DIR "/evenLatterDir")); - for (int i = 0; i < 4; ++i) + for (int i = 0; i < 4; ++i) { + TEST_ASSERT_NOT_NULL(dirs[i]); closedir(dirs[i]); + } rmdir(MAIN_DIR "/formerDir"); rmdir(MAIN_DIR "/latterDir"); @@ -183,20 +225,6 @@ TEST(dirent_opendir, creating_dirs_in_closed_and_open_directories) } -TEST(dirent_opendir, open_too_many_directories) -{ -#ifdef OPEN_MAX - int dir_amount = OPEN_MAX + 100; - errno = 0; - - TEST_ASSERT_EQUAL_INT(-1, test_create_directories(dir_amount)); - TEST_ASSERT_EQUAL_INT(EMFILE, errno); -#else - TEST_IGNORE_MESSAGE("OPEN_MAX not defined"); -#endif -} - - TEST(dirent_opendir, open_small_enough_number_of_directories) { errno = 0; @@ -225,55 +253,78 @@ TEST(dirent_opendir, open_same_dir_multiple_times) TEST(dirent_opendir, symlink_loop) { -#ifndef SYMLOOP_MAX -#define SYMLOOP_MAX 8 -#define SYMLOOP_NOT_DEFINED + int symloopMax = 0; +#if defined(SYMLOOP_MAX) + symloopMax = SYMLOOP_MAX; +#elif defined(_SC_SYMLOOP_MAX) + if ((symloopMax = sysconf(_SC_SYMLOOP_MAX)) == -1) { + TEST_IGNORE_MESSAGE("sysconf() doesn't recognize _SC_SYMLOOP_MAX"); + } +#else + TEST_IGNORE_MESSAGE("Neither SYMLOOP_MAX nor sysconf(_SC_SYMLOOP_MAX) is defined"); #endif - test_mkdir_asserted("A", 0777); + TEST_MKDIR_ASSERTED("A", S_IRWXU); + TEST_MKDIR_ASSERTED("D1", S_IRWXU); + TEST_MKDIR_ASSERTED("D2", S_IRWXU); + + /* SYMLOOP_MAX probably won't be bigger than 40*/ + char selfLoop[40 * 2 + 16]; + char mutualLoop[40 * 4 + 32]; - TEST_ASSERT_EQUAL(0, symlink("A", "D")); - TEST_ASSERT_EQUAL(0, symlink(".", "A/D")); + TEST_ASSERT_EQUAL_INT(0, symlink("../D2", "D1/S1")); + TEST_ASSERT_EQUAL_INT(0, symlink("../D1", "D2/S2")); + TEST_ASSERT_EQUAL_INT(0, symlink(".", "A/B")); - char loopPath[SYMLOOP_MAX * 2 + 16]; - strcpy(loopPath, "A/"); + strcpy(selfLoop, "A"); + strcpy(mutualLoop, "D1"); - /* Create a path to barely valid symloop */ - for (int i = 0; i < SYMLOOP_MAX / 2 - 1; ++i) { - strcat(loopPath, "D/D/"); + /* Create a path to a valid symloop */ + /* Posix says that symloops up to */ + for (int i = 0; i < 4; ++i) { + strcat(selfLoop, "/B/B"); + strcat(mutualLoop, "/S1/S2"); } + errno = 0; + DIR *selfDP = opendir(selfLoop); + DIR *mutualDP = opendir(mutualLoop); - DIR *dp = opendir(loopPath); - TEST_ASSERT_NOT_NULL(dp); - rmdir(loopPath); - closedir(dp); + TEST_ASSERT_NOT_NULL(selfDP); + TEST_ASSERT_NOT_NULL(mutualDP); -/* Check for actually defined symloop */ -#ifndef SYMLOOP_NOT_DEFINED + closedir(selfDP); + closedir(mutualDP); - /* Add a few layers of symloops, so it is too deep */ - for (int i = 0; i < 4; ++i) { - strcat(loopPath, "D/D/"); + + /* Add a few layers of symloops, so it is too deep (selfLoop is not empty at this point)*/ + for (int i = 0; i < symloopMax / 2 - 1; ++i) { + strcat(selfLoop, "/B/B"); + strcat(mutualLoop, "/S1/S2"); } errno = 0; + TEST_ASSERT_NULL(opendir(selfLoop)); + TEST_ASSERT_EQUAL_INT(ELOOP, errno); - TEST_ASSERT_NULL(opendir(loopPath)); + errno = 0; + TEST_ASSERT_NULL(opendir(mutualLoop)); TEST_ASSERT_EQUAL_INT(ELOOP, errno); -#endif - unlink("A/D"); - unlink("D"); - rmdir("A/D"); + unlink("A/B"); + unlink("D1/S1"); + unlink("D2/S2"); + rmdir("A"); + rmdir("D1"); + rmdir("D2"); } TEST(dirent_opendir, opening_inside_open_directory) { - test_mkdir_asserted(MAIN_DIR "/newdir", 0777); + TEST_MKDIR_ASSERTED(MAIN_DIR "/newdir", S_IRUSR); DIR *dp1, *dp2; dp1 = opendir(MAIN_DIR); TEST_ASSERT_NOT_NULL(dp2 = opendir(MAIN_DIR "/newdir")); @@ -285,16 +336,16 @@ TEST(dirent_opendir, opening_inside_open_directory) TEST(dirent_opendir, too_long_path) { - int size = PATH_MAX; - char filename[size + 1]; - char path[size + strlen(MAIN_DIR) + 100]; + char filename[PATH_MAX + 1]; + /* Add 2 for null terminator and slash */ + char path[PATH_MAX + strlen(MAIN_DIR) + 2]; - - memset(filename, 'a', size - strlen(MAIN_DIR) - 3); + memset(filename, 'a', PATH_MAX); + filename[PATH_MAX] = '\0'; strcpy(path, MAIN_DIR); + strcat(path, "/"); strcat(path, filename); - mkdir(path, 0777); errno = 0; TEST_ASSERT_NULL(opendir(path)); @@ -302,84 +353,6 @@ TEST(dirent_opendir, too_long_path) } -TEST(dirent_opendir, preserving_content_after_closedir) -{ - test_mkdir_asserted("test_preserve", 0777); - test_mkdir_asserted("test_preserve/B", 0777); - test_mkdir_asserted("test_preserve/CC", 0777); - test_mkdir_asserted("test_preserve/DDDD", 0777); - test_mkdir_asserted("test_preserve/EEEEEE", 0777); - - char dirNames[7][10]; - ino_t inodes[7]; - struct dirent *info; - DIR *dp1 = opendir("test_preserve"); - char result = 0; - - /* - *Create an array with names of dirs. - *Indexes will be used to associate name of each directory with a bit - */ - { - int i = 0; - while ((info = readdir(dp1)) != NULL) { - inodes[i] = info->d_ino; - strcpy(dirNames[i++], info->d_name); - } - } - - closedir(dp1); - DIR *dp2 = opendir("test_preserve"); - rewinddir(dp2); - - /* - * Map each directory to a bit. - * In case of fail set most left bit to 1. - * Assert every bit is high except the first two. - */ - - /* Go through each entry */ - - while ((info = readdir(dp2)) != NULL) { - - int found = 0; - char name[10]; - strcpy(name, info->d_name); - - /* determine the index of given name */ - for (int i = 0; i < 7; ++i) { - - if (!strcmp(name, dirNames[i])) { - - TEST_ASSERT_EQUAL_INT64(inodes[i], info->d_ino); - - /* Set the index bit of found name */ - result |= 1 << i; - - found = 1; - } - } - - /* Name found, time to search for another name */ - if (found) - continue; - - TEST_FAIL(); - } - - /* result variable should be 0b00111111, which is 63 */ - TEST_ASSERT_EQUAL_INT(63, result); - - closedir(dp2); - - rmdir("test_preserve/B"); - rmdir("test_preserve/CC"); - rmdir("test_preserve/DDDD"); - rmdir("test_preserve/EEEEEE"); - rmdir("test_preserve"); -} - - TEST_GROUP_RUNNER(dirent_opendir) { RUN_TEST_CASE(dirent_opendir, opening_empty_directory); @@ -389,10 +362,8 @@ TEST_GROUP_RUNNER(dirent_opendir) RUN_TEST_CASE(dirent_opendir, not_a_directory); RUN_TEST_CASE(dirent_opendir, symlink_loop); RUN_TEST_CASE(dirent_opendir, too_long_path); + RUN_TEST_CASE(dirent_opendir, creating_dirs_in_closed_and_open_directories); RUN_TEST_CASE(dirent_opendir, opening_inside_open_directory); RUN_TEST_CASE(dirent_opendir, open_small_enough_number_of_directories); - RUN_TEST_CASE(dirent_opendir, open_too_many_directories); - RUN_TEST_CASE(dirent_opendir, preserving_content_after_closedir); RUN_TEST_CASE(dirent_opendir, open_same_dir_multiple_times); - RUN_TEST_CASE(dirent_opendir, creating_dirs_in_closed_and_open_directories); } diff --git a/libc/dirent/readdir.c b/libc/dirent/readdir.c index 49604d37..26c17feb 100644 --- a/libc/dirent/readdir.c +++ b/libc/dirent/readdir.c @@ -6,6 +6,7 @@ * - dirent.h * TESTED: * - readdir() + * * Copyright 2023 Phoenix Systems * Author: Arkadiusz Kozlowski * @@ -24,6 +25,7 @@ #include #include #include +#include #include @@ -34,36 +36,41 @@ #define INO_T_TEST_MAX_DIRS 10 +int d_ino_in(ino_t arg, ino_t *arr) +{ + for (int i = 0; i < INO_T_TEST_MAX_DIRS; ++i) { + if (arg == arr[i]) { + return i; + } + } + return -1; +} + + TEST_GROUP(dirent_readdir); TEST_SETUP(dirent_readdir) { - mkdir(MAIN_DIR, 0777); + mkdir(MAIN_DIR, 0700); - mkdir(MAIN_DIR "/dir1", 0777); - mkdir(MAIN_DIR "/dir2", 0777); + mkdir(MAIN_DIR "/dir1", S_IRUSR | S_IWUSR | S_IXUSR); + mkdir(MAIN_DIR "/dir2", S_IRUSR | S_IWUSR | S_IXUSR); - mkdir(MAIN_DIR "/dir1/nest1", 0777); - mkdir(MAIN_DIR "/dir1/nest2", 0777); + mkdir(MAIN_DIR "/dir1/nest1", S_IRUSR); + mkdir(MAIN_DIR "/dir1/nest2", S_IRUSR); - mkdir(MAIN_DIR "/dir2/nest1", 0777); - mkdir(MAIN_DIR "/dir2/nest2", 0777); + mkdir(MAIN_DIR "/dir2/nest1", S_IRUSR); + mkdir(MAIN_DIR "/dir2/nest2", S_IRUSR); - FILE *files[] = { - fopen(MAIN_DIR "/file1.txt", "w+"), - fopen(MAIN_DIR "/file2.dat", "w+"), - fopen(MAIN_DIR "/file3.json", "w+") + int files[] = { + creat(MAIN_DIR "/file1.txt", S_IRUSR), + creat(MAIN_DIR "/file2.dat", S_IRUSR), + creat(MAIN_DIR "/file3.json", S_IRUSR) }; - if (files[0]) { - fprintf(files[0], "Some data"); - fprintf(files[1], "Some other data"); - - - fclose(files[0]); - fclose(files[1]); - fclose(files[2]); - } + close(files[0]); + close(files[1]); + close(files[2]); } @@ -88,25 +95,24 @@ TEST_TEAR_DOWN(dirent_readdir) TEST(dirent_readdir, long_name_directory_check) { - DIR *dp = test_opendir_asserted(MAIN_DIR); + DIR *dp = TEST_OPENDIR_ASSERTED(MAIN_DIR); struct dirent *info; - char longDirName[NAME_MAX]; + char longDirName[NAME_MAX + 1]; char longDirPath[NAME_MAX + 2 + sizeof(MAIN_DIR)]; - longDirName[NAME_MAX - 1] = '\0'; TEST_ASSERT_NOT_NULL(dp); - memset(longDirName, 'a', NAME_MAX - 1); + memset(longDirName, 'a', NAME_MAX); + longDirName[NAME_MAX] = '\0'; sprintf(longDirPath, MAIN_DIR "/%s", longDirName); errno = 0; - if (mkdir(longDirPath, 0777) == -1 && errno != EEXIST) - TEST_IGNORE_MESSAGE(strerror(errno)); + TEST_MKDIR_ASSERTED(longDirPath, S_IRUSR); while ((info = readdir(dp)) != NULL) { if (!strcmp(longDirName, info->d_name)) { - TEST_ASSERT_EQUAL_INT(NAME_MAX - 1, strlen(info->d_name)); + TEST_ASSERT_EQUAL_INT(NAME_MAX, strlen(info->d_name)); closedir(dp); rmdir(longDirPath); TEST_PASS(); @@ -114,22 +120,19 @@ TEST(dirent_readdir, long_name_directory_check) } closedir(dp); - rmdir(longDirPath); TEST_FAIL(); } TEST(dirent_readdir, basic_listing_count) { - DIR *dp = test_opendir_asserted(MAIN_DIR); + DIR *dp = TEST_OPENDIR_ASSERTED(MAIN_DIR); int entry_counter = 0; struct dirent *info; - if (!dp) - TEST_FAIL_MESSAGE(strerror(errno)); - - while ((info = readdir(dp)) != NULL) + while ((info = readdir(dp)) != NULL) { entry_counter++; + } /* 5 files from setup, and both . and .. directories */ TEST_ASSERT_EQUAL_INT(7, entry_counter); @@ -142,62 +145,64 @@ TEST(dirent_readdir, reading_in_parent_and_child) { DIR *dp1, *dp2; - dp1 = test_opendir_asserted(MAIN_DIR "/dir1"); - dp2 = test_opendir_asserted(MAIN_DIR "/dir2"); - + dp1 = TEST_OPENDIR_ASSERTED(MAIN_DIR "/dir1"); + dp2 = TEST_OPENDIR_ASSERTED(MAIN_DIR "/dir2"); TEST_ASSERT_NOT_NULL(readdir(dp1)); TEST_ASSERT_NOT_NULL(readdir(dp2)); - /* After first readdir is done, removing contents from directory shall not influence output from readdir */ - pid_t pid = fork(); - /* Since there are two different dir streams, there is no reading from the same stream in two processes */ - TEST_ASSERT_NOT_EQUAL_INT(-1, pid); + if (pid == -1) { + TEST_IGNORE_MESSAGE("Fork failed"); + } + /* Since there are two different dir streams, there is no reading from the same stream in two processes */ if (pid) { + int cresult; /* Check for parent */ TEST_ASSERT_NOT_NULL(readdir(dp1)); rewinddir(dp1); TEST_ASSERT_NOT_NULL(readdir(dp1)); - closedir(dp1); closedir(dp2); - wait(NULL); + wait(&cresult); + TEST_ASSERT_EQUAL_INT(EXIT_SUCCESS, cresult); } else { /* Check for child */ - TEST_ASSERT_NOT_NULL(readdir(dp2)); + int status = EXIT_SUCCESS; + if (!readdir(dp2)) { + status = EXIT_FAILURE; + } + rewinddir(dp2); - TEST_ASSERT_NOT_NULL(readdir(dp2)); + + if (!readdir(dp2)) { + status = EXIT_FAILURE; + } closedir(dp1); closedir(dp2); - exit(EXIT_SUCCESS); + exit(status); } } TEST(dirent_readdir, hardlink_inode_correct_number) { - const char *originalFilePath = MAIN_DIR "/original_file.txt"; - const char *linkFilePath = MAIN_DIR "/linked_file.txt"; - /* Create the file */ fclose(fopen(originalFilePath, "w+")); - int fileLinkResult = link(originalFilePath, linkFilePath); - - TEST_ASSERT_EQUAL_INT(0, fileLinkResult); + TEST_ASSERT_EQUAL_INT(0, link(originalFilePath, linkFilePath)); struct stat originalFileStat, linkFileStat; - stat(originalFilePath, &originalFileStat); - stat(linkFilePath, &linkFileStat); + TEST_ASSERT_EQUAL_INT(0, stat(originalFilePath, &originalFileStat)); + TEST_ASSERT_EQUAL_INT(0, stat(linkFilePath, &linkFileStat)); TEST_ASSERT_EQUAL_UINT64(originalFileStat.st_ino, linkFileStat.st_ino); @@ -209,7 +214,7 @@ TEST(dirent_readdir, hardlink_inode_correct_number) TEST(dirent_readdir, distinct_inode_nums) { ino_t inode_arr[INO_T_TEST_MAX_DIRS]; - DIR *dp = test_opendir_asserted(MAIN_DIR); + DIR *dp = TEST_OPENDIR_ASSERTED(MAIN_DIR); struct dirent *info; int inode_counter = 0; @@ -231,8 +236,8 @@ TEST(dirent_readdir, distinct_inode_nums) TEST(dirent_readdir, same_file_reading_by_two_pointers) { DIR *dp1, *dp2; - dp1 = test_opendir_asserted(MAIN_DIR); - dp2 = test_opendir_asserted(MAIN_DIR); + dp1 = TEST_OPENDIR_ASSERTED(MAIN_DIR); + dp2 = TEST_OPENDIR_ASSERTED(MAIN_DIR); int counter = 2; @@ -241,13 +246,15 @@ TEST(dirent_readdir, same_file_reading_by_two_pointers) errno = 0; - while (readdir(dp2) != NULL) + while (readdir(dp2) != NULL) { continue; + } TEST_ASSERT_EQUAL_INT(0, errno); - while (readdir(dp1) != NULL) + while (readdir(dp1) != NULL) { counter++; + } TEST_ASSERT_EQUAL_INT(0, errno); @@ -262,31 +269,39 @@ TEST(dirent_readdir, correct_dirent_names) { struct dirent *info; int filename_bits = 0; - DIR *dp = test_opendir_asserted(MAIN_DIR); + DIR *dp = TEST_OPENDIR_ASSERTED(MAIN_DIR); while ((info = readdir(dp)) != NULL) { /* Set corresponding bit of filename_bits each time info->d_name is encountered */ - if (!strcmp(info->d_name, "dir1")) + if (!strcmp(info->d_name, "dir1")) { + filename_bits |= 1; + } - else if (!strcmp(info->d_name, "file1.txt")) + else if (!strcmp(info->d_name, "file1.txt")) { filename_bits |= 2; + } - else if (!strcmp(info->d_name, "file2.dat")) + else if (!strcmp(info->d_name, "file2.dat")) { filename_bits |= 4; + } - else if (!strcmp(info->d_name, ".")) + else if (!strcmp(info->d_name, ".")) { filename_bits |= 8; + } - else if (!strcmp(info->d_name, "file3.json")) + else if (!strcmp(info->d_name, "file3.json")) { filename_bits |= 16; + } - else if (!strcmp(info->d_name, "..")) + else if (!strcmp(info->d_name, "..")) { filename_bits |= 32; + } - else if (!strcmp(info->d_name, "dir2")) + else if (!strcmp(info->d_name, "dir2")) { filename_bits |= 64; + } else TEST_FAIL_MESSAGE(info->d_name); diff --git a/libc/dirent/rewinddir.c b/libc/dirent/rewinddir.c index e195c5c2..54cef51d 100644 --- a/libc/dirent/rewinddir.c +++ b/libc/dirent/rewinddir.c @@ -16,14 +16,14 @@ */ #include -#include #include #include -#include -#include #include +#include + #include +#include "dirent_helper_functions.h" #include "common.h" @@ -35,19 +35,15 @@ TEST_GROUP(dirent_rewinddir); TEST_SETUP(dirent_rewinddir) { - mkdir(MAIN_DIR, 0777); - mkdir(MAIN_DIR "/dir1", 0777); - mkdir(MAIN_DIR "/dir2", 0777); - mkdir(MAIN_DIR "/dir2/nestDir", 0777); + TEST_MKDIR_ASSERTED(MAIN_DIR, S_IRWXU); + TEST_MKDIR_ASSERTED(MAIN_DIR "/dir1", S_IRUSR); + TEST_MKDIR_ASSERTED(MAIN_DIR "/dir2", S_IRWXU); + TEST_MKDIR_ASSERTED(MAIN_DIR "/dir2/nestDir", S_IRUSR); } TEST_TEAR_DOWN(dirent_rewinddir) { - rmdir(MAIN_DIR "/newdir"); - unlink(MAIN_DIR "/hardlink"); - unlink(MAIN_DIR "/symlink"); - remove(MAIN_DIR "/textfile.txt"); rmdir(MAIN_DIR "/dir2/nestDir"); rmdir(MAIN_DIR "/dir1"); rmdir(MAIN_DIR "/dir2"); @@ -55,23 +51,27 @@ TEST_TEAR_DOWN(dirent_rewinddir) } -TEST(dirent_rewinddir, reset_dirstream_position) +TEST(dirent_rewinddir, rewinddir_basic) { struct stat bufBefore, bufAfter; DIR *dp = opendir(MAIN_DIR); - int counter1 = 0, counter2 = 0, counter3 = 0, counter4 = 0; + int counter1, counter2; + counter1 = counter2 = 0; + TEST_ASSERT_NOT_NULL(dp); stat(MAIN_DIR, &bufBefore); - while (readdir(dp)) + while (readdir(dp)) { counter1++; + } rewinddir(dp); - while (readdir(dp)) + while (readdir(dp)) { counter2++; + } TEST_ASSERT_EQUAL_INT(counter1, counter2); TEST_ASSERT_EQUAL_INT(MAIN_DIR_INIT_CONTENTS, counter1); @@ -86,29 +86,52 @@ TEST(dirent_rewinddir, reset_dirstream_position) TEST_ASSERT_EQUAL(bufBefore.st_ino, bufAfter.st_ino); TEST_ASSERT_EQUAL(bufBefore.st_mode, bufAfter.st_mode); + closedir(dp); +} - mkdir(MAIN_DIR "/newdir", 0777); - fclose(fopen(MAIN_DIR "/textfile.txt", "w+")); - TEST_ASSERT_LESS_OR_EQUAL(0, link(MAIN_DIR, MAIN_DIR "/hardlink")); - TEST_ASSERT_EQUAL(0, symlink(MAIN_DIR "/newdir", MAIN_DIR "/symlink")); - while (readdir(dp)) - counter3++; +TEST(dirent_rewinddir, directory_contents_change) +{ + DIR *dp = opendir(MAIN_DIR); + int counter1, counter2, counter3; + counter1 = counter2 = counter3 = 0; - closedir(dp); - dp = opendir(MAIN_DIR); + while (readdir(dp)) { + counter1++; + } + + TEST_ASSERT_EQUAL_INT(MAIN_DIR_INIT_CONTENTS, counter1); + + mkdir(MAIN_DIR "/newdir", S_IRUSR); + close(creat(MAIN_DIR "/textfile.txt", S_IRUSR | S_IWUSR)); + TEST_ASSERT_LESS_OR_EQUAL_INT(0, link(MAIN_DIR, MAIN_DIR "/hardlink")); + TEST_ASSERT_EQUAL_INT(0, symlink(MAIN_DIR "/newdir", MAIN_DIR "/symlink")); + + rewinddir(dp); while (readdir(dp)) { - counter4++; + counter2++; } - TEST_ASSERT_EQUAL_INT(MAIN_DIR_INIT_CONTENTS + 3, counter3); - TEST_ASSERT_EQUAL_INT(counter3, counter4); + TEST_ASSERT_EQUAL_INT(MAIN_DIR_INIT_CONTENTS + 3, counter2); + + rmdir(MAIN_DIR "/newdir"); + unlink(MAIN_DIR "/hardlink"); + unlink(MAIN_DIR "/symlink"); + remove(MAIN_DIR "/textfile.txt"); + rewinddir(dp); + + while (readdir(dp)) { + counter3++; + } + TEST_ASSERT_EQUAL_INT(MAIN_DIR_INIT_CONTENTS, counter3); closedir(dp); } + TEST_GROUP_RUNNER(dirent_rewinddir) { - RUN_TEST_CASE(dirent_rewinddir, reset_dirstream_position); + RUN_TEST_CASE(dirent_rewinddir, rewinddir_basic); + RUN_TEST_CASE(dirent_rewinddir, directory_contents_change); }