view_test.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. package container // import "github.com/docker/docker/container"
  2. import (
  3. "os"
  4. "path/filepath"
  5. "testing"
  6. "github.com/docker/docker/api/types"
  7. containertypes "github.com/docker/docker/api/types/container"
  8. "github.com/google/uuid"
  9. "gotest.tools/v3/assert"
  10. is "gotest.tools/v3/assert/cmp"
  11. )
  12. var root string
  13. func TestMain(m *testing.M) {
  14. var err error
  15. root, err = os.MkdirTemp("", "docker-container-test-")
  16. if err != nil {
  17. panic(err)
  18. }
  19. defer os.RemoveAll(root)
  20. os.Exit(m.Run())
  21. }
  22. func newContainer(t *testing.T) *Container {
  23. var (
  24. id = uuid.New().String()
  25. cRoot = filepath.Join(root, id)
  26. )
  27. if err := os.MkdirAll(cRoot, 0755); err != nil {
  28. t.Fatal(err)
  29. }
  30. c := NewBaseContainer(id, cRoot)
  31. c.HostConfig = &containertypes.HostConfig{}
  32. return c
  33. }
  34. func TestViewSaveDelete(t *testing.T) {
  35. db, err := NewViewDB()
  36. if err != nil {
  37. t.Fatal(err)
  38. }
  39. c := newContainer(t)
  40. if err := c.CheckpointTo(db); err != nil {
  41. t.Fatal(err)
  42. }
  43. if err := db.Delete(c); err != nil {
  44. t.Fatal(err)
  45. }
  46. }
  47. func TestViewAll(t *testing.T) {
  48. var (
  49. db, _ = NewViewDB()
  50. one = newContainer(t)
  51. two = newContainer(t)
  52. )
  53. one.Pid = 10
  54. if err := one.CheckpointTo(db); err != nil {
  55. t.Fatal(err)
  56. }
  57. two.Pid = 20
  58. if err := two.CheckpointTo(db); err != nil {
  59. t.Fatal(err)
  60. }
  61. all, err := db.Snapshot().All()
  62. if err != nil {
  63. t.Fatal(err)
  64. }
  65. if l := len(all); l != 2 {
  66. t.Fatalf("expected 2 items, got %d", l)
  67. }
  68. byID := make(map[string]Snapshot)
  69. for i := range all {
  70. byID[all[i].ID] = all[i]
  71. }
  72. if s, ok := byID[one.ID]; !ok || s.Pid != 10 {
  73. t.Fatalf("expected something different with for id=%s: %v", one.ID, s)
  74. }
  75. if s, ok := byID[two.ID]; !ok || s.Pid != 20 {
  76. t.Fatalf("expected something different with for id=%s: %v", two.ID, s)
  77. }
  78. }
  79. func TestViewGet(t *testing.T) {
  80. var (
  81. db, _ = NewViewDB()
  82. one = newContainer(t)
  83. )
  84. one.ImageID = "some-image-123"
  85. if err := one.CheckpointTo(db); err != nil {
  86. t.Fatal(err)
  87. }
  88. s, err := db.Snapshot().Get(one.ID)
  89. if err != nil {
  90. t.Fatal(err)
  91. }
  92. if s == nil || s.ImageID != "some-image-123" {
  93. t.Fatalf("expected ImageID=some-image-123. Got: %v", s)
  94. }
  95. }
  96. func TestNames(t *testing.T) {
  97. db, err := NewViewDB()
  98. if err != nil {
  99. t.Fatal(err)
  100. }
  101. assert.Check(t, db.ReserveName("name1", "containerid1"))
  102. assert.Check(t, db.ReserveName("name1", "containerid1")) // idempotent
  103. assert.Check(t, db.ReserveName("name2", "containerid2"))
  104. assert.Check(t, is.Error(db.ReserveName("name2", "containerid3"), ErrNameReserved.Error()))
  105. // Releasing a name allows the name to point to something else later.
  106. assert.Check(t, db.ReleaseName("name2"))
  107. assert.Check(t, db.ReserveName("name2", "containerid3"))
  108. view := db.Snapshot()
  109. id, err := view.GetID("name1")
  110. assert.Check(t, err)
  111. assert.Check(t, is.Equal("containerid1", id))
  112. id, err = view.GetID("name2")
  113. assert.Check(t, err)
  114. assert.Check(t, is.Equal("containerid3", id))
  115. _, err = view.GetID("notreserved")
  116. assert.Check(t, is.Error(err, ErrNameNotReserved.Error()))
  117. // Releasing and re-reserving a name doesn't affect the snapshot.
  118. assert.Check(t, db.ReleaseName("name2"))
  119. assert.Check(t, db.ReserveName("name2", "containerid4"))
  120. id, err = view.GetID("name1")
  121. assert.Check(t, err)
  122. assert.Check(t, is.Equal("containerid1", id))
  123. id, err = view.GetID("name2")
  124. assert.Check(t, err)
  125. assert.Check(t, is.Equal("containerid3", id))
  126. // GetAllNames
  127. assert.Check(t, is.DeepEqual(map[string][]string{"containerid1": {"name1"}, "containerid3": {"name2"}}, view.GetAllNames()))
  128. assert.Check(t, db.ReserveName("name3", "containerid1"))
  129. assert.Check(t, db.ReserveName("name4", "containerid1"))
  130. view = db.Snapshot()
  131. assert.Check(t, is.DeepEqual(map[string][]string{"containerid1": {"name1", "name3", "name4"}, "containerid4": {"name2"}}, view.GetAllNames()))
  132. // Release containerid1's names with Delete even though no container exists
  133. assert.Check(t, db.Delete(&Container{ID: "containerid1"}))
  134. // Reusing one of those names should work
  135. assert.Check(t, db.ReserveName("name1", "containerid4"))
  136. view = db.Snapshot()
  137. assert.Check(t, is.DeepEqual(map[string][]string{"containerid4": {"name1", "name2"}}, view.GetAllNames()))
  138. }
  139. // Test case for GitHub issue 35920
  140. func TestViewWithHealthCheck(t *testing.T) {
  141. var (
  142. db, _ = NewViewDB()
  143. one = newContainer(t)
  144. )
  145. one.Health = &Health{
  146. Health: types.Health{
  147. Status: "starting",
  148. },
  149. }
  150. if err := one.CheckpointTo(db); err != nil {
  151. t.Fatal(err)
  152. }
  153. s, err := db.Snapshot().Get(one.ID)
  154. if err != nil {
  155. t.Fatal(err)
  156. }
  157. if s == nil || s.Health != "starting" {
  158. t.Fatalf("expected Health=starting. Got: %+v", s)
  159. }
  160. }