path_manipulations.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. /* lib/vfs - test vfs_path_t manipulation functions
  2. Copyright (C) 2011-2025
  3. Free Software Foundation, Inc.
  4. Written by:
  5. Slava Zanko <slavazanko@gmail.com>, 2011, 2013
  6. This file is part of the Midnight Commander.
  7. The Midnight Commander is free software: you can redistribute it
  8. and/or modify it under the terms of the GNU General Public License as
  9. published by the Free Software Foundation, either version 3 of the License,
  10. or (at your option) any later version.
  11. The Midnight Commander is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. #define TEST_SUITE_NAME "/lib/vfs"
  19. #include "tests/mctest.h"
  20. #ifdef HAVE_CHARSET
  21. # include "lib/charsets.h"
  22. #endif
  23. #include "lib/strutil.h"
  24. #include "lib/vfs/xdirentry.h"
  25. #include "lib/vfs/path.h"
  26. #include "src/vfs/local/local.c"
  27. static struct vfs_class vfs_test_ops1, vfs_test_ops2, vfs_test_ops3;
  28. /* --------------------------------------------------------------------------------------------- */
  29. static void
  30. init_test_classes (void)
  31. {
  32. vfs_init_class (&vfs_test_ops1, "testfs1", VFSF_NOLINKS | VFSF_REMOTE, "test1");
  33. vfs_register_class (&vfs_test_ops1);
  34. vfs_init_class (&vfs_test_ops2, "testfs2", VFSF_UNKNOWN, "test2");
  35. vfs_register_class (&vfs_test_ops2);
  36. vfs_init_class (&vfs_test_ops3, "testfs3", VFSF_LOCAL, "test3");
  37. vfs_register_class (&vfs_test_ops3);
  38. }
  39. /* --------------------------------------------------------------------------------------------- */
  40. /* @Before */
  41. static void
  42. setup (void)
  43. {
  44. str_init_strings ("UTF-8");
  45. vfs_init ();
  46. vfs_init_localfs ();
  47. vfs_setup_work_dir ();
  48. init_test_classes ();
  49. #ifdef HAVE_CHARSET
  50. mc_global.sysconfig_dir = (char *) TEST_SHARE_DIR;
  51. load_codepages_list ();
  52. #endif
  53. }
  54. /* --------------------------------------------------------------------------------------------- */
  55. /* @After */
  56. static void
  57. teardown (void)
  58. {
  59. #ifdef HAVE_CHARSET
  60. free_codepages_list ();
  61. #endif
  62. vfs_shut ();
  63. str_uninit_strings ();
  64. }
  65. /* --------------------------------------------------------------------------------------------- */
  66. /* @DataSource("test_vfs_path_tokens_count_ds") */
  67. static const struct test_vfs_path_tokens_count_ds
  68. {
  69. const char *input_path;
  70. const vfs_path_flag_t input_flags;
  71. const size_t expected_token_count;
  72. } test_vfs_path_tokens_count_ds[] = {
  73. {
  74. // 0.
  75. "/",
  76. VPF_NONE,
  77. 0,
  78. },
  79. {
  80. // 1.
  81. "/path",
  82. VPF_NONE,
  83. 1,
  84. },
  85. {
  86. // 2.
  87. "/path1/path2/path3",
  88. VPF_NONE,
  89. 3,
  90. },
  91. {
  92. // 3.
  93. "test3://path1/path2/path3/path4",
  94. VPF_NO_CANON,
  95. 4,
  96. },
  97. {
  98. // 4.
  99. "path1/path2/path3",
  100. VPF_NO_CANON,
  101. 3,
  102. },
  103. {
  104. // 5.
  105. "/path1/path2/path3/",
  106. VPF_NONE,
  107. 3,
  108. },
  109. {
  110. // 6.
  111. "/local/path/test1://user:pass@some.host:12345/bla-bla/some/path/",
  112. VPF_NONE,
  113. 5,
  114. },
  115. #ifdef HAVE_CHARSET
  116. {
  117. // 7.
  118. "/local/path/test1://user:pass@some.host:12345/bla-bla/some/path/"
  119. "test2://#enc:KOI8-R/bla-bla/some/path/test3://111/22/33",
  120. VPF_NONE,
  121. 11,
  122. },
  123. #endif
  124. };
  125. /* @Test(dataSource = "test_vfs_path_tokens_count_ds") */
  126. START_PARAMETRIZED_TEST (test_vfs_path_tokens_count, test_vfs_path_tokens_count_ds)
  127. {
  128. // given
  129. size_t tokens_count;
  130. vfs_path_t *vpath;
  131. vpath = vfs_path_from_str_flags (data->input_path, data->input_flags);
  132. // when
  133. tokens_count = vfs_path_tokens_count (vpath);
  134. // then
  135. ck_assert_int_eq (tokens_count, data->expected_token_count);
  136. vfs_path_free (vpath, TRUE);
  137. }
  138. END_PARAMETRIZED_TEST
  139. /* --------------------------------------------------------------------------------------------- */
  140. /* @DataSource("test_vfs_path_tokens_get_ds") */
  141. static const struct test_vfs_path_tokens_get_ds
  142. {
  143. const char *input_path;
  144. const ssize_t input_start_position;
  145. const ssize_t input_length;
  146. const char *expected_path;
  147. } test_vfs_path_tokens_get_ds[] = {
  148. {
  149. // 0. Invalid start position
  150. "/",
  151. 2,
  152. 1,
  153. NULL,
  154. },
  155. {
  156. // 1. Invalid negative position
  157. "/path",
  158. -3,
  159. 1,
  160. NULL,
  161. },
  162. {
  163. // 2. Count of tokens is zero. Count should be autocorrected
  164. "/path",
  165. 0,
  166. 0,
  167. "path",
  168. },
  169. // 3. get 'path2/path3' by 1,2
  170. {
  171. "/path1/path2/path3/path4",
  172. 1,
  173. 2,
  174. "path2/path3",
  175. },
  176. // 4. get 'path2/path3' by 1,2 from LOCAL VFS
  177. {
  178. "test3://path1/path2/path3/path4",
  179. 1,
  180. 2,
  181. "path2/path3",
  182. },
  183. // 5. get 'path2/path3' by 1,2 from non-LOCAL VFS
  184. {
  185. "test2://path1/path2/path3/path4",
  186. 1,
  187. 2,
  188. "test2://path2/path3",
  189. },
  190. // 6. get 'path2/path3' by 1,2 through non-LOCAL VFS
  191. {
  192. "/path1/path2/test1://user:pass@some.host:12345/path3/path4",
  193. 1,
  194. 2,
  195. "path2/test1://user:pass@some.host:12345/path3",
  196. },
  197. // 7. get 'path2/path3' by 1,2 where path2 it's LOCAL VFS
  198. {
  199. "test3://path1/path2/test2://path3/path4",
  200. 1,
  201. 2,
  202. "path2/test2://path3",
  203. },
  204. // 8. get 'path2/path3' by 1,2 where path3 it's LOCAL VFS
  205. {
  206. "test2://path1/path2/test3://path3/path4",
  207. 1,
  208. 2,
  209. "test2://path2/test3://path3",
  210. },
  211. // 9. get 'path4' by -1,1
  212. {
  213. "/path1/path2/path3/path4",
  214. -1,
  215. 1,
  216. "path4",
  217. },
  218. // 10. get 'path2/path3/path4' by -3,0
  219. {
  220. "/path1/path2/path3/path4",
  221. -3,
  222. 0,
  223. "path2/path3/path4",
  224. },
  225. #ifdef HAVE_CHARSET
  226. // 11. get 'path2/path3' by 1,2 from LOCAL VFS with encoding
  227. {
  228. "test3://path1/path2/test3://#enc:KOI8-R/path3/path4",
  229. 1,
  230. 2,
  231. "path2/test3://#enc:KOI8-R/path3",
  232. },
  233. // 12. get 'path2/path3' by 1,2 with encoding
  234. {
  235. "#enc:KOI8-R/path1/path2/path3/path4",
  236. 1,
  237. 2,
  238. "#enc:KOI8-R/path2/path3",
  239. },
  240. #endif
  241. /* TODO: currently this test don't passed. Probably broken string URI parser
  242. * // 13. get 'path2/path3' by 1,2 from LOCAL VFS
  243. {
  244. "test3://path1/path2/test2://test3://path3/path4",
  245. 1,
  246. 2,
  247. "path2/path3"
  248. },
  249. */
  250. };
  251. /* @Test(dataSource = "test_vfs_path_tokens_get_ds") */
  252. START_PARAMETRIZED_TEST (test_vfs_path_tokens_get, test_vfs_path_tokens_get_ds)
  253. {
  254. // given
  255. vfs_path_t *vpath;
  256. char *actual_path;
  257. vpath = vfs_path_from_str_flags (data->input_path, VPF_NO_CANON);
  258. // when
  259. actual_path = vfs_path_tokens_get (vpath, data->input_start_position, data->input_length);
  260. // then
  261. mctest_assert_str_eq (actual_path, data->expected_path);
  262. g_free (actual_path);
  263. vfs_path_free (vpath, TRUE);
  264. }
  265. END_PARAMETRIZED_TEST
  266. /* --------------------------------------------------------------------------------------------- */
  267. /* @DataSource("test_vfs_path_append_vpath_ds") */
  268. static const struct test_vfs_path_append_vpath_ds
  269. {
  270. const char *input_path1;
  271. const char *input_path2;
  272. const int expected_element_count;
  273. const char *expected_path;
  274. } test_vfs_path_append_vpath_ds[] = {
  275. {
  276. // 0.
  277. "/local/path/test1://user:pass@some.host:12345/bla-bla/some/path/test2://bla-bla/some/path/"
  278. "test3://111/22/33",
  279. "/local/path/test1://user:pass@some.host:12345/bla-bla/some/path/",
  280. 6,
  281. "/local/path/test1://user:pass@some.host:12345/bla-bla/some/path/test2://bla-bla/some/path/"
  282. "test3://111/22/33"
  283. "/local/path/test1://user:pass@some.host:12345/bla-bla/some/path",
  284. },
  285. #ifdef HAVE_CHARSET
  286. {
  287. // 1.
  288. "/local/path/test1://user:pass@some.host:12345/bla-bla/some/path/test2://#enc:KOI8-R/"
  289. "bla-bla/some/path/test3://111/22/33",
  290. "/local/path/test1://user:pass@some.host:12345/bla-bla/some/path/",
  291. 6,
  292. "/local/path/test1://user:pass@some.host:12345/bla-bla/some/path/test2://#enc:KOI8-R/"
  293. "bla-bla/some/path/test3://111/22/33"
  294. "/local/path/test1://user:pass@some.host:12345/bla-bla/some/path",
  295. },
  296. #endif
  297. };
  298. /* @Test(dataSource = "test_vfs_path_append_vpath_ds") */
  299. START_PARAMETRIZED_TEST (test_vfs_path_append_vpath, test_vfs_path_append_vpath_ds)
  300. {
  301. // given
  302. vfs_path_t *vpath1, *vpath2, *vpath3;
  303. vpath1 = vfs_path_from_str (data->input_path1);
  304. vpath2 = vfs_path_from_str (data->input_path2);
  305. // when
  306. vpath3 = vfs_path_append_vpath_new (vpath1, vpath2, NULL);
  307. // then
  308. ck_assert_int_eq (vfs_path_elements_count (vpath3), data->expected_element_count);
  309. mctest_assert_str_eq (vfs_path_as_str (vpath3), data->expected_path);
  310. vfs_path_free (vpath1, TRUE);
  311. vfs_path_free (vpath2, TRUE);
  312. vfs_path_free (vpath3, TRUE);
  313. }
  314. END_PARAMETRIZED_TEST
  315. /* --------------------------------------------------------------------------------------------- */
  316. /* @DataSource("test_vfs_path_relative_ds") */
  317. static const struct test_vfs_path_relative_ds
  318. {
  319. const char *input_path;
  320. const char *expected_path;
  321. const char *expected_last_path_in_element;
  322. } test_vfs_path_relative_ds[] = {
  323. {
  324. // 0.
  325. "../bla-bla",
  326. "../bla-bla",
  327. "../bla-bla",
  328. },
  329. {
  330. // 1.
  331. "../path/test1://user:pass@some.host:12345/bla-bla/some/path/",
  332. "../path/test1://user:pass@some.host:12345/bla-bla/some/path/",
  333. "bla-bla/some/path/",
  334. },
  335. };
  336. /* @Test(dataSource = "test_vfs_path_relative_ds") */
  337. START_PARAMETRIZED_TEST (test_vfs_path_relative, test_vfs_path_relative_ds)
  338. {
  339. // given
  340. vfs_path_t *vpath;
  341. // when
  342. vpath = vfs_path_from_str_flags (data->input_path, VPF_NO_CANON);
  343. // then
  344. mctest_assert_true (vpath->relative);
  345. mctest_assert_str_eq (vfs_path_get_last_path_str (vpath), data->expected_last_path_in_element);
  346. mctest_assert_str_eq (vfs_path_as_str (vpath), data->expected_path);
  347. vfs_path_free (vpath, TRUE);
  348. }
  349. END_PARAMETRIZED_TEST
  350. /* --------------------------------------------------------------------------------------------- */
  351. /* @Test(dataSource = "test_vfs_path_relative_ds") */
  352. START_PARAMETRIZED_TEST (test_vfs_path_relative_clone, test_vfs_path_relative_ds)
  353. {
  354. // given
  355. vfs_path_t *vpath, *cloned_vpath;
  356. vpath = vfs_path_from_str_flags (data->input_path, VPF_NO_CANON);
  357. // when
  358. cloned_vpath = vfs_path_clone (vpath);
  359. // then
  360. mctest_assert_true (cloned_vpath->relative);
  361. mctest_assert_str_eq (vfs_path_get_last_path_str (cloned_vpath),
  362. data->expected_last_path_in_element);
  363. mctest_assert_str_eq (vfs_path_as_str (cloned_vpath), data->expected_path);
  364. vfs_path_free (vpath, TRUE);
  365. vfs_path_free (cloned_vpath, TRUE);
  366. }
  367. END_PARAMETRIZED_TEST
  368. /* --------------------------------------------------------------------------------------------- */
  369. int
  370. main (void)
  371. {
  372. TCase *tc_core;
  373. tc_core = tcase_create ("Core");
  374. tcase_add_checked_fixture (tc_core, setup, teardown);
  375. // Add new tests here: ***************
  376. mctest_add_parameterized_test (tc_core, test_vfs_path_tokens_count,
  377. test_vfs_path_tokens_count_ds);
  378. mctest_add_parameterized_test (tc_core, test_vfs_path_tokens_get, test_vfs_path_tokens_get_ds);
  379. mctest_add_parameterized_test (tc_core, test_vfs_path_append_vpath,
  380. test_vfs_path_append_vpath_ds);
  381. mctest_add_parameterized_test (tc_core, test_vfs_path_relative, test_vfs_path_relative_ds);
  382. mctest_add_parameterized_test (tc_core, test_vfs_path_relative_clone,
  383. test_vfs_path_relative_ds);
  384. // ***********************************
  385. return mctest_run_all (tc_core);
  386. }
  387. /* --------------------------------------------------------------------------------------------- */