Stop using pointer of function pointers in sys.Context (#1301)
Signed-off-by: Takeshi Yoneda <takeshi@tetrate.io>
This commit is contained in:
16
config.go
16
config.go
@@ -609,12 +609,12 @@ type moduleConfig struct {
|
||||
stdout io.Writer
|
||||
stderr io.Writer
|
||||
randSource io.Reader
|
||||
walltime *sys.Walltime
|
||||
walltime sys.Walltime
|
||||
walltimeResolution sys.ClockResolution
|
||||
nanotime *sys.Nanotime
|
||||
nanotime sys.Nanotime
|
||||
nanotimeResolution sys.ClockResolution
|
||||
nanosleep *sys.Nanosleep
|
||||
osyield *sys.Osyield
|
||||
nanosleep sys.Nanosleep
|
||||
osyield sys.Osyield
|
||||
args [][]byte
|
||||
// environ is pair-indexed to retain order similar to os.Environ.
|
||||
environ [][]byte
|
||||
@@ -728,7 +728,7 @@ func (c *moduleConfig) WithStdout(stdout io.Writer) ModuleConfig {
|
||||
// WithWalltime implements ModuleConfig.WithWalltime
|
||||
func (c *moduleConfig) WithWalltime(walltime sys.Walltime, resolution sys.ClockResolution) ModuleConfig {
|
||||
ret := c.clone()
|
||||
ret.walltime = &walltime
|
||||
ret.walltime = walltime
|
||||
ret.walltimeResolution = resolution
|
||||
return ret
|
||||
}
|
||||
@@ -745,7 +745,7 @@ func (c *moduleConfig) WithSysWalltime() ModuleConfig {
|
||||
// WithNanotime implements ModuleConfig.WithNanotime
|
||||
func (c *moduleConfig) WithNanotime(nanotime sys.Nanotime, resolution sys.ClockResolution) ModuleConfig {
|
||||
ret := c.clone()
|
||||
ret.nanotime = &nanotime
|
||||
ret.nanotime = nanotime
|
||||
ret.nanotimeResolution = resolution
|
||||
return ret
|
||||
}
|
||||
@@ -758,14 +758,14 @@ func (c *moduleConfig) WithSysNanotime() ModuleConfig {
|
||||
// WithNanosleep implements ModuleConfig.WithNanosleep
|
||||
func (c *moduleConfig) WithNanosleep(nanosleep sys.Nanosleep) ModuleConfig {
|
||||
ret := *c // copy
|
||||
ret.nanosleep = &nanosleep
|
||||
ret.nanosleep = nanosleep
|
||||
return &ret
|
||||
}
|
||||
|
||||
// WithOsyield implements ModuleConfig.WithOsyield
|
||||
func (c *moduleConfig) WithOsyield(osyield sys.Osyield) ModuleConfig {
|
||||
ret := *c // copy
|
||||
ret.osyield = &osyield
|
||||
ret.osyield = osyield
|
||||
return &ret
|
||||
}
|
||||
|
||||
|
||||
417
config_test.go
417
config_test.go
@@ -1,12 +1,11 @@
|
||||
package wazero
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/rand"
|
||||
_ "embed"
|
||||
"io"
|
||||
"math"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/tetratelabs/wazero/api"
|
||||
"github.com/tetratelabs/wazero/internal/fstest"
|
||||
@@ -163,260 +162,214 @@ func TestModuleConfig(t *testing.T) {
|
||||
// TestModuleConfig_toSysContext only tests the cases that change the inputs to
|
||||
// sys.NewContext.
|
||||
func TestModuleConfig_toSysContext(t *testing.T) {
|
||||
// Always assigns clocks so that pointers are constant.
|
||||
var wt sys.Walltime = func() (int64, int32) {
|
||||
return 0, 0
|
||||
}
|
||||
var nt sys.Nanotime = func() int64 {
|
||||
return 0
|
||||
}
|
||||
base := NewModuleConfig()
|
||||
base.(*moduleConfig).walltime = &wt
|
||||
base.(*moduleConfig).walltimeResolution = 1
|
||||
base.(*moduleConfig).nanotime = &nt
|
||||
base.(*moduleConfig).nanotimeResolution = 1
|
||||
|
||||
testFS := testfs.FS{}
|
||||
testFS2 := testfs.FS{"/": &testfs.File{}}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
input ModuleConfig
|
||||
expected *internalsys.Context
|
||||
input func() (mc ModuleConfig, verify func(t *testing.T, sys *internalsys.Context))
|
||||
}{
|
||||
{
|
||||
name: "empty",
|
||||
input: base,
|
||||
expected: requireSysContext(t,
|
||||
math.MaxUint32, // max
|
||||
nil, // args
|
||||
nil, // environ
|
||||
nil, // stdin
|
||||
nil, // stdout
|
||||
nil, // stderr
|
||||
nil, // randSource
|
||||
&wt, 1, // walltime, walltimeResolution
|
||||
&nt, 1, // nanotime, nanotimeResolution
|
||||
nil, // nanosleep
|
||||
nil, // osyield
|
||||
nil, // fs
|
||||
),
|
||||
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
|
||||
return base, func(t *testing.T, sys *internalsys.Context) { require.NotNil(t, sys) }
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "WithNanotime",
|
||||
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
|
||||
config := base.WithNanotime(func() int64 { return 1234567 }, 54321)
|
||||
return config, func(t *testing.T, sys *internalsys.Context) {
|
||||
require.Equal(t, 1234567, int(sys.Nanotime()))
|
||||
require.Equal(t, 54321, int(sys.NanotimeResolution()))
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "WithSysNanotime",
|
||||
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
|
||||
config := base.WithSysNanotime()
|
||||
return config, func(t *testing.T, sys *internalsys.Context) {
|
||||
require.Equal(t, int(1), int(sys.NanotimeResolution()))
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "WithWalltime",
|
||||
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
|
||||
config := base.WithWalltime(func() (sec int64, nsec int32) { return 5, 10 }, 54321)
|
||||
return config, func(t *testing.T, sys *internalsys.Context) {
|
||||
actualSec, actualNano := sys.Walltime()
|
||||
require.Equal(t, 5, int(actualSec))
|
||||
require.Equal(t, 10, int(actualNano))
|
||||
require.Equal(t, 54321, int(sys.WalltimeResolution()))
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "WithSysWalltime",
|
||||
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
|
||||
config := base.WithSysWalltime()
|
||||
return config, func(t *testing.T, sys *internalsys.Context) {
|
||||
require.Equal(t, int(time.Microsecond.Nanoseconds()), int(sys.WalltimeResolution()))
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "WithArgs empty",
|
||||
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
|
||||
config := base.WithArgs()
|
||||
return config, func(t *testing.T, sys *internalsys.Context) {
|
||||
args := sys.Args()
|
||||
require.Equal(t, 0, len(args))
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "WithArgs",
|
||||
input: base.WithArgs("a", "bc"),
|
||||
expected: requireSysContext(t,
|
||||
math.MaxUint32, // max
|
||||
[]string{"a", "bc"}, // args
|
||||
nil, // environ
|
||||
nil, // stdin
|
||||
nil, // stdout
|
||||
nil, // stderr
|
||||
nil, // randSource
|
||||
&wt, 1, // walltime, walltimeResolution
|
||||
&nt, 1, // nanotime, nanotimeResolution
|
||||
nil, // nanosleep
|
||||
nil, // osyield
|
||||
nil, // fs
|
||||
),
|
||||
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
|
||||
config := base.WithArgs("a", "bc")
|
||||
return config, func(t *testing.T, sys *internalsys.Context) {
|
||||
args := sys.Args()
|
||||
require.Equal(t, 2, len(args))
|
||||
require.Equal(t, "a", string(args[0]))
|
||||
require.Equal(t, "bc", string(args[1]))
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "WithArgs empty ok", // Particularly argv[0] can be empty, and we have no rules about others.
|
||||
input: base.WithArgs("", "bc"),
|
||||
expected: requireSysContext(t,
|
||||
math.MaxUint32, // max
|
||||
[]string{"", "bc"}, // args
|
||||
nil, // environ
|
||||
nil, // stdin
|
||||
nil, // stdout
|
||||
nil, // stderr
|
||||
nil, // randSource
|
||||
&wt, 1, // walltime, walltimeResolution
|
||||
&nt, 1, // nanotime, nanotimeResolution
|
||||
nil, // nanosleep
|
||||
nil, // osyield
|
||||
nil, // fs
|
||||
),
|
||||
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
|
||||
config := base.WithArgs("", "bc")
|
||||
return config, func(t *testing.T, sys *internalsys.Context) {
|
||||
args := sys.Args()
|
||||
require.Equal(t, 2, len(args))
|
||||
require.Equal(t, "", string(args[0]))
|
||||
require.Equal(t, "bc", string(args[1]))
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "WithArgs second call overwrites",
|
||||
input: base.WithArgs("a", "bc").WithArgs("bc", "a"),
|
||||
expected: requireSysContext(t,
|
||||
math.MaxUint32, // max
|
||||
[]string{"bc", "a"}, // args
|
||||
nil, // environ
|
||||
nil, // stdin
|
||||
nil, // stdout
|
||||
nil, // stderr
|
||||
nil, // randSource
|
||||
&wt, 1, // walltime, walltimeResolution
|
||||
&nt, 1, // nanotime, nanotimeResolution
|
||||
nil, // nanosleep
|
||||
nil, // osyield
|
||||
nil, // fs
|
||||
),
|
||||
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
|
||||
config := base.WithArgs("a", "bc").WithArgs("bc", "a")
|
||||
return config, func(t *testing.T, sys *internalsys.Context) {
|
||||
args := sys.Args()
|
||||
require.Equal(t, 2, len(args))
|
||||
require.Equal(t, "bc", string(args[0]))
|
||||
require.Equal(t, "a", string(args[1]))
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "WithEnv",
|
||||
input: base.WithEnv("a", "b"),
|
||||
expected: requireSysContext(t,
|
||||
math.MaxUint32, // max
|
||||
nil, // args
|
||||
[]string{"a=b"}, // environ
|
||||
nil, // stdin
|
||||
nil, // stdout
|
||||
nil, // stderr
|
||||
nil, // randSource
|
||||
&wt, 1, // walltime, walltimeResolution
|
||||
&nt, 1, // nanotime, nanotimeResolution
|
||||
nil, // nanosleep
|
||||
nil, // osyield
|
||||
nil, // fs
|
||||
),
|
||||
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
|
||||
config := base.WithEnv("a", "b")
|
||||
return config, func(t *testing.T, sys *internalsys.Context) {
|
||||
envs := sys.Environ()
|
||||
require.Equal(t, 1, len(envs))
|
||||
require.Equal(t, "a=b", string(envs[0]))
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "WithEnv empty value",
|
||||
input: base.WithEnv("a", ""),
|
||||
expected: requireSysContext(t,
|
||||
math.MaxUint32, // max
|
||||
nil, // args
|
||||
[]string{"a="}, // environ
|
||||
nil, // stdin
|
||||
nil, // stdout
|
||||
nil, // stderr
|
||||
nil, // randSource
|
||||
&wt, 1, // walltime, walltimeResolution
|
||||
&nt, 1, // nanotime, nanotimeResolution
|
||||
nil, // nanosleep
|
||||
nil, // osyield
|
||||
nil, // fs
|
||||
),
|
||||
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
|
||||
config := base.WithEnv("a", "")
|
||||
return config, func(t *testing.T, sys *internalsys.Context) {
|
||||
envs := sys.Environ()
|
||||
require.Equal(t, 1, len(envs))
|
||||
require.Equal(t, "a=", string(envs[0]))
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "WithEnv twice",
|
||||
input: base.WithEnv("a", "b").WithEnv("c", "de"),
|
||||
expected: requireSysContext(t,
|
||||
math.MaxUint32, // max
|
||||
nil, // args
|
||||
[]string{"a=b", "c=de"}, // environ
|
||||
nil, // stdin
|
||||
nil, // stdout
|
||||
nil, // stderr
|
||||
nil, // randSource
|
||||
&wt, 1, // walltime, walltimeResolution
|
||||
&nt, 1, // nanotime, nanotimeResolution
|
||||
nil, // nanosleep
|
||||
nil, // osyield
|
||||
nil, // fs
|
||||
),
|
||||
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
|
||||
config := base.WithEnv("a", "b").WithEnv("c", "de")
|
||||
return config, func(t *testing.T, sys *internalsys.Context) {
|
||||
envs := sys.Environ()
|
||||
require.Equal(t, 2, len(envs))
|
||||
require.Equal(t, "a=b", string(envs[0]))
|
||||
require.Equal(t, "c=de", string(envs[1]))
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "WithEnv overwrites",
|
||||
input: base.WithEnv("a", "bc").WithEnv("c", "de").WithEnv("a", "de"),
|
||||
expected: requireSysContext(t,
|
||||
math.MaxUint32, // max
|
||||
nil, // args
|
||||
[]string{"a=de", "c=de"}, // environ
|
||||
nil, // stdin
|
||||
nil, // stdout
|
||||
nil, // stderr
|
||||
nil, // randSource
|
||||
&wt, 1, // walltime, walltimeResolution
|
||||
&nt, 1, // nanotime, nanotimeResolution
|
||||
nil, // nanosleep
|
||||
nil, // osyield
|
||||
nil, // fs
|
||||
),
|
||||
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
|
||||
config := base.WithEnv("a", "bc").WithEnv("c", "de").WithEnv("a", "ff")
|
||||
return config, func(t *testing.T, sys *internalsys.Context) {
|
||||
envs := sys.Environ()
|
||||
require.Equal(t, 2, len(envs))
|
||||
require.Equal(t, "a=ff", string(envs[0]))
|
||||
require.Equal(t, "c=de", string(envs[1]))
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "WithEnv twice",
|
||||
input: base.WithEnv("a", "b").WithEnv("c", "de"),
|
||||
expected: requireSysContext(t,
|
||||
math.MaxUint32, // max
|
||||
nil, // args
|
||||
[]string{"a=b", "c=de"}, // environ
|
||||
nil, // stdin
|
||||
nil, // stdout
|
||||
nil, // stderr
|
||||
nil, // randSource
|
||||
&wt, 1, // walltime, walltimeResolution
|
||||
&nt, 1, // nanotime, nanotimeResolution
|
||||
nil, // nanosleep
|
||||
nil, // osyield
|
||||
nil, // fs
|
||||
),
|
||||
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
|
||||
config := base.WithEnv("a", "b").WithEnv("c", "de")
|
||||
return config, func(t *testing.T, sys *internalsys.Context) {
|
||||
envs := sys.Environ()
|
||||
require.Equal(t, 2, len(envs))
|
||||
require.Equal(t, "a=b", string(envs[0]))
|
||||
require.Equal(t, "c=de", string(envs[1]))
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "WithFS",
|
||||
input: base.WithFS(testFS),
|
||||
expected: requireSysContext(t,
|
||||
math.MaxUint32, // max
|
||||
nil, // args
|
||||
nil, // environ
|
||||
nil, // stdin
|
||||
nil, // stdout
|
||||
nil, // stderr
|
||||
nil, // randSource
|
||||
&wt, 1, // walltime, walltimeResolution
|
||||
&nt, 1, // nanotime, nanotimeResolution
|
||||
nil, // nanosleep
|
||||
nil, // osyield
|
||||
sysfs.Adapt(testFS),
|
||||
),
|
||||
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
|
||||
testFS := &testfs.FS{}
|
||||
config := base.WithFS(testFS)
|
||||
return config, func(t *testing.T, sys *internalsys.Context) {
|
||||
rootfs := sys.FS().RootFS()
|
||||
require.Equal(t, sysfs.Adapt(testFS), rootfs)
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "WithFS overwrites",
|
||||
input: base.WithFS(testFS).WithFS(testFS2),
|
||||
expected: requireSysContext(t,
|
||||
math.MaxUint32, // max
|
||||
nil, // args
|
||||
nil, // environ
|
||||
nil, // stdin
|
||||
nil, // stdout
|
||||
nil, // stderr
|
||||
nil, // randSource
|
||||
&wt, 1, // walltime, walltimeResolution
|
||||
&nt, 1, // nanotime, nanotimeResolution
|
||||
nil, // nanosleep
|
||||
nil, // osyield
|
||||
sysfs.Adapt(testFS2), // fs
|
||||
),
|
||||
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
|
||||
testFS, testFS2 := &testfs.FS{}, &testfs.FS{}
|
||||
config := base.WithFS(testFS).WithFS(testFS2)
|
||||
return config, func(t *testing.T, sys *internalsys.Context) {
|
||||
rootfs := sys.FS().RootFS()
|
||||
require.Equal(t, sysfs.Adapt(testFS2), rootfs)
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "WithFS nil",
|
||||
input: base.WithFS(nil),
|
||||
expected: requireSysContext(t,
|
||||
math.MaxUint32, // max
|
||||
nil, // args
|
||||
nil, // environ
|
||||
nil, // stdin
|
||||
nil, // stdout
|
||||
nil, // stderr
|
||||
nil, // randSource
|
||||
&wt, 1, // walltime, walltimeResolution
|
||||
&nt, 1, // nanotime, nanotimeResolution
|
||||
nil, // nanosleep
|
||||
nil, // osyield
|
||||
nil, // fs
|
||||
),
|
||||
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
|
||||
config := base.WithFS(nil)
|
||||
return config, func(t *testing.T, sys *internalsys.Context) {
|
||||
rootfs := sys.FS().RootFS()
|
||||
require.Equal(t, sysfs.Adapt(nil), rootfs)
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "WithRandSource",
|
||||
input: base.WithRandSource(rand.Reader),
|
||||
expected: requireSysContext(t,
|
||||
math.MaxUint32, // max
|
||||
nil, // args
|
||||
nil, // environ
|
||||
nil, // stdin
|
||||
nil, // stdout
|
||||
nil, // stderr
|
||||
rand.Reader, // randSource
|
||||
&wt, 1, // walltime, walltimeResolution
|
||||
&nt, 1, // nanotime, nanotimeResolution
|
||||
nil, // nanosleep
|
||||
nil, // osyield
|
||||
nil, // fs
|
||||
),
|
||||
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
|
||||
r := bytes.NewReader([]byte{1, 2, 3, 4})
|
||||
config := base.WithRandSource(r)
|
||||
return config, func(t *testing.T, sys *internalsys.Context) {
|
||||
actual := sys.RandSource()
|
||||
require.Equal(t, r, actual)
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "WithRandSource nil",
|
||||
input: func() (ModuleConfig, func(t *testing.T, sys *internalsys.Context)) {
|
||||
config := base.WithRandSource(nil)
|
||||
return config, func(t *testing.T, sys *internalsys.Context) {
|
||||
actual := sys.RandSource()
|
||||
require.Equal(t, platform.NewFakeRandSource(), actual)
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -424,9 +377,10 @@ func TestModuleConfig_toSysContext(t *testing.T) {
|
||||
tc := tt
|
||||
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
sysCtx, err := tc.input.(*moduleConfig).toSysContext()
|
||||
config, verify := tc.input()
|
||||
actual, err := config.(*moduleConfig).toSysContext()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tc.expected, sysCtx)
|
||||
verify(t, actual)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -756,34 +710,3 @@ func TestNewRuntimeConfig(t *testing.T) {
|
||||
require.Equal(t, engineKindInterpreter, c.engineKind)
|
||||
}
|
||||
}
|
||||
|
||||
// requireSysContext ensures wasm.NewContext doesn't return an error, which makes it usable in test matrices.
|
||||
func requireSysContext(
|
||||
t *testing.T,
|
||||
max uint32,
|
||||
args, environ []string,
|
||||
stdin io.Reader,
|
||||
stdout, stderr io.Writer,
|
||||
randSource io.Reader,
|
||||
walltime *sys.Walltime, walltimeResolution sys.ClockResolution,
|
||||
nanotime *sys.Nanotime, nanotimeResolution sys.ClockResolution,
|
||||
nanosleep *sys.Nanosleep,
|
||||
osyield *sys.Osyield,
|
||||
fs sysfs.FS,
|
||||
) *internalsys.Context {
|
||||
sysCtx, err := internalsys.NewContext(
|
||||
max,
|
||||
toByteSlices(args),
|
||||
toByteSlices(environ),
|
||||
stdin,
|
||||
stdout,
|
||||
stderr,
|
||||
randSource,
|
||||
walltime, walltimeResolution,
|
||||
nanotime, nanotimeResolution,
|
||||
nanosleep, osyield,
|
||||
fs,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
return sysCtx
|
||||
}
|
||||
|
||||
@@ -15,32 +15,30 @@ const (
|
||||
|
||||
// NewFakeWalltime implements sys.Walltime with FakeEpochNanos that increases by 1ms each reading.
|
||||
// See /RATIONALE.md
|
||||
func NewFakeWalltime() *sys.Walltime {
|
||||
func NewFakeWalltime() sys.Walltime {
|
||||
// AddInt64 returns the new value. Adjust so the first reading will be FakeEpochNanos
|
||||
t := FakeEpochNanos - ms
|
||||
var wt sys.Walltime = func() (sec int64, nsec int32) {
|
||||
return func() (sec int64, nsec int32) {
|
||||
wt := atomic.AddInt64(&t, ms)
|
||||
return wt / 1e9, int32(wt % 1e9)
|
||||
}
|
||||
return &wt
|
||||
}
|
||||
|
||||
// NewFakeNanotime implements sys.Nanotime that increases by 1ms each reading.
|
||||
// See /RATIONALE.md
|
||||
func NewFakeNanotime() *sys.Nanotime {
|
||||
func NewFakeNanotime() sys.Nanotime {
|
||||
// AddInt64 returns the new value. Adjust so the first reading will be zero.
|
||||
t := int64(0) - ms
|
||||
var nt sys.Nanotime = func() int64 {
|
||||
return func() int64 {
|
||||
return atomic.AddInt64(&t, ms)
|
||||
}
|
||||
return &nt
|
||||
}
|
||||
|
||||
// FakeNanosleep implements sys.Nanosleep by returning without sleeping.
|
||||
func FakeNanosleep(int64) {}
|
||||
var FakeNanosleep = sys.Nanosleep(func(int64) {})
|
||||
|
||||
// FakeOsyield implements sys.Osyield by returning without yielding.
|
||||
func FakeOsyield() {}
|
||||
var FakeOsyield = sys.Osyield(func() {})
|
||||
|
||||
// Walltime implements sys.Walltime with time.Now.
|
||||
//
|
||||
|
||||
@@ -12,22 +12,22 @@ func Test_NewFakeWalltime(t *testing.T) {
|
||||
wt := NewFakeWalltime()
|
||||
|
||||
// Base should be the same as FakeEpochNanos
|
||||
sec, nsec := (*wt)()
|
||||
sec, nsec := wt()
|
||||
ft := time.UnixMicro(FakeEpochNanos / time.Microsecond.Nanoseconds()).UTC()
|
||||
require.Equal(t, ft, time.Unix(sec, int64(nsec)).UTC())
|
||||
|
||||
// next reading should increase by 1ms
|
||||
sec, nsec = (*wt)()
|
||||
sec, nsec = wt()
|
||||
require.Equal(t, ft.Add(time.Millisecond), time.Unix(sec, int64(nsec)).UTC())
|
||||
}
|
||||
|
||||
func Test_NewFakeNanotime(t *testing.T) {
|
||||
nt := NewFakeNanotime()
|
||||
|
||||
require.Equal(t, int64(0), (*nt)())
|
||||
require.Equal(t, int64(0), nt())
|
||||
|
||||
// next reading should increase by 1ms
|
||||
require.Equal(t, int64(time.Millisecond), (*nt)())
|
||||
require.Equal(t, int64(time.Millisecond), nt())
|
||||
}
|
||||
|
||||
func Test_Walltime(t *testing.T) {
|
||||
|
||||
@@ -252,32 +252,32 @@ type FileTable = descriptor.Table[uint32, *FileEntry]
|
||||
//
|
||||
// If `preopened` is not sysfs.UnimplementedFS, it is inserted into
|
||||
// the file descriptor table as FdPreopen.
|
||||
func NewFSContext(stdin io.Reader, stdout, stderr io.Writer, rootFS sysfs.FS) (fsc *FSContext, err error) {
|
||||
fsc = &FSContext{rootFS: rootFS}
|
||||
func (c *Context) NewFSContext(stdin io.Reader, stdout, stderr io.Writer, rootFS sysfs.FS) (err error) {
|
||||
c.fsc.rootFS = rootFS
|
||||
inReader, err := stdinReader(stdin)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
fsc.openedFiles.Insert(inReader)
|
||||
c.fsc.openedFiles.Insert(inReader)
|
||||
outWriter, err := stdioWriter(stdout, noopStdoutStat)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
fsc.openedFiles.Insert(outWriter)
|
||||
c.fsc.openedFiles.Insert(outWriter)
|
||||
errWriter, err := stdioWriter(stderr, noopStderrStat)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
fsc.openedFiles.Insert(errWriter)
|
||||
c.fsc.openedFiles.Insert(errWriter)
|
||||
|
||||
if _, ok := rootFS.(sysfs.UnimplementedFS); ok {
|
||||
return fsc, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
if comp, ok := rootFS.(*sysfs.CompositeFS); ok {
|
||||
preopens := comp.FS()
|
||||
for i, p := range comp.GuestPaths() {
|
||||
fsc.openedFiles.Insert(&FileEntry{
|
||||
c.fsc.openedFiles.Insert(&FileEntry{
|
||||
FS: preopens[i],
|
||||
Name: p,
|
||||
IsPreopen: true,
|
||||
@@ -285,7 +285,7 @@ func NewFSContext(stdin io.Reader, stdout, stderr io.Writer, rootFS sysfs.FS) (f
|
||||
})
|
||||
}
|
||||
} else {
|
||||
fsc.openedFiles.Insert(&FileEntry{
|
||||
c.fsc.openedFiles.Insert(&FileEntry{
|
||||
FS: rootFS,
|
||||
Name: "/",
|
||||
IsPreopen: true,
|
||||
@@ -293,7 +293,7 @@ func NewFSContext(stdin io.Reader, stdout, stderr io.Writer, rootFS sysfs.FS) (f
|
||||
})
|
||||
}
|
||||
|
||||
return fsc, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func stdinReader(r io.Reader) (*FileEntry, error) {
|
||||
|
||||
@@ -66,8 +66,10 @@ func TestNewFSContext(t *testing.T) {
|
||||
tc := tt
|
||||
|
||||
t.Run(tc.name, func(b *testing.T) {
|
||||
fsc, err := NewFSContext(nil, nil, nil, tc.fs)
|
||||
c := Context{}
|
||||
err := c.NewFSContext(nil, nil, nil, tc.fs)
|
||||
require.NoError(t, err)
|
||||
fsc := c.fsc
|
||||
defer fsc.Close(testCtx)
|
||||
|
||||
preopenedDir, _ := fsc.openedFiles.Lookup(FdPreopen)
|
||||
@@ -102,8 +104,10 @@ func TestFSContext_CloseFile(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
testFS := sysfs.Adapt(embedFS)
|
||||
|
||||
fsc, err := NewFSContext(nil, nil, nil, testFS)
|
||||
c := Context{}
|
||||
err = c.NewFSContext(nil, nil, nil, testFS)
|
||||
require.NoError(t, err)
|
||||
fsc := c.fsc
|
||||
defer fsc.Close(testCtx)
|
||||
|
||||
fdToClose, errno := fsc.OpenFile(testFS, "empty.txt", os.O_RDONLY, 0)
|
||||
@@ -132,7 +136,10 @@ func TestFSContext_CloseFile(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUnimplementedFSContext(t *testing.T) {
|
||||
testFS, err := NewFSContext(nil, nil, nil, sysfs.UnimplementedFS{})
|
||||
c := Context{}
|
||||
err := c.NewFSContext(nil, nil, nil, sysfs.UnimplementedFS{})
|
||||
require.NoError(t, err)
|
||||
testFS := &c.fsc
|
||||
require.NoError(t, err)
|
||||
|
||||
expected := &FSContext{rootFS: sysfs.UnimplementedFS{}}
|
||||
@@ -159,8 +166,10 @@ func TestCompositeFSContext(t *testing.T) {
|
||||
rootFS, err := sysfs.NewRootFS([]sysfs.FS{testFS2, testFS1}, []string{"/tmp", "/"})
|
||||
require.NoError(t, err)
|
||||
|
||||
testFS, err := NewFSContext(nil, nil, nil, rootFS)
|
||||
c := Context{}
|
||||
err = c.NewFSContext(nil, nil, nil, rootFS)
|
||||
require.NoError(t, err)
|
||||
testFS := &c.fsc
|
||||
|
||||
// Ensure the pre-opens have exactly the name specified, and are in order.
|
||||
preopen3, ok := testFS.openedFiles.Lookup(3)
|
||||
@@ -182,8 +191,10 @@ func TestCompositeFSContext(t *testing.T) {
|
||||
func TestContext_Close(t *testing.T) {
|
||||
testFS := sysfs.Adapt(testfs.FS{"foo": &testfs.File{}})
|
||||
|
||||
fsc, err := NewFSContext(nil, nil, nil, testFS)
|
||||
c := Context{}
|
||||
err := c.NewFSContext(nil, nil, nil, testFS)
|
||||
require.NoError(t, err)
|
||||
fsc := c.fsc
|
||||
|
||||
// Verify base case
|
||||
require.Equal(t, 1+FdPreopen, uint32(fsc.openedFiles.Len()))
|
||||
@@ -207,8 +218,10 @@ func TestContext_Close_Error(t *testing.T) {
|
||||
|
||||
testFS := sysfs.Adapt(testfs.FS{"foo": file})
|
||||
|
||||
fsc, err := NewFSContext(nil, nil, nil, testFS)
|
||||
c := Context{}
|
||||
err := c.NewFSContext(nil, nil, nil, testFS)
|
||||
require.NoError(t, err)
|
||||
fsc := c.fsc
|
||||
|
||||
// open another file
|
||||
_, errno := fsc.OpenFile(testFS, "foo", os.O_RDONLY, 0)
|
||||
@@ -228,7 +241,11 @@ func TestFSContext_ReOpenDir(t *testing.T) {
|
||||
errno := dirFs.Mkdir(dirName, 0o700)
|
||||
require.Zero(t, errno)
|
||||
|
||||
fsc, err := NewFSContext(nil, nil, nil, dirFs)
|
||||
c := Context{}
|
||||
err := c.NewFSContext(nil, nil, nil, dirFs)
|
||||
require.NoError(t, err)
|
||||
fsc := c.fsc
|
||||
|
||||
require.NoError(t, err)
|
||||
defer func() {
|
||||
require.NoError(t, fsc.Close(context.Background()))
|
||||
@@ -275,45 +292,48 @@ func TestFSContext_Renumber(t *testing.T) {
|
||||
errno := dirFs.Mkdir(dirName, 0o700)
|
||||
require.Zero(t, errno)
|
||||
|
||||
c, err := NewFSContext(nil, nil, nil, dirFs)
|
||||
c := Context{}
|
||||
err := c.NewFSContext(nil, nil, nil, dirFs)
|
||||
require.NoError(t, err)
|
||||
fsc := c.fsc
|
||||
|
||||
defer func() {
|
||||
require.NoError(t, c.Close(context.Background()))
|
||||
require.NoError(t, fsc.Close(context.Background()))
|
||||
}()
|
||||
|
||||
for _, toFd := range []uint32{10, 100, 100} {
|
||||
fromFd, errno := c.OpenFile(dirFs, dirName, os.O_RDONLY, 0)
|
||||
fromFd, errno := fsc.OpenFile(dirFs, dirName, os.O_RDONLY, 0)
|
||||
require.Zero(t, errno)
|
||||
|
||||
prevDirFile, ok := c.LookupFile(fromFd)
|
||||
prevDirFile, ok := fsc.LookupFile(fromFd)
|
||||
require.True(t, ok)
|
||||
|
||||
require.Zero(t, c.Renumber(fromFd, toFd))
|
||||
require.Zero(t, fsc.Renumber(fromFd, toFd))
|
||||
|
||||
renumberedDirFile, ok := c.LookupFile(toFd)
|
||||
renumberedDirFile, ok := fsc.LookupFile(toFd)
|
||||
require.True(t, ok)
|
||||
|
||||
require.Equal(t, prevDirFile, renumberedDirFile)
|
||||
|
||||
// Previous file descriptor shouldn't be used.
|
||||
_, ok = c.LookupFile(fromFd)
|
||||
_, ok = fsc.LookupFile(fromFd)
|
||||
require.False(t, ok)
|
||||
}
|
||||
|
||||
t.Run("errors", func(t *testing.T) {
|
||||
// Sanity check for 3 being preopen.
|
||||
preopen, ok := c.LookupFile(3)
|
||||
preopen, ok := fsc.LookupFile(3)
|
||||
require.True(t, ok)
|
||||
require.True(t, preopen.IsPreopen)
|
||||
|
||||
// From is preopen.
|
||||
require.Equal(t, syscall.ENOTSUP, c.Renumber(3, 100))
|
||||
require.Equal(t, syscall.ENOTSUP, fsc.Renumber(3, 100))
|
||||
|
||||
// From does not exist.
|
||||
require.Equal(t, syscall.EBADF, c.Renumber(12345, 3))
|
||||
require.Equal(t, syscall.EBADF, fsc.Renumber(12345, 3))
|
||||
|
||||
// Both are preopen.
|
||||
require.Equal(t, syscall.ENOTSUP, c.Renumber(3, 3))
|
||||
require.Equal(t, syscall.ENOTSUP, fsc.Renumber(3, 3))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -324,36 +344,41 @@ func TestFSContext_ChangeOpenFlag(t *testing.T) {
|
||||
const fileName = "dir"
|
||||
require.NoError(t, os.WriteFile(path.Join(tmpDir, fileName), []byte("0123456789"), 0o600))
|
||||
|
||||
c, errno := NewFSContext(nil, nil, nil, dirFs)
|
||||
require.NoError(t, errno)
|
||||
c := Context{}
|
||||
err := c.NewFSContext(nil, nil, nil, dirFs)
|
||||
require.NoError(t, err)
|
||||
fsc := c.fsc
|
||||
|
||||
defer func() {
|
||||
require.NoError(t, c.Close(context.Background()))
|
||||
require.NoError(t, fsc.Close(context.Background()))
|
||||
}()
|
||||
|
||||
// Without APPEND.
|
||||
fd, errno := c.OpenFile(dirFs, fileName, os.O_RDWR, 0o600)
|
||||
fd, errno := fsc.OpenFile(dirFs, fileName, os.O_RDWR, 0o600)
|
||||
require.Zero(t, errno)
|
||||
|
||||
f0, ok := c.openedFiles.Lookup(fd)
|
||||
f0, ok := fsc.openedFiles.Lookup(fd)
|
||||
require.True(t, ok)
|
||||
require.Equal(t, f0.openFlag&syscall.O_APPEND, 0)
|
||||
|
||||
// Set the APPEND flag.
|
||||
require.Zero(t, c.ChangeOpenFlag(fd, syscall.O_APPEND))
|
||||
f1, ok := c.openedFiles.Lookup(fd)
|
||||
require.Zero(t, fsc.ChangeOpenFlag(fd, syscall.O_APPEND))
|
||||
f1, ok := fsc.openedFiles.Lookup(fd)
|
||||
require.True(t, ok)
|
||||
require.Equal(t, f1.openFlag&syscall.O_APPEND, syscall.O_APPEND)
|
||||
|
||||
// Remove the APPEND flag.
|
||||
require.Zero(t, c.ChangeOpenFlag(fd, 0))
|
||||
f2, ok := c.openedFiles.Lookup(fd)
|
||||
require.Zero(t, fsc.ChangeOpenFlag(fd, 0))
|
||||
f2, ok := fsc.openedFiles.Lookup(fd)
|
||||
require.True(t, ok)
|
||||
require.Equal(t, f2.openFlag&syscall.O_APPEND, 0)
|
||||
}
|
||||
|
||||
func TestWriterForFile(t *testing.T) {
|
||||
testFS, err := NewFSContext(nil, nil, nil, sysfs.UnimplementedFS{})
|
||||
c := Context{}
|
||||
err := c.NewFSContext(nil, nil, nil, sysfs.UnimplementedFS{})
|
||||
require.NoError(t, err)
|
||||
testFS := &c.fsc
|
||||
|
||||
require.Nil(t, WriterForFile(testFS, FdStdin))
|
||||
require.Equal(t, noopStdout.File, WriterForFile(testFS, FdStdout))
|
||||
|
||||
@@ -17,16 +17,14 @@ type Context struct {
|
||||
args, environ [][]byte
|
||||
argsSize, environSize uint32
|
||||
|
||||
// Note: Using function pointers here keeps them stable for tests.
|
||||
|
||||
walltime *sys.Walltime
|
||||
walltime sys.Walltime
|
||||
walltimeResolution sys.ClockResolution
|
||||
nanotime *sys.Nanotime
|
||||
nanotime sys.Nanotime
|
||||
nanotimeResolution sys.ClockResolution
|
||||
nanosleep *sys.Nanosleep
|
||||
osyield *sys.Osyield
|
||||
nanosleep sys.Nanosleep
|
||||
osyield sys.Osyield
|
||||
randSource io.Reader
|
||||
fsc *FSContext
|
||||
fsc FSContext
|
||||
}
|
||||
|
||||
// Args is like os.Args and defaults to nil.
|
||||
@@ -65,7 +63,7 @@ func (c *Context) EnvironSize() uint32 {
|
||||
|
||||
// Walltime implements platform.Walltime.
|
||||
func (c *Context) Walltime() (sec int64, nsec int32) {
|
||||
return (*(c.walltime))()
|
||||
return c.walltime()
|
||||
}
|
||||
|
||||
// WalltimeNanos returns platform.Walltime as epoch nanoseconds.
|
||||
@@ -81,7 +79,7 @@ func (c *Context) WalltimeResolution() sys.ClockResolution {
|
||||
|
||||
// Nanotime implements sys.Nanotime.
|
||||
func (c *Context) Nanotime() int64 {
|
||||
return (*(c.nanotime))()
|
||||
return c.nanotime()
|
||||
}
|
||||
|
||||
// NanotimeResolution returns resolution of Nanotime.
|
||||
@@ -91,17 +89,17 @@ func (c *Context) NanotimeResolution() sys.ClockResolution {
|
||||
|
||||
// Nanosleep implements sys.Nanosleep.
|
||||
func (c *Context) Nanosleep(ns int64) {
|
||||
(*(c.nanosleep))(ns)
|
||||
c.nanosleep(ns)
|
||||
}
|
||||
|
||||
// Osyield implements sys.Osyield.
|
||||
func (c *Context) Osyield() {
|
||||
(*(c.osyield))()
|
||||
c.osyield()
|
||||
}
|
||||
|
||||
// FS returns the possibly empty (sysfs.UnimplementedFS) file system context.
|
||||
func (c *Context) FS() *FSContext {
|
||||
return c.fsc
|
||||
return &c.fsc
|
||||
}
|
||||
|
||||
// RandSource is a source of random bytes and defaults to a deterministic source.
|
||||
@@ -120,6 +118,8 @@ func (eofReader) Read([]byte) (int, error) {
|
||||
}
|
||||
|
||||
// DefaultContext returns Context with no values set except a possible nil fs.FS
|
||||
//
|
||||
// This is only used for testing.
|
||||
func DefaultContext(fs sysfs.FS) *Context {
|
||||
if sysCtx, err := NewContext(0, nil, nil, nil, nil, nil, nil, nil, 0, nil, 0, nil, nil, fs); err != nil {
|
||||
panic(fmt.Errorf("BUG: DefaultContext should never error: %w", err))
|
||||
@@ -128,12 +128,6 @@ func DefaultContext(fs sysfs.FS) *Context {
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
_ = DefaultContext(nil) // Force panic on bug.
|
||||
ns sys.Nanosleep = platform.FakeNanosleep
|
||||
oy sys.Osyield = platform.FakeOsyield
|
||||
)
|
||||
|
||||
// NewContext is a factory function which helps avoid needing to know defaults or exporting all fields.
|
||||
// Note: max is exposed for testing. max is only used for env/args validation.
|
||||
func NewContext(
|
||||
@@ -142,12 +136,12 @@ func NewContext(
|
||||
stdin io.Reader,
|
||||
stdout, stderr io.Writer,
|
||||
randSource io.Reader,
|
||||
walltime *sys.Walltime,
|
||||
walltime sys.Walltime,
|
||||
walltimeResolution sys.ClockResolution,
|
||||
nanotime *sys.Nanotime,
|
||||
nanotime sys.Nanotime,
|
||||
nanotimeResolution sys.ClockResolution,
|
||||
nanosleep *sys.Nanosleep,
|
||||
osyield *sys.Osyield,
|
||||
nanosleep sys.Nanosleep,
|
||||
osyield sys.Osyield,
|
||||
rootFS sysfs.FS,
|
||||
) (sysCtx *Context, err error) {
|
||||
sysCtx = &Context{args: args, environ: environ}
|
||||
@@ -191,19 +185,19 @@ func NewContext(
|
||||
if nanosleep != nil {
|
||||
sysCtx.nanosleep = nanosleep
|
||||
} else {
|
||||
sysCtx.nanosleep = &ns
|
||||
sysCtx.nanosleep = platform.FakeNanosleep
|
||||
}
|
||||
|
||||
if osyield != nil {
|
||||
sysCtx.osyield = osyield
|
||||
} else {
|
||||
sysCtx.osyield = &oy
|
||||
sysCtx.osyield = platform.FakeOsyield
|
||||
}
|
||||
|
||||
if rootFS != nil {
|
||||
sysCtx.fsc, err = NewFSContext(stdin, stdout, stderr, rootFS)
|
||||
err = sysCtx.NewFSContext(stdin, stdout, stderr, rootFS)
|
||||
} else {
|
||||
sysCtx.fsc, err = NewFSContext(stdin, stdout, stderr, sysfs.UnimplementedFS{})
|
||||
err = sysCtx.NewFSContext(stdin, stdout, stderr, sysfs.UnimplementedFS{})
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
@@ -15,15 +15,6 @@ import (
|
||||
"github.com/tetratelabs/wazero/sys"
|
||||
)
|
||||
|
||||
func TestContext_FS(t *testing.T) {
|
||||
sysCtx := DefaultContext(nil)
|
||||
|
||||
fsc, err := NewFSContext(nil, nil, nil, sysfs.UnimplementedFS{})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, fsc, sysCtx.FS())
|
||||
}
|
||||
|
||||
func TestContext_WalltimeNanos(t *testing.T) {
|
||||
sysCtx := DefaultContext(nil)
|
||||
|
||||
@@ -60,11 +51,9 @@ func TestDefaultSysContext(t *testing.T) {
|
||||
require.Equal(t, sys.ClockResolution(1_000), sysCtx.WalltimeResolution())
|
||||
require.Zero(t, sysCtx.Nanotime()) // See above on functions.
|
||||
require.Equal(t, sys.ClockResolution(1), sysCtx.NanotimeResolution())
|
||||
require.Equal(t, &ns, sysCtx.nanosleep)
|
||||
require.Equal(t, platform.FakeNanosleep, sysCtx.nanosleep)
|
||||
require.Equal(t, platform.NewFakeRandSource(), sysCtx.RandSource())
|
||||
|
||||
expectedFS, _ := NewFSContext(nil, nil, nil, testFS)
|
||||
|
||||
expectedOpenedFiles := FileTable{}
|
||||
expectedOpenedFiles.Insert(noopStdin)
|
||||
expectedOpenedFiles.Insert(noopStdout)
|
||||
@@ -75,9 +64,7 @@ func TestDefaultSysContext(t *testing.T) {
|
||||
FS: testFS,
|
||||
File: &lazyDir{fs: testFS},
|
||||
})
|
||||
|
||||
require.Equal(t, expectedOpenedFiles, expectedFS.openedFiles)
|
||||
require.Equal(t, expectedFS, sysCtx.FS())
|
||||
require.Equal(t, expectedOpenedFiles, sysCtx.FS().openedFiles)
|
||||
}
|
||||
|
||||
func TestFileEntry_cachedStat(t *testing.T) {
|
||||
@@ -104,7 +91,9 @@ func TestFileEntry_cachedStat(t *testing.T) {
|
||||
tc := tc
|
||||
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
fsc, _ := NewFSContext(nil, nil, nil, tc.fs)
|
||||
c := Context{}
|
||||
_ = c.NewFSContext(nil, nil, nil, tc.fs)
|
||||
fsc := c.fsc
|
||||
defer fsc.Close(testCtx)
|
||||
|
||||
f, ok := fsc.LookupFile(FdPreopen)
|
||||
@@ -258,7 +247,7 @@ func TestNewContext_Environ(t *testing.T) {
|
||||
func TestNewContext_Walltime(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
time *sys.Walltime
|
||||
time sys.Walltime
|
||||
resolution sys.ClockResolution
|
||||
expectedErr string
|
||||
}{
|
||||
@@ -307,7 +296,7 @@ func TestNewContext_Walltime(t *testing.T) {
|
||||
func TestNewContext_Nanotime(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
time *sys.Nanotime
|
||||
time sys.Nanotime
|
||||
resolution sys.ClockResolution
|
||||
expectedErr string
|
||||
}{
|
||||
@@ -396,12 +385,12 @@ func TestNewContext_Nanosleep(t *testing.T) {
|
||||
nil, // randSource
|
||||
nil, 0, // Nanosleep, NanosleepResolution
|
||||
nil, 0, // Nanosleep, NanosleepResolution
|
||||
&aNs, // nanosleep
|
||||
aNs, // nanosleep
|
||||
nil, // osyield
|
||||
nil, // rootFS
|
||||
)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, &aNs, sysCtx.nanosleep)
|
||||
require.Equal(t, aNs, sysCtx.nanosleep)
|
||||
}
|
||||
|
||||
func TestNewContext_Osyield(t *testing.T) {
|
||||
@@ -417,9 +406,9 @@ func TestNewContext_Osyield(t *testing.T) {
|
||||
nil, 0, // Nanosleep, NanosleepResolution
|
||||
nil, 0, // Nanosleep, NanosleepResolution
|
||||
nil, // nanosleep
|
||||
&oy, // osyield
|
||||
oy, // osyield
|
||||
nil, // rootFS
|
||||
)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, &oy, sysCtx.osyield)
|
||||
require.Equal(t, oy, sysCtx.osyield)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user