From a49cc7f252eb3751abd1ea46dc2be819667cbe9e Mon Sep 17 00:00:00 2001 From: Victor Marmol Date: Fri, 25 Apr 2014 17:44:40 +0000 Subject: [PATCH] Adding a test for blkio stats. Also adds a test utility we can use for other cgroup tests. Docker-DCO-1.1-Signed-off-by: Victor Marmol (github: vmarmol) --- cgroups/fs/blkio_test.go | 169 +++++++++++++++++++++++++++++++++++++++ cgroups/fs/test_util.go | 75 +++++++++++++++++ 2 files changed, 244 insertions(+) create mode 100644 cgroups/fs/blkio_test.go create mode 100644 cgroups/fs/test_util.go diff --git a/cgroups/fs/blkio_test.go b/cgroups/fs/blkio_test.go new file mode 100644 index 0000000..5279ac4 --- /dev/null +++ b/cgroups/fs/blkio_test.go @@ -0,0 +1,169 @@ +package fs + +import ( + "testing" +) + +const ( + sectorsRecursiveContents = `8:0 1024` + serviceBytesRecursiveContents = `8:0 Read 100 +8:0 Write 400 +8:0 Sync 200 +8:0 Async 300 +8:0 Total 500 +Total 500` + servicedRecursiveContents = `8:0 Read 10 +8:0 Write 40 +8:0 Sync 20 +8:0 Async 30 +8:0 Total 50 +Total 50` + queuedRecursiveContents = `8:0 Read 1 +8:0 Write 4 +8:0 Sync 2 +8:0 Async 3 +8:0 Total 5 +Total 5` +) + +func TestBlkioStats(t *testing.T) { + helper := NewCgroupTestUtil("blkio", t) + defer helper.cleanup() + helper.writeFileContents(map[string]string{ + "blkio.io_service_bytes_recursive": serviceBytesRecursiveContents, + "blkio.io_serviced_recursive": servicedRecursiveContents, + "blkio.io_queued_recursive": queuedRecursiveContents, + "blkio.sectors_recursive": sectorsRecursiveContents, + }) + + blkio := &blkioGroup{} + stats, err := blkio.Stats(helper.CgroupData) + if err != nil { + t.Fatal(err) + } + + // Verify expected stats. + expectedStats := map[string]float64{ + "blkio.sectors_recursive:8:0": 1024.0, + + // Serviced bytes. + "io_service_bytes_recursive:8:0:Read": 100.0, + "io_service_bytes_recursive:8:0:Write": 400.0, + "io_service_bytes_recursive:8:0:Sync": 200.0, + "io_service_bytes_recursive:8:0:Async": 300.0, + "io_service_bytes_recursive:8:0:Total": 500.0, + + // Serviced requests. + "io_serviced_recursive:8:0:Read": 10.0, + "io_serviced_recursive:8:0:Write": 40.0, + "io_serviced_recursive:8:0:Sync": 20.0, + "io_serviced_recursive:8:0:Async": 30.0, + "io_serviced_recursive:8:0:Total": 50.0, + + // Queued requests. + "io_queued_recursive:8:0:Read": 1.0, + "io_queued_recursive:8:0:Write": 4.0, + "io_queued_recursive:8:0:Sync": 2.0, + "io_queued_recursive:8:0:Async": 3.0, + "io_queued_recursive:8:0:Total": 5.0, + } + expectStats(t, expectedStats, stats) +} + +func TestBlkioStatsNoSectorsFile(t *testing.T) { + helper := NewCgroupTestUtil("blkio", t) + defer helper.cleanup() + helper.writeFileContents(map[string]string{ + "blkio.io_service_bytes_recursive": serviceBytesRecursiveContents, + "blkio.io_serviced_recursive": servicedRecursiveContents, + "blkio.io_queued_recursive": queuedRecursiveContents, + }) + + blkio := &blkioGroup{} + _, err := blkio.Stats(helper.CgroupData) + if err == nil { + t.Fatal("Expected to fail, but did not") + } +} + +func TestBlkioStatsNoServiceBytesFile(t *testing.T) { + helper := NewCgroupTestUtil("blkio", t) + defer helper.cleanup() + helper.writeFileContents(map[string]string{ + "blkio.io_serviced_recursive": servicedRecursiveContents, + "blkio.io_queued_recursive": queuedRecursiveContents, + "blkio.sectors_recursive": sectorsRecursiveContents, + }) + + blkio := &blkioGroup{} + _, err := blkio.Stats(helper.CgroupData) + if err == nil { + t.Fatal("Expected to fail, but did not") + } +} + +func TestBlkioStatsNoServicedFile(t *testing.T) { + helper := NewCgroupTestUtil("blkio", t) + defer helper.cleanup() + helper.writeFileContents(map[string]string{ + "blkio.io_service_bytes_recursive": serviceBytesRecursiveContents, + "blkio.io_queued_recursive": queuedRecursiveContents, + "blkio.sectors_recursive": sectorsRecursiveContents, + }) + + blkio := &blkioGroup{} + _, err := blkio.Stats(helper.CgroupData) + if err == nil { + t.Fatal("Expected to fail, but did not") + } +} + +func TestBlkioStatsNoQueuedFile(t *testing.T) { + helper := NewCgroupTestUtil("blkio", t) + defer helper.cleanup() + helper.writeFileContents(map[string]string{ + "blkio.io_service_bytes_recursive": serviceBytesRecursiveContents, + "blkio.io_serviced_recursive": servicedRecursiveContents, + "blkio.sectors_recursive": sectorsRecursiveContents, + }) + + blkio := &blkioGroup{} + _, err := blkio.Stats(helper.CgroupData) + if err == nil { + t.Fatal("Expected to fail, but did not") + } +} + +func TestBlkioStatsUnexpectedNumberOfFields(t *testing.T) { + helper := NewCgroupTestUtil("blkio", t) + defer helper.cleanup() + helper.writeFileContents(map[string]string{ + "blkio.io_service_bytes_recursive": "8:0 Read 100 100", + "blkio.io_serviced_recursive": servicedRecursiveContents, + "blkio.io_queued_recursive": queuedRecursiveContents, + "blkio.sectors_recursive": sectorsRecursiveContents, + }) + + blkio := &blkioGroup{} + _, err := blkio.Stats(helper.CgroupData) + if err == nil { + t.Fatal("Expected to fail, but did not") + } +} + +func TestBlkioStatsUnexpectedFieldType(t *testing.T) { + helper := NewCgroupTestUtil("blkio", t) + defer helper.cleanup() + helper.writeFileContents(map[string]string{ + "blkio.io_service_bytes_recursive": "8:0 Read Write", + "blkio.io_serviced_recursive": servicedRecursiveContents, + "blkio.io_queued_recursive": queuedRecursiveContents, + "blkio.sectors_recursive": sectorsRecursiveContents, + }) + + blkio := &blkioGroup{} + _, err := blkio.Stats(helper.CgroupData) + if err == nil { + t.Fatal("Expected to fail, but did not") + } +} diff --git a/cgroups/fs/test_util.go b/cgroups/fs/test_util.go new file mode 100644 index 0000000..11b90b2 --- /dev/null +++ b/cgroups/fs/test_util.go @@ -0,0 +1,75 @@ +/* +Utility for testing cgroup operations. + +Creates a mock of the cgroup filesystem for the duration of the test. +*/ +package fs + +import ( + "fmt" + "io/ioutil" + "log" + "os" + "testing" +) + +type cgroupTestUtil struct { + // data to use in tests. + CgroupData *data + + // Path to the mock cgroup directory. + CgroupPath string + + // Temporary directory to store mock cgroup filesystem. + tempDir string + t *testing.T +} + +// Creates a new test util for the specified subsystem +func NewCgroupTestUtil(subsystem string, t *testing.T) *cgroupTestUtil { + d := &data{} + tempDir, err := ioutil.TempDir("", fmt.Sprintf("%s_cgroup_test", subsystem)) + if err != nil { + t.Fatal(err) + } + d.root = tempDir + testCgroupPath, err := d.path(subsystem) + if err != nil { + t.Fatal(err) + } + + // Ensure the full mock cgroup path exists. + err = os.MkdirAll(testCgroupPath, 0755) + if err != nil { + t.Fatal(err) + } + return &cgroupTestUtil{CgroupData: d, CgroupPath: testCgroupPath, tempDir: tempDir, t: t} +} + +func (c *cgroupTestUtil) cleanup() { + os.RemoveAll(c.tempDir) +} + +// Write the specified contents on the mock of the specified cgroup files. +func (c *cgroupTestUtil) writeFileContents(fileContents map[string]string) { + for file, contents := range fileContents { + err := writeFile(c.CgroupPath, file, contents) + if err != nil { + c.t.Fatal(err) + } + } +} + +// Expect the specified stats. +func expectStats(t *testing.T, expected, actual map[string]float64) { + for stat, expectedValue := range expected { + actualValue, ok := actual[stat] + if !ok { + log.Printf("Expected stat %s to exist: %s", stat, actual) + t.Fail() + } else if actualValue != expectedValue { + log.Printf("Expected stats %s to have value %f but had %f instead", stat, expectedValue, actualValue) + t.Fail() + } + } +}