]> Kevux Git Server - fll/commitdiff
Update: Add unit tests for f_path.
authorKevin Day <thekevinday@gmail.com>
Fri, 13 May 2022 06:26:33 +0000 (01:26 -0500)
committerKevin Day <thekevinday@gmail.com>
Fri, 13 May 2022 06:26:33 +0000 (01:26 -0500)
26 files changed:
level_0/f_path/data/build/dependencies-tests [new file with mode: 0644]
level_0/f_path/data/build/settings-mocks [new file with mode: 0644]
level_0/f_path/data/build/settings-tests [new file with mode: 0644]
level_0/f_path/data/build/testfile [new file with mode: 0644]
level_0/f_path/tests/unit/c/mock-path.c [new file with mode: 0644]
level_0/f_path/tests/unit/c/mock-path.h [new file with mode: 0644]
level_0/f_path/tests/unit/c/test-path-change.c [new file with mode: 0644]
level_0/f_path/tests/unit/c/test-path-change.h [new file with mode: 0644]
level_0/f_path/tests/unit/c/test-path-change_at.c [new file with mode: 0644]
level_0/f_path/tests/unit/c/test-path-change_at.h [new file with mode: 0644]
level_0/f_path/tests/unit/c/test-path-current.c [new file with mode: 0644]
level_0/f_path/tests/unit/c/test-path-current.h [new file with mode: 0644]
level_0/f_path/tests/unit/c/test-path-directory_cleanup.c [new file with mode: 0644]
level_0/f_path/tests/unit/c/test-path-directory_cleanup.h [new file with mode: 0644]
level_0/f_path/tests/unit/c/test-path-is.c [new file with mode: 0644]
level_0/f_path/tests/unit/c/test-path-is.h [new file with mode: 0644]
level_0/f_path/tests/unit/c/test-path-is_absolute.c [new file with mode: 0644]
level_0/f_path/tests/unit/c/test-path-is_absolute.h [new file with mode: 0644]
level_0/f_path/tests/unit/c/test-path-is_relative.c [new file with mode: 0644]
level_0/f_path/tests/unit/c/test-path-is_relative.h [new file with mode: 0644]
level_0/f_path/tests/unit/c/test-path-is_relative_current.c [new file with mode: 0644]
level_0/f_path/tests/unit/c/test-path-is_relative_current.h [new file with mode: 0644]
level_0/f_path/tests/unit/c/test-path-real.c [new file with mode: 0644]
level_0/f_path/tests/unit/c/test-path-real.h [new file with mode: 0644]
level_0/f_path/tests/unit/c/test-path.c [new file with mode: 0644]
level_0/f_path/tests/unit/c/test-path.h [new file with mode: 0644]

