Merge pull request 'Add directory stream wrappers' (#40) from 10 into main
All checks were successful
All checks were successful
Reviewed-on: #40
This commit was merged in pull request #40.
This commit is contained in:
154
tests/test_dir.c
Normal file
154
tests/test_dir.c
Normal file
@@ -0,0 +1,154 @@
|
||||
#include "aksl_capture.h"
|
||||
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
static int make_directory(char *path, size_t size)
|
||||
{
|
||||
const char *tmp = getenv("TMPDIR");
|
||||
if ( tmp == NULL || tmp[0] == '\0' ) {
|
||||
tmp = "/tmp";
|
||||
}
|
||||
if ( (size_t)snprintf(path, size, "%s/aksl_dir_XXXXXX", tmp) >= size ) {
|
||||
return 1;
|
||||
}
|
||||
return mkdtemp(path) == NULL;
|
||||
}
|
||||
|
||||
static int test_open_errors_and_nulls(void)
|
||||
{
|
||||
char file[AKSL_TMP_MAX];
|
||||
DIR *dirp = (DIR *)1;
|
||||
struct dirent entry;
|
||||
|
||||
/* opendir propagates missing-path and non-directory failures. */
|
||||
AKSL_CHECK_STATUS(aksl_opendir("/nonexistent/aksl/dir", &dirp), ENOENT);
|
||||
AKSL_CHECK(dirp == NULL);
|
||||
AKSL_CHECK(aksl_temp_file(file, sizeof(file)) == 0);
|
||||
AKSL_CHECK_STATUS(aksl_opendir(file, &dirp), ENOTDIR);
|
||||
|
||||
/* Every pointer required by the wrapped operation rejects NULL. */
|
||||
AKSL_CHECK_STATUS(aksl_opendir(NULL, &dirp), AKERR_NULLPOINTER);
|
||||
AKSL_CHECK_STATUS(aksl_opendir(".", NULL), AKERR_NULLPOINTER);
|
||||
|
||||
/* fdopendir propagates an invalid descriptor and validates its out-param. */
|
||||
AKSL_CHECK_STATUS(aksl_fdopendir(-1, &dirp), EBADF);
|
||||
AKSL_CHECK_STATUS(aksl_fdopendir(0, NULL), AKERR_NULLPOINTER);
|
||||
|
||||
/* The remaining wrappers reject NULL streams and destinations. */
|
||||
AKSL_CHECK_STATUS(aksl_readdir(NULL, &entry), AKERR_NULLPOINTER);
|
||||
AKSL_CHECK_OK(aksl_opendir(".", &dirp));
|
||||
AKSL_CHECK_STATUS(aksl_readdir(dirp, NULL), AKERR_NULLPOINTER);
|
||||
AKSL_CHECK_OK(aksl_closedir(dirp));
|
||||
AKSL_CHECK_STATUS(aksl_closedir(NULL), AKERR_NULLPOINTER);
|
||||
AKSL_CHECK_STATUS(aksl_rewinddir(NULL), AKERR_NULLPOINTER);
|
||||
AKSL_CHECK(unlink(file) == 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_copy_eof_rewind_and_fdopendir(void)
|
||||
{
|
||||
char path[AKSL_TMP_MAX], first_path[AKSL_TMP_MAX], second_path[AKSL_TMP_MAX];
|
||||
struct dirent entry, saved;
|
||||
char first_read[sizeof(entry.d_name)];
|
||||
DIR *dirp = NULL;
|
||||
int fd = -1, seen_first = 0, seen_second = 0;
|
||||
|
||||
AKSL_CHECK(make_directory(path, sizeof(path)) == 0);
|
||||
AKSL_CHECK(snprintf(first_path, sizeof(first_path), "%s/first", path) < (int)sizeof(first_path));
|
||||
AKSL_CHECK(snprintf(second_path, sizeof(second_path), "%s/second", path) < (int)sizeof(second_path));
|
||||
fd = open(first_path, O_CREAT | O_WRONLY, 0600);
|
||||
AKSL_CHECK(fd >= 0);
|
||||
AKSL_CHECK(close(fd) == 0);
|
||||
fd = open(second_path, O_CREAT | O_WRONLY, 0600);
|
||||
AKSL_CHECK(fd >= 0);
|
||||
AKSL_CHECK(close(fd) == 0);
|
||||
|
||||
AKSL_CHECK_OK(aksl_opendir(path, &dirp));
|
||||
do {
|
||||
akerr_ErrorContext *error = aksl_readdir(dirp, &entry);
|
||||
if ( error != NULL ) {
|
||||
int status = error->status;
|
||||
RELEASE_ERROR(error);
|
||||
AKSL_CHECK(status == AKERR_EOF);
|
||||
break;
|
||||
}
|
||||
if ( strcmp(entry.d_name, "first") == 0 ) { saved = entry; seen_first++; }
|
||||
if ( strcmp(entry.d_name, "second") == 0 ) seen_second++;
|
||||
} while ( 1 );
|
||||
AKSL_CHECK(seen_first == 1 && seen_second == 1);
|
||||
AKSL_CHECK(strcmp(saved.d_name, "first") == 0);
|
||||
AKSL_CHECK_OK(aksl_rewinddir(dirp));
|
||||
AKSL_CHECK_OK(aksl_readdir(dirp, &entry));
|
||||
AKSL_CHECK(snprintf(first_read, sizeof(first_read), "%s", entry.d_name) < (int)sizeof(first_read));
|
||||
AKSL_CHECK_OK(aksl_readdir(dirp, &entry));
|
||||
AKSL_CHECK_OK(aksl_rewinddir(dirp));
|
||||
AKSL_CHECK_OK(aksl_readdir(dirp, &entry));
|
||||
AKSL_CHECK(strcmp(entry.d_name, first_read) == 0);
|
||||
AKSL_CHECK_OK(aksl_closedir(dirp));
|
||||
|
||||
fd = open(path, O_RDONLY | O_DIRECTORY);
|
||||
AKSL_CHECK(fd >= 0);
|
||||
AKSL_CHECK_OK(aksl_fdopendir(fd, &dirp));
|
||||
AKSL_CHECK_OK(aksl_readdir(dirp, &entry));
|
||||
AKSL_CHECK_OK(aksl_closedir(dirp));
|
||||
AKSL_CHECK(unlink(first_path) == 0);
|
||||
AKSL_CHECK(unlink(second_path) == 0);
|
||||
AKSL_CHECK(rmdir(path) == 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_empty_directory_reaches_eof_after_dot_entries(void)
|
||||
{
|
||||
char path[AKSL_TMP_MAX];
|
||||
struct dirent entry;
|
||||
DIR *dirp = NULL;
|
||||
int count = 0, saw_dot = 0, saw_dotdot = 0;
|
||||
|
||||
AKSL_CHECK(make_directory(path, sizeof(path)) == 0);
|
||||
AKSL_CHECK_OK(aksl_opendir(path, &dirp));
|
||||
for ( ;; ) {
|
||||
akerr_ErrorContext *error = aksl_readdir(dirp, &entry);
|
||||
if ( error != NULL ) {
|
||||
int status = error->status;
|
||||
RELEASE_ERROR(error);
|
||||
AKSL_CHECK(status == AKERR_EOF);
|
||||
break;
|
||||
}
|
||||
count++;
|
||||
if ( strcmp(entry.d_name, ".") == 0 ) saw_dot++;
|
||||
if ( strcmp(entry.d_name, "..") == 0 ) saw_dotdot++;
|
||||
}
|
||||
AKSL_CHECK(count == 2 && saw_dot == 1 && saw_dotdot == 1);
|
||||
AKSL_CHECK_OK(aksl_closedir(dirp));
|
||||
AKSL_CHECK(rmdir(path) == 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_permission_denied(void)
|
||||
{
|
||||
char path[AKSL_TMP_MAX];
|
||||
DIR *dirp = NULL;
|
||||
AKSL_CHECK(make_directory(path, sizeof(path)) == 0);
|
||||
AKSL_CHECK(chmod(path, 0000) == 0);
|
||||
if ( geteuid() == 0 ) {
|
||||
fprintf(stderr, " (skipped: running as root, chmod 000 denies nothing)\n");
|
||||
} else {
|
||||
AKSL_CHECK_STATUS(aksl_opendir(path, &dirp), EACCES);
|
||||
}
|
||||
AKSL_CHECK(chmod(path, 0700) == 0);
|
||||
AKSL_CHECK(rmdir(path) == 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int failures = 0;
|
||||
AKSL_RUN(failures, test_open_errors_and_nulls);
|
||||
AKSL_RUN(failures, test_copy_eof_rewind_and_fdopendir);
|
||||
AKSL_RUN(failures, test_empty_directory_reaches_eof_after_dot_entries);
|
||||
AKSL_RUN(failures, test_permission_denied);
|
||||
AKSL_REPORT(failures);
|
||||
}
|
||||
Reference in New Issue
Block a user