Skip to content

Commit 4d2756c

Browse files
committed
libcontainer: add test cases for Intel RDT/CAT
Signed-off-by: Xiaochen Shen <[email protected]>
1 parent 692f6e1 commit 4d2756c

File tree

4 files changed

+198
-4
lines changed

4 files changed

+198
-4
lines changed

libcontainer/container_linux_test.go

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99

1010
"github.com/opencontainers/runc/libcontainer/cgroups"
1111
"github.com/opencontainers/runc/libcontainer/configs"
12+
"github.com/opencontainers/runc/libcontainer/intelrdt"
1213
"github.com/opencontainers/runc/libcontainer/system"
1314
)
1415

@@ -19,6 +20,11 @@ type mockCgroupManager struct {
1920
paths map[string]string
2021
}
2122

23+
type mockIntelRdtManager struct {
24+
stats *intelrdt.Stats
25+
path string
26+
}
27+
2228
func (m *mockCgroupManager) GetPids() ([]int, error) {
2329
return m.pids, nil
2430
}
@@ -51,6 +57,26 @@ func (m *mockCgroupManager) Freeze(state configs.FreezerState) error {
5157
return nil
5258
}
5359

60+
func (m *mockIntelRdtManager) Apply(pid int) error {
61+
return nil
62+
}
63+
64+
func (m *mockIntelRdtManager) GetStats() (*intelrdt.Stats, error) {
65+
return m.stats, nil
66+
}
67+
68+
func (m *mockIntelRdtManager) Destroy() error {
69+
return nil
70+
}
71+
72+
func (m *mockIntelRdtManager) GetPath() string {
73+
return m.path
74+
}
75+
76+
func (m *mockIntelRdtManager) Set(container *configs.Config) error {
77+
return nil
78+
}
79+
5480
type mockProcess struct {
5581
_pid int
5682
started uint64
@@ -118,6 +144,11 @@ func TestGetContainerStats(t *testing.T) {
118144
},
119145
},
120146
},
147+
intelRdtManager: &mockIntelRdtManager{
148+
stats: &intelrdt.Stats{
149+
L3CacheSchema: "L3:0=f;1=f0",
150+
},
151+
},
121152
}
122153
stats, err := container.Stats()
123154
if err != nil {
@@ -129,13 +160,22 @@ func TestGetContainerStats(t *testing.T) {
129160
if stats.CgroupStats.MemoryStats.Usage.Usage != 1024 {
130161
t.Fatalf("expected memory usage 1024 but recevied %d", stats.CgroupStats.MemoryStats.Usage.Usage)
131162
}
163+
if intelrdt.IsIntelRdtEnabled() {
164+
if stats.IntelRdtStats == nil {
165+
t.Fatal("intel rdt stats are nil")
166+
}
167+
if stats.IntelRdtStats.L3CacheSchema != "L3:0=f;1=f0" {
168+
t.Fatalf("expected L3CacheSchema L3:0=f;1=f0 but recevied %s", stats.IntelRdtStats.L3CacheSchema)
169+
}
170+
}
132171
}
133172

134173
func TestGetContainerState(t *testing.T) {
135174
var (
136-
pid = os.Getpid()
137-
expectedMemoryPath = "/sys/fs/cgroup/memory/myid"
138-
expectedNetworkPath = fmt.Sprintf("/proc/%d/ns/net", pid)
175+
pid = os.Getpid()
176+
expectedMemoryPath = "/sys/fs/cgroup/memory/myid"
177+
expectedNetworkPath = fmt.Sprintf("/proc/%d/ns/net", pid)
178+
expectedIntelRdtPath = "/sys/fs/resctrl/myid"
139179
)
140180
container := &linuxContainer{
141181
id: "myid",
@@ -166,6 +206,12 @@ func TestGetContainerState(t *testing.T) {
166206
"memory": expectedMemoryPath,
167207
},
168208
},
209+
intelRdtManager: &mockIntelRdtManager{
210+
stats: &intelrdt.Stats{
211+
L3CacheSchema: "L3:0=f0;1=f",
212+
},
213+
path: expectedIntelRdtPath,
214+
},
169215
}
170216
container.state = &createdState{c: container}
171217
state, err := container.State()
@@ -185,6 +231,15 @@ func TestGetContainerState(t *testing.T) {
185231
if memPath := paths["memory"]; memPath != expectedMemoryPath {
186232
t.Fatalf("expected memory path %q but received %q", expectedMemoryPath, memPath)
187233
}
234+
if intelrdt.IsIntelRdtEnabled() {
235+
intelRdtPath := state.IntelRdtPath
236+
if intelRdtPath == "" {
237+
t.Fatal("intel rdt path should not be empty")
238+
}
239+
if intelRdtPath != expectedIntelRdtPath {
240+
t.Fatalf("expected intel rdt path %q but received %q", expectedIntelRdtPath, intelRdtPath)
241+
}
242+
}
188243
for _, ns := range container.config.Namespaces {
189244
path := state.NamespacePaths[ns.Type]
190245
if path == "" {

libcontainer/factory_linux_test.go

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,32 @@ func TestFactoryNew(t *testing.T) {
5050
}
5151
}
5252

53+
func TestFactoryNewIntelRdt(t *testing.T) {
54+
root, rerr := newTestRoot()
55+
if rerr != nil {
56+
t.Fatal(rerr)
57+
}
58+
defer os.RemoveAll(root)
59+
factory, err := New(root, Cgroupfs, IntelRdtFs)
60+
if err != nil {
61+
t.Fatal(err)
62+
}
63+
if factory == nil {
64+
t.Fatal("factory should not be nil")
65+
}
66+
lfactory, ok := factory.(*LinuxFactory)
67+
if !ok {
68+
t.Fatal("expected linux factory returned on linux based systems")
69+
}
70+
if lfactory.Root != root {
71+
t.Fatalf("expected factory root to be %q but received %q", root, lfactory.Root)
72+
}
73+
74+
if factory.Type() != "libcontainer" {
75+
t.Fatalf("unexpected factory type: %q, expected %q", factory.Type(), "libcontainer")
76+
}
77+
}
78+
5379
func TestFactoryNewTmpfs(t *testing.T) {
5480
root, rerr := newTestRoot()
5581
if rerr != nil {
@@ -164,7 +190,7 @@ func TestFactoryLoadContainer(t *testing.T) {
164190
if err := marshal(filepath.Join(root, id, stateFilename), expectedState); err != nil {
165191
t.Fatal(err)
166192
}
167-
factory, err := New(root, Cgroupfs)
193+
factory, err := New(root, Cgroupfs, IntelRdtFs)
168194
if err != nil {
169195
t.Fatal(err)
170196
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// +build linux
2+
3+
package intelrdt
4+
5+
import (
6+
"strings"
7+
"testing"
8+
)
9+
10+
func TestIntelRdtSetL3CacheSchema(t *testing.T) {
11+
if !IsIntelRdtEnabled() {
12+
return
13+
}
14+
15+
helper := NewIntelRdtTestUtil(t)
16+
defer helper.cleanup()
17+
18+
const (
19+
l3CacheSchemaBefore = "L3:0=f;1=f0"
20+
l3CacheSchemeAfter = "L3:0=f0;1=f"
21+
)
22+
23+
helper.writeFileContents(map[string]string{
24+
"schemata": l3CacheSchemaBefore + "\n",
25+
})
26+
27+
helper.IntelRdtData.config.IntelRdt.L3CacheSchema = l3CacheSchemeAfter
28+
intelrdt := &IntelRdtManager{
29+
Config: helper.IntelRdtData.config,
30+
Path: helper.IntelRdtPath,
31+
}
32+
if err := intelrdt.Set(helper.IntelRdtData.config); err != nil {
33+
t.Fatal(err)
34+
}
35+
36+
tmpStrings, err := getIntelRdtParamString(helper.IntelRdtPath, "schemata")
37+
if err != nil {
38+
t.Fatalf("Failed to parse file 'schemata' - %s", err)
39+
}
40+
values := strings.Split(tmpStrings, "\n")
41+
value := values[0]
42+
43+
if value != l3CacheSchemeAfter {
44+
t.Fatal("Got the wrong value, set 'schemata' failed.")
45+
}
46+
}

libcontainer/intelrdt/util_test.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// +build linux
2+
3+
/*
4+
* Utility for testing Intel RDT operations.
5+
* Creates a mock of the Intel RDT "resource control" filesystem for the duration of the test.
6+
*/
7+
package intelrdt
8+
9+
import (
10+
"io/ioutil"
11+
"os"
12+
"path/filepath"
13+
"testing"
14+
15+
"github.com/opencontainers/runc/libcontainer/configs"
16+
)
17+
18+
type intelRdtTestUtil struct {
19+
// intelRdt data to use in tests
20+
IntelRdtData *intelRdtData
21+
22+
// Path to the mock Intel RDT "resource control" filesystem directory
23+
IntelRdtPath string
24+
25+
// Temporary directory to store mock Intel RDT "resource control" filesystem
26+
tempDir string
27+
t *testing.T
28+
}
29+
30+
// Creates a new test util
31+
func NewIntelRdtTestUtil(t *testing.T) *intelRdtTestUtil {
32+
d := &intelRdtData{
33+
config: &configs.Config{
34+
IntelRdt: &configs.IntelRdt{},
35+
},
36+
}
37+
tempDir, err := ioutil.TempDir("", "intelrdt_test")
38+
if err != nil {
39+
t.Fatal(err)
40+
}
41+
d.root = tempDir
42+
testIntelRdtPath := filepath.Join(d.root, "resctrl")
43+
if err != nil {
44+
t.Fatal(err)
45+
}
46+
47+
// Ensure the full mock Intel RDT "resource control" filesystem path exists
48+
err = os.MkdirAll(testIntelRdtPath, 0755)
49+
if err != nil {
50+
t.Fatal(err)
51+
}
52+
return &intelRdtTestUtil{IntelRdtData: d, IntelRdtPath: testIntelRdtPath, tempDir: tempDir, t: t}
53+
}
54+
55+
func (c *intelRdtTestUtil) cleanup() {
56+
os.RemoveAll(c.tempDir)
57+
}
58+
59+
// Write the specified contents on the mock of the specified Intel RDT "resource control" files
60+
func (c *intelRdtTestUtil) writeFileContents(fileContents map[string]string) {
61+
for file, contents := range fileContents {
62+
err := writeFile(c.IntelRdtPath, file, contents)
63+
if err != nil {
64+
c.t.Fatal(err)
65+
}
66+
}
67+
}

0 commit comments

Comments
 (0)