...

Source file src/github.com/containerd/cgroups/v2/manager_test.go

Documentation: github.com/containerd/cgroups/v2

     1  /*
     2     Copyright The containerd Authors.
     3  
     4     Licensed under the Apache License, Version 2.0 (the "License");
     5     you may not use this file except in compliance with the License.
     6     You may obtain a copy of the License at
     7  
     8         http://www.apache.org/licenses/LICENSE-2.0
     9  
    10     Unless required by applicable law or agreed to in writing, software
    11     distributed under the License is distributed on an "AS IS" BASIS,
    12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     See the License for the specific language governing permissions and
    14     limitations under the License.
    15  */
    16  
    17  package v2
    18  
    19  import (
    20  	"fmt"
    21  	"os"
    22  	"os/exec"
    23  	"testing"
    24  	"time"
    25  
    26  	"github.com/opencontainers/runtime-spec/specs-go"
    27  	"github.com/stretchr/testify/assert"
    28  	"go.uber.org/goleak"
    29  )
    30  
    31  func TestEventChanCleanupOnCgroupRemoval(t *testing.T) {
    32  	checkCgroupMode(t)
    33  
    34  	cmd := exec.Command("cat")
    35  	stdin, err := cmd.StdinPipe()
    36  	if err != nil {
    37  		t.Fatalf("Failed to create cat process: %v", err)
    38  	}
    39  	if err := cmd.Start(); err != nil {
    40  		t.Fatalf("Failed to start cat process: %v", err)
    41  	}
    42  	proc := cmd.Process
    43  	if proc == nil {
    44  		t.Fatal("Process is nil")
    45  	}
    46  
    47  	group := fmt.Sprintf("testing-watcher-%d.scope", proc.Pid)
    48  	c, err := NewSystemd("", group, proc.Pid, &Resources{})
    49  	if err != nil {
    50  		t.Fatalf("Failed to init new cgroup manager: %v", err)
    51  	}
    52  
    53  	evCh, errCh := c.EventChan()
    54  
    55  	// give event goroutine a chance to start
    56  	time.Sleep(500 * time.Millisecond)
    57  
    58  	if err := stdin.Close(); err != nil {
    59  		t.Fatalf("Failed closing stdin: %v", err)
    60  	}
    61  	if err := cmd.Wait(); err != nil {
    62  		t.Fatalf("Failed waiting for cmd: %v", err)
    63  	}
    64  
    65  	done := false
    66  	for !done {
    67  		select {
    68  		case <-evCh:
    69  		case err := <-errCh:
    70  			if err != nil {
    71  				t.Fatalf("Unexpected error on error channel: %v", err)
    72  			}
    73  			done = true
    74  		case <-time.After(5 * time.Second):
    75  			t.Fatal("Timed out")
    76  		}
    77  	}
    78  	goleak.VerifyNone(t)
    79  }
    80  
    81  func TestSystemdFullPath(t *testing.T) {
    82  	tests := []struct {
    83  		inputSlice  string
    84  		inputGroup  string
    85  		expectedOut string
    86  	}{
    87  		{
    88  			inputSlice:  "user.slice",
    89  			inputGroup:  "myGroup.slice",
    90  			expectedOut: "/sys/fs/cgroup/user.slice/myGroup.slice",
    91  		},
    92  		{
    93  			inputSlice:  "/",
    94  			inputGroup:  "myGroup.slice",
    95  			expectedOut: "/sys/fs/cgroup/myGroup.slice",
    96  		},
    97  		{
    98  			inputSlice:  "system.slice",
    99  			inputGroup:  "myGroup.slice",
   100  			expectedOut: "/sys/fs/cgroup/system.slice/myGroup.slice",
   101  		},
   102  		{
   103  			inputSlice:  "user.slice",
   104  			inputGroup:  "my-group.slice",
   105  			expectedOut: "/sys/fs/cgroup/user.slice/my.slice/my-group.slice",
   106  		},
   107  		{
   108  			inputSlice:  "user.slice",
   109  			inputGroup:  "my-group-more-dashes.slice",
   110  			expectedOut: "/sys/fs/cgroup/user.slice/my.slice/my-group.slice/my-group-more.slice/my-group-more-dashes.slice",
   111  		},
   112  		{
   113  			inputSlice:  "user.slice",
   114  			inputGroup:  "my-group-dashes.slice",
   115  			expectedOut: "/sys/fs/cgroup/user.slice/my.slice/my-group.slice/my-group-dashes.slice",
   116  		},
   117  		{
   118  			inputSlice:  "user.slice",
   119  			inputGroup:  "myGroup.scope",
   120  			expectedOut: "/sys/fs/cgroup/user.slice/myGroup.scope",
   121  		},
   122  		{
   123  			inputSlice:  "user.slice",
   124  			inputGroup:  "my-group-dashes.scope",
   125  			expectedOut: "/sys/fs/cgroup/user.slice/my-group-dashes.scope",
   126  		},
   127  		{
   128  			inputSlice:  "test-waldo.slice",
   129  			inputGroup:  "my-group.slice",
   130  			expectedOut: "/sys/fs/cgroup/test.slice/test-waldo.slice/my.slice/my-group.slice",
   131  		},
   132  		{
   133  			inputSlice:  "test-waldo.slice",
   134  			inputGroup:  "my.service",
   135  			expectedOut: "/sys/fs/cgroup/test.slice/test-waldo.slice/my.service",
   136  		},
   137  	}
   138  
   139  	for _, test := range tests {
   140  		actual := getSystemdFullPath(test.inputSlice, test.inputGroup)
   141  		assert.Equal(t, test.expectedOut, actual)
   142  	}
   143  }
   144  
   145  func TestMoveTo(t *testing.T) {
   146  	checkCgroupMode(t)
   147  	manager, err := NewManager(defaultCgroup2Path, "/test1", ToResources(&specs.LinuxResources{}))
   148  	if err != nil {
   149  		t.Error(err)
   150  		return
   151  	}
   152  	proc := os.Getpid()
   153  	if err := manager.AddProc(uint64(proc)); err != nil {
   154  		t.Error(err)
   155  		return
   156  	}
   157  	destination, err := NewManager(defaultCgroup2Path, "/test2", ToResources(&specs.LinuxResources{}))
   158  	if err != nil {
   159  		t.Error(err)
   160  		return
   161  	}
   162  	if err := manager.MoveTo(destination); err != nil {
   163  		t.Error(err)
   164  		return
   165  	}
   166  	desProcs, err := destination.Procs(true)
   167  	desMap := make(map[int]bool)
   168  	for _, p := range desProcs {
   169  		desMap[int(p)] = true
   170  	}
   171  	if !desMap[proc] {
   172  		t.Errorf("process %v not in destination cgroup", proc)
   173  		return
   174  	}
   175  }
   176  

View as plain text