diff --git a/level_0/f_path/data/build/dependencies-tests b/level_0/f_path/data/build/dependencies-tests
new file mode 100644 (file)
index 0000000..dea3179
--- /dev/null
@@ -0,0 +1,3 @@
+# fss-0001
+
+cmocka 1.*
diff --git a/level_0/f_path/data/build/settings-mocks b/level_0/f_path/data/build/settings-mocks
new file mode 100644 (file)
index 0000000..a9730e0
--- /dev/null
@@ -0,0 +1,63 @@
+# fss-0001
+#
+# Build the project with appropriate mocks linked in via the dynamic linker's "--wrap" functionality.
+#
+# The -Wl,--wrap does not work across shared files.
+# Therefore, this file is a work-around to inject the mocks into the library for testing purposes.
+# This should exactly match the "settings" file, except for the additional "-Wl,--wrap" parts and the additional mock source file.
+#
+# The flags -o0 must be passed to prevent the compiler from optimizing away any functions being mocked (which results in the mock not happening and a real function being called).
+# Alternatively, figure out which optimization that is disabled by -o0 and have that specific optimization disabled.
+#
+
+build_name f_path
+
+version_major 0
+version_minor 5
+version_micro 9
+version_file micro
+version_target minor
+
+modes individual clang test
+modes_default individual
+
+build_compiler gcc
+build_compiler-clang clang
+build_indexer ar
+build_indexer_arguments rcs
+build_language c
+
+build_libraries -lc
+build_libraries-individual -lf_memory -lf_string
+
+build_sources_library path.c private-path.c path/common.c ../../tests/unit/c/mock-path.c
+
+build_sources_headers path.h path/common.h
+
+build_script yes
+build_shared yes
+build_static no
+
+path_headers fll/level_0
+path_library_script script
+path_library_shared shared
+path_library_static static
+
+has_path_standard yes
+preserve_path_headers yes
+
+search_exclusive yes
+search_shared yes
+search_static yes
+
+flags -O0 -z now -g -fdiagnostics-color=always -Wno-logical-not-parentheses -Wno-parentheses
+flags-clang -Wno-logical-op-parentheses
+flags-test -fstack-protector
+
+flags_library -fPIC
+
+# Inject mocks.
+flags -Wl,--wrap=chdir
+flags -Wl,--wrap=fchdir
+flags -Wl,--wrap=getcwd
+flags -Wl,--wrap=realpath
diff --git a/level_0/f_path/data/build/settings-tests b/level_0/f_path/data/build/settings-tests
new file mode 100644 (file)
index 0000000..f9fed5a
--- /dev/null
@@ -0,0 +1,53 @@
+# fss-0001
+#
+# Builds a program that is links to the generated library and is executed to perform tests.
+#
+# Memory leaks in the test program can be checked for by running valgrind with this executable.
+#
+
+build_name test-f_path
+
+version_major 0
+version_minor 5
+version_micro 9
+version_file major
+version_target major
+
+modes individual clang test
+modes_default individual
+
+build_compiler gcc
+build_compiler-clang clang
+build_indexer ar
+build_indexer_arguments rcs
+build_language c
+
+build_libraries -lc -lcmocka
+build_libraries-individual -lf_memory -lf_string -lf_type_array -lf_utf -lf_path
+
+build_sources_program test-path-change.c test-path-change_at.c test-path-current.c test-path-directory_cleanup.c test-path-is.c test-path-is_absolute.c test-path-is_relative.c test-path-is_relative_current.c test-path-real.c
+build_sources_program test-path.c
+
+build_script no
+build_shared yes
+build_static no
+
+path_headers tests/unit/c
+path_sources tests/unit/c
+
+has_path_standard no
+preserve_path_headers yes
+
+search_exclusive yes
+search_shared yes
+search_static yes
+
+defines -Ibuild/includes
+defines_static -Lbuild/libraries/static
+defines_shared -Lbuild/libraries/shared
+
+flags -O2 -z now -g -fdiagnostics-color=always -Wno-logical-not-parentheses -Wno-parentheses
+flags-clang -Wno-logical-op-parentheses
+flags-test -fstack-protector -Wall
+
+flags_program -fPIE
diff --git a/level_0/f_path/data/build/testfile b/level_0/f_path/data/build/testfile
new file mode 100644 (file)
index 0000000..c0f71b4
--- /dev/null
@@ -0,0 +1,45 @@
+# fss-0005 iki-0002
+
+settings:
+  load_build yes
+  fail exit
+
+  environment LD_LIBRARY_PATH
+
+main:
+  build settings-mocks
+  build settings-tests
+
+  operate ld_library_path
+
+  if exists build/programs/shared/test-f_path
+    shell build/programs/shared/test-f_path
+
+  if exists build/programs/static/test-f_path
+    shell build/programs/static/test-f_path
+
+  if not exists build/programs/shared/test-f_path
+  and not exists build/programs/static/test-f_path
+    operate not_created
+
+not_created:
+  print
+  print 'context:"error"Failed to test due to being unable to find either a shared or static test binary to perform tests. context:"reset"'
+
+  exit failure
+
+ld_library_path:
+  if defined environment LD_LIBRARY_PATH
+  and defined parameter work
+    define LD_LIBRARY_PATH 'build/libraries/shared:parameter:"work:value"libraries/shared:define:"LD_LIBRARY_PATH"'
+
+  else
+  if defined environment LD_LIBRARY_PATH
+    define LD_LIBRARY_PATH 'build/libraries/shared:parameter:define:"LD_LIBRARY_PATH"'
+
+  else
+  if defined parameter work
+    define LD_LIBRARY_PATH 'build/libraries/shared:parameter:"work:value"libraries/shared'
+
+  else
+    define LD_LIBRARY_PATH build/libraries/shared
diff --git a/level_0/f_path/tests/unit/c/mock-path.c b/level_0/f_path/tests/unit/c/mock-path.c
new file mode 100644 (file)
index 0000000..ea7d9ff
--- /dev/null
@@ -0,0 +1,63 @@
+#include "mock-path.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int __wrap_chdir(const char *path) {
+
+  const bool failure = mock_type(bool);
+
+  if (failure) {
+    errno = mock_type(int);
+
+    return -1;
+  }
+
+  return mock_type(int);
+}
+
+int __wrap_fchdir(int fd) {
+
+  const bool failure = mock_type(bool);
+
+  if (failure) {
+    errno = mock_type(int);
+
+    return -1;
+  }
+
+  return mock_type(int);
+}
+
+char *__wrap_getcwd(char *buf, size_t size) {
+
+  const bool failure = mock_type(bool);
+
+  if (failure) {
+    errno = mock_type(int);
+
+    return 0;
+  }
+
+  return mock_type(char *);
+}
+
+char *__wrap_realpath(const char *path, char *resolved_path) {
+
+  const bool failure = mock_type(bool);
+
+  if (failure) {
+    errno = mock_type(int);
+
+    return 0;
+  }
+
+  resolved_path = mock_type(char *);
+
+  return resolved_path;
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_path/tests/unit/c/mock-path.h b/level_0/f_path/tests/unit/c/mock-path.h
new file mode 100644 (file)
index 0000000..505eea4
--- /dev/null
@@ -0,0 +1,40 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: Path
+ * API Version: 0.5
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the path project.
+ */
+#ifndef _MOCK__path_h
+#define _MOCK__path_h
+
+// Libc includes.
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <stdint.h>
+
+// cmocka includes.
+#include <cmocka.h>
+
+// FLL-0 includes.
+#include <fll/level_0/path.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+const static int mock_errno_generic = 32767;
+
+extern int __wrap_chdir(const char *path);
+extern int __wrap_fchdir(int fd);
+extern char *__wrap_getcwd(char *buf, size_t size);
+extern char *__wrap_realpath(const char *path, char *resolved_path);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _MOCK__path_h
diff --git a/level_0/f_path/tests/unit/c/test-path-change.c b/level_0/f_path/tests/unit/c/test-path-change.c
new file mode 100644 (file)
index 0000000..ca8b704
--- /dev/null
@@ -0,0 +1,63 @@
+#include "test-path.h"
+#include "test-path-change.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void test__f_path_change__fails(void **state) {
+
+  const f_string_static_t path = macro_f_string_static_t_initialize("test", 0, 4);
+
+  int errnos[] = {
+    EACCES,
+    EFAULT,
+    EIO,
+    ELOOP,
+    ENAMETOOLONG,
+    ENOENT,
+    ENOMEM,
+    ENOTDIR,
+    mock_errno_generic,
+  };
+
+  f_status_t statuss[] = {
+    F_access_denied,
+    F_buffer,
+    F_input_output,
+    F_loop,
+    F_name,
+    F_file_found_not,
+    F_memory_not,
+    F_directory,
+    F_failure,
+  };
+
+  for (int i = 0; i < 9; ++i) {
+
+    will_return(__wrap_chdir, true);
+    will_return(__wrap_chdir, errnos[i]);
+
+    const f_status_t status = f_path_change(path);
+
+    assert_int_equal(status, F_status_set_error(statuss[i]));
+  } // for
+}
+
+void test__f_path_change__works(void **state) {
+
+  const f_string_static_t path = macro_f_string_static_t_initialize("test", 0, 4);
+
+  {
+    will_return(__wrap_chdir, F_false);
+    will_return(__wrap_chdir, 0);
+
+    const f_status_t status = f_path_change(path);
+
+    assert_int_equal(status, F_none);
+  }
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_path/tests/unit/c/test-path-change.h b/level_0/f_path/tests/unit/c/test-path-change.h
new file mode 100644 (file)
index 0000000..9bc56ee
--- /dev/null
@@ -0,0 +1,27 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: Path
+ * API Version: 0.5
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the path project.
+ */
+#ifndef _TEST__F_path_change_h
+#define _TEST__F_path_change_h
+
+/**
+ * Test that function fails.
+ *
+ * @see f_path_change()
+ */
+extern void test__f_path_change__fails(void **state);
+
+/**
+ * Test that function works.
+ *
+ * @see f_path_change()
+ */
+extern void test__f_path_change__works(void **state);
+
+#endif // _TEST__F_path_change_h
diff --git a/level_0/f_path/tests/unit/c/test-path-change_at.c b/level_0/f_path/tests/unit/c/test-path-change_at.c
new file mode 100644 (file)
index 0000000..a13ee01
--- /dev/null
@@ -0,0 +1,65 @@
+#include "test-path.h"
+#include "test-path-change_at.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void test__f_path_change_at__fails(void **state) {
+
+  const int id = 1;
+
+  int errnos[] = {
+    EACCES,
+    EBADF,
+    EFAULT,
+    EIO,
+    ELOOP,
+    ENAMETOOLONG,
+    ENOENT,
+    ENOMEM,
+    ENOTDIR,
+    mock_errno_generic,
+  };
+
+  f_status_t statuss[] = {
+    F_access_denied,
+    F_directory_descriptor,
+    F_buffer,
+    F_input_output,
+    F_loop,
+    F_name,
+    F_file_found_not,
+    F_memory_not,
+    F_directory,
+    F_failure,
+  };
+
+  for (int i = 0; i < 10; ++i) {
+
+    will_return(__wrap_fchdir, true);
+    will_return(__wrap_fchdir, errnos[i]);
+
+    const f_status_t status = f_path_change_at(id);
+
+    assert_int_equal(status, F_status_set_error(statuss[i]));
+  } // for
+}
+
+void test__f_path_change_at__works(void **state) {
+
+  const int id = 1;
+
+  {
+    will_return(__wrap_fchdir, F_false);
+    will_return(__wrap_fchdir, 0);
+
+    const f_status_t status = f_path_change_at(id);
+
+    assert_int_equal(status, F_none);
+  }
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_path/tests/unit/c/test-path-change_at.h b/level_0/f_path/tests/unit/c/test-path-change_at.h
new file mode 100644 (file)
index 0000000..c1e79dd
--- /dev/null
@@ -0,0 +1,27 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: Path
+ * API Version: 0.5
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the path project.
+ */
+#ifndef _TEST__F_path_change_at_h
+#define _TEST__F_path_change_at_h
+
+/**
+ * Test that function fails.
+ *
+ * @see f_path_change_at()
+ */
+extern void test__f_path_change_at__fails(void **state);
+
+/**
+ * Test that function works.
+ *
+ * @see f_path_change_at()
+ */
+extern void test__f_path_change_at__works(void **state);
+
+#endif // _TEST__F_path_change_at_h
diff --git a/level_0/f_path/tests/unit/c/test-path-current.c b/level_0/f_path/tests/unit/c/test-path-current.c
new file mode 100644 (file)
index 0000000..5627d2e
--- /dev/null
@@ -0,0 +1,140 @@
+#include "test-path.h"
+#include "test-path-current.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void test__f_path_current__fails(void **state) {
+
+  f_string_dynamic_t destination = f_string_dynamic_t_initialize;
+
+  {
+    int errnos[] = {
+      EACCES,
+      EFAULT,
+      EINVAL,
+      ENAMETOOLONG,
+      ENOENT,
+      ENOMEM,
+      ERANGE,
+      mock_errno_generic,
+    };
+
+    f_status_t statuss[] = {
+      F_access_denied,
+      F_buffer,
+      F_parameter,
+      F_name,
+      F_file_found_not,
+      F_memory_not,
+      F_buffer_too_small,
+      F_failure,
+    };
+
+    for (int i = 0; i < 8; ++i) {
+
+      will_return(__wrap_getcwd, true);
+      will_return(__wrap_getcwd, errnos[i]);
+
+      const f_status_t status = f_path_current(F_false, &destination);
+
+      assert_int_equal(status, F_status_set_error(statuss[i]));
+    } // for
+  }
+
+  destination.used = 0;
+
+  {
+    int errnos[] = {
+      EACCES,
+      EINVAL,
+      EIO,
+      ELOOP,
+      ENAMETOOLONG,
+      ENOENT,
+      ENOMEM,
+      ENOTDIR,
+      mock_errno_generic,
+    };
+
+    f_status_t statuss[] = {
+      F_access_denied,
+      F_parameter,
+      F_input_output,
+      F_loop,
+      F_name,
+      F_file_found_not,
+      F_memory_not,
+      F_directory,
+      F_failure,
+    };
+
+    for (int i = 0; i < 9; ++i) {
+
+      will_return(__wrap_getcwd, false);
+      will_return(__wrap_getcwd, 0);
+
+      will_return(__wrap_realpath, true);
+      will_return(__wrap_realpath, errnos[i]);
+
+      const f_status_t status = f_path_current(F_true, &destination);
+
+      assert_int_equal(status, F_status_set_error(statuss[i]));
+    } // for
+  }
+
+  f_string_dynamic_resize(0, &destination);
+}
+
+#ifndef _di_level_0_parameter_checking_
+  void test__f_path_current__parameter_checking(void **state) {
+
+    {
+      const f_status_t status = f_path_current(F_false, 0);
+
+      assert_int_equal(F_status_set_fine(status), F_parameter);
+    }
+  }
+#endif // _di_level_0_parameter_checking_
+
+void test__f_path_current__works(void **state) {
+
+  const f_string_static_t path = macro_f_string_static_t_initialize("test", 0, 4);
+  const f_string_static_t path_real = macro_f_string_static_t_initialize("/test", 0, 5);
+
+  f_string_dynamic_t destination = f_string_dynamic_t_initialize;
+
+  {
+    will_return(__wrap_getcwd, F_false);
+    will_return(__wrap_getcwd, path.string);
+
+    const f_status_t status = f_path_current(F_false, &destination);
+
+    assert_int_equal(status, F_none);
+    assert_int_equal(destination.used, path.used);
+    assert_string_equal(destination.string, path.string);
+  }
+
+  destination.used = 0;
+
+  {
+    will_return(__wrap_getcwd, F_false);
+    will_return(__wrap_getcwd, path.string);
+
+    will_return(__wrap_realpath, F_false);
+    will_return(__wrap_realpath, path_real.string);
+
+    const f_status_t status = f_path_current(F_true, &destination);
+
+    assert_int_equal(status, F_none);
+    assert_int_equal(destination.used, path_real.used);
+    assert_string_equal(destination.string, path_real.string);
+  }
+
+  f_string_dynamic_resize(0, &destination);
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_path/tests/unit/c/test-path-current.h b/level_0/f_path/tests/unit/c/test-path-current.h
new file mode 100644 (file)
index 0000000..0f3acb8
--- /dev/null
@@ -0,0 +1,22 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: Path
+ * API Version: 0.5
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the path project.
+ */
+#ifndef _TEST__F_path_current_h
+#define _TEST__F_path_current_h
+
+/**
+ * Test that parameter checking works as expected.
+ *
+ * @see f_path_current()
+ */
+#ifndef _di_level_0_parameter_checking_
+  extern void test__f_path_current__parameter_checking(void **state);
+#endif // _di_level_0_parameter_checking_
+
+#endif // _TEST__F_path_current_h
diff --git a/level_0/f_path/tests/unit/c/test-path-directory_cleanup.c b/level_0/f_path/tests/unit/c/test-path-directory_cleanup.c
new file mode 100644 (file)
index 0000000..744c616
--- /dev/null
@@ -0,0 +1,83 @@
+#include "test-path.h"
+#include "test-path-directory_cleanup.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _di_level_0_parameter_checking_
+  void test__f_path_directory_cleanup__parameter_checking(void **state) {
+
+    const f_string_static_t path = macro_f_string_static_t_initialize("test", 0, 4);
+
+    {
+      const f_status_t status = f_path_directory_cleanup(path, 0);
+
+      assert_int_equal(F_status_set_fine(status), F_parameter);
+    }
+  }
+#endif // _di_level_0_parameter_checking_
+
+void test__f_path_directory_cleanup__works(void **state) {
+
+  const f_string_static_t paths[] = {
+    macro_f_string_static_t_initialize("path", 0, 4),
+    macro_f_string_static_t_initialize("also path", 0, 9),
+    macro_f_string_static_t_initialize("", 0, 0),
+    macro_f_string_static_t_initialize("/", 0, 1),
+    macro_f_string_static_t_initialize("///", 0, 3),
+    macro_f_string_static_t_initialize("///path", 0, 7),
+    macro_f_string_static_t_initialize("///path////", 0, 11),
+    macro_f_string_static_t_initialize("///also////path", 0, 15),
+    macro_f_string_static_t_initialize("../", 0, 3),
+    macro_f_string_static_t_initialize("..///", 0, 3),
+    macro_f_string_static_t_initialize("..///path", 0, 9),
+    macro_f_string_static_t_initialize("..///path////", 0, 11),
+    macro_f_string_static_t_initialize("..///also////path", 0, 17),
+    macro_f_string_static_t_initialize("also///..//path", 0, 15),
+  };
+
+  const f_string_static_t expecteds[] = {
+    macro_f_string_static_t_initialize("path/", 0, 5),
+    macro_f_string_static_t_initialize("also path/", 0, 10),
+    macro_f_string_static_t_initialize("", 0, 0),
+    macro_f_string_static_t_initialize("/", 0, 1),
+    macro_f_string_static_t_initialize("/", 0, 1),
+    macro_f_string_static_t_initialize("/path/", 0, 6),
+    macro_f_string_static_t_initialize("/path/", 0, 6),
+    macro_f_string_static_t_initialize("/also/path/", 0, 11),
+    macro_f_string_static_t_initialize("../", 0, 3),
+    macro_f_string_static_t_initialize("../", 0, 3),
+    macro_f_string_static_t_initialize("../path/", 0, 8),
+    macro_f_string_static_t_initialize("../path/", 0, 8),
+    macro_f_string_static_t_initialize("../also/path/", 0, 13),
+    macro_f_string_static_t_initialize("also/../path/", 0, 13),
+  };
+
+  f_string_dynamic_t destination = f_string_dynamic_t_initialize;
+
+  for (f_array_length_t i = 0; i < 14; ++i, destination.used = 0) {
+
+    const f_status_t status = f_path_directory_cleanup(paths[i], &destination);
+
+    assert_int_equal(status, F_none);
+    assert_int_equal(destination.used, expecteds[i].used);
+
+    if (destination.used) {
+      assert_string_equal(destination.string, expecteds[i].string);
+
+      // Check that string is NULL terminated.
+      assert_true(destination.size > destination.used);
+      assert_int_equal(destination.string[destination.used], 0);
+    }
+
+    // De-allocate each pass to ensure that the NULL termination check is accurate.
+    f_string_dynamic_resize(0, &destination);
+  } // for
+
+  f_string_dynamic_resize(0, &destination);
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_path/tests/unit/c/test-path-directory_cleanup.h b/level_0/f_path/tests/unit/c/test-path-directory_cleanup.h
new file mode 100644 (file)
index 0000000..6c64516
--- /dev/null
@@ -0,0 +1,29 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: Path
+ * API Version: 0.5
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the path project.
+ */
+#ifndef _TEST__F_path_directory_cleanup_h
+#define _TEST__F_path_directory_cleanup_h
+
+/**
+ * Test that parameter checking works as expected.
+ *
+ * @see f_path_directory_cleanup()
+ */
+#ifndef _di_level_0_parameter_checking_
+  extern void test__f_path_directory_cleanup__parameter_checking(void **state);
+#endif // _di_level_0_parameter_checking_
+
+/**
+ * Test that function works.
+ *
+ * @see f_path_directory_cleanup()
+ */
+extern void test__f_path_directory_cleanup__works(void **state);
+
+#endif // _TEST__F_path_directory_cleanup_h
diff --git a/level_0/f_path/tests/unit/c/test-path-is.c b/level_0/f_path/tests/unit/c/test-path-is.c
new file mode 100644 (file)
index 0000000..5f1d0dd
--- /dev/null
@@ -0,0 +1,53 @@
+#include "test-path.h"
+#include "test-path-is.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void test__f_path_is__returns_false(void **state) {
+
+  const f_string_static_t paths[] = {
+    macro_f_string_static_t_initialize("'false", 0, 6),
+    macro_f_string_static_t_initialize("false'", 0, 6),
+    macro_f_string_static_t_initialize("f a l s e", 0, 9),
+    macro_f_string_static_t_initialize("0+-12, false", 0, 12),
+  };
+
+  for (uint8_t i = 0; i < 4; ++i) {
+
+    const f_status_t status = f_path_is(paths[i]);
+
+    assert_int_equal(F_status_set_fine(status), F_false);
+  } // for
+}
+
+void test__f_path_is__returns_data_not(void **state) {
+
+  {
+    const f_status_t status = f_path_is(f_string_empty_s);
+
+    assert_int_equal(F_status_set_fine(status), F_data_not);
+  }
+}
+
+void test__f_path_is__returns_true(void **state) {
+
+  const f_string_static_t paths[] = {
+    macro_f_string_static_t_initialize("'true/", 0, 6),
+    macro_f_string_static_t_initialize("/true'", 0, 6),
+    macro_f_string_static_t_initialize("t /r u e", 0, 8),
+    macro_f_string_static_t_initialize("0+-12,/ true", 0, 12),
+  };
+
+  for (uint8_t i = 0; i < 4; ++i) {
+
+    const f_status_t status = f_path_is(paths[i]);
+
+    assert_int_equal(F_status_set_fine(status), F_true);
+  } // for
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_path/tests/unit/c/test-path-is.h b/level_0/f_path/tests/unit/c/test-path-is.h
new file mode 100644 (file)
index 0000000..b42dab8
--- /dev/null
@@ -0,0 +1,34 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: Path
+ * API Version: 0.5
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the path project.
+ */
+#ifndef _TEST__F_path_is_h
+#define _TEST__F_path_is_h
+
+/**
+ * Test that function returns F_false.
+ *
+ * @see f_path_is()
+ */
+extern void test__f_path_is__returns_false(void **state);
+
+/**
+ * Test that function returns F_data_not.
+ *
+ * @see f_path_is()
+ */
+extern void test__f_path_is__returns_data_not(void **state);
+
+/**
+ * Test that function returns F_true.
+ *
+ * @see f_path_is()
+ */
+extern void test__f_path_is__returns_true(void **state);
+
+#endif // _TEST__F_path_is_h
diff --git a/level_0/f_path/tests/unit/c/test-path-is_absolute.c b/level_0/f_path/tests/unit/c/test-path-is_absolute.c
new file mode 100644 (file)
index 0000000..eab0ed6
--- /dev/null
@@ -0,0 +1,53 @@
+#include "test-path.h"
+#include "test-path-is_absolute.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void test__f_path_is_absolute__returns_false(void **state) {
+
+  const f_string_static_t paths[] = {
+    macro_f_string_static_t_initialize("'fa/lse", 0, 7),
+    macro_f_string_static_t_initialize("false'/", 0, 7),
+    macro_f_string_static_t_initialize("f a l s e", 0, 9),
+    macro_f_string_static_t_initialize("0+-12,/ false", 0, 13),
+  };
+
+  for (uint8_t i = 0; i < 4; ++i) {
+
+    const f_status_t status = f_path_is_absolute(paths[i]);
+
+    assert_int_equal(F_status_set_fine(status), F_false);
+  } // for
+}
+
+void test__f_path_is_absolute__returns_data_not(void **state) {
+
+  {
+    const f_status_t status = f_path_is_absolute(f_string_empty_s);
+
+    assert_int_equal(F_status_set_fine(status), F_data_not);
+  }
+}
+
+void test__f_path_is_absolute__returns_true(void **state) {
+
+  const f_string_static_t paths[] = {
+    macro_f_string_static_t_initialize("/'true/", 0, 7),
+    macro_f_string_static_t_initialize("/true'", 0, 6),
+    macro_f_string_static_t_initialize("/t /r u e", 0, 9),
+    macro_f_string_static_t_initialize("/0+-12,/ true", 0, 13),
+  };
+
+  for (uint8_t i = 0; i < 4; ++i) {
+
+    const f_status_t status = f_path_is_absolute(paths[i]);
+
+    assert_int_equal(F_status_set_fine(status), F_true);
+  } // for
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_path/tests/unit/c/test-path-is_absolute.h b/level_0/f_path/tests/unit/c/test-path-is_absolute.h
new file mode 100644 (file)
index 0000000..c31444b
--- /dev/null
@@ -0,0 +1,34 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: Path
+ * API Version: 0.5
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the path project.
+ */
+#ifndef _TEST__F_path_is_absolute_h
+#define _TEST__F_path_is_absolute_h
+
+/**
+ * Test that function returns F_false.
+ *
+ * @see f_path_is_absolute()
+ */
+extern void test__f_path_is_absolute__returns_false(void **state);
+
+/**
+ * Test that function returns F_data_not.
+ *
+ * @see f_path_is_absolute()
+ */
+extern void test__f_path_is_absolute__returns_data_not(void **state);
+
+/**
+ * Test that function returns F_true.
+ *
+ * @see f_path_is_absolute()
+ */
+extern void test__f_path_is_absolute__returns_true(void **state);
+
+#endif // _TEST__F_path_is_absolute_h
diff --git a/level_0/f_path/tests/unit/c/test-path-is_relative.c b/level_0/f_path/tests/unit/c/test-path-is_relative.c
new file mode 100644 (file)
index 0000000..e18b750
--- /dev/null
@@ -0,0 +1,53 @@
+#include "test-path.h"
+#include "test-path-is_relative.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void test__f_path_is_relative__returns_false(void **state) {
+
+  const f_string_static_t paths[] = {
+    macro_f_string_static_t_initialize("/'false", 0, 7),
+    macro_f_string_static_t_initialize("/false'", 0, 7),
+    macro_f_string_static_t_initialize("/f a l s e", 0, 10),
+    macro_f_string_static_t_initialize("/0+-12, false", 0, 13),
+  };
+
+  for (uint8_t i = 0; i < 4; ++i) {
+
+    const f_status_t status = f_path_is_relative(paths[i]);
+
+    assert_int_equal(F_status_set_fine(status), F_false);
+  } // for
+}
+
+void test__f_path_is_relative__returns_data_not(void **state) {
+
+  {
+    const f_status_t status = f_path_is_relative(f_string_empty_s);
+
+    assert_int_equal(F_status_set_fine(status), F_data_not);
+  }
+}
+
+void test__f_path_is_relative__returns_true(void **state) {
+
+  const f_string_static_t paths[] = {
+    macro_f_string_static_t_initialize("'true/", 0, 6),
+    macro_f_string_static_t_initialize("./true'", 0, 7),
+    macro_f_string_static_t_initialize("t /r u e", 0, 8),
+    macro_f_string_static_t_initialize("0+-12,/ true", 0, 12),
+  };
+
+  for (uint8_t i = 0; i < 4; ++i) {
+
+    const f_status_t status = f_path_is_relative(paths[i]);
+
+    assert_int_equal(F_status_set_fine(status), F_true);
+  } // for
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_path/tests/unit/c/test-path-is_relative.h b/level_0/f_path/tests/unit/c/test-path-is_relative.h
new file mode 100644 (file)
index 0000000..6ee94aa
--- /dev/null
@@ -0,0 +1,34 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: Path
+ * API Version: 0.5
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the path project.
+ */
+#ifndef _TEST__F_path_is_relative_h
+#define _TEST__F_path_is_relative_h
+
+/**
+ * Test that function returns F_false.
+ *
+ * @see f_path_is_relative()
+ */
+extern void test__f_path_is_relative__returns_false(void **state);
+
+/**
+ * Test that function returns F_data_not.
+ *
+ * @see f_path_is_relative()
+ */
+extern void test__f_path_is_relative__returns_data_not(void **state);
+
+/**
+ * Test that function returns F_true.
+ *
+ * @see f_path_is_relative()
+ */
+extern void test__f_path_is_relative__returns_true(void **state);
+
+#endif // _TEST__F_path_is_relative_h
diff --git a/level_0/f_path/tests/unit/c/test-path-is_relative_current.c b/level_0/f_path/tests/unit/c/test-path-is_relative_current.c
new file mode 100644 (file)
index 0000000..677a1fc
--- /dev/null
@@ -0,0 +1,53 @@
+#include "test-path.h"
+#include "test-path-is_relative_current.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void test__f_path_is_relative_current__returns_false(void **state) {
+
+  const f_string_static_t paths[] = {
+    macro_f_string_static_t_initialize("'false", 0, 6),
+    macro_f_string_static_t_initialize("false'", 0, 6),
+    macro_f_string_static_t_initialize("f a l s e", 0, 9),
+    macro_f_string_static_t_initialize("0+-12, false", 0, 12),
+  };
+
+  for (uint8_t i = 0; i < 4; ++i) {
+
+    const f_status_t status = f_path_is_relative_current(paths[i]);
+
+    assert_int_equal(F_status_set_fine(status), F_false);
+  } // for
+}
+
+void test__f_path_is_relative_current__returns_data_not(void **state) {
+
+  {
+    const f_status_t status = f_path_is_relative_current(f_string_empty_s);
+
+    assert_int_equal(F_status_set_fine(status), F_data_not);
+  }
+}
+
+void test__f_path_is_relative_current__returns_true(void **state) {
+
+  const f_string_static_t paths[] = {
+    macro_f_string_static_t_initialize("./'true/", 0, 8),
+    macro_f_string_static_t_initialize("../true'", 0, 8),
+    macro_f_string_static_t_initialize("./../t /r u e", 0, 13),
+    macro_f_string_static_t_initialize("./0+-12,/ true", 0, 14),
+  };
+
+  for (uint8_t i = 0; i < 4; ++i) {
+
+    const f_status_t status = f_path_is_relative_current(paths[i]);
+
+    assert_int_equal(F_status_set_fine(status), F_true);
+  } // for
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_path/tests/unit/c/test-path-is_relative_current.h b/level_0/f_path/tests/unit/c/test-path-is_relative_current.h
new file mode 100644 (file)
index 0000000..90ca5a6
--- /dev/null
@@ -0,0 +1,34 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: Path
+ * API Version: 0.5
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the path project.
+ */
+#ifndef _TEST__F_path_is_relative_current_h
+#define _TEST__F_path_is_relative_current_h
+
+/**
+ * Test that function returns F_false.
+ *
+ * @see f_path_is_relative_current()
+ */
+extern void test__f_path_is_relative_current__returns_false(void **state);
+
+/**
+ * Test that function returns F_data_not.
+ *
+ * @see f_path_is_relative_current()
+ */
+extern void test__f_path_is_relative_current__returns_data_not(void **state);
+
+/**
+ * Test that function returns F_true.
+ *
+ * @see f_path_is_relative_current()
+ */
+extern void test__f_path_is_relative_current__returns_true(void **state);
+
+#endif // _TEST__F_path_is_relative_current_h
diff --git a/level_0/f_path/tests/unit/c/test-path-real.c b/level_0/f_path/tests/unit/c/test-path-real.c
new file mode 100644 (file)
index 0000000..a3957f6
--- /dev/null
@@ -0,0 +1,87 @@
+#include "test-path.h"
+#include "test-path-real.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void test__f_path_real__fails(void **state) {
+
+  const f_string_static_t path = macro_f_string_static_t_initialize("test", 0, 4);
+
+  f_string_dynamic_t destination = f_string_dynamic_t_initialize;
+
+  int errnos[] = {
+    EACCES,
+    EINVAL,
+    EIO,
+    ELOOP,
+    ENAMETOOLONG,
+    ENOENT,
+    ENOMEM,
+    ENOTDIR,
+    mock_errno_generic,
+  };
+
+  f_status_t statuss[] = {
+    F_access_denied,
+    F_parameter,
+    F_input_output,
+    F_loop,
+    F_name,
+    F_file_found_not,
+    F_memory_not,
+    F_directory,
+    F_failure,
+  };
+
+  for (int i = 0; i < 9; ++i, destination.used = 0) {
+
+    will_return(__wrap_realpath, true);
+    will_return(__wrap_realpath, errnos[i]);
+
+    const f_status_t status = f_path_real(path, &destination);
+
+    assert_int_equal(status, F_status_set_error(statuss[i]));
+  } // for
+
+  f_string_dynamic_resize(0, &destination);
+}
+
+#ifndef _di_level_0_parameter_checking_
+  void test__f_path_real__parameter_checking(void **state) {
+
+    const f_string_static_t path = macro_f_string_static_t_initialize("test", 0, 4);
+
+    {
+      const f_status_t status = f_path_real(path, 0);
+
+      assert_int_equal(F_status_set_fine(status), F_parameter);
+    }
+  }
+#endif // _di_level_0_parameter_checking_
+
+void test__f_path_real__works(void **state) {
+
+  const f_string_static_t path = macro_f_string_static_t_initialize("test", 0, 4);
+  const f_string_static_t path_real = macro_f_string_static_t_initialize("/test", 0, 5);
+
+  f_string_dynamic_t destination = f_string_dynamic_t_initialize;
+
+  {
+    will_return(__wrap_realpath, F_false);
+    will_return(__wrap_realpath, path_real.string);
+
+    const f_status_t status = f_path_real(path, &destination);
+
+    assert_int_equal(status, F_none);
+    assert_int_equal(destination.used, path_real.used);
+    assert_string_equal(destination.string, path_real.string);
+  }
+
+  f_string_dynamic_resize(0, &destination);
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_path/tests/unit/c/test-path-real.h b/level_0/f_path/tests/unit/c/test-path-real.h
new file mode 100644 (file)
index 0000000..c6af1ba
--- /dev/null
@@ -0,0 +1,36 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: Path
+ * API Version: 0.5
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the path project.
+ */
+#ifndef _TEST__F_path_real_h
+#define _TEST__F_path_real_h
+
+/**
+ * Test that function fails.
+ *
+ * @see f_path_real()
+ */
+extern void test__f_path_real__fails(void **state);
+
+/**
+ * Test that parameter checking works as expected.
+ *
+ * @see f_path_real()
+ */
+#ifndef _di_level_0_parameter_checking_
+  extern void test__f_path_real__parameter_checking(void **state);
+#endif // _di_level_0_parameter_checking_
+
+/**
+ * Test that function works.
+ *
+ * @see f_path_real()
+ */
+extern void test__f_path_real__works(void **state);
+
+#endif // _TEST__F_path_real_h
diff --git a/level_0/f_path/tests/unit/c/test-path.c b/level_0/f_path/tests/unit/c/test-path.c
new file mode 100644 (file)
index 0000000..d3d3540
--- /dev/null
@@ -0,0 +1,68 @@
+#include "test-path.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int setup(void **state) {
+
+  return 0;
+}
+
+int setdown(void **state) {
+
+  errno = 0;
+
+  return 0;
+}
+
+int main(void) {
+
+  const struct CMUnitTest tests[] = {
+    cmocka_unit_test(test__f_path_change__fails),
+    cmocka_unit_test(test__f_path_change__works),
+
+    cmocka_unit_test(test__f_path_change_at__fails),
+    cmocka_unit_test(test__f_path_change_at__works),
+
+    // test__f_path_directory_cleanup__fails test isn't needed yet as f_string_dynamic_increase_by() aren't tested at this time.
+    cmocka_unit_test(test__f_path_directory_cleanup__works),
+
+    cmocka_unit_test(test__f_path_is__returns_false),
+    cmocka_unit_test(test__f_path_is__returns_data_not),
+    cmocka_unit_test(test__f_path_is__returns_true),
+
+    cmocka_unit_test(test__f_path_is_absolute__returns_false),
+    cmocka_unit_test(test__f_path_is_absolute__returns_data_not),
+    cmocka_unit_test(test__f_path_is_absolute__returns_true),
+
+    cmocka_unit_test(test__f_path_is_relative__returns_false),
+    cmocka_unit_test(test__f_path_is_relative__returns_data_not),
+    cmocka_unit_test(test__f_path_is_relative__returns_true),
+
+    cmocka_unit_test(test__f_path_is_relative_current__returns_false),
+    cmocka_unit_test(test__f_path_is_relative_current__returns_data_not),
+    cmocka_unit_test(test__f_path_is_relative_current__returns_true),
+
+    cmocka_unit_test(test__f_path_real__fails),
+    cmocka_unit_test(test__f_path_real__works),
+
+    #ifndef _di_level_0_parameter_checking_
+      // f_path_change() doesn't use parameter checking.
+      // f_path_change_at() doesn't use parameter checking.
+      cmocka_unit_test(test__f_path_current__parameter_checking),
+      cmocka_unit_test(test__f_path_directory_cleanup__parameter_checking),
+      // f_path_is() doesn't use parameter checking.
+      // f_path_is_absolute() doesn't use parameter checking.
+      // f_path_is_relative() doesn't use parameter checking.
+      // f_path_is_relative_current() doesn't use parameter checking.
+      cmocka_unit_test(test__f_path_real__parameter_checking),
+    #endif // _di_level_0_parameter_checking_
+  };
+
+  return cmocka_run_group_tests(tests, setup, setdown);
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/level_0/f_path/tests/unit/c/test-path.h b/level_0/f_path/tests/unit/c/test-path.h
new file mode 100644 (file)
index 0000000..a8fb827
--- /dev/null
@@ -0,0 +1,80 @@
+/**
+ * FLL - Level 0
+ *
+ * Project: Path
+ * API Version: 0.5
+ * Licenses: lgpl-2.1-or-later
+ *
+ * Test the path project.
+ */
+#ifndef _TEST__F_path_h
+#define _TEST__F_path_h
+
+// Libc includes.
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <stdint.h>
+
+// cmocka includes.
+#include <cmocka.h>
+
+// FLL-0 includes.
+#include <fll/level_0/path.h>
+
+// Mock includes.
+#include "mock-path.h"
+
+// Test includes.
+#include "test-path-change.h"
+#include "test-path-change_at.h"
+#include "test-path-current.h"
+#include "test-path-directory_cleanup.h"
+#include "test-path-is.h"
+#include "test-path-is_absolute.h"
+#include "test-path-is_relative.h"
+#include "test-path-is_relative_current.h"
+#include "test-path-real.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Perform any setup operations.
+ *
+ * @param state
+ *   The test state.
+ *
+ * @return
+ *   The status of this function, where 0 means success.
+ */
+extern int setup(void **state);
+
+/**
+ * Peform any setdown operations.
+ *
+ * @param state
+ *   The test state.
+ *
+ * @return
+ *   The status of this function, where 0 means success.
+ */
+extern int setdown(void **state);
+
+/**
+ * Run all tests.
+ *
+ * @return
+ *   The final result of the tests.
+ *
+ * @see cmocka_run_group_tests()
+ * @see cmocka_unit_test()
+ */
+extern int main(void);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // _TEST__F_path_h