gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/pkg/sentry/control/proc_test.go (about)

     1  // Copyright 2018 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package control
    16  
    17  import (
    18  	"testing"
    19  
    20  	"gvisor.dev/gvisor/pkg/log"
    21  	ktime "gvisor.dev/gvisor/pkg/sentry/kernel/time"
    22  	"gvisor.dev/gvisor/pkg/sentry/usage"
    23  )
    24  
    25  func init() {
    26  	log.SetLevel(log.Debug)
    27  }
    28  
    29  // Tests that ProcessData.Table() prints with the correct format.
    30  func TestProcessListTable(t *testing.T) {
    31  	testCases := []struct {
    32  		pl       []*Process
    33  		expected string
    34  	}{
    35  		{
    36  			pl:       []*Process{},
    37  			expected: "UID       PID       PPID      C         TTY       STIME     TIME      CMD",
    38  		},
    39  		{
    40  			pl: []*Process{
    41  				{
    42  					UID:   0,
    43  					PID:   0,
    44  					PPID:  0,
    45  					C:     0,
    46  					TTY:   "?",
    47  					STime: "0",
    48  					Time:  "0",
    49  					Cmd:   "zero",
    50  				},
    51  				{
    52  					UID:   1,
    53  					PID:   1,
    54  					PPID:  1,
    55  					C:     1,
    56  					TTY:   "pts/4",
    57  					STime: "1",
    58  					Time:  "1",
    59  					Cmd:   "one",
    60  				},
    61  			},
    62  			expected: `UID       PID       PPID      C         TTY       STIME     TIME      CMD
    63  0         0         0         0         ?         0         0         zero
    64  1         1         1         1         pts/4     1         1         one`,
    65  		},
    66  	}
    67  
    68  	for _, tc := range testCases {
    69  		output := ProcessListToTable(tc.pl)
    70  
    71  		if tc.expected != output {
    72  			t.Errorf("PrintTable(%v): got:\n%s\nwant:\n%s", tc.pl, output, tc.expected)
    73  		}
    74  	}
    75  }
    76  
    77  func TestProcessListJSON(t *testing.T) {
    78  	testCases := []struct {
    79  		pl       []*Process
    80  		expected string
    81  	}{
    82  		{
    83  			pl:       []*Process{},
    84  			expected: "[]",
    85  		},
    86  		{
    87  			pl: []*Process{
    88  				{
    89  					UID:   0,
    90  					PID:   0,
    91  					PPID:  0,
    92  					C:     0,
    93  					STime: "0",
    94  					Time:  "0",
    95  					Cmd:   "zero",
    96  				},
    97  				{
    98  					UID:   1,
    99  					PID:   1,
   100  					PPID:  1,
   101  					C:     1,
   102  					STime: "1",
   103  					Time:  "1",
   104  					Cmd:   "one",
   105  				},
   106  			},
   107  			expected: "[0,1]",
   108  		},
   109  	}
   110  
   111  	for _, tc := range testCases {
   112  		output, err := PrintPIDsJSON(tc.pl)
   113  		if err != nil {
   114  			t.Errorf("failed to generate JSON: %v", err)
   115  		}
   116  
   117  		if tc.expected != output {
   118  			t.Errorf("PrintJSON(%v): got:\n%s\nwant:\n%s", tc.pl, output, tc.expected)
   119  		}
   120  	}
   121  }
   122  
   123  func TestPercentCPU(t *testing.T) {
   124  	testCases := []struct {
   125  		stats     usage.CPUStats
   126  		startTime ktime.Time
   127  		now       ktime.Time
   128  		expected  int32
   129  	}{
   130  		{
   131  			// Verify that 100% use is capped at 99.
   132  			stats:     usage.CPUStats{UserTime: 1e9, SysTime: 1e9},
   133  			startTime: ktime.FromNanoseconds(7e9),
   134  			now:       ktime.FromNanoseconds(9e9),
   135  			expected:  99,
   136  		},
   137  		{
   138  			// Verify that if usage > lifetime, we get at most 99%
   139  			// usage.
   140  			stats:     usage.CPUStats{UserTime: 2e9, SysTime: 2e9},
   141  			startTime: ktime.FromNanoseconds(7e9),
   142  			now:       ktime.FromNanoseconds(9e9),
   143  			expected:  99,
   144  		},
   145  		{
   146  			// Verify that 50% usage is reported correctly.
   147  			stats:     usage.CPUStats{UserTime: 1e9, SysTime: 1e9},
   148  			startTime: ktime.FromNanoseconds(12e9),
   149  			now:       ktime.FromNanoseconds(16e9),
   150  			expected:  50,
   151  		},
   152  		{
   153  			// Verify that 0% usage is reported correctly.
   154  			stats:     usage.CPUStats{UserTime: 0, SysTime: 0},
   155  			startTime: ktime.FromNanoseconds(12e9),
   156  			now:       ktime.FromNanoseconds(14e9),
   157  			expected:  0,
   158  		},
   159  	}
   160  
   161  	for _, tc := range testCases {
   162  		if pcpu := percentCPU(tc.stats, tc.startTime, tc.now); pcpu != tc.expected {
   163  			t.Errorf("percentCPU(%v, %v, %v): got %d, want %d", tc.stats, tc.startTime, tc.now, pcpu, tc.expected)
   164  		}
   165  	}
   166  }