aufs_test.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697
  1. package aufs
  2. import (
  3. "crypto/sha256"
  4. "encoding/hex"
  5. "fmt"
  6. "github.com/dotcloud/docker/archive"
  7. "github.com/dotcloud/docker/daemon/graphdriver"
  8. "io/ioutil"
  9. "os"
  10. "path"
  11. "testing"
  12. )
  13. var (
  14. tmp = path.Join(os.TempDir(), "aufs-tests", "aufs")
  15. )
  16. func testInit(dir string, t *testing.T) graphdriver.Driver {
  17. d, err := Init(dir)
  18. if err != nil {
  19. if err == graphdriver.ErrNotSupported {
  20. t.Skip(err)
  21. } else {
  22. t.Fatal(err)
  23. }
  24. }
  25. return d
  26. }
  27. func newDriver(t *testing.T) *Driver {
  28. if err := os.MkdirAll(tmp, 0755); err != nil {
  29. t.Fatal(err)
  30. }
  31. d := testInit(tmp, t)
  32. return d.(*Driver)
  33. }
  34. func TestNewDriver(t *testing.T) {
  35. if err := os.MkdirAll(tmp, 0755); err != nil {
  36. t.Fatal(err)
  37. }
  38. d := testInit(tmp, t)
  39. defer os.RemoveAll(tmp)
  40. if d == nil {
  41. t.Fatalf("Driver should not be nil")
  42. }
  43. }
  44. func TestAufsString(t *testing.T) {
  45. d := newDriver(t)
  46. defer os.RemoveAll(tmp)
  47. if d.String() != "aufs" {
  48. t.Fatalf("Expected aufs got %s", d.String())
  49. }
  50. }
  51. func TestCreateDirStructure(t *testing.T) {
  52. newDriver(t)
  53. defer os.RemoveAll(tmp)
  54. paths := []string{
  55. "mnt",
  56. "layers",
  57. "diff",
  58. }
  59. for _, p := range paths {
  60. if _, err := os.Stat(path.Join(tmp, p)); err != nil {
  61. t.Fatal(err)
  62. }
  63. }
  64. }
  65. // We should be able to create two drivers with the same dir structure
  66. func TestNewDriverFromExistingDir(t *testing.T) {
  67. if err := os.MkdirAll(tmp, 0755); err != nil {
  68. t.Fatal(err)
  69. }
  70. testInit(tmp, t)
  71. testInit(tmp, t)
  72. os.RemoveAll(tmp)
  73. }
  74. func TestCreateNewDir(t *testing.T) {
  75. d := newDriver(t)
  76. defer os.RemoveAll(tmp)
  77. if err := d.Create("1", ""); err != nil {
  78. t.Fatal(err)
  79. }
  80. }
  81. func TestCreateNewDirStructure(t *testing.T) {
  82. d := newDriver(t)
  83. defer os.RemoveAll(tmp)
  84. if err := d.Create("1", ""); err != nil {
  85. t.Fatal(err)
  86. }
  87. paths := []string{
  88. "mnt",
  89. "diff",
  90. "layers",
  91. }
  92. for _, p := range paths {
  93. if _, err := os.Stat(path.Join(tmp, p, "1")); err != nil {
  94. t.Fatal(err)
  95. }
  96. }
  97. }
  98. func TestRemoveImage(t *testing.T) {
  99. d := newDriver(t)
  100. defer os.RemoveAll(tmp)
  101. if err := d.Create("1", ""); err != nil {
  102. t.Fatal(err)
  103. }
  104. if err := d.Remove("1"); err != nil {
  105. t.Fatal(err)
  106. }
  107. paths := []string{
  108. "mnt",
  109. "diff",
  110. "layers",
  111. }
  112. for _, p := range paths {
  113. if _, err := os.Stat(path.Join(tmp, p, "1")); err == nil {
  114. t.Fatalf("Error should not be nil because dirs with id 1 should be delted: %s", p)
  115. }
  116. }
  117. }
  118. func TestGetWithoutParent(t *testing.T) {
  119. d := newDriver(t)
  120. defer os.RemoveAll(tmp)
  121. if err := d.Create("1", ""); err != nil {
  122. t.Fatal(err)
  123. }
  124. diffPath, err := d.Get("1", "")
  125. if err != nil {
  126. t.Fatal(err)
  127. }
  128. expected := path.Join(tmp, "diff", "1")
  129. if diffPath != expected {
  130. t.Fatalf("Expected path %s got %s", expected, diffPath)
  131. }
  132. }
  133. func TestCleanupWithNoDirs(t *testing.T) {
  134. d := newDriver(t)
  135. defer os.RemoveAll(tmp)
  136. if err := d.Cleanup(); err != nil {
  137. t.Fatal(err)
  138. }
  139. }
  140. func TestCleanupWithDir(t *testing.T) {
  141. d := newDriver(t)
  142. defer os.RemoveAll(tmp)
  143. if err := d.Create("1", ""); err != nil {
  144. t.Fatal(err)
  145. }
  146. if err := d.Cleanup(); err != nil {
  147. t.Fatal(err)
  148. }
  149. }
  150. func TestMountedFalseResponse(t *testing.T) {
  151. d := newDriver(t)
  152. defer os.RemoveAll(tmp)
  153. if err := d.Create("1", ""); err != nil {
  154. t.Fatal(err)
  155. }
  156. response, err := d.mounted("1")
  157. if err != nil {
  158. t.Fatal(err)
  159. }
  160. if response != false {
  161. t.Fatalf("Response if dir id 1 is mounted should be false")
  162. }
  163. }
  164. func TestMountedTrueReponse(t *testing.T) {
  165. d := newDriver(t)
  166. defer os.RemoveAll(tmp)
  167. defer d.Cleanup()
  168. if err := d.Create("1", ""); err != nil {
  169. t.Fatal(err)
  170. }
  171. if err := d.Create("2", "1"); err != nil {
  172. t.Fatal(err)
  173. }
  174. _, err := d.Get("2", "")
  175. if err != nil {
  176. t.Fatal(err)
  177. }
  178. response, err := d.mounted("2")
  179. if err != nil {
  180. t.Fatal(err)
  181. }
  182. if response != true {
  183. t.Fatalf("Response if dir id 2 is mounted should be true")
  184. }
  185. }
  186. func TestMountWithParent(t *testing.T) {
  187. d := newDriver(t)
  188. defer os.RemoveAll(tmp)
  189. if err := d.Create("1", ""); err != nil {
  190. t.Fatal(err)
  191. }
  192. if err := d.Create("2", "1"); err != nil {
  193. t.Fatal(err)
  194. }
  195. defer func() {
  196. if err := d.Cleanup(); err != nil {
  197. t.Fatal(err)
  198. }
  199. }()
  200. mntPath, err := d.Get("2", "")
  201. if err != nil {
  202. t.Fatal(err)
  203. }
  204. if mntPath == "" {
  205. t.Fatal("mntPath should not be empty string")
  206. }
  207. expected := path.Join(tmp, "mnt", "2")
  208. if mntPath != expected {
  209. t.Fatalf("Expected %s got %s", expected, mntPath)
  210. }
  211. }
  212. func TestRemoveMountedDir(t *testing.T) {
  213. d := newDriver(t)
  214. defer os.RemoveAll(tmp)
  215. if err := d.Create("1", ""); err != nil {
  216. t.Fatal(err)
  217. }
  218. if err := d.Create("2", "1"); err != nil {
  219. t.Fatal(err)
  220. }
  221. defer func() {
  222. if err := d.Cleanup(); err != nil {
  223. t.Fatal(err)
  224. }
  225. }()
  226. mntPath, err := d.Get("2", "")
  227. if err != nil {
  228. t.Fatal(err)
  229. }
  230. if mntPath == "" {
  231. t.Fatal("mntPath should not be empty string")
  232. }
  233. mounted, err := d.mounted("2")
  234. if err != nil {
  235. t.Fatal(err)
  236. }
  237. if !mounted {
  238. t.Fatalf("Dir id 2 should be mounted")
  239. }
  240. if err := d.Remove("2"); err != nil {
  241. t.Fatal(err)
  242. }
  243. }
  244. func TestCreateWithInvalidParent(t *testing.T) {
  245. d := newDriver(t)
  246. defer os.RemoveAll(tmp)
  247. if err := d.Create("1", "docker"); err == nil {
  248. t.Fatalf("Error should not be nil with parent does not exist")
  249. }
  250. }
  251. func TestGetDiff(t *testing.T) {
  252. d := newDriver(t)
  253. defer os.RemoveAll(tmp)
  254. if err := d.Create("1", ""); err != nil {
  255. t.Fatal(err)
  256. }
  257. diffPath, err := d.Get("1", "")
  258. if err != nil {
  259. t.Fatal(err)
  260. }
  261. // Add a file to the diff path with a fixed size
  262. size := int64(1024)
  263. f, err := os.Create(path.Join(diffPath, "test_file"))
  264. if err != nil {
  265. t.Fatal(err)
  266. }
  267. if err := f.Truncate(size); err != nil {
  268. t.Fatal(err)
  269. }
  270. f.Close()
  271. a, err := d.Diff("1")
  272. if err != nil {
  273. t.Fatal(err)
  274. }
  275. if a == nil {
  276. t.Fatalf("Archive should not be nil")
  277. }
  278. }
  279. func TestChanges(t *testing.T) {
  280. d := newDriver(t)
  281. defer os.RemoveAll(tmp)
  282. if err := d.Create("1", ""); err != nil {
  283. t.Fatal(err)
  284. }
  285. if err := d.Create("2", "1"); err != nil {
  286. t.Fatal(err)
  287. }
  288. defer func() {
  289. if err := d.Cleanup(); err != nil {
  290. t.Fatal(err)
  291. }
  292. }()
  293. mntPoint, err := d.Get("2", "")
  294. if err != nil {
  295. t.Fatal(err)
  296. }
  297. // Create a file to save in the mountpoint
  298. f, err := os.Create(path.Join(mntPoint, "test.txt"))
  299. if err != nil {
  300. t.Fatal(err)
  301. }
  302. if _, err := f.WriteString("testline"); err != nil {
  303. t.Fatal(err)
  304. }
  305. if err := f.Close(); err != nil {
  306. t.Fatal(err)
  307. }
  308. changes, err := d.Changes("2")
  309. if err != nil {
  310. t.Fatal(err)
  311. }
  312. if len(changes) != 1 {
  313. t.Fatalf("Dir 2 should have one change from parent got %d", len(changes))
  314. }
  315. change := changes[0]
  316. expectedPath := "/test.txt"
  317. if change.Path != expectedPath {
  318. t.Fatalf("Expected path %s got %s", expectedPath, change.Path)
  319. }
  320. if change.Kind != archive.ChangeAdd {
  321. t.Fatalf("Change kind should be ChangeAdd got %s", change.Kind)
  322. }
  323. if err := d.Create("3", "2"); err != nil {
  324. t.Fatal(err)
  325. }
  326. mntPoint, err = d.Get("3", "")
  327. if err != nil {
  328. t.Fatal(err)
  329. }
  330. // Create a file to save in the mountpoint
  331. f, err = os.Create(path.Join(mntPoint, "test2.txt"))
  332. if err != nil {
  333. t.Fatal(err)
  334. }
  335. if _, err := f.WriteString("testline"); err != nil {
  336. t.Fatal(err)
  337. }
  338. if err := f.Close(); err != nil {
  339. t.Fatal(err)
  340. }
  341. changes, err = d.Changes("3")
  342. if err != nil {
  343. t.Fatal(err)
  344. }
  345. if len(changes) != 1 {
  346. t.Fatalf("Dir 2 should have one change from parent got %d", len(changes))
  347. }
  348. change = changes[0]
  349. expectedPath = "/test2.txt"
  350. if change.Path != expectedPath {
  351. t.Fatalf("Expected path %s got %s", expectedPath, change.Path)
  352. }
  353. if change.Kind != archive.ChangeAdd {
  354. t.Fatalf("Change kind should be ChangeAdd got %s", change.Kind)
  355. }
  356. }
  357. func TestDiffSize(t *testing.T) {
  358. d := newDriver(t)
  359. defer os.RemoveAll(tmp)
  360. if err := d.Create("1", ""); err != nil {
  361. t.Fatal(err)
  362. }
  363. diffPath, err := d.Get("1", "")
  364. if err != nil {
  365. t.Fatal(err)
  366. }
  367. // Add a file to the diff path with a fixed size
  368. size := int64(1024)
  369. f, err := os.Create(path.Join(diffPath, "test_file"))
  370. if err != nil {
  371. t.Fatal(err)
  372. }
  373. if err := f.Truncate(size); err != nil {
  374. t.Fatal(err)
  375. }
  376. s, err := f.Stat()
  377. if err != nil {
  378. t.Fatal(err)
  379. }
  380. size = s.Size()
  381. if err := f.Close(); err != nil {
  382. t.Fatal(err)
  383. }
  384. diffSize, err := d.DiffSize("1")
  385. if err != nil {
  386. t.Fatal(err)
  387. }
  388. if diffSize != size {
  389. t.Fatalf("Expected size to be %d got %d", size, diffSize)
  390. }
  391. }
  392. func TestChildDiffSize(t *testing.T) {
  393. d := newDriver(t)
  394. defer os.RemoveAll(tmp)
  395. defer d.Cleanup()
  396. if err := d.Create("1", ""); err != nil {
  397. t.Fatal(err)
  398. }
  399. diffPath, err := d.Get("1", "")
  400. if err != nil {
  401. t.Fatal(err)
  402. }
  403. // Add a file to the diff path with a fixed size
  404. size := int64(1024)
  405. f, err := os.Create(path.Join(diffPath, "test_file"))
  406. if err != nil {
  407. t.Fatal(err)
  408. }
  409. if err := f.Truncate(size); err != nil {
  410. t.Fatal(err)
  411. }
  412. s, err := f.Stat()
  413. if err != nil {
  414. t.Fatal(err)
  415. }
  416. size = s.Size()
  417. if err := f.Close(); err != nil {
  418. t.Fatal(err)
  419. }
  420. diffSize, err := d.DiffSize("1")
  421. if err != nil {
  422. t.Fatal(err)
  423. }
  424. if diffSize != size {
  425. t.Fatalf("Expected size to be %d got %d", size, diffSize)
  426. }
  427. if err := d.Create("2", "1"); err != nil {
  428. t.Fatal(err)
  429. }
  430. diffSize, err = d.DiffSize("2")
  431. if err != nil {
  432. t.Fatal(err)
  433. }
  434. // The diff size for the child should be zero
  435. if diffSize != 0 {
  436. t.Fatalf("Expected size to be %d got %d", 0, diffSize)
  437. }
  438. }
  439. func TestExists(t *testing.T) {
  440. d := newDriver(t)
  441. defer os.RemoveAll(tmp)
  442. defer d.Cleanup()
  443. if err := d.Create("1", ""); err != nil {
  444. t.Fatal(err)
  445. }
  446. if d.Exists("none") {
  447. t.Fatal("id name should not exist in the driver")
  448. }
  449. if !d.Exists("1") {
  450. t.Fatal("id 1 should exist in the driver")
  451. }
  452. }
  453. func TestStatus(t *testing.T) {
  454. d := newDriver(t)
  455. defer os.RemoveAll(tmp)
  456. defer d.Cleanup()
  457. if err := d.Create("1", ""); err != nil {
  458. t.Fatal(err)
  459. }
  460. status := d.Status()
  461. if status == nil || len(status) == 0 {
  462. t.Fatal("Status should not be nil or empty")
  463. }
  464. rootDir := status[0]
  465. dirs := status[1]
  466. if rootDir[0] != "Root Dir" {
  467. t.Fatalf("Expected Root Dir got %s", rootDir[0])
  468. }
  469. if rootDir[1] != d.rootPath() {
  470. t.Fatalf("Expected %s got %s", d.rootPath(), rootDir[1])
  471. }
  472. if dirs[0] != "Dirs" {
  473. t.Fatalf("Expected Dirs got %s", dirs[0])
  474. }
  475. if dirs[1] != "1" {
  476. t.Fatalf("Expected 1 got %s", dirs[1])
  477. }
  478. }
  479. func TestApplyDiff(t *testing.T) {
  480. d := newDriver(t)
  481. defer os.RemoveAll(tmp)
  482. defer d.Cleanup()
  483. if err := d.Create("1", ""); err != nil {
  484. t.Fatal(err)
  485. }
  486. diffPath, err := d.Get("1", "")
  487. if err != nil {
  488. t.Fatal(err)
  489. }
  490. // Add a file to the diff path with a fixed size
  491. size := int64(1024)
  492. f, err := os.Create(path.Join(diffPath, "test_file"))
  493. if err != nil {
  494. t.Fatal(err)
  495. }
  496. if err := f.Truncate(size); err != nil {
  497. t.Fatal(err)
  498. }
  499. f.Close()
  500. diff, err := d.Diff("1")
  501. if err != nil {
  502. t.Fatal(err)
  503. }
  504. if err := d.Create("2", ""); err != nil {
  505. t.Fatal(err)
  506. }
  507. if err := d.Create("3", "2"); err != nil {
  508. t.Fatal(err)
  509. }
  510. if err := d.ApplyDiff("3", diff); err != nil {
  511. t.Fatal(err)
  512. }
  513. // Ensure that the file is in the mount point for id 3
  514. mountPoint, err := d.Get("3", "")
  515. if err != nil {
  516. t.Fatal(err)
  517. }
  518. if _, err := os.Stat(path.Join(mountPoint, "test_file")); err != nil {
  519. t.Fatal(err)
  520. }
  521. }
  522. func hash(c string) string {
  523. h := sha256.New()
  524. fmt.Fprint(h, c)
  525. return hex.EncodeToString(h.Sum(nil))
  526. }
  527. func TestMountMoreThan42Layers(t *testing.T) {
  528. d := newDriver(t)
  529. defer os.RemoveAll(tmp)
  530. defer d.Cleanup()
  531. var last string
  532. var expected int
  533. for i := 1; i < 127; i++ {
  534. expected++
  535. var (
  536. parent = fmt.Sprintf("%d", i-1)
  537. current = fmt.Sprintf("%d", i)
  538. )
  539. if parent == "0" {
  540. parent = ""
  541. } else {
  542. parent = hash(parent)
  543. }
  544. current = hash(current)
  545. if err := d.Create(current, parent); err != nil {
  546. t.Logf("Current layer %d", i)
  547. t.Fatal(err)
  548. }
  549. point, err := d.Get(current, "")
  550. if err != nil {
  551. t.Logf("Current layer %d", i)
  552. t.Fatal(err)
  553. }
  554. f, err := os.Create(path.Join(point, current))
  555. if err != nil {
  556. t.Logf("Current layer %d", i)
  557. t.Fatal(err)
  558. }
  559. f.Close()
  560. if i%10 == 0 {
  561. if err := os.Remove(path.Join(point, parent)); err != nil {
  562. t.Logf("Current layer %d", i)
  563. t.Fatal(err)
  564. }
  565. expected--
  566. }
  567. last = current
  568. }
  569. // Perform the actual mount for the top most image
  570. point, err := d.Get(last, "")
  571. if err != nil {
  572. t.Fatal(err)
  573. }
  574. files, err := ioutil.ReadDir(point)
  575. if err != nil {
  576. t.Fatal(err)
  577. }
  578. if len(files) != expected {
  579. t.Fatalf("Expected %d got %d", expected, len(files))
  580. }
  581. }