dirwalk_test.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. #include "../minunit.h"
  2. #include <furi.h>
  3. #include <m-dict.h>
  4. #include <toolbox/dir_walk.h>
  5. static const char* const storage_test_dirwalk_paths[] = {
  6. "1",
  7. "11",
  8. "111",
  9. "1/2",
  10. "1/22",
  11. "1/222",
  12. "11/2",
  13. "111/2",
  14. "111/22",
  15. "111/22/33",
  16. };
  17. static const char* const storage_test_dirwalk_files[] = {
  18. "file1.test",
  19. "file2.test",
  20. "file3.ext_test",
  21. "1/file1.test",
  22. "111/22/33/file1.test",
  23. "111/22/33/file2.test",
  24. "111/22/33/file3.ext_test",
  25. "111/22/33/file4.ext_test",
  26. };
  27. typedef struct {
  28. const char* const path;
  29. bool is_dir;
  30. } StorageTestPathDesc;
  31. const StorageTestPathDesc storage_test_dirwalk_full[] = {
  32. {.path = "1", .is_dir = true},
  33. {.path = "11", .is_dir = true},
  34. {.path = "111", .is_dir = true},
  35. {.path = "1/2", .is_dir = true},
  36. {.path = "1/22", .is_dir = true},
  37. {.path = "1/222", .is_dir = true},
  38. {.path = "11/2", .is_dir = true},
  39. {.path = "111/2", .is_dir = true},
  40. {.path = "111/22", .is_dir = true},
  41. {.path = "111/22/33", .is_dir = true},
  42. {.path = "file1.test", .is_dir = false},
  43. {.path = "file2.test", .is_dir = false},
  44. {.path = "file3.ext_test", .is_dir = false},
  45. {.path = "1/file1.test", .is_dir = false},
  46. {.path = "111/22/33/file1.test", .is_dir = false},
  47. {.path = "111/22/33/file2.test", .is_dir = false},
  48. {.path = "111/22/33/file3.ext_test", .is_dir = false},
  49. {.path = "111/22/33/file4.ext_test", .is_dir = false},
  50. };
  51. const StorageTestPathDesc storage_test_dirwalk_no_recursive[] = {
  52. {.path = "1", .is_dir = true},
  53. {.path = "11", .is_dir = true},
  54. {.path = "111", .is_dir = true},
  55. {.path = "file1.test", .is_dir = false},
  56. {.path = "file2.test", .is_dir = false},
  57. {.path = "file3.ext_test", .is_dir = false},
  58. };
  59. const StorageTestPathDesc storage_test_dirwalk_filter[] = {
  60. {.path = "file1.test", .is_dir = false},
  61. {.path = "file2.test", .is_dir = false},
  62. {.path = "1/file1.test", .is_dir = false},
  63. {.path = "111/22/33/file1.test", .is_dir = false},
  64. {.path = "111/22/33/file2.test", .is_dir = false},
  65. };
  66. typedef struct {
  67. bool is_dir;
  68. bool visited;
  69. } StorageTestPath;
  70. DICT_DEF2(StorageTestPathDict, FuriString*, FURI_STRING_OPLIST, StorageTestPath, M_POD_OPLIST)
  71. static StorageTestPathDict_t*
  72. storage_test_paths_alloc(const StorageTestPathDesc paths[], size_t paths_count) {
  73. StorageTestPathDict_t* data = malloc(sizeof(StorageTestPathDict_t));
  74. StorageTestPathDict_init(*data);
  75. for(size_t i = 0; i < paths_count; i++) {
  76. FuriString* key;
  77. key = furi_string_alloc_set(paths[i].path);
  78. StorageTestPath value = {
  79. .is_dir = paths[i].is_dir,
  80. .visited = false,
  81. };
  82. StorageTestPathDict_set_at(*data, key, value);
  83. furi_string_free(key);
  84. }
  85. return data;
  86. }
  87. static void storage_test_paths_free(StorageTestPathDict_t* data) {
  88. StorageTestPathDict_clear(*data);
  89. free(data);
  90. }
  91. static bool storage_test_paths_mark(StorageTestPathDict_t* data, FuriString* path, bool is_dir) {
  92. bool found = false;
  93. StorageTestPath* record = StorageTestPathDict_get(*data, path);
  94. if(record) {
  95. if(is_dir == record->is_dir) {
  96. if(record->visited == false) {
  97. record->visited = true;
  98. found = true;
  99. }
  100. }
  101. }
  102. return found;
  103. }
  104. static bool storage_test_paths_check(StorageTestPathDict_t* data) {
  105. bool error = false;
  106. StorageTestPathDict_it_t it;
  107. for(StorageTestPathDict_it(it, *data); !StorageTestPathDict_end_p(it);
  108. StorageTestPathDict_next(it)) {
  109. const StorageTestPathDict_itref_t* itref = StorageTestPathDict_cref(it);
  110. if(itref->value.visited == false) {
  111. error = true;
  112. break;
  113. }
  114. }
  115. return error;
  116. }
  117. static bool write_file_13DA(Storage* storage, const char* path) {
  118. File* file = storage_file_alloc(storage);
  119. bool result = false;
  120. if(storage_file_open(file, path, FSAM_WRITE, FSOM_CREATE_ALWAYS)) {
  121. result = storage_file_write(file, "13DA", 4) == 4;
  122. }
  123. storage_file_close(file);
  124. storage_file_free(file);
  125. return result;
  126. }
  127. static void storage_dirs_create(Storage* storage, const char* base) {
  128. FuriString* path;
  129. path = furi_string_alloc();
  130. storage_common_mkdir(storage, base);
  131. for(size_t i = 0; i < COUNT_OF(storage_test_dirwalk_paths); i++) {
  132. furi_string_printf(path, "%s/%s", base, storage_test_dirwalk_paths[i]);
  133. storage_common_mkdir(storage, furi_string_get_cstr(path));
  134. }
  135. for(size_t i = 0; i < COUNT_OF(storage_test_dirwalk_files); i++) {
  136. furi_string_printf(path, "%s/%s", base, storage_test_dirwalk_files[i]);
  137. write_file_13DA(storage, furi_string_get_cstr(path));
  138. }
  139. furi_string_free(path);
  140. }
  141. MU_TEST_1(test_dirwalk_full, Storage* storage) {
  142. FuriString* path;
  143. path = furi_string_alloc();
  144. FileInfo fileinfo;
  145. StorageTestPathDict_t* paths =
  146. storage_test_paths_alloc(storage_test_dirwalk_full, COUNT_OF(storage_test_dirwalk_full));
  147. DirWalk* dir_walk = dir_walk_alloc(storage);
  148. mu_check(dir_walk_open(dir_walk, EXT_PATH("dirwalk")));
  149. while(dir_walk_read(dir_walk, path, &fileinfo) == DirWalkOK) {
  150. furi_string_right(path, strlen(EXT_PATH("dirwalk/")));
  151. mu_check(storage_test_paths_mark(paths, path, file_info_is_dir(&fileinfo)));
  152. }
  153. dir_walk_free(dir_walk);
  154. furi_string_free(path);
  155. mu_check(storage_test_paths_check(paths) == false);
  156. storage_test_paths_free(paths);
  157. }
  158. MU_TEST_1(test_dirwalk_no_recursive, Storage* storage) {
  159. FuriString* path;
  160. path = furi_string_alloc();
  161. FileInfo fileinfo;
  162. StorageTestPathDict_t* paths = storage_test_paths_alloc(
  163. storage_test_dirwalk_no_recursive, COUNT_OF(storage_test_dirwalk_no_recursive));
  164. DirWalk* dir_walk = dir_walk_alloc(storage);
  165. dir_walk_set_recursive(dir_walk, false);
  166. mu_check(dir_walk_open(dir_walk, EXT_PATH("dirwalk")));
  167. while(dir_walk_read(dir_walk, path, &fileinfo) == DirWalkOK) {
  168. furi_string_right(path, strlen(EXT_PATH("dirwalk/")));
  169. mu_check(storage_test_paths_mark(paths, path, file_info_is_dir(&fileinfo)));
  170. }
  171. dir_walk_free(dir_walk);
  172. furi_string_free(path);
  173. mu_check(storage_test_paths_check(paths) == false);
  174. storage_test_paths_free(paths);
  175. }
  176. static bool test_dirwalk_filter_no_folder_ext(const char* name, FileInfo* fileinfo, void* ctx) {
  177. UNUSED(ctx);
  178. // only files
  179. if(!file_info_is_dir(fileinfo)) {
  180. // with ".test" in name
  181. if(strstr(name, ".test") != NULL) {
  182. return true;
  183. }
  184. }
  185. return false;
  186. }
  187. MU_TEST_1(test_dirwalk_filter, Storage* storage) {
  188. FuriString* path;
  189. path = furi_string_alloc();
  190. FileInfo fileinfo;
  191. StorageTestPathDict_t* paths = storage_test_paths_alloc(
  192. storage_test_dirwalk_filter, COUNT_OF(storage_test_dirwalk_filter));
  193. DirWalk* dir_walk = dir_walk_alloc(storage);
  194. dir_walk_set_filter_cb(dir_walk, test_dirwalk_filter_no_folder_ext, NULL);
  195. mu_check(dir_walk_open(dir_walk, EXT_PATH("dirwalk")));
  196. while(dir_walk_read(dir_walk, path, &fileinfo) == DirWalkOK) {
  197. furi_string_right(path, strlen(EXT_PATH("dirwalk/")));
  198. mu_check(storage_test_paths_mark(paths, path, file_info_is_dir(&fileinfo)));
  199. }
  200. dir_walk_free(dir_walk);
  201. furi_string_free(path);
  202. mu_check(storage_test_paths_check(paths) == false);
  203. storage_test_paths_free(paths);
  204. }
  205. MU_TEST_SUITE(test_dirwalk_suite) {
  206. Storage* storage = furi_record_open(RECORD_STORAGE);
  207. storage_dirs_create(storage, EXT_PATH("dirwalk"));
  208. MU_RUN_TEST_1(test_dirwalk_full, storage);
  209. MU_RUN_TEST_1(test_dirwalk_no_recursive, storage);
  210. MU_RUN_TEST_1(test_dirwalk_filter, storage);
  211. storage_simply_remove_recursive(storage, EXT_PATH("dirwalk"));
  212. furi_record_close(RECORD_STORAGE);
  213. }
  214. int run_minunit_test_dirwalk() {
  215. MU_RUN_SUITE(test_dirwalk_suite);
  216. return MU_EXIT_CODE;
  217. }