unix_mountree_test.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. package mountree_test
  2. import (
  3. "git.swzry.com/ProjectNagae/FsUtils/mountree"
  4. "testing"
  5. )
  6. type Mount struct {
  7. FileSystemName string
  8. MountPoint string
  9. }
  10. type TestCase struct {
  11. Path string
  12. FileSystemName string
  13. RemainPath string
  14. }
  15. type Payload struct {
  16. FsName string
  17. }
  18. func (p *Payload) Name() string {
  19. return p.FsName
  20. }
  21. func (p *Payload) Description() string {
  22. return p.FsName
  23. }
  24. var _ mountree.PayloadType = (*Payload)(nil)
  25. var FS *mountree.SimpleUnixLikePathTree[*Payload]
  26. func TestAll(t *testing.T) {
  27. t.Log("==== Phase1 ====")
  28. mounts1 := []Mount{
  29. {"fs1", "/"},
  30. {"fs2", "/foo"},
  31. {"fs3", "/foo/bar"},
  32. {"fs4", "/foo/baz"},
  33. {"fs5", "/foo/baz/qux/tac/mud"},
  34. {"fs6", "/foo/baz/qux/fox"},
  35. }
  36. for _, mount := range mounts1 {
  37. err := FS.Mount(mount.MountPoint, &Payload{FsName: mount.FileSystemName}, false)
  38. if err != nil {
  39. t.Fatalf("failed to mount %v: %v", mount.MountPoint, err)
  40. } else {
  41. t.Logf("mounted %s at %s.", mount.FileSystemName, mount.MountPoint)
  42. }
  43. }
  44. t.Log("-- Mount Test OK --")
  45. t.Log("Mount Table:")
  46. FS.ListAllMount(func(path string, payload *Payload) {
  47. t.Logf("\t%s\t\t%s", payload.Name(), path)
  48. })
  49. t.Log("-- List Mount Table OK --")
  50. tc1 := []TestCase{
  51. {"/", "fs1", ""},
  52. {"///", "fs1", ""},
  53. {"", "fs1", ""},
  54. {"/foobar", "fs1", "foobar"},
  55. {"/reimu", "fs1", "reimu"},
  56. {"/foobar/satori", "fs1", "foobar/satori"},
  57. {"/reimu/cirno", "fs1", "reimu/cirno"},
  58. {"/foo", "fs2", ""},
  59. {"/foo/cirno", "fs2", "cirno"},
  60. {"/foo/cirno/satori", "fs2", "cirno/satori"},
  61. {"/foo/cirno/satori_komeiji", "fs2", "cirno/satori_komeiji"},
  62. {"/foo/bar", "fs3", ""},
  63. {"/foo/bar/////", "fs3", ""},
  64. {"/foo/bar/", "fs3", ""},
  65. {"/foo/bar/koishi", "fs3", "koishi"},
  66. {"/foo/baz", "fs4", ""},
  67. {"/foo/baz/qux114514", "fs4", "qux114514"},
  68. {"/foo/baz/qux114514.fox", "fs4", "qux114514.fox"},
  69. {"/foo/baz/qux/tac/mud", "fs5", ""},
  70. {"/foo/baz/qux/tac/mud/can", "fs5", "can"},
  71. {"/foo/baz/qux/fox", "fs6", ""},
  72. {"/foo/baz/qux/fox/can/tell/you", "fs6", "can/tell/you"},
  73. }
  74. for _, tc := range tc1 {
  75. payload, remain, err := FS.GetPayload(tc.Path)
  76. if err != nil {
  77. t.Fatalf("failed to get payload for %s: %v", tc, err)
  78. }
  79. if (*payload).Name() != tc.FileSystemName {
  80. t.Fatalf("at '%s': payload mismatch: want %#v, got %#v", tc.Path, tc.FileSystemName, *payload)
  81. }
  82. if remain != tc.RemainPath {
  83. t.Fatalf("at '%s': remain path mismatch: want %#v, got %#v", tc.Path, tc.RemainPath, remain)
  84. }
  85. t.Logf("at '%s': payload: %s, remain: %s", tc.Path, *payload, remain)
  86. }
  87. t.Log("-- GetPayload Test OK --")
  88. t.Log("==== Phase2 ====")
  89. umounts1 := []string{
  90. "/foo/baz/qux/fox",
  91. "/foo/bar",
  92. }
  93. for _, mount := range umounts1 {
  94. err := FS.Umount(mount)
  95. if err != nil {
  96. t.Fatalf("failed to umount %v: %v", mount, err)
  97. } else {
  98. t.Logf("umounted %s.", mount)
  99. }
  100. }
  101. t.Log("-- Umount Test OK --")
  102. t.Log("Mount Table:")
  103. FS.ListAllMount(func(path string, payload *Payload) {
  104. t.Logf("\t%s\t\t%s", payload.Name(), path)
  105. })
  106. t.Log("-- List Mount Table OK --")
  107. tc2 := []TestCase{
  108. {"/", "fs1", ""},
  109. {"///", "fs1", ""},
  110. {"", "fs1", ""},
  111. {"/foobar", "fs1", "foobar"},
  112. {"/reimu", "fs1", "reimu"},
  113. {"/foobar/satori", "fs1", "foobar/satori"},
  114. {"/reimu/cirno", "fs1", "reimu/cirno"},
  115. {"/foo", "fs2", ""},
  116. {"/foo/cirno", "fs2", "cirno"},
  117. {"/foo/cirno/satori", "fs2", "cirno/satori"},
  118. {"/foo/cirno/satori_komeiji", "fs2", "cirno/satori_komeiji"},
  119. {"/foo/bar", "fs2", "bar"},
  120. {"/foo/bar/////", "fs2", "bar"},
  121. {"/foo/bar/", "fs2", "bar"},
  122. {"/foo/bar/koishi", "fs2", "bar/koishi"},
  123. {"/foo/baz", "fs4", ""},
  124. {"/foo/baz/qux114514", "fs4", "qux114514"},
  125. {"/foo/baz/qux114514.fox", "fs4", "qux114514.fox"},
  126. {"/foo/baz/qux/tac/mud", "fs5", ""},
  127. {"/foo/baz/qux/tac/mud/can", "fs5", "can"},
  128. {"/foo/baz/qux/fox", "fs4", "qux/fox"},
  129. {"/foo/baz/qux/fox/can/tell/you", "fs4", "qux/fox/can/tell/you"},
  130. }
  131. for _, tc := range tc2 {
  132. payload, remain, err := FS.GetPayload(tc.Path)
  133. if err != nil {
  134. t.Fatalf("failed to get payload for %s: %v", tc.Path, err.Error())
  135. }
  136. if (*payload).Name() != tc.FileSystemName {
  137. t.Fatalf("at '%s': payload mismatch: want %#v, got %#v", tc.Path, tc.FileSystemName, *payload)
  138. }
  139. if remain != tc.RemainPath {
  140. t.Fatalf("at '%s': remain path mismatch: want %#v, got %#v", tc.Path, tc.RemainPath, remain)
  141. }
  142. t.Logf("at '%s': payload: %s, remain: %s", tc.Path, (*payload).Name(), remain)
  143. }
  144. t.Log("-- GetPayload Test OK --")
  145. t.Log("==== Phase3 ====")
  146. t.Log("mount an already mounted path '/' without force")
  147. err := FS.Mount("/", &Payload{FsName: "errfs1"}, false)
  148. if err != nil {
  149. if mountree.CheckErrorType(err, mountree.ErrMountPointAlreadyExists) {
  150. t.Log("Ok")
  151. } else {
  152. t.Fatalf(
  153. "unexpected error type: want '%s', got '%s'",
  154. mountree.ErrMountPointAlreadyExists.Error(),
  155. err.Error(),
  156. )
  157. }
  158. } else {
  159. t.Fatal("test failed: this action should cause error")
  160. }
  161. t.Log("mount an already mounted path '/foo' without force")
  162. err = FS.Mount("/", &Payload{FsName: "errfs2"}, false)
  163. if err != nil {
  164. if mountree.CheckErrorType(err, mountree.ErrMountPointAlreadyExists) {
  165. t.Log("Ok")
  166. } else {
  167. t.Fatalf(
  168. "unexpected error type: want '%s', got '%s'",
  169. mountree.ErrMountPointAlreadyExists.Error(),
  170. err.Error(),
  171. )
  172. }
  173. } else {
  174. t.Fatal("test failed: this action should cause error")
  175. }
  176. t.Log("mount an already mounted path '/' with force")
  177. err = FS.Mount("/", &Payload{FsName: "fs7"}, true)
  178. if err != nil {
  179. t.Fatal("force remount '/' failed: ", err.Error())
  180. } else {
  181. t.Log("Ok")
  182. }
  183. t.Log("Mount Table:")
  184. FS.ListAllMount(func(path string, payload *Payload) {
  185. t.Logf("\t%s\t\t%s", payload.Name(), path)
  186. })
  187. t.Log("-- List Mount Table OK --")
  188. tc3 := []TestCase{
  189. {"/", "fs7", ""},
  190. {"///", "fs7", ""},
  191. {"", "fs7", ""},
  192. {"/foobar", "fs7", "foobar"},
  193. {"/foo/baz/qux/tac/mud", "fs5", ""},
  194. {"/foo/baz/qux/tac/mud/can", "fs5", "can"},
  195. }
  196. for _, tc := range tc3 {
  197. payload, remain, err := FS.GetPayload(tc.Path)
  198. if err != nil {
  199. t.Fatalf("failed to get payload for %s: %v", tc.Path, err.Error())
  200. }
  201. if (*payload).Name() != tc.FileSystemName {
  202. t.Fatalf("at '%s': payload mismatch: want %#v, got %#v", tc.Path, tc.FileSystemName, *payload)
  203. }
  204. if remain != tc.RemainPath {
  205. t.Fatalf("at '%s': remain path mismatch: want %#v, got %#v", tc.Path, tc.RemainPath, remain)
  206. }
  207. t.Logf("at '%s': payload: %s, remain: %s", tc.Path, (*payload).Name(), remain)
  208. }
  209. t.Log("-- GetPayload Test OK --")
  210. t.Log("==== Phase4 ====")
  211. t.Log("umount mount point that not exists: '/foo/cirno'")
  212. err = FS.Umount("/foo/cirno")
  213. if err != nil {
  214. if mountree.CheckErrorType(err, mountree.ErrMountPointNotExists) {
  215. t.Log("Ok")
  216. } else {
  217. t.Fatalf(
  218. "unexpected error type: want '%s', got '%s'",
  219. mountree.ErrMountPointNotExists.Error(),
  220. err.Error(),
  221. )
  222. }
  223. } else {
  224. t.Fatal("test failed: this action should cause error")
  225. }
  226. t.Log("umount '/'")
  227. err = FS.Umount("/")
  228. if err != nil {
  229. t.Fatal("umount '/' failed: ", err.Error())
  230. } else {
  231. t.Log("Ok")
  232. }
  233. t.Log("Mount Table:")
  234. FS.ListAllMount(func(path string, payload *Payload) {
  235. t.Logf("\t%s\t\t%s", payload.Name(), path)
  236. })
  237. t.Log("-- List Mount Table OK --")
  238. t.Log("test for '/'")
  239. _, _, err = FS.GetPayload("/")
  240. if err != nil {
  241. if mountree.CheckErrorType(err, mountree.ErrNoAvailableMountPointForThisPath) {
  242. t.Log("Ok")
  243. } else {
  244. t.Fatalf(
  245. "unexpected error type: want '%s', got '%s'",
  246. mountree.ErrNoAvailableMountPointForThisPath.Error(),
  247. err.Error(),
  248. )
  249. }
  250. } else {
  251. t.Fatal("test failed: this action should cause error")
  252. }
  253. t.Log("test for '/cirno/koishi'")
  254. _, _, err = FS.GetPayload("/cirno/koishi")
  255. if err != nil {
  256. if mountree.CheckErrorType(err, mountree.ErrNoAvailableMountPointForThisPath) {
  257. t.Log("Ok")
  258. } else {
  259. t.Fatalf(
  260. "unexpected error type: want '%s', got '%s'",
  261. mountree.ErrNoAvailableMountPointForThisPath.Error(),
  262. err.Error(),
  263. )
  264. }
  265. } else {
  266. t.Fatal("test failed: this action should cause error")
  267. }
  268. t.Log("==== Phase5 ====")
  269. mounts2 := []Mount{
  270. {"fs8", "/"},
  271. {"fs9", "/foo/bar"},
  272. {"fs10", "/foo/baz/qux/fox"},
  273. {"fs11", "/foo/baz/lut"},
  274. {"fs12", "/foo/baz/cuk"},
  275. {"fs13", "/foo/baz/zek"},
  276. {"fs14", "/foo/baz/zek/cirno"},
  277. }
  278. for _, mount := range mounts2 {
  279. err := FS.Mount(mount.MountPoint, &Payload{FsName: mount.FileSystemName}, false)
  280. if err != nil {
  281. t.Fatalf("failed to mount %v: %v", mount.MountPoint, err)
  282. } else {
  283. t.Logf("mounted %s at %s.", mount.FileSystemName, mount.MountPoint)
  284. }
  285. }
  286. t.Log("-- Mount Test OK --")
  287. t.Log("Mount Table:")
  288. FS.ListAllMount(func(path string, payload *Payload) {
  289. t.Logf("\t%s\t\t%s", payload.Name(), path)
  290. })
  291. t.Log("-- List Mount Table OK --")
  292. tc4 := []TestCase{
  293. {"/", "fs8", ""},
  294. {"///", "fs8", ""},
  295. {"", "fs8", ""},
  296. {"/foo/bar/810", "fs9", "810"},
  297. {"/foo/baz/qux/tac/mud", "fs5", ""},
  298. {"/foo/baz/qux/tac/mud/can", "fs5", "can"},
  299. {"/foo/baz/qux/fox/cat/dog", "fs10", "cat/dog"},
  300. {"/foo/baz/lut/fox/cat/dog", "fs11", "fox/cat/dog"},
  301. {"/foo/baz/cuk/cat/dog/fox", "fs12", "cat/dog/fox"},
  302. {"/foo/baz/zek", "fs13", ""},
  303. {"/foo/baz/zek/cirno", "fs14", ""},
  304. {"/foo/baz/zek/cirno/satori", "fs14", "satori"},
  305. {"/foo/baz", "fs4", ""},
  306. {"/foo/baz/zun", "fs4", "zun"},
  307. }
  308. for _, tc := range tc4 {
  309. payload, remain, err := FS.GetPayload(tc.Path)
  310. if err != nil {
  311. t.Fatalf("failed to get payload for %s: %v", tc.Path, err.Error())
  312. }
  313. if (*payload).Name() != tc.FileSystemName {
  314. t.Fatalf("at '%s': payload mismatch: want %#v, got %#v", tc.Path, tc.FileSystemName, *payload)
  315. }
  316. if remain != tc.RemainPath {
  317. t.Fatalf("at '%s': remain path mismatch: want %#v, got %#v", tc.Path, tc.RemainPath, remain)
  318. }
  319. t.Logf("at '%s': payload: %s, remain: %s", tc.Path, (*payload).Name(), remain)
  320. }
  321. t.Log("-- GetPayload Test OK --")
  322. t.Log("==== Phase5 ====")
  323. t.Log("umount '/foo/baz'")
  324. err = FS.Umount("/foo/baz")
  325. if err != nil {
  326. t.Fatal("umount '/' failed: ", err.Error())
  327. } else {
  328. t.Log("Ok")
  329. }
  330. t.Log("Mount Table:")
  331. FS.ListAllMount(func(path string, payload *Payload) {
  332. t.Logf("\t%s\t\t%s", payload.Name(), path)
  333. })
  334. t.Log("-- List Mount Table OK --")
  335. tc5 := []TestCase{
  336. {"/", "fs8", ""},
  337. {"///", "fs8", ""},
  338. {"", "fs8", ""},
  339. {"/foo/bar/810", "fs9", "810"},
  340. {"/foo/baz/qux/tac/mud", "fs5", ""},
  341. {"/foo/baz/qux/tac/mud/can", "fs5", "can"},
  342. {"/foo/baz/qux/fox/cat/dog", "fs10", "cat/dog"},
  343. {"/foo/baz/lut/fox/cat/dog", "fs11", "fox/cat/dog"},
  344. {"/foo/baz/cuk/cat/dog/fox", "fs12", "cat/dog/fox"},
  345. {"/foo/baz/zek", "fs13", ""},
  346. {"/foo/baz/zek/cirno", "fs14", ""},
  347. {"/foo/baz/zek/cirno/satori", "fs14", "satori"},
  348. {"/foo/baz", "fs2", "baz"},
  349. {"/foo/baz/zun", "fs2", "baz/zun"},
  350. }
  351. for _, tc := range tc5 {
  352. payload, remain, err := FS.GetPayload(tc.Path)
  353. if err != nil {
  354. t.Fatalf("failed to get payload for %s: %v", tc.Path, err.Error())
  355. }
  356. if (*payload).Name() != tc.FileSystemName {
  357. t.Fatalf("at '%s': payload mismatch: want %#v, got %#v", tc.Path, tc.FileSystemName, *payload)
  358. }
  359. if remain != tc.RemainPath {
  360. t.Fatalf("at '%s': remain path mismatch: want %#v, got %#v", tc.Path, tc.RemainPath, remain)
  361. }
  362. t.Logf("at '%s': payload: %s, remain: %s", tc.Path, (*payload).Name(), remain)
  363. }
  364. t.Log("-- GetPayload Test OK --")
  365. }
  366. func TestMain(m *testing.M) {
  367. FS = mountree.NewSimpleUnixLikePathTree[*Payload]()
  368. m.Run()
  369. }