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 }