oom_watcher_linux_test.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /*
  2. Copyright 2015 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package oom
  14. import (
  15. "fmt"
  16. "testing"
  17. "time"
  18. v1 "k8s.io/api/core/v1"
  19. "k8s.io/client-go/tools/record"
  20. "github.com/google/cadvisor/utils/oomparser"
  21. "github.com/stretchr/testify/assert"
  22. )
  23. type fakeStreamer struct {
  24. oomInstancesToStream []*oomparser.OomInstance
  25. }
  26. func (fs *fakeStreamer) StreamOoms(outStream chan<- *oomparser.OomInstance) {
  27. for _, oomInstance := range fs.oomInstancesToStream {
  28. outStream <- oomInstance
  29. }
  30. }
  31. // TestStartingWatcher tests that the watcher, using the actual streamer
  32. // and not the fake, starts successfully.
  33. func TestStartingWatcher(t *testing.T) {
  34. fakeRecorder := &record.FakeRecorder{}
  35. node := &v1.ObjectReference{}
  36. oomWatcher, err := NewWatcher(fakeRecorder)
  37. assert.NoError(t, err)
  38. assert.NoError(t, oomWatcher.Start(node))
  39. }
  40. // TestWatcherRecordsEventsForOomEvents ensures that our OomInstances coming
  41. // from `StreamOoms` are translated into events in our recorder.
  42. func TestWatcherRecordsEventsForOomEvents(t *testing.T) {
  43. oomInstancesToStream := []*oomparser.OomInstance{
  44. {
  45. Pid: 1000,
  46. ProcessName: "fakeProcess",
  47. TimeOfDeath: time.Now(),
  48. ContainerName: recordEventContainerName,
  49. VictimContainerName: "some-container",
  50. },
  51. }
  52. numExpectedOomEvents := len(oomInstancesToStream)
  53. fakeStreamer := &fakeStreamer{
  54. oomInstancesToStream: oomInstancesToStream,
  55. }
  56. fakeRecorder := record.NewFakeRecorder(numExpectedOomEvents)
  57. node := &v1.ObjectReference{}
  58. oomWatcher := &realWatcher{
  59. recorder: fakeRecorder,
  60. oomStreamer: fakeStreamer,
  61. }
  62. assert.NoError(t, oomWatcher.Start(node))
  63. eventsRecorded := getRecordedEvents(fakeRecorder, numExpectedOomEvents)
  64. assert.Equal(t, numExpectedOomEvents, len(eventsRecorded))
  65. }
  66. func getRecordedEvents(fakeRecorder *record.FakeRecorder, numExpectedOomEvents int) []string {
  67. eventsRecorded := []string{}
  68. select {
  69. case event := <-fakeRecorder.Events:
  70. eventsRecorded = append(eventsRecorded, event)
  71. if len(eventsRecorded) == numExpectedOomEvents {
  72. break
  73. }
  74. case <-time.After(10 * time.Second):
  75. break
  76. }
  77. return eventsRecorded
  78. }
  79. // TestWatcherRecordsEventsForOomEventsCorrectContainerName verifies that we
  80. // only record OOM events when the container name is the one for which we want
  81. // to record events (i.e. /).
  82. func TestWatcherRecordsEventsForOomEventsCorrectContainerName(t *testing.T) {
  83. // By "incorrect" container name, we mean a container name for which we
  84. // don't want to record an oom event.
  85. numOomEventsWithIncorrectContainerName := 1
  86. oomInstancesToStream := []*oomparser.OomInstance{
  87. {
  88. Pid: 1000,
  89. ProcessName: "fakeProcess",
  90. TimeOfDeath: time.Now(),
  91. ContainerName: recordEventContainerName,
  92. VictimContainerName: "some-container",
  93. },
  94. {
  95. Pid: 1000,
  96. ProcessName: "fakeProcess",
  97. TimeOfDeath: time.Now(),
  98. ContainerName: "/dont-record-oom-event",
  99. VictimContainerName: "some-container",
  100. },
  101. }
  102. numExpectedOomEvents := len(oomInstancesToStream) - numOomEventsWithIncorrectContainerName
  103. fakeStreamer := &fakeStreamer{
  104. oomInstancesToStream: oomInstancesToStream,
  105. }
  106. fakeRecorder := record.NewFakeRecorder(numExpectedOomEvents)
  107. node := &v1.ObjectReference{}
  108. oomWatcher := &realWatcher{
  109. recorder: fakeRecorder,
  110. oomStreamer: fakeStreamer,
  111. }
  112. assert.NoError(t, oomWatcher.Start(node))
  113. eventsRecorded := getRecordedEvents(fakeRecorder, numExpectedOomEvents)
  114. assert.Equal(t, numExpectedOomEvents, len(eventsRecorded))
  115. }
  116. // TestWatcherRecordsEventsForOomEventsWithAdditionalInfo verifies that our the
  117. // emitted event has the proper pid/process data when appropriate.
  118. func TestWatcherRecordsEventsForOomEventsWithAdditionalInfo(t *testing.T) {
  119. // The process and event info should appear in the event message.
  120. eventPid := 1000
  121. processName := "fakeProcess"
  122. oomInstancesToStream := []*oomparser.OomInstance{
  123. {
  124. Pid: eventPid,
  125. ProcessName: processName,
  126. TimeOfDeath: time.Now(),
  127. ContainerName: recordEventContainerName,
  128. VictimContainerName: "some-container",
  129. },
  130. }
  131. numExpectedOomEvents := len(oomInstancesToStream)
  132. fakeStreamer := &fakeStreamer{
  133. oomInstancesToStream: oomInstancesToStream,
  134. }
  135. fakeRecorder := record.NewFakeRecorder(numExpectedOomEvents)
  136. node := &v1.ObjectReference{}
  137. oomWatcher := &realWatcher{
  138. recorder: fakeRecorder,
  139. oomStreamer: fakeStreamer,
  140. }
  141. assert.NoError(t, oomWatcher.Start(node))
  142. eventsRecorded := getRecordedEvents(fakeRecorder, numExpectedOomEvents)
  143. assert.Equal(t, numExpectedOomEvents, len(eventsRecorded))
  144. assert.Contains(t, eventsRecorded[0], systemOOMEvent)
  145. assert.Contains(t, eventsRecorded[0], fmt.Sprintf("pid: %d", eventPid))
  146. assert.Contains(t, eventsRecorded[0], fmt.Sprintf("victim process: %s", processName))
  147. }