graphtest_unix.go 8.6 KB

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