File: cpuacct_test.go

package info (click to toggle)
golang-github-opencontainers-cgroups 0.0.6-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 876 kB
  • sloc: makefile: 2
file content (161 lines) | stat: -rw-r--r-- 4,854 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
package fs

import (
	"reflect"
	"slices"
	"testing"

	"github.com/opencontainers/cgroups"
)

const (
	cpuAcctUsageContents       = "12262454190222160"
	cpuAcctUsagePerCPUContents = "1564936537989058 1583937096487821 1604195415465681 1596445226820187 1481069084155629 1478735613864327 1477610593414743 1476362015778086"
	cpuAcctStatContents        = "user 452278264\nsystem 291429664"
	cpuAcctUsageAll            = `cpu user system
	0 962250696038415 637727786389114
	1 981956408513304 638197595421064
	2 1002658817529022 638956774598358
	3 994937703492523 637985531181620
	4 874843781648690 638837766495476
	5 872544369885276 638763309884944
	6 870104915696359 640081778921247
	7 870202363887496 638716766259495
	`
)

func TestCpuacctStats(t *testing.T) {
	path := tempDir(t, "cpuacct")
	writeFileContents(t, path, map[string]string{
		"cpuacct.usage":        cpuAcctUsageContents,
		"cpuacct.usage_percpu": cpuAcctUsagePerCPUContents,
		"cpuacct.stat":         cpuAcctStatContents,
		"cpuacct.usage_all":    cpuAcctUsageAll,
	})

	cpuacct := &CpuacctGroup{}
	actualStats := *cgroups.NewStats()
	err := cpuacct.GetStats(path, &actualStats)
	if err != nil {
		t.Fatal(err)
	}

	expectedStats := cgroups.CpuUsage{
		TotalUsage: uint64(12262454190222160),
		PercpuUsage: []uint64{
			1564936537989058, 1583937096487821, 1604195415465681, 1596445226820187,
			1481069084155629, 1478735613864327, 1477610593414743, 1476362015778086,
		},
		PercpuUsageInKernelmode: []uint64{
			637727786389114, 638197595421064, 638956774598358, 637985531181620,
			638837766495476, 638763309884944, 640081778921247, 638716766259495,
		},
		PercpuUsageInUsermode: []uint64{
			962250696038415, 981956408513304, 1002658817529022, 994937703492523,
			874843781648690, 872544369885276, 870104915696359, 870202363887496,
		},
		UsageInKernelmode: (uint64(291429664) * nsInSec) / clockTicks,
		UsageInUsermode:   (uint64(452278264) * nsInSec) / clockTicks,
	}

	if !reflect.DeepEqual(expectedStats, actualStats.CpuStats.CpuUsage) {
		t.Errorf("Expected CPU usage %#v but found %#v\n",
			expectedStats, actualStats.CpuStats.CpuUsage)
	}
}

func TestCpuacctStatsWithoutUsageAll(t *testing.T) {
	path := tempDir(t, "cpuacct")
	writeFileContents(t, path, map[string]string{
		"cpuacct.usage":        cpuAcctUsageContents,
		"cpuacct.usage_percpu": cpuAcctUsagePerCPUContents,
		"cpuacct.stat":         cpuAcctStatContents,
	})

	cpuacct := &CpuacctGroup{}
	actualStats := *cgroups.NewStats()
	err := cpuacct.GetStats(path, &actualStats)
	if err != nil {
		t.Fatal(err)
	}

	expectedStats := cgroups.CpuUsage{
		TotalUsage: uint64(12262454190222160),
		PercpuUsage: []uint64{
			1564936537989058, 1583937096487821, 1604195415465681, 1596445226820187,
			1481069084155629, 1478735613864327, 1477610593414743, 1476362015778086,
		},
		PercpuUsageInKernelmode: []uint64{},
		PercpuUsageInUsermode:   []uint64{},
		UsageInKernelmode:       (uint64(291429664) * nsInSec) / clockTicks,
		UsageInUsermode:         (uint64(452278264) * nsInSec) / clockTicks,
	}

	if !reflect.DeepEqual(expectedStats, actualStats.CpuStats.CpuUsage) {
		t.Errorf("Expected CPU usage %#v but found %#v\n",
			expectedStats, actualStats.CpuStats.CpuUsage)
	}
}

// TestCpuacctUsageAllExtra checks that if there are extra columns
// in cpuacct.usage_all, yet the first three are as expected, we
// can still parse it successfully.
func TestCpuacctUsageAllExtra(t *testing.T) {
	path := tempDir(t, "cpuacct")
	// These extra columns come from the custom Tencent kernel,
	// see https://github.com/OpenCloudOS/TencentOS-kernel-0/commit/0b667819c3aaa9c8ac904c6b03256b86be93fc05
	err := cgroups.WriteFile(path, "cpuacct.usage_all",
		`cpu user system bt_user bt_system
0 962250696038415 637727786389114 0 0
1 981956408513304 638197595421064 0 0
`)
	if err != nil {
		t.Fatal(err)
	}

	system, user, err := getPercpuUsageInModes(path)
	if err != nil {
		t.Fatal(err)
	}

	expUser := []uint64{962250696038415, 981956408513304}
	expSystem := []uint64{637727786389114, 638197595421064}
	if !slices.Equal(user, expUser) {
		t.Fatalf("unexpected user data (want %+v, got %+v", expUser, user)
	}
	if !slices.Equal(system, expSystem) {
		t.Fatalf("unexpected system data (want %+v, got +%v)", expSystem, system)
	}
}

func TestCpuacctUsageAllBad(t *testing.T) {
	path := tempDir(t, "cpuacct")
	err := cgroups.WriteFile(path, "cpuacct.usage_all",
		`cpu bad data fields
0 1 2
`)
	if err != nil {
		t.Fatal(err)
	}

	_, _, err = getPercpuUsageInModes(path)
	t.Log(err)
	if err == nil {
		t.Fatal("want error, got nil")
	}
}

func BenchmarkGetCpuUsageBreakdown(b *testing.B) {
	path := tempDir(b, "cpuacct")
	writeFileContents(b, path, map[string]string{
		"cpuacct.stat": cpuAcctStatContents,
	})

	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		_, _, err := getCpuUsageBreakdown(path)
		if err != nil {
			b.Fatal(err)
		}
	}
}