Beispiel #1
0
func TestMemoryStats(t *testing.T) {
	helper := NewCgroupTestUtil("memory", t)
	defer helper.cleanup()
	helper.writeFileContents(map[string]string{
		"memory.stat":                     memoryStatContents,
		"memory.usage_in_bytes":           memoryUsageContents,
		"memory.limit_in_bytes":           memoryLimitContents,
		"memory.max_usage_in_bytes":       memoryMaxUsageContents,
		"memory.failcnt":                  memoryFailcnt,
		"memory.memsw.usage_in_bytes":     memoryUsageContents,
		"memory.memsw.max_usage_in_bytes": memoryMaxUsageContents,
		"memory.memsw.failcnt":            memoryFailcnt,
		"memory.memsw.limit_in_bytes":     memoryLimitContents,
		"memory.kmem.usage_in_bytes":      memoryUsageContents,
		"memory.kmem.max_usage_in_bytes":  memoryMaxUsageContents,
		"memory.kmem.failcnt":             memoryFailcnt,
		"memory.kmem.limit_in_bytes":      memoryLimitContents,
	})

	memory := &MemoryGroup{}
	actualStats := *cgroups.NewStats()
	err := memory.GetStats(helper.CgroupPath, &actualStats)
	if err != nil {
		t.Fatal(err)
	}
	expectedStats := cgroups.MemoryStats{Cache: 512, Usage: cgroups.MemoryData{Usage: 2048, MaxUsage: 4096, Failcnt: 100, Limit: 8192}, SwapUsage: cgroups.MemoryData{Usage: 2048, MaxUsage: 4096, Failcnt: 100, Limit: 8192}, KernelUsage: cgroups.MemoryData{Usage: 2048, MaxUsage: 4096, Failcnt: 100, Limit: 8192}, Stats: map[string]uint64{"cache": 512, "rss": 1024}}
	expectMemoryStatEquals(t, expectedStats, actualStats.MemoryStats)
}
Beispiel #2
0
func TestCpuStats(t *testing.T) {
	helper := NewCgroupTestUtil("cpu", t)
	defer helper.cleanup()

	const (
		kNrPeriods     = 2000
		kNrThrottled   = 200
		kThrottledTime = uint64(18446744073709551615)
	)

	cpuStatContent := fmt.Sprintf("nr_periods %d\n nr_throttled %d\n throttled_time %d\n",
		kNrPeriods, kNrThrottled, kThrottledTime)
	helper.writeFileContents(map[string]string{
		"cpu.stat": cpuStatContent,
	})

	cpu := &CpuGroup{}
	actualStats := *cgroups.NewStats()
	err := cpu.GetStats(helper.CgroupPath, &actualStats)
	if err != nil {
		t.Fatal(err)
	}

	expectedStats := cgroups.ThrottlingData{
		Periods:          kNrPeriods,
		ThrottledPeriods: kNrThrottled,
		ThrottledTime:    kThrottledTime}

	expectThrottlingDataEquals(t, expectedStats, actualStats.CpuStats.ThrottlingData)
}
func TestGetMetrics(t *testing.T) {
	Convey("Given docker id and running containers info", t, func() {
		longDockerId := "1234567890ab9207edb4e6188cf5be3294c23c936ca449c3d48acd2992e357a8"
		containersInfo := []ContainerInfo{ContainerInfo{Id: longDockerId}}
		mountPoint := "cgroup/mount/point/path"
		stats := cgroups.NewStats()

		Convey("and docker plugin initialized", func() {
			mockClient := new(ClientMock)
			mockStats := new(StatsMock)
			mockTools := new(ToolsMock)
			mockWrapper := map[string]Stats{"cpu": mockStats}

			mockTools.On(
				"Map2Namespace",
				mock.Anything,
				mock.AnythingOfType("string"),
				mock.AnythingOfType("*[]string"),
			).Return().Run(
				func(args mock.Arguments) {
					id := args.String(1)
					ns := args.Get(2).(*[]string)
					*ns = append(*ns, filepath.Join(id, "cpu_stats/cpu_usage/total_usage"))
				})

			mockClient.On("FindCgroupMountpoint", "cpu").Return(mountPoint, nil)
			mockStats.On("GetStats", mock.AnythingOfType("string"), mock.AnythingOfType("*cgroups.Stats")).Return(nil)

			d := &docker{
				stats:          stats,
				client:         mockClient,
				tools:          mockTools,
				groupWrap:      mockWrapper,
				containersInfo: containersInfo,
				hostname:       "",
			}

			Convey("When GetMetrics is called", func() {
				mts, err := d.GetMetricTypes(plugin.PluginConfigType{})

				Convey("Then no error should be reported", func() {
					So(err, ShouldBeNil)
				})

				Convey("Then one explicit metric should be returned and wildcard docker id metric", func() {
					So(len(mts), ShouldEqual, 2)
				})

				Convey("Then metric namespace should be correctly set", func() {
					ns := filepath.Join(mts[0].Namespace()...)
					expected := filepath.Join(
						NS_VENDOR, NS_CLASS, NS_PLUGIN, longDockerId[:12], "cpu_stats", "cpu_usage", "total_usage")
					So(ns, ShouldEqual, expected)
				})
			})
		})

	})
}
func newCgroupsStats() *cgroups.Stats {
	cgroupStats := cgroups.NewStats()
	// set names of default memory statistics which are supported
	for _, memstatName := range listOfMemoryStats {
		cgroupStats.MemoryStats.Stats[memstatName] = 0
	}
	return cgroupStats
}
func TestCollectMetricsWildcard(t *testing.T) {

	Convey("Given * wildcard in requested metric type", t, func() {

		mountPoint := "cgroup/mount/point/path"
		longDockerId1 := "1234567890ab9207edb4e6188cf5be3294c23c936ca449c3d48acd2992e357a8"
		longDockerId2 := "0987654321yz9207edb4e6188cf5be3294c23c936ca449c3d48acd2992e357a8"

		ns := []string{NS_VENDOR, NS_CLASS, NS_PLUGIN, "*", "cpu_stats", "cpu_usage", "total_usage"}
		metricTypes := []plugin.PluginMetricType{plugin.PluginMetricType{Namespace_: ns}}

		Convey("and docker plugin intitialized", func() {

			stats := cgroups.NewStats()

			mockClient := new(ClientMock)
			mockStats := new(StatsMock)
			mockTools := new(ToolsMock)
			mockWrapper := map[string]Stats{"cpu": mockStats}

			mockClient.On("FindCgroupMountpoint", "cpu").Return(mountPoint, nil)

			mockStats.On("GetStats", mock.AnythingOfType("string"), stats).Return(nil)

			mockTools.On("GetValueByNamespace", mock.AnythingOfType("*cgroups.Stats"), mock.Anything).Return(43)

			d := &docker{
				stats:  stats,
				client: mockClient,
				tools:  mockTools,
				containersInfo: []ContainerInfo{
					ContainerInfo{Id: longDockerId1},
					ContainerInfo{Id: longDockerId2}},
				groupWrap: mockWrapper,
				hostname:  "",
			}

			Convey("When CollectMetric is called", func() {
				mts, err := d.CollectMetrics(metricTypes)

				Convey("Then error should not be reported", func() {
					So(err, ShouldBeNil)
				})

				Convey("Two metrics should be returned", func() {
					So(len(mts), ShouldEqual, 2)
				})

				Convey("Metric value should be correctly set", func() {
					So(mts[0].Data(), ShouldEqual, 43)
					So(mts[1].Data(), ShouldEqual, 43)
				})
			})

		})
	})
}
Beispiel #6
0
func (v VMStatFile) readAll() ([]byte, error) {
	stats := cgroups.NewStats()
	v.blkioGroup.GetStats(v.cgroupdir, stats)
	vmstat, err := ioutil.ReadFile("/proc/vmstat")
	if err != nil {
		return []byte{}, fmt.Errorf("failed to read /proc/vmstat: %v", err)
	}
	return getVMStat(vmstat, stats.BlkioStats)
}
Beispiel #7
0
func (ds DiskStatsFile) readAll() ([]byte, error) {
	stats := cgroups.NewStats()
	ds.blkioGroup.GetStats(ds.cgroupdir, stats)

	diskStats, err := ioutil.ReadFile("/proc/diskstats")
	if err != nil {
		return []byte{}, fmt.Errorf("failed to read /proc/diskstats: %v", err)
	}
	return getDiskStats(diskStats, stats.BlkioStats), nil
}
Beispiel #8
0
func TestNoCpuStatFile(t *testing.T) {
	helper := NewCgroupTestUtil("cpu", t)
	defer helper.cleanup()

	cpu := &CpuGroup{}
	actualStats := *cgroups.NewStats()
	err := cpu.GetStats(helper.CgroupPath, &actualStats)
	if err != nil {
		t.Fatal("Expected not to fail, but did")
	}
}
Beispiel #9
0
func TestHugetlbStatsNoUsageFile(t *testing.T) {
	helper := NewCgroupTestUtil("hugetlb", t)
	defer helper.cleanup()
	helper.writeFileContents(map[string]string{
		maxUsage: hugetlbMaxUsageContents,
	})

	hugetlb := &HugetlbGroup{}
	actualStats := *cgroups.NewStats()
	err := hugetlb.GetStats(helper.CgroupPath, &actualStats)
	if err == nil {
		t.Fatal("Expected failure")
	}
}
Beispiel #10
0
func TestNonCFQBlkioStats(t *testing.T) {
	helper := NewCgroupTestUtil("blkio", t)
	defer helper.cleanup()
	helper.writeFileContents(map[string]string{
		"blkio.io_service_bytes_recursive": "",
		"blkio.io_serviced_recursive":      "",
		"blkio.io_queued_recursive":        "",
		"blkio.sectors_recursive":          "",
		"blkio.io_service_time_recursive":  "",
		"blkio.io_wait_time_recursive":     "",
		"blkio.io_merged_recursive":        "",
		"blkio.time_recursive":             "",
		"blkio.throttle.io_service_bytes":  throttleServiceBytes,
		"blkio.throttle.io_serviced":       throttleServiced,
	})

	blkio := &BlkioGroup{}
	actualStats := *cgroups.NewStats()
	err := blkio.GetStats(helper.CgroupPath, &actualStats)
	if err != nil {
		t.Fatal(err)
	}

	// Verify expected stats.
	expectedStats := cgroups.BlkioStats{}

	appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 11030528, "Read")
	appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 23, "Write")
	appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 42, "Sync")
	appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 11030528, "Async")
	appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 11030528, "Total")
	appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 11030528, "Read")
	appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 23, "Write")
	appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 42, "Sync")
	appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 11030528, "Async")
	appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 252, 0, 11030528, "Total")

	appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 164, "Read")
	appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 23, "Write")
	appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 42, "Sync")
	appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 164, "Async")
	appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 164, "Total")
	appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 164, "Read")
	appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 23, "Write")
	appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 42, "Sync")
	appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 164, "Async")
	appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 252, 0, 164, "Total")

	expectBlkioStatsEquals(t, expectedStats, actualStats.BlkioStats)
}
Beispiel #11
0
func (m *Manager) GetStats() (*cgroups.Stats, error) {
	m.mu.Lock()
	defer m.mu.Unlock()
	stats := cgroups.NewStats()
	for name, path := range m.Paths {
		sys, err := subsystems.Get(name)
		if err == errSubsystemDoesNotExist || !cgroups.PathExists(path) {
			continue
		}
		if err := sys.GetStats(path, stats); err != nil {
			return nil, err
		}
	}
	return stats, nil
}
Beispiel #12
0
func TestMemoryStatsNoMaxUsageFile(t *testing.T) {
	helper := NewCgroupTestUtil("memory", t)
	defer helper.cleanup()
	helper.writeFileContents(map[string]string{
		"memory.stat":           memoryStatContents,
		"memory.usage_in_bytes": memoryUsageContents,
	})

	memory := &MemoryGroup{}
	actualStats := *cgroups.NewStats()
	err := memory.GetStats(helper.CgroupPath, &actualStats)
	if err == nil {
		t.Fatal("Expected failure")
	}
}
func TestGetStats(t *testing.T) {

	Convey("Given docker id, stats, client", t, func() {

		dockerId := "1234567890ab"
		mountPoint := "mount/point/path"
		mockStats := new(StatsMock)
		mockClient := new(ClientMock)
		stats := cgroups.NewStats()

		mockClient.On("FindCgroupMountpoint", "cpu").Return(mountPoint, nil)
		mockStats.On("GetStats", mock.AnythingOfType("string"), stats).Return(nil).Run(
			func(args mock.Arguments) {
				arg := args.Get(1).(*cgroups.Stats)
				arg.CpuStats.CpuUsage.TotalUsage = 43
				arg.CpuStats.CpuUsage.PercpuUsage = []uint64{99, 88}
			})

		Convey("and cgroups stats wrapper", func() {

			mockWrapper := map[string]Stats{"cpu": mockStats}

			Convey("When docker stats are requested", func() {

				d := &docker{
					stats:          stats,
					client:         mockClient,
					tools:          new(MyTools),
					containersInfo: []ContainerInfo{},
					groupWrap:      mockWrapper,
					hostname:       "",
				}

				err := d.getStats(dockerId)

				Convey("Then no error should be reported", func() {
					So(err, ShouldBeNil)
				})

				Convey("Then stats should be set", func() {
					So(stats.CpuStats.CpuUsage.TotalUsage, ShouldEqual, 43)
					So(stats.CpuStats.CpuUsage.PercpuUsage[0], ShouldEqual, 99)
					So(stats.CpuStats.CpuUsage.PercpuUsage[1], ShouldEqual, 88)
				})
			})
		})
	})
}
Beispiel #14
0
func TestMemoryStatsNoStatFile(t *testing.T) {
	helper := NewCgroupTestUtil("memory", t)
	defer helper.cleanup()
	helper.writeFileContents(map[string]string{
		"memory.usage_in_bytes":     memoryUsageContents,
		"memory.max_usage_in_bytes": memoryMaxUsageContents,
		"memory.limit_in_bytes":     memoryLimitContents,
	})

	memory := &MemoryGroup{}
	actualStats := *cgroups.NewStats()
	err := memory.GetStats(helper.CgroupPath, &actualStats)
	if err != nil {
		t.Fatal(err)
	}
}
Beispiel #15
0
func TestHugetlbStatsNoMaxUsageFile(t *testing.T) {
	helper := NewCgroupTestUtil("hugetlb", t)
	defer helper.cleanup()
	for _, pageSize := range HugePageSizes {
		helper.writeFileContents(map[string]string{
			fmt.Sprintf(usage, pageSize): hugetlbUsageContents,
		})
	}

	hugetlb := &HugetlbGroup{}
	actualStats := *cgroups.NewStats()
	err := hugetlb.GetStats(helper.CgroupPath, &actualStats)
	if err == nil {
		t.Fatal("Expected failure")
	}
}
Beispiel #16
0
func (mi MemInfoFile) readAll() ([]byte, error) {
	stats := cgroups.NewStats()
	mi.memCgroup.GetStats(mi.cgroupdir, stats)
	memStats := stats.MemoryStats
	mls := mi.getLimits()
	memInfo := fmt.Sprintf(content,
		mls[hardLimit]/1024,
		(mls[hardLimit]-memStats.Usage.Usage)/1024,
		(mls[hardLimit]-memStats.Usage.Usage)/1024,
		0,
		memStats.Stats["total_cache"]/1024,
		0,
	)
	logrus.Debugf("memInfo \n%s", memInfo)
	return []byte(memInfo), nil
}
Beispiel #17
0
func TestInvalidCpuStat(t *testing.T) {
	helper := NewCgroupTestUtil("cpu", t)
	defer helper.cleanup()
	cpuStatContent := `nr_periods 2000
	nr_throttled 200
	throttled_time fortytwo`
	helper.writeFileContents(map[string]string{
		"cpu.stat": cpuStatContent,
	})

	cpu := &CpuGroup{}
	actualStats := *cgroups.NewStats()
	err := cpu.GetStats(helper.CgroupPath, &actualStats)
	if err == nil {
		t.Fatal("Expected failed stat parsing.")
	}
}
Beispiel #18
0
func TestHugetlbStats(t *testing.T) {
	helper := NewCgroupTestUtil("hugetlb", t)
	defer helper.cleanup()
	helper.writeFileContents(map[string]string{
		usage:    hugetlbUsageContents,
		maxUsage: hugetlbMaxUsageContents,
		failcnt:  hugetlbFailcnt,
	})

	hugetlb := &HugetlbGroup{}
	actualStats := *cgroups.NewStats()
	err := hugetlb.GetStats(helper.CgroupPath, &actualStats)
	if err != nil {
		t.Fatal(err)
	}
	expectedStats := cgroups.HugetlbStats{Usage: 128, MaxUsage: 256, Failcnt: 100}
	expectHugetlbStatEquals(t, expectedStats, actualStats.HugetlbStats[hugePageSize[0]])
}
Beispiel #19
0
func TestDiskStats(t *testing.T) {
	stats := cgroups.NewStats()
	pkgPath := packagePath()
	if pkgPath == "" {
		t.Skip("failed to find pkg path")
	}
	hackDir := filepath.Join(pkgPath, "src/github.com/chenchun/cgroupfs/hack/")
	blkioCgroup := &fs.BlkioGroup{}
	blkioCgroup.GetStats(filepath.Join(hackDir, "blkio"), stats)

	diskStats, err := ioutil.ReadFile(filepath.Join(hackDir, "/proc/diskstats"))
	if err != nil {
		t.Fatalf("failed to read /proc/diskstats: %v", err)
	}
	ret := string(getDiskStats(diskStats, stats.BlkioStats))
	if ret != "8       0 sda 137 1 1608 730 377 3 3392 263 0 0 688\n" {
		t.Fatalf("%q", ret)
	}
}
Beispiel #20
0
func TestPidsStats(t *testing.T) {
	helper := NewCgroupTestUtil("pids", t)
	defer helper.cleanup()

	helper.writeFileContents(map[string]string{
		"pids.current": strconv.Itoa(1337),
		"pids.max":     strconv.Itoa(maxLimited),
	})

	pids := &PidsGroup{}
	stats := *cgroups.NewStats()
	if err := pids.GetStats(helper.CgroupPath, &stats); err != nil {
		t.Fatal(err)
	}

	if stats.PidsStats.Current != 1337 {
		t.Fatalf("Expected %d, got %d for pids.current", 1337, stats.PidsStats.Current)
	}
}
Beispiel #21
0
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.io_service_time_recursive":  serviceTimeRecursiveContents,
		"blkio.io_wait_time_recursive":     waitTimeRecursiveContents,
		"blkio.io_merged_recursive":        mergedRecursiveContents,
		"blkio.time_recursive":             timeRecursiveContents,
	})

	blkio := &BlkioGroup{}
	actualStats := *cgroups.NewStats()
	err := blkio.GetStats(helper.CgroupPath, &actualStats)
	if err != nil {
		t.Fatalf("Failed unexpectedly: %s", err)
	}
}
Beispiel #22
0
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.io_service_time_recursive":  serviceTimeRecursiveContents,
		"blkio.io_wait_time_recursive":     waitTimeRecursiveContents,
		"blkio.io_merged_recursive":        mergedRecursiveContents,
		"blkio.time_recursive":             timeRecursiveContents,
	})

	blkio := &BlkioGroup{}
	actualStats := *cgroups.NewStats()
	err := blkio.GetStats(helper.CgroupPath, &actualStats)
	if err == nil {
		t.Fatal("Expected to fail, but did not")
	}
}
// Docker plugin initializer
func NewDocker() (*docker, error) {
	host, _ := os.Hostname()
	// create new docker client
	dockerClient := client.NewDockerClient()
	// list all running containers
	containers, err := dockerClient.ListContainers()

	if err != nil {
		return nil, err
	}

	d := &docker{
		stats:          cgroups.NewStats(),
		client:         dockerClient,
		tools:          new(tls.MyTools),
		containersInfo: containers,
		groupWrap:      wrapper.Cgroups2Stats,
		hostname:       host}

	return d, nil
}
Beispiel #24
0
func TestHugetlbStats(t *testing.T) {
	helper := NewCgroupTestUtil("hugetlb", t)
	defer helper.cleanup()
	for _, pageSize := range HugePageSizes {
		helper.writeFileContents(map[string]string{
			fmt.Sprintf(usage, pageSize):    hugetlbUsageContents,
			fmt.Sprintf(maxUsage, pageSize): hugetlbMaxUsageContents,
			fmt.Sprintf(failcnt, pageSize):  hugetlbFailcnt,
		})
	}

	hugetlb := &HugetlbGroup{}
	actualStats := *cgroups.NewStats()
	err := hugetlb.GetStats(helper.CgroupPath, &actualStats)
	if err != nil {
		t.Fatal(err)
	}
	expectedStats := cgroups.HugetlbStats{Usage: 128, MaxUsage: 256, Failcnt: 100}
	for _, pageSize := range HugePageSizes {
		expectHugetlbStatEquals(t, expectedStats, actualStats.HugetlbStats[pageSize])
	}
}
Beispiel #25
0
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.io_service_time_recursive":  serviceTimeRecursiveContents,
		"blkio.io_wait_time_recursive":     waitTimeRecursiveContents,
		"blkio.io_merged_recursive":        mergedRecursiveContents,
		"blkio.time_recursive":             timeRecursiveContents,
		"blkio.sectors_recursive":          sectorsRecursiveContents,
	})

	blkio := &BlkioGroup{}
	actualStats := *cgroups.NewStats()
	err := blkio.GetStats(helper.CgroupPath, &actualStats)
	if err != nil {
		t.Fatal(err)
	}

	// Verify expected stats.
	expectedStats := cgroups.BlkioStats{}
	appendBlkioStatEntry(&expectedStats.SectorsRecursive, 8, 0, 1024, "")

	appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 100, "Read")
	appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 200, "Write")
	appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 300, "Sync")
	appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 500, "Async")
	appendBlkioStatEntry(&expectedStats.IoServiceBytesRecursive, 8, 0, 500, "Total")

	appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 10, "Read")
	appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 40, "Write")
	appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 20, "Sync")
	appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 30, "Async")
	appendBlkioStatEntry(&expectedStats.IoServicedRecursive, 8, 0, 50, "Total")

	appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 1, "Read")
	appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 4, "Write")
	appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 2, "Sync")
	appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 3, "Async")
	appendBlkioStatEntry(&expectedStats.IoQueuedRecursive, 8, 0, 5, "Total")

	appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 173959, "Read")
	appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 0, "Write")
	appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 0, "Sync")
	appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 173959, "Async")
	appendBlkioStatEntry(&expectedStats.IoServiceTimeRecursive, 8, 0, 17395, "Total")

	appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 15571, "Read")
	appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 0, "Write")
	appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 0, "Sync")
	appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 15571, "Async")
	appendBlkioStatEntry(&expectedStats.IoWaitTimeRecursive, 8, 0, 15571, "Total")

	appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 5, "Read")
	appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 10, "Write")
	appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 0, "Sync")
	appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 0, "Async")
	appendBlkioStatEntry(&expectedStats.IoMergedRecursive, 8, 0, 15, "Total")

	appendBlkioStatEntry(&expectedStats.IoTimeRecursive, 8, 0, 8, "")

	expectBlkioStatsEquals(t, expectedStats, actualStats.BlkioStats)
}