test_vfs_paths.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. // Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include <stdbool.h>
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <errno.h>
  19. #include <sys/fcntl.h>
  20. #include <sys/dirent.h>
  21. #include "esp_vfs.h"
  22. #include "unity.h"
  23. #include "esp_log.h"
  24. /* Dummy VFS implementation to check if VFS is called or not with expected path
  25. */
  26. typedef struct {
  27. const char* match_path;
  28. bool called;
  29. } dummy_vfs_t;
  30. static int dummy_open(void* ctx, const char * path, int flags, int mode)
  31. {
  32. dummy_vfs_t* dummy = (dummy_vfs_t*) ctx;
  33. dummy->called = true;
  34. if (strcmp(dummy->match_path, path) == 0) {
  35. return 1;
  36. }
  37. errno = ENOENT;
  38. return -1;
  39. }
  40. static int dummy_close(void* ctx, int fd)
  41. {
  42. dummy_vfs_t* dummy = (dummy_vfs_t*) ctx;
  43. dummy->called = true;
  44. if (fd == 1) {
  45. return 0;
  46. }
  47. errno = EBADF;
  48. return -1;
  49. }
  50. static DIR* dummy_opendir(void* ctx, const char* path)
  51. {
  52. dummy_vfs_t* dummy = (dummy_vfs_t*) ctx;
  53. dummy->called = true;
  54. if (strcmp(dummy->match_path, path) == 0) {
  55. DIR* result = calloc(1, sizeof(DIR));
  56. TEST_ASSERT_NOT_NULL(result);
  57. return result;
  58. }
  59. errno = ENOENT;
  60. return NULL;
  61. }
  62. static int dummy_closedir(void* ctx, DIR* pdir)
  63. {
  64. dummy_vfs_t* dummy = (dummy_vfs_t*) ctx;
  65. dummy->called = true;
  66. free(pdir);
  67. return 0;
  68. }
  69. /* Initializer for this dummy VFS implementation
  70. */
  71. #define DUMMY_VFS() { \
  72. .flags = ESP_VFS_FLAG_CONTEXT_PTR, \
  73. .open_p = dummy_open, \
  74. .close_p = dummy_close, \
  75. .opendir_p = dummy_opendir, \
  76. .closedir_p = dummy_closedir \
  77. }
  78. /* Helper functions to test VFS behavior
  79. */
  80. static void test_open(dummy_vfs_t* instance, const char* path,
  81. bool should_be_called, bool should_be_opened, int line)
  82. {
  83. const int flags = O_CREAT | O_TRUNC | O_RDWR;
  84. instance->called = false;
  85. int fd = esp_vfs_open(__getreent(), path, flags, 0);
  86. UNITY_TEST_ASSERT_EQUAL_INT(should_be_called, instance->called, line,
  87. "should_be_called check failed");
  88. if (should_be_called) {
  89. if (should_be_opened) {
  90. UNITY_TEST_ASSERT(fd >= 0, line, "should be opened");
  91. } else {
  92. UNITY_TEST_ASSERT(fd < 0, line, "should not be opened");
  93. }
  94. }
  95. esp_vfs_close(__getreent(), fd);
  96. }
  97. static void test_opendir(dummy_vfs_t* instance, const char* path,
  98. bool should_be_called, bool should_be_opened, int line)
  99. {
  100. instance->called = false;
  101. DIR* dir = opendir(path);
  102. UNITY_TEST_ASSERT_EQUAL_INT(should_be_called, instance->called, line,
  103. "should_be_called check failed");
  104. if (should_be_called) {
  105. if (should_be_opened) {
  106. UNITY_TEST_ASSERT(dir != NULL, line, "should be opened");
  107. } else {
  108. UNITY_TEST_ASSERT(dir == 0, line, "should not be opened");
  109. }
  110. }
  111. if (dir) {
  112. closedir(dir);
  113. }
  114. }
  115. /* Helper macros which forward line number to assertion macros inside test_open
  116. * and test_opendir
  117. */
  118. #define test_opened(instance, path) test_open(instance, path, true, true, __LINE__)
  119. #define test_not_opened(instance, path) test_open(instance, path, true, false, __LINE__)
  120. #define test_not_called(instance, path) test_open(instance, path, false, false, __LINE__)
  121. #define test_dir_opened(instance, path) test_opendir(instance, path, true, true, __LINE__)
  122. #define test_dir_not_opened(instance, path) test_opendir(instance, path, true, false, __LINE__)
  123. #define test_dir_not_called(instance, path) test_opendir(instance, path, false, false, __LINE__)
  124. TEST_CASE("vfs parses paths correctly", "[vfs]")
  125. {
  126. dummy_vfs_t inst_foo = {
  127. .match_path = "",
  128. .called = false
  129. };
  130. esp_vfs_t desc_foo = DUMMY_VFS();
  131. TEST_ESP_OK( esp_vfs_register("/foo", &desc_foo, &inst_foo) );
  132. dummy_vfs_t inst_foo1 = {
  133. .match_path = "",
  134. .called = false
  135. };
  136. esp_vfs_t desc_foo1 = DUMMY_VFS();
  137. TEST_ESP_OK( esp_vfs_register("/foo1", &desc_foo1, &inst_foo1) );
  138. inst_foo.match_path = "/file";
  139. test_opened(&inst_foo, "/foo/file");
  140. test_not_opened(&inst_foo, "/foo/file1");
  141. test_not_called(&inst_foo, "/foo1/file");
  142. test_not_called(&inst_foo, "/foo1");
  143. test_not_opened(&inst_foo, "/foo");
  144. inst_foo.match_path = "/junk";
  145. test_dir_opened(&inst_foo, "/foo/junk");
  146. inst_foo.match_path = "/";
  147. test_dir_opened(&inst_foo, "/foo/");
  148. test_dir_opened(&inst_foo, "/foo");
  149. test_dir_not_called(&inst_foo1, "/foo");
  150. test_dir_not_opened(&inst_foo, "/foo/1");
  151. test_dir_not_called(&inst_foo, "/foo1");
  152. inst_foo1.match_path = "/file1";
  153. test_not_called(&inst_foo1, "/foo/file1");
  154. test_opened(&inst_foo1, "/foo1/file1");
  155. test_not_opened(&inst_foo1, "/foo1/file");
  156. // Test nested VFS entries
  157. dummy_vfs_t inst_foobar = {
  158. .match_path = "",
  159. .called = false
  160. };
  161. esp_vfs_t desc_foobar = DUMMY_VFS();
  162. TEST_ESP_OK( esp_vfs_register("/foo/bar", &desc_foobar, &inst_foobar) );
  163. dummy_vfs_t inst_toplevel = {
  164. .match_path = "",
  165. .called = false
  166. };
  167. esp_vfs_t desc_toplevel = DUMMY_VFS();
  168. TEST_ESP_OK( esp_vfs_register("", &desc_toplevel, &inst_toplevel) );
  169. inst_foo.match_path = "/bar/file";
  170. inst_foobar.match_path = "/file";
  171. test_not_called(&inst_foo, "/foo/bar/file");
  172. test_opened(&inst_foobar, "/foo/bar/file");
  173. test_dir_not_called(&inst_foo, "/foo/bar/file");
  174. test_dir_opened(&inst_foobar, "/foo/bar/file");
  175. inst_toplevel.match_path = "/tmp/foo";
  176. test_opened(&inst_toplevel, "/tmp/foo");
  177. inst_toplevel.match_path = "foo";
  178. test_opened(&inst_toplevel, "foo");
  179. TEST_ESP_OK( esp_vfs_unregister("/foo") );
  180. TEST_ESP_OK( esp_vfs_unregister("/foo1") );
  181. TEST_ESP_OK( esp_vfs_unregister("/foo/bar") );
  182. TEST_ESP_OK( esp_vfs_unregister("") );
  183. }
  184. TEST_CASE("vfs unregisters correct nested mount point", "[vfs]")
  185. {
  186. dummy_vfs_t inst_foobar = {
  187. .match_path = "/file",
  188. .called = false
  189. };
  190. esp_vfs_t desc_foobar = DUMMY_VFS();
  191. TEST_ESP_OK( esp_vfs_register("/foo/bar", &desc_foobar, &inst_foobar) );
  192. dummy_vfs_t inst_foo = {
  193. .match_path = "/bar/file",
  194. .called = false
  195. };
  196. esp_vfs_t desc_foo = DUMMY_VFS();
  197. TEST_ESP_OK( esp_vfs_register("/foo", &desc_foo, &inst_foo) );
  198. /* basic operation */
  199. test_opened(&inst_foobar, "/foo/bar/file");
  200. test_not_called(&inst_foo, "/foo/bar/file");
  201. /* this should not match anything */
  202. TEST_ESP_ERR(ESP_ERR_INVALID_STATE, esp_vfs_unregister("/foo/b"));
  203. /* unregister "/foo" and check that we haven't unregistered "/foo/bar" */
  204. TEST_ESP_OK( esp_vfs_unregister("/foo") );
  205. test_not_called(&inst_foo, "/foo/bar/file");
  206. test_opened(&inst_foobar, "/foo/bar/file");
  207. /* repeat the above, with the reverse order of registration */
  208. TEST_ESP_OK( esp_vfs_unregister("/foo/bar") );
  209. TEST_ESP_OK( esp_vfs_register("/foo", &desc_foo, &inst_foo) );
  210. TEST_ESP_OK( esp_vfs_register("/foo/bar", &desc_foobar, &inst_foobar) );
  211. test_opened(&inst_foobar, "/foo/bar/file");
  212. test_not_called(&inst_foo, "/foo/bar/file");
  213. TEST_ESP_OK( esp_vfs_unregister("/foo") );
  214. test_not_called(&inst_foo, "/foo/bar/file");
  215. test_opened(&inst_foobar, "/foo/bar/file");
  216. TEST_ESP_OK( esp_vfs_unregister("/foo/bar") );
  217. }
  218. void test_vfs_register(const char* prefix, bool expect_success, int line)
  219. {
  220. dummy_vfs_t inst;
  221. esp_vfs_t desc = DUMMY_VFS();
  222. esp_err_t err = esp_vfs_register(prefix, &desc, &inst);
  223. if (expect_success) {
  224. UNITY_TEST_ASSERT_EQUAL_INT(ESP_OK, err, line, "esp_vfs_register should succeed");
  225. } else {
  226. UNITY_TEST_ASSERT_EQUAL_INT(ESP_ERR_INVALID_ARG,
  227. err, line, "esp_vfs_register should fail");
  228. }
  229. if (err == ESP_OK) {
  230. TEST_ESP_OK( esp_vfs_unregister(prefix) );
  231. }
  232. }
  233. #define test_register_ok(prefix) test_vfs_register(prefix, true, __LINE__)
  234. #define test_register_fail(prefix) test_vfs_register(prefix, false, __LINE__)
  235. TEST_CASE("vfs checks mount point path", "[vfs]")
  236. {
  237. test_register_ok("");
  238. test_register_fail("/");
  239. test_register_fail("a");
  240. test_register_fail("aa");
  241. test_register_fail("aaa");
  242. test_register_ok("/a");
  243. test_register_ok("/aa");
  244. test_register_ok("/aaa/bbb");
  245. test_register_fail("/aaa/");
  246. test_register_fail("/aaa/bbb/");
  247. test_register_ok("/23456789012345");
  248. test_register_fail("/234567890123456");
  249. }