unix_mountree_test.go 11 KB

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