github.com/tetratelabs/wazero@v1.2.1/internal/sys/sys_test.go (about)

     1  package sys
     2  
     3  import (
     4  	"bytes"
     5  	"testing"
     6  	"time"
     7  
     8  	"github.com/tetratelabs/wazero/internal/fstest"
     9  	"github.com/tetratelabs/wazero/internal/platform"
    10  	"github.com/tetratelabs/wazero/internal/sysfs"
    11  	"github.com/tetratelabs/wazero/internal/testing/require"
    12  	"github.com/tetratelabs/wazero/sys"
    13  )
    14  
    15  func TestContext_WalltimeNanos(t *testing.T) {
    16  	sysCtx := DefaultContext(nil)
    17  
    18  	require.Equal(t, int64(1640995200000000000), sysCtx.WalltimeNanos())
    19  }
    20  
    21  func TestDefaultSysContext(t *testing.T) {
    22  	testFS := sysfs.Adapt(fstest.FS)
    23  
    24  	sysCtx, err := NewContext(0, nil, nil, nil, nil, nil, nil, nil, 0, nil, 0, nil, nil, testFS, nil)
    25  	require.NoError(t, err)
    26  
    27  	require.Nil(t, sysCtx.Args())
    28  	require.Zero(t, sysCtx.ArgsSize())
    29  	require.Nil(t, sysCtx.Environ())
    30  	require.Zero(t, sysCtx.EnvironSize())
    31  	// To compare functions, we can only compare pointers, but the pointer will
    32  	// change. Hence, we have to compare the results instead.
    33  	sec, _ := sysCtx.Walltime()
    34  	require.Equal(t, platform.FakeEpochNanos/time.Second.Nanoseconds(), sec)
    35  	require.Equal(t, sys.ClockResolution(1_000), sysCtx.WalltimeResolution())
    36  	require.Zero(t, sysCtx.Nanotime()) // See above on functions.
    37  	require.Equal(t, sys.ClockResolution(1), sysCtx.NanotimeResolution())
    38  	require.Equal(t, platform.FakeNanosleep, sysCtx.nanosleep)
    39  	require.Equal(t, platform.NewFakeRandSource(), sysCtx.RandSource())
    40  
    41  	expected := FileTable{}
    42  	noopStdin, _ := stdinFileEntry(nil)
    43  	expected.Insert(noopStdin)
    44  	noopStdout, _ := stdioWriterFileEntry("stdout", nil)
    45  	expected.Insert(noopStdout)
    46  	noopStderr, _ := stdioWriterFileEntry("stderr", nil)
    47  	expected.Insert(noopStderr)
    48  	expected.Insert(&FileEntry{
    49  		IsPreopen: true,
    50  		Name:      "/",
    51  		FS:        testFS,
    52  		File:      &lazyDir{fs: testFS},
    53  	})
    54  	require.Equal(t, expected, sysCtx.FS().openedFiles)
    55  }
    56  
    57  func TestNewContext_Args(t *testing.T) {
    58  	tests := []struct {
    59  		name         string
    60  		args         [][]byte
    61  		maxSize      uint32
    62  		expectedSize uint32
    63  		expectedErr  string
    64  	}{
    65  		{
    66  			name:         "ok",
    67  			maxSize:      10,
    68  			args:         [][]byte{[]byte("a"), []byte("bc")},
    69  			expectedSize: 5,
    70  		},
    71  		{
    72  			name:        "exceeds max count",
    73  			maxSize:     1,
    74  			args:        [][]byte{[]byte("a"), []byte("bc")},
    75  			expectedErr: "args invalid: exceeds maximum count",
    76  		},
    77  		{
    78  			name:        "exceeds max size",
    79  			maxSize:     4,
    80  			args:        [][]byte{[]byte("a"), []byte("bc")},
    81  			expectedErr: "args invalid: exceeds maximum size",
    82  		},
    83  		{
    84  			name:        "null character",
    85  			maxSize:     10,
    86  			args:        [][]byte{[]byte("a"), {'b', 0}},
    87  			expectedErr: "args invalid: contains NUL character",
    88  		},
    89  	}
    90  
    91  	for _, tt := range tests {
    92  		tc := tt
    93  
    94  		t.Run(tc.name, func(t *testing.T) {
    95  			sysCtx, err := NewContext(tc.maxSize, tc.args, nil, bytes.NewReader(make([]byte, 0)), nil, nil, nil, nil, 0, nil, 0, nil, nil, nil, nil)
    96  			if tc.expectedErr == "" {
    97  				require.Nil(t, err)
    98  				require.Equal(t, tc.args, sysCtx.Args())
    99  				require.Equal(t, tc.expectedSize, sysCtx.ArgsSize())
   100  			} else {
   101  				require.EqualError(t, err, tc.expectedErr)
   102  			}
   103  		})
   104  	}
   105  }
   106  
   107  func TestNewContext_Environ(t *testing.T) {
   108  	tests := []struct {
   109  		name         string
   110  		environ      [][]byte
   111  		maxSize      uint32
   112  		expectedSize uint32
   113  		expectedErr  string
   114  	}{
   115  		{
   116  			name:         "ok",
   117  			maxSize:      10,
   118  			environ:      [][]byte{[]byte("a=b"), []byte("c=de")},
   119  			expectedSize: 9,
   120  		},
   121  		{
   122  			name:        "exceeds max count",
   123  			maxSize:     1,
   124  			environ:     [][]byte{[]byte("a=b"), []byte("c=de")},
   125  			expectedErr: "environ invalid: exceeds maximum count",
   126  		},
   127  		{
   128  			name:        "exceeds max size",
   129  			maxSize:     4,
   130  			environ:     [][]byte{[]byte("a=b"), []byte("c=de")},
   131  			expectedErr: "environ invalid: exceeds maximum size",
   132  		},
   133  		{
   134  			name:        "null character",
   135  			maxSize:     10,
   136  			environ:     [][]byte{[]byte("a=b"), append([]byte("c=d"), 0)},
   137  			expectedErr: "environ invalid: contains NUL character",
   138  		},
   139  	}
   140  
   141  	for _, tt := range tests {
   142  		tc := tt
   143  
   144  		t.Run(tc.name, func(t *testing.T) {
   145  			sysCtx, err := NewContext(tc.maxSize, nil, tc.environ, bytes.NewReader(make([]byte, 0)), nil, nil, nil, nil, 0, nil, 0, nil, nil, nil, nil)
   146  			if tc.expectedErr == "" {
   147  				require.Nil(t, err)
   148  				require.Equal(t, tc.environ, sysCtx.Environ())
   149  				require.Equal(t, tc.expectedSize, sysCtx.EnvironSize())
   150  			} else {
   151  				require.EqualError(t, err, tc.expectedErr)
   152  			}
   153  		})
   154  	}
   155  }
   156  
   157  func TestNewContext_Walltime(t *testing.T) {
   158  	tests := []struct {
   159  		name        string
   160  		time        sys.Walltime
   161  		resolution  sys.ClockResolution
   162  		expectedErr string
   163  	}{
   164  		{
   165  			name:       "ok",
   166  			time:       platform.NewFakeWalltime(),
   167  			resolution: 3,
   168  		},
   169  		{
   170  			name:        "invalid resolution",
   171  			time:        platform.NewFakeWalltime(),
   172  			resolution:  0,
   173  			expectedErr: "invalid Walltime resolution: 0",
   174  		},
   175  	}
   176  
   177  	for _, tt := range tests {
   178  		tc := tt
   179  
   180  		t.Run(tc.name, func(t *testing.T) {
   181  			sysCtx, err := NewContext(0, nil, nil, nil, nil, nil, nil, tc.time, tc.resolution, nil, 0, nil, nil, nil, nil)
   182  			if tc.expectedErr == "" {
   183  				require.Nil(t, err)
   184  				require.Equal(t, tc.time, sysCtx.walltime)
   185  				require.Equal(t, tc.resolution, sysCtx.WalltimeResolution())
   186  			} else {
   187  				require.EqualError(t, err, tc.expectedErr)
   188  			}
   189  		})
   190  	}
   191  }
   192  
   193  func TestNewContext_Nanotime(t *testing.T) {
   194  	tests := []struct {
   195  		name        string
   196  		time        sys.Nanotime
   197  		resolution  sys.ClockResolution
   198  		expectedErr string
   199  	}{
   200  		{
   201  			name:       "ok",
   202  			time:       platform.NewFakeNanotime(),
   203  			resolution: 3,
   204  		},
   205  		{
   206  			name:        "invalid resolution",
   207  			time:        platform.NewFakeNanotime(),
   208  			resolution:  0,
   209  			expectedErr: "invalid Nanotime resolution: 0",
   210  		},
   211  	}
   212  
   213  	for _, tt := range tests {
   214  		tc := tt
   215  
   216  		t.Run(tc.name, func(t *testing.T) {
   217  			sysCtx, err := NewContext(0, nil, nil, nil, nil, nil, nil, nil, 0, tc.time, tc.resolution, nil, nil, nil, nil)
   218  			if tc.expectedErr == "" {
   219  				require.Nil(t, err)
   220  				require.Equal(t, tc.time, sysCtx.nanotime)
   221  				require.Equal(t, tc.resolution, sysCtx.NanotimeResolution())
   222  			} else {
   223  				require.EqualError(t, err, tc.expectedErr)
   224  			}
   225  		})
   226  	}
   227  }
   228  
   229  func Test_clockResolutionInvalid(t *testing.T) {
   230  	tests := []struct {
   231  		name       string
   232  		resolution sys.ClockResolution
   233  		expected   bool
   234  	}{
   235  		{
   236  			name:       "ok",
   237  			resolution: 1,
   238  		},
   239  		{
   240  			name:       "zero",
   241  			resolution: 0,
   242  			expected:   true,
   243  		},
   244  		{
   245  			name:       "too big",
   246  			resolution: sys.ClockResolution(time.Hour.Nanoseconds() * 2),
   247  			expected:   true,
   248  		},
   249  	}
   250  
   251  	for _, tt := range tests {
   252  		tc := tt
   253  
   254  		t.Run(tc.name, func(t *testing.T) {
   255  			require.Equal(t, tc.expected, clockResolutionInvalid(tc.resolution))
   256  		})
   257  	}
   258  }
   259  
   260  func TestNewContext_Nanosleep(t *testing.T) {
   261  	var aNs sys.Nanosleep = func(int64) {}
   262  	sysCtx, err := NewContext(0, nil, nil, nil, nil, nil, nil, nil, 0, nil, 0, aNs, nil, nil, nil)
   263  	require.Nil(t, err)
   264  	require.Equal(t, aNs, sysCtx.nanosleep)
   265  }
   266  
   267  func TestNewContext_Osyield(t *testing.T) {
   268  	var oy sys.Osyield = func() {}
   269  	sysCtx, err := NewContext(0, nil, nil, nil, nil, nil, nil, nil, 0, nil, 0, nil, oy, nil, nil)
   270  	require.Nil(t, err)
   271  	require.Equal(t, oy, sysCtx.osyield)
   272  }