--- /dev/null
+#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