libcontainer: add test cases for Intel RDT/CAT
Signed-off-by: Xiaochen Shen <xiaochen.shen@intel.com>
This commit is contained in:
parent
692f6e1e27
commit
4d2756c116
|
@ -9,6 +9,7 @@ import (
|
|||
|
||||
"github.com/opencontainers/runc/libcontainer/cgroups"
|
||||
"github.com/opencontainers/runc/libcontainer/configs"
|
||||
"github.com/opencontainers/runc/libcontainer/intelrdt"
|
||||
"github.com/opencontainers/runc/libcontainer/system"
|
||||
)
|
||||
|
||||
|
@ -19,6 +20,11 @@ type mockCgroupManager struct {
|
|||
paths map[string]string
|
||||
}
|
||||
|
||||
type mockIntelRdtManager struct {
|
||||
stats *intelrdt.Stats
|
||||
path string
|
||||
}
|
||||
|
||||
func (m *mockCgroupManager) GetPids() ([]int, error) {
|
||||
return m.pids, nil
|
||||
}
|
||||
|
@ -51,6 +57,26 @@ func (m *mockCgroupManager) Freeze(state configs.FreezerState) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (m *mockIntelRdtManager) Apply(pid int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockIntelRdtManager) GetStats() (*intelrdt.Stats, error) {
|
||||
return m.stats, nil
|
||||
}
|
||||
|
||||
func (m *mockIntelRdtManager) Destroy() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockIntelRdtManager) GetPath() string {
|
||||
return m.path
|
||||
}
|
||||
|
||||
func (m *mockIntelRdtManager) Set(container *configs.Config) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type mockProcess struct {
|
||||
_pid int
|
||||
started uint64
|
||||
|
@ -118,6 +144,11 @@ func TestGetContainerStats(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
intelRdtManager: &mockIntelRdtManager{
|
||||
stats: &intelrdt.Stats{
|
||||
L3CacheSchema: "L3:0=f;1=f0",
|
||||
},
|
||||
},
|
||||
}
|
||||
stats, err := container.Stats()
|
||||
if err != nil {
|
||||
|
@ -129,6 +160,14 @@ func TestGetContainerStats(t *testing.T) {
|
|||
if stats.CgroupStats.MemoryStats.Usage.Usage != 1024 {
|
||||
t.Fatalf("expected memory usage 1024 but recevied %d", stats.CgroupStats.MemoryStats.Usage.Usage)
|
||||
}
|
||||
if intelrdt.IsIntelRdtEnabled() {
|
||||
if stats.IntelRdtStats == nil {
|
||||
t.Fatal("intel rdt stats are nil")
|
||||
}
|
||||
if stats.IntelRdtStats.L3CacheSchema != "L3:0=f;1=f0" {
|
||||
t.Fatalf("expected L3CacheSchema L3:0=f;1=f0 but recevied %s", stats.IntelRdtStats.L3CacheSchema)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetContainerState(t *testing.T) {
|
||||
|
@ -136,6 +175,7 @@ func TestGetContainerState(t *testing.T) {
|
|||
pid = os.Getpid()
|
||||
expectedMemoryPath = "/sys/fs/cgroup/memory/myid"
|
||||
expectedNetworkPath = fmt.Sprintf("/proc/%d/ns/net", pid)
|
||||
expectedIntelRdtPath = "/sys/fs/resctrl/myid"
|
||||
)
|
||||
container := &linuxContainer{
|
||||
id: "myid",
|
||||
|
@ -166,6 +206,12 @@ func TestGetContainerState(t *testing.T) {
|
|||
"memory": expectedMemoryPath,
|
||||
},
|
||||
},
|
||||
intelRdtManager: &mockIntelRdtManager{
|
||||
stats: &intelrdt.Stats{
|
||||
L3CacheSchema: "L3:0=f0;1=f",
|
||||
},
|
||||
path: expectedIntelRdtPath,
|
||||
},
|
||||
}
|
||||
container.state = &createdState{c: container}
|
||||
state, err := container.State()
|
||||
|
@ -185,6 +231,15 @@ func TestGetContainerState(t *testing.T) {
|
|||
if memPath := paths["memory"]; memPath != expectedMemoryPath {
|
||||
t.Fatalf("expected memory path %q but received %q", expectedMemoryPath, memPath)
|
||||
}
|
||||
if intelrdt.IsIntelRdtEnabled() {
|
||||
intelRdtPath := state.IntelRdtPath
|
||||
if intelRdtPath == "" {
|
||||
t.Fatal("intel rdt path should not be empty")
|
||||
}
|
||||
if intelRdtPath != expectedIntelRdtPath {
|
||||
t.Fatalf("expected intel rdt path %q but received %q", expectedIntelRdtPath, intelRdtPath)
|
||||
}
|
||||
}
|
||||
for _, ns := range container.config.Namespaces {
|
||||
path := state.NamespacePaths[ns.Type]
|
||||
if path == "" {
|
||||
|
|
|
@ -50,6 +50,32 @@ func TestFactoryNew(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestFactoryNewIntelRdt(t *testing.T) {
|
||||
root, rerr := newTestRoot()
|
||||
if rerr != nil {
|
||||
t.Fatal(rerr)
|
||||
}
|
||||
defer os.RemoveAll(root)
|
||||
factory, err := New(root, Cgroupfs, IntelRdtFs)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if factory == nil {
|
||||
t.Fatal("factory should not be nil")
|
||||
}
|
||||
lfactory, ok := factory.(*LinuxFactory)
|
||||
if !ok {
|
||||
t.Fatal("expected linux factory returned on linux based systems")
|
||||
}
|
||||
if lfactory.Root != root {
|
||||
t.Fatalf("expected factory root to be %q but received %q", root, lfactory.Root)
|
||||
}
|
||||
|
||||
if factory.Type() != "libcontainer" {
|
||||
t.Fatalf("unexpected factory type: %q, expected %q", factory.Type(), "libcontainer")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFactoryNewTmpfs(t *testing.T) {
|
||||
root, rerr := newTestRoot()
|
||||
if rerr != nil {
|
||||
|
@ -164,7 +190,7 @@ func TestFactoryLoadContainer(t *testing.T) {
|
|||
if err := marshal(filepath.Join(root, id, stateFilename), expectedState); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
factory, err := New(root, Cgroupfs)
|
||||
factory, err := New(root, Cgroupfs, IntelRdtFs)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
// +build linux
|
||||
|
||||
package intelrdt
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestIntelRdtSetL3CacheSchema(t *testing.T) {
|
||||
if !IsIntelRdtEnabled() {
|
||||
return
|
||||
}
|
||||
|
||||
helper := NewIntelRdtTestUtil(t)
|
||||
defer helper.cleanup()
|
||||
|
||||
const (
|
||||
l3CacheSchemaBefore = "L3:0=f;1=f0"
|
||||
l3CacheSchemeAfter = "L3:0=f0;1=f"
|
||||
)
|
||||
|
||||
helper.writeFileContents(map[string]string{
|
||||
"schemata": l3CacheSchemaBefore + "\n",
|
||||
})
|
||||
|
||||
helper.IntelRdtData.config.IntelRdt.L3CacheSchema = l3CacheSchemeAfter
|
||||
intelrdt := &IntelRdtManager{
|
||||
Config: helper.IntelRdtData.config,
|
||||
Path: helper.IntelRdtPath,
|
||||
}
|
||||
if err := intelrdt.Set(helper.IntelRdtData.config); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
tmpStrings, err := getIntelRdtParamString(helper.IntelRdtPath, "schemata")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to parse file 'schemata' - %s", err)
|
||||
}
|
||||
values := strings.Split(tmpStrings, "\n")
|
||||
value := values[0]
|
||||
|
||||
if value != l3CacheSchemeAfter {
|
||||
t.Fatal("Got the wrong value, set 'schemata' failed.")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
// +build linux
|
||||
|
||||
/*
|
||||
* Utility for testing Intel RDT operations.
|
||||
* Creates a mock of the Intel RDT "resource control" filesystem for the duration of the test.
|
||||
*/
|
||||
package intelrdt
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/opencontainers/runc/libcontainer/configs"
|
||||
)
|
||||
|
||||
type intelRdtTestUtil struct {
|
||||
// intelRdt data to use in tests
|
||||
IntelRdtData *intelRdtData
|
||||
|
||||
// Path to the mock Intel RDT "resource control" filesystem directory
|
||||
IntelRdtPath string
|
||||
|
||||
// Temporary directory to store mock Intel RDT "resource control" filesystem
|
||||
tempDir string
|
||||
t *testing.T
|
||||
}
|
||||
|
||||
// Creates a new test util
|
||||
func NewIntelRdtTestUtil(t *testing.T) *intelRdtTestUtil {
|
||||
d := &intelRdtData{
|
||||
config: &configs.Config{
|
||||
IntelRdt: &configs.IntelRdt{},
|
||||
},
|
||||
}
|
||||
tempDir, err := ioutil.TempDir("", "intelrdt_test")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
d.root = tempDir
|
||||
testIntelRdtPath := filepath.Join(d.root, "resctrl")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Ensure the full mock Intel RDT "resource control" filesystem path exists
|
||||
err = os.MkdirAll(testIntelRdtPath, 0755)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return &intelRdtTestUtil{IntelRdtData: d, IntelRdtPath: testIntelRdtPath, tempDir: tempDir, t: t}
|
||||
}
|
||||
|
||||
func (c *intelRdtTestUtil) cleanup() {
|
||||
os.RemoveAll(c.tempDir)
|
||||
}
|
||||
|
||||
// Write the specified contents on the mock of the specified Intel RDT "resource control" files
|
||||
func (c *intelRdtTestUtil) writeFileContents(fileContents map[string]string) {
|
||||
for file, contents := range fileContents {
|
||||
err := writeFile(c.IntelRdtPath, file, contents)
|
||||
if err != nil {
|
||||
c.t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue