github.com/opencontainers/runc@v1.2.0-rc.1.0.20240520010911-492dc558cdd6/libcontainer/cgroups/fs2/misc_test.go (about)

     1  package fs2
     2  
     3  import (
     4  	"os"
     5  	"path/filepath"
     6  	"strings"
     7  	"testing"
     8  
     9  	"github.com/opencontainers/runc/libcontainer/cgroups"
    10  )
    11  
    12  const exampleMiscCurrentData = `res_a 123
    13  res_b 456
    14  res_c 42`
    15  
    16  const exampleMiscEventsData = `res_a.max 1
    17  res_b.max 2
    18  res_c.max 3`
    19  
    20  func TestStatMiscPodCgroupEmpty(t *testing.T) {
    21  	// We're using a fake cgroupfs.
    22  	cgroups.TestMode = true
    23  	fakeCgroupDir := t.TempDir()
    24  
    25  	// create empty misc.current and misc.events files to test the common case
    26  	// where no misc resource keys are available
    27  	for _, file := range []string{"misc.current", "misc.events"} {
    28  		if _, err := os.Create(filepath.Join(fakeCgroupDir, file)); err != nil {
    29  			t.Fatal(err)
    30  		}
    31  	}
    32  
    33  	gotStats := cgroups.NewStats()
    34  
    35  	err := statMisc(fakeCgroupDir, gotStats)
    36  	if err != nil {
    37  		t.Errorf("expected no error when statting empty misc.current/misc.events for cgroupv2, but got %#v", err)
    38  	}
    39  
    40  	if len(gotStats.MiscStats) != 0 {
    41  		t.Errorf("parsed cgroupv2 misc.* returns unexpected resources: got %#v but expected nothing", gotStats.MiscStats)
    42  	}
    43  }
    44  
    45  func TestStatMiscPodCgroupNotFound(t *testing.T) {
    46  	// We're using a fake cgroupfs.
    47  	cgroups.TestMode = true
    48  	fakeCgroupDir := t.TempDir()
    49  
    50  	// only write misc.current to ensure pod cgroup usage
    51  	// still reads misc.events.
    52  	statPath := filepath.Join(fakeCgroupDir, "misc.current")
    53  	if err := os.WriteFile(statPath, []byte(exampleMiscCurrentData), 0o644); err != nil {
    54  		t.Fatal(err)
    55  	}
    56  
    57  	gotStats := cgroups.NewStats()
    58  
    59  	// use a fake root path to mismatch the file we wrote.
    60  	// this triggers the non-root path which should fail to find misc.events.
    61  	err := statMisc(fakeCgroupDir, gotStats)
    62  	if err == nil {
    63  		t.Errorf("expected error when statting misc.current for cgroupv2 root, but was nil")
    64  	}
    65  
    66  	if !strings.Contains(err.Error(), "misc.events: no such file or directory") {
    67  		t.Errorf("expected error to contain 'misc.events: no such file or directory', but was %s", err.Error())
    68  	}
    69  }
    70  
    71  func TestStatMiscPodCgroup(t *testing.T) {
    72  	// We're using a fake cgroupfs.
    73  	cgroups.TestMode = true
    74  	fakeCgroupDir := t.TempDir()
    75  
    76  	currentPath := filepath.Join(fakeCgroupDir, "misc.current")
    77  	if err := os.WriteFile(currentPath, []byte(exampleMiscCurrentData), 0o644); err != nil {
    78  		t.Fatal(err)
    79  	}
    80  
    81  	eventsPath := filepath.Join(fakeCgroupDir, "misc.events")
    82  	if err := os.WriteFile(eventsPath, []byte(exampleMiscEventsData), 0o644); err != nil {
    83  		t.Fatal(err)
    84  	}
    85  
    86  	gotStats := cgroups.NewStats()
    87  
    88  	// use a fake root path to trigger the pod cgroup lookup.
    89  	err := statMisc(fakeCgroupDir, gotStats)
    90  	if err != nil {
    91  		t.Errorf("expected no error when statting misc for cgroupv2 root, but got %#+v", err)
    92  	}
    93  
    94  	// make sure all res_* from exampleMisc*Data are returned
    95  	if len(gotStats.MiscStats) != 3 {
    96  		t.Errorf("parsed cgroupv2 misc doesn't return all expected resources: \ngot %#v\nexpected %#v\n", len(gotStats.MiscStats), 3)
    97  	}
    98  
    99  	var expectedUsageBytes uint64 = 42
   100  	if gotStats.MiscStats["res_c"].Usage != expectedUsageBytes {
   101  		t.Errorf("parsed cgroupv2 misc.current for res_c doesn't match expected result: \ngot %#v\nexpected %#v\n", gotStats.MiscStats["res_c"].Usage, expectedUsageBytes)
   102  	}
   103  }