container_linux_test.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. // +build linux
  2. package libcontainer
  3. import (
  4. "fmt"
  5. "os"
  6. "testing"
  7. "github.com/docker/libcontainer/cgroups"
  8. "github.com/docker/libcontainer/configs"
  9. )
  10. type mockCgroupManager struct {
  11. pids []int
  12. stats *cgroups.Stats
  13. paths map[string]string
  14. }
  15. func (m *mockCgroupManager) GetPids() ([]int, error) {
  16. return m.pids, nil
  17. }
  18. func (m *mockCgroupManager) GetStats() (*cgroups.Stats, error) {
  19. return m.stats, nil
  20. }
  21. func (m *mockCgroupManager) Apply(pid int) error {
  22. return nil
  23. }
  24. func (m *mockCgroupManager) Set(container *configs.Config) error {
  25. return nil
  26. }
  27. func (m *mockCgroupManager) Destroy() error {
  28. return nil
  29. }
  30. func (m *mockCgroupManager) GetPaths() map[string]string {
  31. return m.paths
  32. }
  33. func (m *mockCgroupManager) Freeze(state configs.FreezerState) error {
  34. return nil
  35. }
  36. type mockProcess struct {
  37. _pid int
  38. started string
  39. }
  40. func (m *mockProcess) terminate() error {
  41. return nil
  42. }
  43. func (m *mockProcess) pid() int {
  44. return m._pid
  45. }
  46. func (m *mockProcess) startTime() (string, error) {
  47. return m.started, nil
  48. }
  49. func (m *mockProcess) start() error {
  50. return nil
  51. }
  52. func (m *mockProcess) wait() (*os.ProcessState, error) {
  53. return nil, nil
  54. }
  55. func (m *mockProcess) signal(_ os.Signal) error {
  56. return nil
  57. }
  58. func TestGetContainerPids(t *testing.T) {
  59. container := &linuxContainer{
  60. id: "myid",
  61. config: &configs.Config{},
  62. cgroupManager: &mockCgroupManager{pids: []int{1, 2, 3}},
  63. }
  64. pids, err := container.Processes()
  65. if err != nil {
  66. t.Fatal(err)
  67. }
  68. for i, expected := range []int{1, 2, 3} {
  69. if pids[i] != expected {
  70. t.Fatalf("expected pid %d but received %d", expected, pids[i])
  71. }
  72. }
  73. }
  74. func TestGetContainerStats(t *testing.T) {
  75. container := &linuxContainer{
  76. id: "myid",
  77. config: &configs.Config{},
  78. cgroupManager: &mockCgroupManager{
  79. pids: []int{1, 2, 3},
  80. stats: &cgroups.Stats{
  81. MemoryStats: cgroups.MemoryStats{
  82. Usage: 1024,
  83. },
  84. },
  85. },
  86. }
  87. stats, err := container.Stats()
  88. if err != nil {
  89. t.Fatal(err)
  90. }
  91. if stats.CgroupStats == nil {
  92. t.Fatal("cgroup stats are nil")
  93. }
  94. if stats.CgroupStats.MemoryStats.Usage != 1024 {
  95. t.Fatalf("expected memory usage 1024 but recevied %d", stats.CgroupStats.MemoryStats.Usage)
  96. }
  97. }
  98. func TestGetContainerState(t *testing.T) {
  99. var (
  100. pid = os.Getpid()
  101. expectedMemoryPath = "/sys/fs/cgroup/memory/myid"
  102. expectedNetworkPath = "/networks/fd"
  103. )
  104. container := &linuxContainer{
  105. id: "myid",
  106. config: &configs.Config{
  107. Namespaces: configs.Namespaces{
  108. {Type: configs.NEWPID},
  109. {Type: configs.NEWNS},
  110. {Type: configs.NEWNET, Path: expectedNetworkPath},
  111. {Type: configs.NEWUTS},
  112. {Type: configs.NEWIPC},
  113. },
  114. },
  115. initProcess: &mockProcess{
  116. _pid: pid,
  117. started: "010",
  118. },
  119. cgroupManager: &mockCgroupManager{
  120. pids: []int{1, 2, 3},
  121. stats: &cgroups.Stats{
  122. MemoryStats: cgroups.MemoryStats{
  123. Usage: 1024,
  124. },
  125. },
  126. paths: map[string]string{
  127. "memory": expectedMemoryPath,
  128. },
  129. },
  130. }
  131. state, err := container.State()
  132. if err != nil {
  133. t.Fatal(err)
  134. }
  135. if state.InitProcessPid != pid {
  136. t.Fatalf("expected pid %d but received %d", pid, state.InitProcessPid)
  137. }
  138. if state.InitProcessStartTime != "010" {
  139. t.Fatalf("expected process start time 010 but received %s", state.InitProcessStartTime)
  140. }
  141. paths := state.CgroupPaths
  142. if paths == nil {
  143. t.Fatal("cgroup paths should not be nil")
  144. }
  145. if memPath := paths["memory"]; memPath != expectedMemoryPath {
  146. t.Fatalf("expected memory path %q but received %q", expectedMemoryPath, memPath)
  147. }
  148. for _, ns := range container.config.Namespaces {
  149. path := state.NamespacePaths[ns.Type]
  150. if path == "" {
  151. t.Fatalf("expected non nil namespace path for %s", ns.Type)
  152. }
  153. if ns.Type == configs.NEWNET {
  154. if path != expectedNetworkPath {
  155. t.Fatalf("expected path %q but received %q", expectedNetworkPath, path)
  156. }
  157. } else {
  158. file := ""
  159. switch ns.Type {
  160. case configs.NEWNET:
  161. file = "net"
  162. case configs.NEWNS:
  163. file = "mnt"
  164. case configs.NEWPID:
  165. file = "pid"
  166. case configs.NEWIPC:
  167. file = "ipc"
  168. case configs.NEWUSER:
  169. file = "user"
  170. case configs.NEWUTS:
  171. file = "uts"
  172. }
  173. expected := fmt.Sprintf("/proc/%d/ns/%s", pid, file)
  174. if expected != path {
  175. t.Fatalf("expected path %q but received %q", expected, path)
  176. }
  177. }
  178. }
  179. }