cadvisor/utils/oomparser/oomparser_test.go
Katie Knister 1291347c73 small change to the way time is parsed from the kernel log in oomparser
small change to the way time is parsed from the kernel log in oomparser
2015-02-04 18:48:34 -08:00

204 lines
6.9 KiB
Go

// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package oomparser
import (
"os"
"testing"
"time"
)
const startLine = "Jan 21 22:01:49 localhost kernel: [62278.816267] ruby invoked oom-killer: gfp_mask=0x201da, order=0, oom_score_adj=0"
const endLine = "Jan 21 22:01:49 localhost kernel: [62279.421192] Killed process 19667 (evilprogram2) total-vm:1460016kB, anon-rss:1414008kB, file-rss:4kB"
const containerLine = "Jan 26 14:10:07 kateknister0.mtv.corp.google.com kernel: [1814368.465205] Task in /mem2 killed as a result of limit of /mem2"
const containerLogFile = "containerOomExampleLog.txt"
const systemLogFile = "systemOomExampleLog.txt"
func createExpectedContainerOomInstance(t *testing.T) *OomInstance {
const longForm = "Jan _2 15:04:05 2006"
deathTime, err := time.Parse(longForm, "Jan 5 15:19:27 2015")
if err != nil {
t.Fatalf("could not parse expected time when creating expected container oom instance. Had error %v", err)
return nil
}
return &OomInstance{
Pid: 13536,
ProcessName: "memorymonster",
TimeOfDeath: deathTime,
ContainerName: "/mem2",
}
}
func createExpectedSystemOomInstance(t *testing.T) *OomInstance {
const longForm = "Jan _2 15:04:05 2006"
deathTime, err := time.Parse(longForm, "Jan 28 19:58:45 2015")
if err != nil {
t.Fatalf("could not parse expected time when creating expected system oom instance. Had error %v", err)
return nil
}
return &OomInstance{
Pid: 1532,
ProcessName: "badsysprogram",
TimeOfDeath: deathTime,
ContainerName: "/",
}
}
func TestGetContainerName(t *testing.T) {
currentOomInstance := new(OomInstance)
err := getContainerName(startLine, currentOomInstance)
if err != nil {
t.Errorf("bad line fed to getContainerName should yield no error, but had error %v", err)
}
if currentOomInstance.ContainerName != "" {
t.Errorf("bad line fed to getContainerName yielded no container name but set it to %s", currentOomInstance.ContainerName)
}
err = getContainerName(containerLine, currentOomInstance)
if err != nil {
t.Errorf("container line fed to getContainerName should yield no error, but had error %v", err)
}
if currentOomInstance.ContainerName != "/mem2" {
t.Errorf("getContainerName should have set containerName to /mem2, not %s", currentOomInstance.ContainerName)
}
}
func TestGetProcessNamePid(t *testing.T) {
currentOomInstance := new(OomInstance)
couldParseLine, err := getProcessNamePid(startLine, currentOomInstance)
if err != nil {
t.Errorf("bad line fed to getProcessNamePid should yield no error, but had error %v", err)
}
if couldParseLine {
t.Errorf("bad line fed to getProcessNamePid should return false but returned %v", couldParseLine)
}
const longForm = "Jan _2 15:04:05 2006"
correctTime, err := time.Parse(longForm, "Jan 21 22:01:49 2015")
couldParseLine, err = getProcessNamePid(endLine, currentOomInstance)
if err != nil {
t.Errorf("good line fed to getProcessNamePid should yield no error, but had error %v", err)
}
if !couldParseLine {
t.Errorf("good line fed to getProcessNamePid should return true but returned %v", couldParseLine)
}
if currentOomInstance.ProcessName != "evilprogram2" {
t.Errorf("getProcessNamePid should have set processName to evilprogram2, not %s", currentOomInstance.ProcessName)
}
if currentOomInstance.Pid != 19667 {
t.Errorf("getProcessNamePid should have set PID to 19667, not %d", currentOomInstance.Pid)
}
if !correctTime.Equal(currentOomInstance.TimeOfDeath) {
t.Errorf("getProcessNamePid should have set date to %v, not %v", correctTime, currentOomInstance.TimeOfDeath)
}
}
func TestCheckIfStartOfMessages(t *testing.T) {
couldParseLine, err := checkIfStartOfOomMessages(endLine)
if err != nil {
t.Errorf("bad line fed to checkIfStartOfMessages should yield no error, but had error %v", err)
}
if couldParseLine {
t.Errorf("bad line fed to checkIfStartOfMessages should return false but returned %v", couldParseLine)
}
couldParseLine, err = checkIfStartOfOomMessages(startLine)
if err != nil {
t.Errorf("start line fed to checkIfStartOfMessages should yield no error, but had error %v", err)
}
if !couldParseLine {
t.Errorf("start line fed to checkIfStartOfMessages should return true but returned %v", couldParseLine)
}
}
func TestAnalyzeLinesContainerOom(t *testing.T) {
expectedContainerOomInstance := createExpectedContainerOomInstance(t)
helpTestAnalyzeLines(expectedContainerOomInstance, containerLogFile, t)
}
func TestAnalyzeLinesSystemOom(t *testing.T) {
expectedSystemOomInstance := createExpectedSystemOomInstance(t)
helpTestAnalyzeLines(expectedSystemOomInstance, systemLogFile, t)
}
func helpTestAnalyzeLines(oomCheckInstance *OomInstance, sysFile string, t *testing.T) {
outStream := make(chan *OomInstance)
oomLog := new(OomParser)
oomLog.systemFile = sysFile
file, err := os.Open(oomLog.systemFile)
if err != nil {
t.Errorf("couldn't open test log: %v", err)
}
timeout := make(chan bool, 1)
go func() {
time.Sleep(1 * time.Second)
timeout <- true
}()
go oomLog.analyzeLines(file, outStream)
select {
case oomInstance := <-outStream:
if *oomCheckInstance != *oomInstance {
t.Errorf("wrong instance returned. Expected %v and got %v",
oomCheckInstance, oomInstance)
}
case <-timeout:
t.Error(
"timeout happened before oomInstance was found in test file")
}
}
func TestStreamOomsContainer(t *testing.T) {
expectedContainerOomInstance := createExpectedContainerOomInstance(t)
helpTestStreamOoms(expectedContainerOomInstance, containerLogFile, t)
}
func TestStreamOomsSystem(t *testing.T) {
expectedSystemOomInstance := createExpectedSystemOomInstance(t)
helpTestStreamOoms(expectedSystemOomInstance, systemLogFile, t)
}
func helpTestStreamOoms(oomCheckInstance *OomInstance, sysFile string, t *testing.T) {
outStream := make(chan *OomInstance)
oomLog := new(OomParser)
oomLog.systemFile = sysFile
timeout := make(chan bool, 1)
go func() {
time.Sleep(1 * time.Second)
timeout <- true
}()
err := oomLog.StreamOoms(outStream)
if err != nil {
t.Errorf("had an error opening file: %v", err)
}
select {
case oomInstance := <-outStream:
if *oomCheckInstance != *oomInstance {
t.Errorf("wrong instance returned. Expected %v and got %v",
oomCheckInstance, oomInstance)
}
case <-timeout:
t.Error(
"timeout happened before oomInstance was found in test file")
}
}
func TestNew(t *testing.T) {
_, err := New()
if err != nil {
t.Errorf("function New() had error %v", err)
}
}