From 07edf5a13302e866d4c1f4cb13354bd414a94402 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Tue, 21 Jan 2025 22:09:22 -0600 Subject: [PATCH] Feature: Add fl_path_clean() for stripping out NULLs and redundant slashes. --- build/stand_alone/fake.config.h | 1 + build/stand_alone/firewall.config.h | 1 + level_1/fl_path/c/path.c | 48 ++++ level_1/fl_path/c/path.h | 33 +++ level_1/fl_path/data/build/settings-tests | 2 +- level_1/fl_path/tests/unit/c/test-path-clean.c | 352 +++++++++++++++++++++++++ level_1/fl_path/tests/unit/c/test-path-clean.h | 55 ++++ level_1/fl_path/tests/unit/c/test-path.c | 7 + level_1/fl_path/tests/unit/c/test-path.h | 1 + 9 files changed, 499 insertions(+), 1 deletion(-) create mode 100644 level_1/fl_path/tests/unit/c/test-path-clean.c create mode 100644 level_1/fl_path/tests/unit/c/test-path-clean.h diff --git a/build/stand_alone/fake.config.h b/build/stand_alone/fake.config.h index a2cda19..2ba8618 100644 --- a/build/stand_alone/fake.config.h +++ b/build/stand_alone/fake.config.h @@ -1961,6 +1961,7 @@ #define _di_fl_iki_eki_read_ //#define _di_fl_iki_read_ //#define _di_fl_path_canonical_ +#define _di_fl_path_clean_ //#define _di_fl_print_debug_s_ //#define _di_fl_print_error_s_ //#define _di_fl_print_format_ diff --git a/build/stand_alone/firewall.config.h b/build/stand_alone/firewall.config.h index 95ec51a..9e6d8e5 100644 --- a/build/stand_alone/firewall.config.h +++ b/build/stand_alone/firewall.config.h @@ -2024,6 +2024,7 @@ #define _di_fl_iki_eki_read_ #define _di_fl_iki_read_ #define _di_fl_path_canonical_ +#define _di_fl_path_clean_ //#define _di_fl_print_debug_s_ //#define _di_fl_print_error_s_ //#define _di_fl_print_format_ diff --git a/level_1/fl_path/c/path.c b/level_1/fl_path/c/path.c index 1c30d74..8463066 100644 --- a/level_1/fl_path/c/path.c +++ b/level_1/fl_path/c/path.c @@ -143,6 +143,54 @@ extern "C" { } #endif // _di_fl_path_canonical_ +#ifndef _di_fl_path_clean_ + f_status_t fl_path_clean(const f_string_static_t path, f_string_dynamic_t * const clean) { + #ifndef _di_level_1_parameter_checking_ + if (!clean) return F_status_set_error(F_parameter); + #endif // _di_level_1_parameter_checking_ + + if (!path.used) return F_okay; + + f_status_t status = F_okay; + f_number_unsigned_t at = 0; + f_number_unsigned_t position = 0; + f_number_unsigned_t size_chunk = 0; + + while (at < path.used) { + + if (path.string[at] == f_path_separator_s.string[0]) { + status = f_string_append_nulless(path.string + position, size_chunk + 1, clean); + if (F_status_is_error(status)) return status; + + position = at; + + while (at < path.used && (!path.string[at] || path.string[at] == f_path_separator_s.string[0])) ++at; + + position = at; + size_chunk = 0; + + if (at == path.used) break; + } + else { + ++size_chunk; + ++at; + } + } // while + + if (size_chunk) { + status = f_string_append_nulless(path.string + position, size_chunk, clean); + if (F_status_is_error(status)) return status; + } + + // Assure there is no trailing forward slash, unless it is the first slash. + if (clean->used > 1 && clean->string[clean->used - 1] == f_path_separator_s.string[0]) { + --clean->used; + } + + return F_okay; + } +#endif // _di_fl_path_clean_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_1/fl_path/c/path.h b/level_1/fl_path/c/path.h index 6fa567e..d5ae40b 100644 --- a/level_1/fl_path/c/path.h +++ b/level_1/fl_path/c/path.h @@ -59,6 +59,39 @@ extern "C" { extern f_status_t fl_path_canonical(const f_string_static_t path, f_string_dynamic_t * const canonical); #endif // _di_fl_path_canonical_ +/** + * Get the cleaned up path for some path, removing redundant slashes. + * + * This does not check if the path exists or not. + * This leaves relative parts in place: './', '../', and extra '/'. + * This does not process symbolic links. + * This has a max size of F_string_t_size_d. + * This removes trailing slashes, but leaves the leading slash ('/' remains as-is, but '/a/' becomes '/a'). + * This removes redundant slashes '/'. + * + * An empty path (first character is NULL or path.used is 0) appends only the current path to canonical. + * + * @param path + * The source path to determine what the canonical path is. + * NULLs within the path are not copied to the clean. + * This need not be NULL terminated. + * @param simple + * The (allocated) cleaned up file path. + * This will be NULL terminated at clean->used + 1. + * + * @return + * F_okay on success. + * + * Errors (with error bit) from: f_string_append_nulless(). + * Errors (with error bit) from: f_string_dynamic_append_assure(). + * + * @see f_string_append_nulless() + * @see f_string_dynamic_append_assure() + */ +#ifndef _di_fl_path_clean_ + extern f_status_t fl_path_clean(const f_string_static_t path, f_string_dynamic_t * const clean); +#endif // _di_fl_path_clean_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_1/fl_path/data/build/settings-tests b/level_1/fl_path/data/build/settings-tests index d8bee06..d617204 100644 --- a/level_1/fl_path/data/build/settings-tests +++ b/level_1/fl_path/data/build/settings-tests @@ -25,7 +25,7 @@ build_language c build_libraries -lc -lcmocka build_libraries-individual -lf_memory -lf_path -lf_string -lfl_path -build_sources_program test-path-canonical.c +build_sources_program test-path-canonical.c test-path-clean.c build_sources_program test-path.c diff --git a/level_1/fl_path/tests/unit/c/test-path-clean.c b/level_1/fl_path/tests/unit/c/test-path-clean.c new file mode 100644 index 0000000..827baea --- /dev/null +++ b/level_1/fl_path/tests/unit/c/test-path-clean.c @@ -0,0 +1,352 @@ +#include "test-path.h" +#include "test-path-clean.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void test__fl_path_clean__back_paths(void **state) { + + const f_string_static_t contents[] = { + macro_f_string_static_t_initialize_1("a/../", 0, 5), + macro_f_string_static_t_initialize_1("a/../b", 0, 6), + macro_f_string_static_t_initialize_1("a/../b/", 0, 7), + macro_f_string_static_t_initialize_1("a/../b/c", 0, 8), + macro_f_string_static_t_initialize_1("a/../b/c/", 0, 9), + macro_f_string_static_t_initialize_1("a/../b/c//", 0, 10), + macro_f_string_static_t_initialize_1("a/.././", 0, 7), + macro_f_string_static_t_initialize_1("a/.././b", 0, 8), + macro_f_string_static_t_initialize_1("a/.././b/", 0, 9), + macro_f_string_static_t_initialize_1("a/.././b/c", 0, 10), + macro_f_string_static_t_initialize_1("a/.././b/c/", 0, 11), + macro_f_string_static_t_initialize_1("a/.././b/c//", 0, 12), + macro_f_string_static_t_initialize_1("a/.././/", 0, 8), + macro_f_string_static_t_initialize_1("a/.././/b", 0, 9), + macro_f_string_static_t_initialize_1("a/.././/b/", 0, 10), + macro_f_string_static_t_initialize_1("a/.././/b/c", 0, 11), + macro_f_string_static_t_initialize_1("a/.././/b/c/", 0, 12), + macro_f_string_static_t_initialize_1("a/.././/b/c//", 0, 13), + macro_f_string_static_t_initialize_1("/z/../", 0, 6), + macro_f_string_static_t_initialize_1("/z/../b", 0, 7), + macro_f_string_static_t_initialize_1("/z/../b/", 0, 8), + macro_f_string_static_t_initialize_1("/z/../b/c", 0, 9), + macro_f_string_static_t_initialize_1("/z/../b/c/", 0, 10), + macro_f_string_static_t_initialize_1("/z/../b/c//", 0, 11), + macro_f_string_static_t_initialize_1("/z/.\0./b/c//", 0, 12), + macro_f_string_static_t_initialize_1("/z\0/.\0./b/c/\0/", 0, 14), + macro_f_string_static_t_initialize_1("\0a/../", 0, 6), + macro_f_string_static_t_initialize_1("a/../\0", 0, 6), + }; + + const f_string_static_t expected[] = { + macro_f_string_static_t_initialize_1("a/..", 0, 4), + macro_f_string_static_t_initialize_1("a/../b", 0, 6), + macro_f_string_static_t_initialize_1("a/../b", 0, 6), + macro_f_string_static_t_initialize_1("a/../b/c", 0, 8), + macro_f_string_static_t_initialize_1("a/../b/c", 0, 8), + macro_f_string_static_t_initialize_1("a/../b/c", 0, 8), + macro_f_string_static_t_initialize_1("a/../.", 0, 6), + macro_f_string_static_t_initialize_1("a/.././b", 0, 8), + macro_f_string_static_t_initialize_1("a/.././b", 0, 8), + macro_f_string_static_t_initialize_1("a/.././b/c", 0, 10), + macro_f_string_static_t_initialize_1("a/.././b/c", 0, 10), + macro_f_string_static_t_initialize_1("a/.././b/c", 0, 10), + macro_f_string_static_t_initialize_1("a/../.", 0, 6), + macro_f_string_static_t_initialize_1("a/.././b", 0, 8), + macro_f_string_static_t_initialize_1("a/.././b", 0, 8), + macro_f_string_static_t_initialize_1("a/.././b/c", 0, 10), + macro_f_string_static_t_initialize_1("a/.././b/c", 0, 10), + macro_f_string_static_t_initialize_1("a/.././b/c", 0, 10), + macro_f_string_static_t_initialize_1("/z/..", 0, 5), + macro_f_string_static_t_initialize_1("/z/../b", 0, 7), + macro_f_string_static_t_initialize_1("/z/../b", 0, 7), + macro_f_string_static_t_initialize_1("/z/../b/c", 0, 9), + macro_f_string_static_t_initialize_1("/z/../b/c", 0, 9), + macro_f_string_static_t_initialize_1("/z/../b/c", 0, 9), + macro_f_string_static_t_initialize_1("/z/../b/c", 0, 9), + macro_f_string_static_t_initialize_1("/z/../b/c", 0, 9), + macro_f_string_static_t_initialize_1("a/..", 0, 4), + macro_f_string_static_t_initialize_1("a/..", 0, 4), + }; + + f_string_dynamic_t path = f_string_dynamic_t_initialize; + + for (uint8_t i = 0; i < 28; ++i) { + + path.used = 0; + + const f_status_t status = fl_path_clean(contents[i], &path); + + assert_int_equal(status, F_okay); + + // Assert_string_equal() is NULL terminated, so ensure NULL termination at end of path.used. + path.string[path.used] = 0; + + assert_int_equal(expected[i].used, path.used); + assert_string_equal(expected[i].string, path.string); + + memset(path.string, 0, path.used); + } // for + + free((void *) path.string); +} + +void test__fl_path_clean__empty_stays_empty(void **state) { + + f_string_dynamic_t path = f_string_dynamic_t_initialize; + + { + const f_status_t status = fl_path_clean(f_string_empty_s, &path); + + assert_int_equal(status, F_okay); + assert_int_equal(path.used, path.used); + } // for + + free((void *) path.string); +} + +void test__fl_path_clean__present_paths(void **state) { + + const f_string_static_t contents[] = { + macro_f_string_static_t_initialize_1("", 0, 1), + macro_f_string_static_t_initialize_1("a", 0, 2), + macro_f_string_static_t_initialize_1("a/", 0, 3), + macro_f_string_static_t_initialize_1("a/b", 0, 4), + macro_f_string_static_t_initialize_1("a/b/", 0, 5), + macro_f_string_static_t_initialize_1("a/b//", 0, 6), + macro_f_string_static_t_initialize_1("./", 0, 2), + macro_f_string_static_t_initialize_1("./a", 0, 3), + macro_f_string_static_t_initialize_1("./a/", 0, 4), + macro_f_string_static_t_initialize_1("./a/b", 0, 5), + macro_f_string_static_t_initialize_1("./a/b/", 0, 6), + macro_f_string_static_t_initialize_1("./a/b//", 0, 7), + macro_f_string_static_t_initialize_1(".//", 0, 3), + macro_f_string_static_t_initialize_1(".//a", 0, 4), + macro_f_string_static_t_initialize_1(".//a/", 0, 5), + macro_f_string_static_t_initialize_1(".//a/b", 0, 6), + macro_f_string_static_t_initialize_1(".//a/b/", 0, 7), + macro_f_string_static_t_initialize_1(".//a/b//", 0, 8), + macro_f_string_static_t_initialize_1(".//a/\0b//", 0, 9), + macro_f_string_static_t_initialize_1(".\0//a/\0b/\0/", 0, 11), + macro_f_string_static_t_initialize_1("\0a", 0, 2), + macro_f_string_static_t_initialize_1("a\0", 0, 2), + }; + + const f_string_static_t expected[] = { + macro_f_string_static_t_initialize_1("", 0, 0), + macro_f_string_static_t_initialize_1("a", 0, 1), + macro_f_string_static_t_initialize_1("a", 0, 1), + macro_f_string_static_t_initialize_1("a/b", 0, 3), + macro_f_string_static_t_initialize_1("a/b", 0, 3), + macro_f_string_static_t_initialize_1("a/b", 0, 3), + macro_f_string_static_t_initialize_1(".", 0, 1), + macro_f_string_static_t_initialize_1("./a", 0, 3), + macro_f_string_static_t_initialize_1("./a", 0, 3), + macro_f_string_static_t_initialize_1("./a/b", 0, 5), + macro_f_string_static_t_initialize_1("./a/b", 0, 5), + macro_f_string_static_t_initialize_1("./a/b", 0, 5), + macro_f_string_static_t_initialize_1(".", 0, 1), + macro_f_string_static_t_initialize_1("./a", 0, 3), + macro_f_string_static_t_initialize_1("./a", 0, 3), + macro_f_string_static_t_initialize_1("./a/b", 0, 5), + macro_f_string_static_t_initialize_1("./a/b", 0, 5), + macro_f_string_static_t_initialize_1("./a/b", 0, 5), + macro_f_string_static_t_initialize_1("./a/b", 0, 5), + macro_f_string_static_t_initialize_1("./a/b", 0, 5), + macro_f_string_static_t_initialize_1("a", 0, 1), + macro_f_string_static_t_initialize_1("a", 0, 1), + }; + + f_string_dynamic_t path = f_string_dynamic_t_initialize; + + for (uint8_t i = 0; i < 22; ++i) { + + path.used = 0; + + const f_status_t status = fl_path_clean(contents[i], &path); + + assert_int_equal(status, F_okay); + + // Assert_string_equal() is NULL terminated, so ensure NULL termination at end of path.used. + path.string[path.used] = 0; + + assert_int_equal(expected[i].used, path.used); + assert_string_equal(expected[i].string, path.string); + + memset(path.string, 0, path.used); + } // for + + free((void *) path.string); +} + +void test__fl_path_clean__root_paths(void **state) { + + const f_string_static_t contents[] = { + macro_f_string_static_t_initialize_1("/", 0, 1), + macro_f_string_static_t_initialize_1("//", 0, 2), + macro_f_string_static_t_initialize_1("///", 0, 3), + macro_f_string_static_t_initialize_1("/a", 0, 2), + macro_f_string_static_t_initialize_1("//a", 0, 3), + macro_f_string_static_t_initialize_1("///a", 0, 4), + macro_f_string_static_t_initialize_1("/a/", 0, 3), + macro_f_string_static_t_initialize_1("//a/", 0, 4), + macro_f_string_static_t_initialize_1("///a/", 0, 5), + macro_f_string_static_t_initialize_1("/a/b", 0, 4), + macro_f_string_static_t_initialize_1("//a/b", 0, 5), + macro_f_string_static_t_initialize_1("///a/b", 0, 6), + macro_f_string_static_t_initialize_1("/a/b/", 0, 5), + macro_f_string_static_t_initialize_1("//a/b/", 0, 6), + macro_f_string_static_t_initialize_1("///a/b/", 0, 7), + macro_f_string_static_t_initialize_1("/a/b//", 0, 6), + macro_f_string_static_t_initialize_1("//a/b//", 0, 7), + macro_f_string_static_t_initialize_1("///a/b//", 0, 8), + macro_f_string_static_t_initialize_1("///a/\0b//", 0, 9), + macro_f_string_static_t_initialize_1("/\0//a/\0b\0//", 0, 11), + macro_f_string_static_t_initialize_1("\0/", 0, 2), + macro_f_string_static_t_initialize_1("/\0", 0, 2), + }; + + const f_string_static_t expected[] = { + macro_f_string_static_t_initialize_1("/", 0, 1), + macro_f_string_static_t_initialize_1("/", 0, 1), + macro_f_string_static_t_initialize_1("/", 0, 1), + macro_f_string_static_t_initialize_1("/a", 0, 2), + macro_f_string_static_t_initialize_1("/a", 0, 2), + macro_f_string_static_t_initialize_1("/a", 0, 2), + macro_f_string_static_t_initialize_1("/a", 0, 2), + macro_f_string_static_t_initialize_1("/a", 0, 2), + macro_f_string_static_t_initialize_1("/a", 0, 2), + macro_f_string_static_t_initialize_1("/a/b", 0, 4), + macro_f_string_static_t_initialize_1("/a/b", 0, 4), + macro_f_string_static_t_initialize_1("/a/b", 0, 4), + macro_f_string_static_t_initialize_1("/a/b", 0, 4), + macro_f_string_static_t_initialize_1("/a/b", 0, 4), + macro_f_string_static_t_initialize_1("/a/b", 0, 4), + macro_f_string_static_t_initialize_1("/a/b", 0, 4), + macro_f_string_static_t_initialize_1("/a/b", 0, 4), + macro_f_string_static_t_initialize_1("/a/b", 0, 4), + macro_f_string_static_t_initialize_1("/a/b", 0, 4), + macro_f_string_static_t_initialize_1("/a/b", 0, 4), + macro_f_string_static_t_initialize_1("/", 0, 1), + macro_f_string_static_t_initialize_1("/", 0, 1), + }; + + f_string_dynamic_t path = f_string_dynamic_t_initialize; + + for (uint8_t i = 0; i < 22; ++i) { + + path.used = 0; + + const f_status_t status = fl_path_clean(contents[i], &path); + + // Assert_string_equal() is NULL terminated, so ensure NULL termination at end of path.used. + if (status == F_okay) { + path.string[path.used] = 0; + } + + assert_int_equal(status, F_okay); + assert_int_equal(expected[i].used, path.used); + assert_string_equal(expected[i].string, path.string); + + memset(path.string, 0, path.used); + } // for + + free((void *) path.string); +} + +void test__fl_path_clean__tilde_remains(void **state) { + + const f_string_static_t contents[] = { + macro_f_string_static_t_initialize_1("~", 0, 1), + macro_f_string_static_t_initialize_1("~/", 0, 2), + macro_f_string_static_t_initialize_1("~//", 0, 3), + macro_f_string_static_t_initialize_1("~a", 0, 2), + macro_f_string_static_t_initialize_1("a~", 0, 2), + macro_f_string_static_t_initialize_1("a~b", 0, 3), + macro_f_string_static_t_initialize_1("/~", 0, 2), + macro_f_string_static_t_initialize_1("//~", 0, 3), + macro_f_string_static_t_initialize_1("~ ", 0, 2), + macro_f_string_static_t_initialize_1("~ /", 0, 3), + macro_f_string_static_t_initialize_1("./~", 0, 3), + macro_f_string_static_t_initialize_1("./~a", 0, 4), + macro_f_string_static_t_initialize_1("./a~", 0, 4), + macro_f_string_static_t_initialize_1("./a~b", 0, 5), + macro_f_string_static_t_initialize_1("a/~/b", 0, 5), + macro_f_string_static_t_initialize_1("a/~b", 0, 4), + macro_f_string_static_t_initialize_1("a/~b/c", 0, 6), + macro_f_string_static_t_initialize_1("/a/~/b", 0, 6), + macro_f_string_static_t_initialize_1("/a/~b", 0, 5), + macro_f_string_static_t_initialize_1("/a/~b/c", 0, 7), + macro_f_string_static_t_initialize_1("//a/~/b", 0, 7), + macro_f_string_static_t_initialize_1("//a/~b", 0, 6), + macro_f_string_static_t_initialize_1("//a/~b/c", 0, 8), + macro_f_string_static_t_initialize_1("//a/~\0b/c", 0, 9), + macro_f_string_static_t_initialize_1("/\0/a/~\0b\0/c", 0, 11), + macro_f_string_static_t_initialize_1("\0~", 0, 2), + macro_f_string_static_t_initialize_1("~\0", 0, 2), + }; + + const f_string_static_t expected[] = { + macro_f_string_static_t_initialize_1("~", 0, 1), + macro_f_string_static_t_initialize_1("~", 0, 1), + macro_f_string_static_t_initialize_1("~", 0, 1), + macro_f_string_static_t_initialize_1("~a", 0, 2), + macro_f_string_static_t_initialize_1("a~", 0, 2), + macro_f_string_static_t_initialize_1("a~b", 0, 3), + macro_f_string_static_t_initialize_1("/~", 0, 2), + macro_f_string_static_t_initialize_1("/~", 0, 2), + macro_f_string_static_t_initialize_1("~ ", 0, 2), + macro_f_string_static_t_initialize_1("~ ", 0, 2), + macro_f_string_static_t_initialize_1("./~", 0, 3), + macro_f_string_static_t_initialize_1("./~a", 0, 4), + macro_f_string_static_t_initialize_1("./a~", 0, 4), + macro_f_string_static_t_initialize_1("./a~b", 0, 5), + macro_f_string_static_t_initialize_1("a/~/b", 0, 5), + macro_f_string_static_t_initialize_1("a/~b", 0, 4), + macro_f_string_static_t_initialize_1("a/~b/c", 0, 6), + macro_f_string_static_t_initialize_1("/a/~/b", 0, 6), + macro_f_string_static_t_initialize_1("/a/~b", 0, 5), + macro_f_string_static_t_initialize_1("/a/~b/c", 0, 7), + macro_f_string_static_t_initialize_1("/a/~/b", 0, 6), + macro_f_string_static_t_initialize_1("/a/~b", 0, 5), + macro_f_string_static_t_initialize_1("/a/~b/c", 0, 7), + macro_f_string_static_t_initialize_1("/a/~b/c", 0, 7), + macro_f_string_static_t_initialize_1("/a/~b/c", 0, 7), + macro_f_string_static_t_initialize_1("~", 0, 1), + macro_f_string_static_t_initialize_1("~", 0, 1), + }; + + f_string_dynamic_t path = f_string_dynamic_t_initialize; + + for (uint8_t i = 0; i < 27; ++i) { + + path.used = 0; + + const f_status_t status = fl_path_clean(contents[i], &path); + + assert_int_equal(status, F_okay); + + // Assert_string_equal() is NULL terminated, so ensure NULL termination at end of path.used. + path.string[path.used] = 0; + + assert_int_equal(expected[i].used, path.used); + assert_string_equal(expected[i].string, path.string); + + memset(path.string, 0, path.used); + } // for + + free((void *) path.string); +} + +void test__fl_path_clean__parameter_checking(void **state) { + + { + const f_status_t status = fl_path_clean(f_string_empty_s, 0); + + assert_int_equal(status, F_status_set_error(F_parameter)); + } +} + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/level_1/fl_path/tests/unit/c/test-path-clean.h b/level_1/fl_path/tests/unit/c/test-path-clean.h new file mode 100644 index 0000000..841f661 --- /dev/null +++ b/level_1/fl_path/tests/unit/c/test-path-clean.h @@ -0,0 +1,55 @@ +/** + * FLL - Level 2 + * + * Project: Path + * API Version: 0.6 + * Licenses: lgpl-2.1-or-later + * + * Test the fl_path project. + */ +#ifndef _TEST__FL_path_simple_h +#define _TEST__FL_path_simple_h + +/** + * Test that function works with back paths (such as '../'). + * + * @see fl_path_clean() + */ +extern void test__fl_path_clean__back_paths(void **state); + +/** + * Test that function leaves clean alone when the path is an empty string. + * + * @see fl_path_clean() + */ +extern void test__fl_path_clean__empty_stays_empty(void **state); + +/** + * Test that function works with present directory paths. + * + * @see fl_path_clean() + */ +extern void test__fl_path_clean__present_paths(void **state); + +/** + * Test that function works with root paths. + * + * @see fl_path_clean() + */ +extern void test__fl_path_clean__root_paths(void **state); + +/** + * Test that function returns the string without expanding the tilde. + * + * @see fl_path_clean() + */ +extern void test__fl_path_clean__tilde_remains(void **state); + +/** + * Test that parameter checking works as expected. + * + * @see fl_path_clean() + */ +extern void test__fl_path_clean__parameter_checking(void **state); + +#endif // _TEST__FL_path_simple_h diff --git a/level_1/fl_path/tests/unit/c/test-path.c b/level_1/fl_path/tests/unit/c/test-path.c index ff06622..7c1d609 100644 --- a/level_1/fl_path/tests/unit/c/test-path.c +++ b/level_1/fl_path/tests/unit/c/test-path.c @@ -25,8 +25,15 @@ int main(void) { cmocka_unit_test(test__fl_path_canonical__root_paths), cmocka_unit_test(test__fl_path_canonical__tilde_remains), + cmocka_unit_test(test__fl_path_clean__back_paths), + cmocka_unit_test(test__fl_path_clean__empty_stays_empty), + cmocka_unit_test(test__fl_path_clean__present_paths), + cmocka_unit_test(test__fl_path_clean__root_paths), + cmocka_unit_test(test__fl_path_clean__tilde_remains), + #ifndef _di_level_0_parameter_checking_ cmocka_unit_test(test__fl_path_canonical__parameter_checking), + cmocka_unit_test(test__fl_path_clean__parameter_checking), #endif // _di_level_0_parameter_checking_ }; diff --git a/level_1/fl_path/tests/unit/c/test-path.h b/level_1/fl_path/tests/unit/c/test-path.h index 505ba75..18a57ca 100644 --- a/level_1/fl_path/tests/unit/c/test-path.h +++ b/level_1/fl_path/tests/unit/c/test-path.h @@ -29,6 +29,7 @@ // Test includes. #include "test-path-canonical.h" +#include "test-path-clean.h" #ifdef __cplusplus extern "C" { -- 1.8.3.1