/* TestEventGeneratorGetCpuEventFirstPass simulates the case when a cpu event should be generated It simulates following status: - a common container - a common CPU stats This test checks parameters passed to the calculator and checks that the event generated is well formatted. */ func TestEventGeneratorGetCpuEvent(t *testing.T) { // GIVEN // docker socket socket := "unix:///some/docker/socket" // a container labels := map[string]string{} labels["label1"] = "value1" labels["label2"] = "value2" containerId := "container_id" container := docker.APIContainers{ ID: containerId, Image: "container_image", Command: "container command", Created: 9876543210, Status: "Up", Ports: []docker.APIPort{{PrivatePort: 1234, PublicPort: 4567, Type: "portType", IP: "123.456.879.1"}}, SizeRw: 123, SizeRootFs: 456, Names: []string{"/name1", "name1/fake"}, Labels: labels, Networks: docker.NetworkList{}, } // CPU stats from Docker API preCPUStats := getCPUStats(1) cpuStats := getCPUStats(2) // main stats object var stats = new(docker.Stats) stats.Read = time.Now() stats.CPUStats = cpuStats stats.PreCPUStats = preCPUStats // mocking calculator // first - generate expected calls (CPUStats to CPUData conversion) cpuData := calculator.CPUData{ PerCpuUsage: cpuStats.CPUUsage.PercpuUsage, TotalUsage: cpuStats.CPUUsage.TotalUsage, UsageInKernelmode: cpuStats.CPUUsage.UsageInKernelmode, UsageInUsermode: cpuStats.CPUUsage.UsageInUsermode, } preCPUData := calculator.CPUData{ PerCpuUsage: preCPUStats.CPUUsage.PercpuUsage, TotalUsage: preCPUStats.CPUUsage.TotalUsage, UsageInKernelmode: preCPUStats.CPUUsage.UsageInKernelmode, UsageInUsermode: preCPUStats.CPUUsage.UsageInUsermode, } // second - instantiate mock // calculator will no be called for em1 network, it will generate zero-values event for em1 mockedCalculatorFactory := new(mocks.CalculatorFactory) mockedCPUCalculator := getMockedCPUCalculator(1.0) mockedCalculatorFactory.On("NewCPUCalculator", preCPUData, cpuData).Return(mockedCPUCalculator) // expected events expectedEvent := common.MapStr{ "@timestamp": common.Time(stats.Read), "type": "cpu", "containerID": container.ID, "containerName": "name1", "containerLabels": []common.MapStr{ { "key": "label1", "value": "value1", }, { "key": "label2", "value": "value2", }, }, "dockerSocket": &socket, "cpu": common.MapStr{ "percpuUsage": mockedCPUCalculator.PerCpuUsage(), "totalUsage": mockedCPUCalculator.TotalUsage(), "usageInKernelmode": mockedCPUCalculator.UsageInKernelmode(), "usageInUsermode": mockedCPUCalculator.UsageInUsermode(), }, } // the eventGenerator to test var eventGenerator = EventGenerator{&socket, EGNetworkStats{}, EGBlkioStats{}, mockedCalculatorFactory, time.Second} // WHEN event := eventGenerator.GetCpuEvent(&container, stats) // THEN // check returned events assert.True(t, equalEvent(expectedEvent, event)) }
/* TestEventGeneratorGetNetworksEventFirstPass simulates the case when a new network event should be generated It simulates following status: - a common container - network stats with two networks "eth0" and "em1" The network "eth0" already have an saved status from previous tick. This test checks that it generate two network events: - an event for "eth0" with calculated data from saved stats (+ new stats saved) - an event for "em1" with zeros values (+ new stats saved) */ func TestEventGeneratorGetNetworksEventFirstPass(t *testing.T) { // GIVEN // docker socket socket := "unix:///some/docker/socket" // old and current timestamps oldTimestamp := time.Now() period := time.Second newTimestamp := oldTimestamp.Add(period) // a container labels := map[string]string{} labels["label1"] = "value1" labels["label2"] = "value2" containerId := "container_id" container := docker.APIContainers{ ID: containerId, Image: "container_image", Command: "container command", Created: 9876543210, Status: "Up", Ports: []docker.APIPort{{PrivatePort: 1234, PublicPort: 4567, Type: "portType", IP: "123.456.879.1"}}, SizeRw: 123, SizeRootFs: 456, Names: []string{"/name1", "name1/fake"}, Labels: labels, Networks: docker.NetworkList{}, } // network stats from Docker API networkStatsMap := map[string]docker.NetworkStats{} networkStatsMap["eth0"] = docker.NetworkStats{ RxBytes: 10, RxDropped: 20, RxErrors: 30, RxPackets: 40, TxBytes: 50, TxDropped: 60, TxErrors: 70, TxPackets: 80, } networkStatsMap["em1"] = docker.NetworkStats{ RxBytes: 90, RxDropped: 100, RxErrors: 110, RxPackets: 120, TxBytes: 130, TxDropped: 140, TxErrors: 150, TxPackets: 160, } // main stats object var stats = new(docker.Stats) stats.Read = newTimestamp stats.Networks = networkStatsMap // saved network status (em1 does not already exists) oldNetworkData := map[string]map[string]calculator.NetworkData{} oldNetworkData[containerId] = map[string]calculator.NetworkData{} oldNetworkData[containerId]["eth0"] = calculator.NetworkData{ Time: oldTimestamp, RxBytes: 1, RxDropped: 2, RxErrors: 3, RxPackets: 4, TxBytes: 5, TxDropped: 6, TxErrors: 7, TxPackets: 8, } // mocking calculators // first - generate expected calls (NetworkStats to NetworkData conversion) newNetworkData := map[string]calculator.NetworkData{} newNetworkData["eth0"] = calculator.NetworkData{ Time: newTimestamp, RxBytes: 10, RxDropped: 20, RxErrors: 30, RxPackets: 40, TxBytes: 50, TxDropped: 60, TxErrors: 70, TxPackets: 80, } newNetworkData["em1"] = calculator.NetworkData{ Time: newTimestamp, RxBytes: 90, RxDropped: 100, RxErrors: 110, RxPackets: 120, TxBytes: 130, TxDropped: 140, TxErrors: 150, TxPackets: 160, } // second - instantiate mock // calculator will no be called for em1 network, it will generate zero-values event for em1 mockedCalculatorFactory := new(mocks.CalculatorFactory) mockedNetworkCalculatorEth0 := getMockedNetworkCalculator(1.0) mockedCalculatorFactory.On("NewNetworkCalculator", oldNetworkData[containerId]["eth0"], newNetworkData["eth0"]).Return(mockedNetworkCalculatorEth0) // expected events expectedEvents := []common.MapStr{} expectedEvents = append(expectedEvents, common.MapStr{ "@timestamp": common.Time(newTimestamp), "type": "net", "containerID": container.ID, "containerName": "name1", "containerLabels": []common.MapStr{ { "key": "label1", "value": "value1", }, { "key": "label2", "value": "value2", }, }, "dockerSocket": &socket, "net": common.MapStr{ "name": "eth0", "rxBytes_ps": mockedNetworkCalculatorEth0.GetRxBytesPerSecond(), "rxDropped_ps": mockedNetworkCalculatorEth0.GetRxDroppedPerSecond(), "rxErrors_ps": mockedNetworkCalculatorEth0.GetRxErrorsPerSecond(), "rxPackets_ps": mockedNetworkCalculatorEth0.GetRxPacketsPerSecond(), "txBytes_ps": mockedNetworkCalculatorEth0.GetTxBytesPerSecond(), "txDropped_ps": mockedNetworkCalculatorEth0.GetTxDroppedPerSecond(), "txErrors_ps": mockedNetworkCalculatorEth0.GetTxErrorsPerSecond(), "txPackets_ps": mockedNetworkCalculatorEth0.GetTxPacketsPerSecond(), }}, common.MapStr{ "@timestamp": common.Time(newTimestamp), "type": "net", "containerID": container.ID, "containerName": "name1", "containerLabels": []common.MapStr{ { "key": "label1", "value": "value1", }, { "key": "label2", "value": "value2", }, }, "dockerSocket": &socket, "net": common.MapStr{ "name": "em1", "rxBytes_ps": 0, "rxDropped_ps": 0, "rxErrors_ps": 0, "rxPackets_ps": 0, "txBytes_ps": 0, "txDropped_ps": 0, "txErrors_ps": 0, "txPackets_ps": 0, }}) // the eventGenerator to test var eventGenerator = EventGenerator{&socket, EGNetworkStats{M: oldNetworkData}, EGBlkioStats{}, mockedCalculatorFactory, period} // WHEN events := eventGenerator.GetNetworksEvent(&container, stats) // THEN // check returned events assert.Equal(t, len(expectedEvents), 2) for i := range expectedEvents { checked := false for j := range events { if equalEvent(expectedEvents[i], events[j]) { checked = true break } } if !checked { assert.Fail(t, "unable to find network in events: %v", expectedEvents[i].String()) } } // check that new stats saved assert.Equal(t, eventGenerator.NetworkStats.M[container.ID]["eth0"], newNetworkData["eth0"]) assert.Equal(t, eventGenerator.NetworkStats.M[container.ID]["em1"], newNetworkData["em1"]) }
/* TestEventGeneratorGetNetworksEvent simulates the case when a saved network should be cleaned from saved status It simulates following status: - a common container - network stats with one network "eth0" Networks "eth0" have an saved status from previous tick. An existing saved status for "em1" network is too old and should be removed. This test checks that it generate one network event: - an event for "eth0" with calculated data from saved stats (+ new stats saved) - the "em1" saved network status should be removed */ func TestEventGeneratorGetNetworksEventCleanSavedEvents(t *testing.T) { // GIVEN // docker socket socket := "unix:///some/docker/socket" // old and current timestamps oldTimestamp := time.Now() veryOldTimestamp := oldTimestamp.AddDate(0, -1, 0) period := time.Second newTimestamp := oldTimestamp.Add(period) // a container labels := map[string]string{} labels["label1"] = "value1" labels["label2"] = "value2" containerId := "container_id" container := docker.APIContainers{ ID: containerId, Image: "container_image", Command: "container command", Created: 9876543210, Status: "Up", Ports: []docker.APIPort{{PrivatePort: 1234, PublicPort: 4567, Type: "portType", IP: "123.456.879.1"}}, SizeRw: 123, SizeRootFs: 456, Names: []string{"/name1", "name1/fake"}, Labels: labels, Networks: docker.NetworkList{}, } // network stats from Docker API networkStatsMap := map[string]docker.NetworkStats{} networkStatsMap["eth0"] = docker.NetworkStats{ RxBytes: 10, RxDropped: 20, RxErrors: 30, RxPackets: 40, TxBytes: 50, TxDropped: 60, TxErrors: 70, TxPackets: 80, } // main stats object var stats = new(docker.Stats) stats.Read = newTimestamp stats.Networks = networkStatsMap // saved network status oldNetworkData := map[string]map[string]calculator.NetworkData{} oldNetworkData[containerId] = map[string]calculator.NetworkData{} oldNetworkData[containerId]["eth0"] = calculator.NetworkData{ Time: oldTimestamp, RxBytes: 1, RxDropped: 2, RxErrors: 3, RxPackets: 4, TxBytes: 5, TxDropped: 6, TxErrors: 7, TxPackets: 8, } // em1 has a very old timestamp, and should be removed because no em1 event come from stats API oldNetworkData[containerId]["em1"] = calculator.NetworkData{ Time: veryOldTimestamp, RxBytes: 9, RxDropped: 10, RxErrors: 11, RxPackets: 12, TxBytes: 13, TxDropped: 14, TxErrors: 15, TxPackets: 16, } // mocking calculators // first - generate expected calls (NetworkStats to NetworkData conversion) newNetworkData := map[string]calculator.NetworkData{} newNetworkData["eth0"] = calculator.NetworkData{ Time: newTimestamp, RxBytes: 10, RxDropped: 20, RxErrors: 30, RxPackets: 40, TxBytes: 50, TxDropped: 60, TxErrors: 70, TxPackets: 80, } // second - instantiate mock mockedCalculatorFactory := new(mocks.CalculatorFactory) mockedNetworkCalculatorEth0 := getMockedNetworkCalculator(1.0) mockedCalculatorFactory.On("NewNetworkCalculator", oldNetworkData[containerId]["eth0"], newNetworkData["eth0"]).Return(mockedNetworkCalculatorEth0) // expected events expectedEvents := []common.MapStr{} expectedEvents = append(expectedEvents, common.MapStr{ "@timestamp": common.Time(newTimestamp), "type": "net", "containerID": container.ID, "containerName": "name1", "containerLabels": []common.MapStr{ { "key": "label1", "value": "value1", }, { "key": "label2", "value": "value2", }, }, "dockerSocket": &socket, "net": common.MapStr{ "name": "eth0", "rxBytes_ps": mockedNetworkCalculatorEth0.GetRxBytesPerSecond(), "rxDropped_ps": mockedNetworkCalculatorEth0.GetRxDroppedPerSecond(), "rxErrors_ps": mockedNetworkCalculatorEth0.GetRxErrorsPerSecond(), "rxPackets_ps": mockedNetworkCalculatorEth0.GetRxPacketsPerSecond(), "txBytes_ps": mockedNetworkCalculatorEth0.GetTxBytesPerSecond(), "txDropped_ps": mockedNetworkCalculatorEth0.GetTxDroppedPerSecond(), "txErrors_ps": mockedNetworkCalculatorEth0.GetTxErrorsPerSecond(), "txPackets_ps": mockedNetworkCalculatorEth0.GetTxPacketsPerSecond(), }}) // the eventGenerator to test var eventGenerator = EventGenerator{&socket, EGNetworkStats{M: oldNetworkData}, EGBlkioStats{}, mockedCalculatorFactory, period} // WHEN events := eventGenerator.GetNetworksEvent(&container, stats) // THEN // check returned events for i := 0; i < len(expectedEvents); i++ { assert.True(t, equalEvent(expectedEvents[i], events[i])) } // check that new stats saved assert.Equal(t, eventGenerator.NetworkStats.M[container.ID]["eth0"], newNetworkData["eth0"]) // check that expired state has been deleted _, ok := eventGenerator.NetworkStats.M[container.ID]["em1"] if ok { assert.Fail(t, "Expired event has not been deleted") } }
/* TestEventGeneratorGetBlkioEventCleanSavedEvents simulates the case when method should clean old blkio stats It simulates following status: - a common container - blkio stats with saved status The blkio stats for this container already have an saved status from previous tick. A saved event is too old and should be remove from saved stats. */ func TestEventGeneratorGetBlkioEventCleanSavedEvents(t *testing.T) { // GIVEN // docker socket socket := "unix:///some/docker/socket" // old and current timestamps oldTimestamp := time.Now() veryOldTimestamp := oldTimestamp.AddDate(0, -1, 0) period := time.Second newTimestamp := oldTimestamp.Add(period) // a container labels := map[string]string{} labels["label1"] = "value1" labels["label2"] = "value2" containerId := "container_id" anotherContainerId := "container_id2" container := docker.APIContainers{ ID: containerId, Image: "container_image", Command: "container command", Created: 9876543210, Status: "Up", Ports: []docker.APIPort{{PrivatePort: 1234, PublicPort: 4567, Type: "portType", IP: "123.456.879.1"}}, SizeRw: 123, SizeRootFs: 456, Names: []string{"/name1", "name1/fake"}, Labels: labels, Networks: docker.NetworkList{}, } // main stats object var stats = getBlkioStats(newTimestamp, 10, 20, 30) // saved blkio stats oldBlkioData := map[string]calculator.BlkioData{} oldBlkioData[containerId] = calculator.BlkioData{ Time: oldTimestamp, Reads: 1, Writes: 2, Totals: 3, } // another container has a very old blkio stats oldBlkioData[anotherContainerId] = calculator.BlkioData{ Time: veryOldTimestamp, Reads: 4, Writes: 5, Totals: 6, } // mocking calculators // first - generate expected calls (BlkioStats to BlkioData conversion) newBlkioData := calculator.BlkioData{ Time: newTimestamp, Reads: 10, Writes: 20, Totals: 30, } // second - instantiate mock mockedCalculatorFactory := new(mocks.CalculatorFactory) mockedBlkioCalculator := getMockedBlkioCalculator(1) mockedCalculatorFactory.On("NewBlkioCalculator", oldBlkioData[containerId], newBlkioData).Return(mockedBlkioCalculator) // expected events expectedEvent := common.MapStr{ "@timestamp": common.Time(newTimestamp), "type": "blkio", "containerID": container.ID, "containerName": "name1", "containerLabels": []common.MapStr{ { "key": "label1", "value": "value1", }, { "key": "label2", "value": "value2", }, }, "dockerSocket": &socket, "blkio": common.MapStr{ "read_ps": mockedBlkioCalculator.GetReadPs(), "write_ps": mockedBlkioCalculator.GetWritePs(), "total_ps": mockedBlkioCalculator.GetTotalPs(), }, } // the eventGenerator to test var eventGenerator = EventGenerator{&socket, EGNetworkStats{}, EGBlkioStats{M: oldBlkioData}, mockedCalculatorFactory, period} // WHEN event := eventGenerator.GetBlkioEvent(&container, &stats) // THEN // check returned events assert.True(t, equalEvent(expectedEvent, event)) // check that new stats saved assert.Equal(t, eventGenerator.BlkioStats.M[container.ID], newBlkioData) // check that expired state has been deleted _, ok := eventGenerator.BlkioStats.M[anotherContainerId] if ok { assert.Fail(t, "Expired event has not been deleted") } }