graphtest_unix.go 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. //go:build linux || freebsd
  2. package graphtest // import "github.com/docker/docker/daemon/graphdriver/graphtest"
  3. import (
  4. "bytes"
  5. "crypto/rand"
  6. "os"
  7. "path"
  8. "testing"
  9. "github.com/docker/docker/daemon/graphdriver"
  10. "github.com/docker/docker/pkg/stringid"
  11. "github.com/docker/docker/quota"
  12. units "github.com/docker/go-units"
  13. "golang.org/x/sys/unix"
  14. "gotest.tools/v3/assert"
  15. is "gotest.tools/v3/assert/cmp"
  16. )
  17. var (
  18. drv *Driver
  19. )
  20. // Driver conforms to graphdriver.Driver interface and
  21. // contains information such as root and reference count of the number of clients using it.
  22. // This helps in testing drivers added into the framework.
  23. type Driver struct {
  24. graphdriver.Driver
  25. root string
  26. refCount int
  27. }
  28. func newDriver(t testing.TB, name string, options []string) *Driver {
  29. root, err := os.MkdirTemp("", "docker-graphtest-")
  30. assert.NilError(t, err)
  31. assert.NilError(t, os.MkdirAll(root, 0755))
  32. d, err := graphdriver.GetDriver(name, nil, graphdriver.Options{DriverOptions: options, Root: root})
  33. if err != nil {
  34. t.Logf("graphdriver: %v\n", err)
  35. if graphdriver.IsDriverNotSupported(err) {
  36. t.Skipf("Driver %s not supported", name)
  37. }
  38. t.Fatal(err)
  39. }
  40. return &Driver{d, root, 1}
  41. }
  42. func cleanup(t testing.TB, d *Driver) {
  43. if err := drv.Cleanup(); err != nil {
  44. t.Fatal(err)
  45. }
  46. os.RemoveAll(d.root)
  47. }
  48. // GetDriver create a new driver with given name or return an existing driver with the name updating the reference count.
  49. func GetDriver(t testing.TB, name string, options ...string) graphdriver.Driver {
  50. if drv == nil {
  51. drv = newDriver(t, name, options)
  52. } else {
  53. drv.refCount++
  54. }
  55. return drv
  56. }
  57. // PutDriver removes the driver if it is no longer used and updates the reference count.
  58. func PutDriver(t testing.TB) {
  59. if drv == nil {
  60. t.Skip("No driver to put!")
  61. }
  62. drv.refCount--
  63. if drv.refCount == 0 {
  64. cleanup(t, drv)
  65. drv = nil
  66. }
  67. }
  68. // DriverTestCreateEmpty creates a new image and verifies it is empty and the right metadata
  69. func DriverTestCreateEmpty(t testing.TB, drivername string, driverOptions ...string) {
  70. driver := GetDriver(t, drivername, driverOptions...)
  71. defer PutDriver(t)
  72. err := driver.Create("empty", "", nil)
  73. assert.NilError(t, err)
  74. defer func() {
  75. assert.NilError(t, driver.Remove("empty"))
  76. }()
  77. if !driver.Exists("empty") {
  78. t.Fatal("Newly created image doesn't exist")
  79. }
  80. dir, err := driver.Get("empty", "")
  81. assert.NilError(t, err)
  82. verifyFile(t, dir, 0755|os.ModeDir, 0, 0)
  83. // Verify that the directory is empty
  84. fis, err := readDir(dir)
  85. assert.NilError(t, err)
  86. assert.Check(t, is.Len(fis, 0))
  87. driver.Put("empty")
  88. }
  89. // DriverTestCreateBase create a base driver and verify.
  90. func DriverTestCreateBase(t testing.TB, drivername string, driverOptions ...string) {
  91. driver := GetDriver(t, drivername, driverOptions...)
  92. defer PutDriver(t)
  93. createBase(t, driver, "Base")
  94. defer func() {
  95. assert.NilError(t, driver.Remove("Base"))
  96. }()
  97. verifyBase(t, driver, "Base")
  98. }
  99. // DriverTestCreateSnap Create a driver and snap and verify.
  100. func DriverTestCreateSnap(t testing.TB, drivername string, driverOptions ...string) {
  101. driver := GetDriver(t, drivername, driverOptions...)
  102. defer PutDriver(t)
  103. createBase(t, driver, "Base")
  104. defer func() {
  105. assert.NilError(t, driver.Remove("Base"))
  106. }()
  107. err := driver.Create("Snap", "Base", nil)
  108. assert.NilError(t, err)
  109. defer func() {
  110. assert.NilError(t, driver.Remove("Snap"))
  111. }()
  112. verifyBase(t, driver, "Snap")
  113. }
  114. // DriverTestDeepLayerRead reads a file from a lower layer under a given number of layers
  115. func DriverTestDeepLayerRead(t testing.TB, layerCount int, drivername string, driverOptions ...string) {
  116. driver := GetDriver(t, drivername, driverOptions...)
  117. defer PutDriver(t)
  118. base := stringid.GenerateRandomID()
  119. if err := driver.Create(base, "", nil); err != nil {
  120. t.Fatal(err)
  121. }
  122. content := []byte("test content")
  123. if err := addFile(driver, base, "testfile.txt", content); err != nil {
  124. t.Fatal(err)
  125. }
  126. topLayer, err := addManyLayers(driver, base, layerCount)
  127. if err != nil {
  128. t.Fatal(err)
  129. }
  130. err = checkManyLayers(driver, topLayer, layerCount)
  131. if err != nil {
  132. t.Fatal(err)
  133. }
  134. if err := checkFile(driver, topLayer, "testfile.txt", content); err != nil {
  135. t.Fatal(err)
  136. }
  137. }
  138. // DriverTestDiffApply tests diffing and applying produces the same layer
  139. func DriverTestDiffApply(t testing.TB, fileCount int, drivername string, driverOptions ...string) {
  140. driver := GetDriver(t, drivername, driverOptions...)
  141. defer PutDriver(t)
  142. base := stringid.GenerateRandomID()
  143. upper := stringid.GenerateRandomID()
  144. deleteFile := "file-remove.txt"
  145. deleteFileContent := []byte("This file should get removed in upper!")
  146. deleteDir := "var/lib"
  147. if err := driver.Create(base, "", nil); err != nil {
  148. t.Fatal(err)
  149. }
  150. if err := addManyFiles(driver, base, fileCount, 3); err != nil {
  151. t.Fatal(err)
  152. }
  153. if err := addFile(driver, base, deleteFile, deleteFileContent); err != nil {
  154. t.Fatal(err)
  155. }
  156. if err := addDirectory(driver, base, deleteDir); err != nil {
  157. t.Fatal(err)
  158. }
  159. if err := driver.Create(upper, base, nil); err != nil {
  160. t.Fatal(err)
  161. }
  162. if err := addManyFiles(driver, upper, fileCount, 6); err != nil {
  163. t.Fatal(err)
  164. }
  165. if err := removeAll(driver, upper, deleteFile, deleteDir); err != nil {
  166. t.Fatal(err)
  167. }
  168. diffSize, err := driver.DiffSize(upper, "")
  169. if err != nil {
  170. t.Fatal(err)
  171. }
  172. diff := stringid.GenerateRandomID()
  173. if err := driver.Create(diff, base, nil); err != nil {
  174. t.Fatal(err)
  175. }
  176. if err := checkManyFiles(driver, diff, fileCount, 3); err != nil {
  177. t.Fatal(err)
  178. }
  179. if err := checkFile(driver, diff, deleteFile, deleteFileContent); err != nil {
  180. t.Fatal(err)
  181. }
  182. arch, err := driver.Diff(upper, base)
  183. if err != nil {
  184. t.Fatal(err)
  185. }
  186. buf := bytes.NewBuffer(nil)
  187. if _, err := buf.ReadFrom(arch); err != nil {
  188. t.Fatal(err)
  189. }
  190. if err := arch.Close(); err != nil {
  191. t.Fatal(err)
  192. }
  193. applyDiffSize, err := driver.ApplyDiff(diff, base, bytes.NewReader(buf.Bytes()))
  194. if err != nil {
  195. t.Fatal(err)
  196. }
  197. if applyDiffSize != diffSize {
  198. t.Fatalf("Apply diff size different, got %d, expected %d", applyDiffSize, diffSize)
  199. }
  200. if err := checkManyFiles(driver, diff, fileCount, 6); err != nil {
  201. t.Fatal(err)
  202. }
  203. if err := checkFileRemoved(driver, diff, deleteFile); err != nil {
  204. t.Fatal(err)
  205. }
  206. if err := checkFileRemoved(driver, diff, deleteDir); err != nil {
  207. t.Fatal(err)
  208. }
  209. }
  210. // DriverTestChanges tests computed changes on a layer matches changes made
  211. func DriverTestChanges(t testing.TB, drivername string, driverOptions ...string) {
  212. driver := GetDriver(t, drivername, driverOptions...)
  213. defer PutDriver(t)
  214. base := stringid.GenerateRandomID()
  215. upper := stringid.GenerateRandomID()
  216. if err := driver.Create(base, "", nil); err != nil {
  217. t.Fatal(err)
  218. }
  219. if err := addManyFiles(driver, base, 20, 3); err != nil {
  220. t.Fatal(err)
  221. }
  222. if err := driver.Create(upper, base, nil); err != nil {
  223. t.Fatal(err)
  224. }
  225. expectedChanges, err := changeManyFiles(driver, upper, 20, 6)
  226. if err != nil {
  227. t.Fatal(err)
  228. }
  229. changes, err := driver.Changes(upper, base)
  230. if err != nil {
  231. t.Fatal(err)
  232. }
  233. if err = checkChanges(expectedChanges, changes); err != nil {
  234. t.Fatal(err)
  235. }
  236. }
  237. func writeRandomFile(path string, size uint64) error {
  238. data := make([]byte, size)
  239. _, err := rand.Read(data)
  240. if err != nil {
  241. return err
  242. }
  243. return os.WriteFile(path, data, 0700)
  244. }
  245. // DriverTestSetQuota Create a driver and test setting quota.
  246. func DriverTestSetQuota(t *testing.T, drivername string, required bool) {
  247. driver := GetDriver(t, drivername)
  248. defer PutDriver(t)
  249. createBase(t, driver, "Base")
  250. createOpts := &graphdriver.CreateOpts{}
  251. createOpts.StorageOpt = make(map[string]string, 1)
  252. createOpts.StorageOpt["size"] = "50M"
  253. layerName := drivername + "Test"
  254. if err := driver.CreateReadWrite(layerName, "Base", createOpts); err == quota.ErrQuotaNotSupported && !required {
  255. t.Skipf("Quota not supported on underlying filesystem: %v", err)
  256. } else if err != nil {
  257. t.Fatal(err)
  258. }
  259. mountPath, err := driver.Get(layerName, "")
  260. if err != nil {
  261. t.Fatal(err)
  262. }
  263. quota := uint64(50 * units.MiB)
  264. // Try to write a file smaller than quota, and ensure it works
  265. err = writeRandomFile(path.Join(mountPath, "smallfile"), quota/2)
  266. if err != nil {
  267. t.Fatal(err)
  268. }
  269. defer os.Remove(path.Join(mountPath, "smallfile"))
  270. // Try to write a file bigger than quota. We've already filled up half the quota, so hitting the limit should be easy
  271. err = writeRandomFile(path.Join(mountPath, "bigfile"), quota)
  272. if err == nil {
  273. t.Fatalf("expected write to fail(), instead had success")
  274. }
  275. if pathError, ok := err.(*os.PathError); ok && pathError.Err != unix.EDQUOT && pathError.Err != unix.ENOSPC {
  276. os.Remove(path.Join(mountPath, "bigfile"))
  277. t.Fatalf("expect write() to fail with %v or %v, got %v", unix.EDQUOT, unix.ENOSPC, pathError.Err)
  278. }
  279. }