logging: adds clock scope (#1071)

Signed-off-by: Adrian Cole <adrian@tetrate.io>
This commit is contained in:
Crypt Keeper
2023-01-28 19:11:37 +02:00
committed by GitHub
parent bd9a791c7a
commit d944c3c70d
14 changed files with 312 additions and 94 deletions

View File

@@ -3,6 +3,7 @@ package main
import (
"context"
"crypto/rand"
"errors"
"flag"
"fmt"
"io"
@@ -123,10 +124,10 @@ func doRun(args []string, stdOut io.Writer, stdErr logging.Writer, exit func(cod
"This may be specified multiple times. When <wasm path> is unset, <path> is used. "+
"For read-only mounts, append the suffix ':ro'.")
var hostlogging sliceFlag
var hostlogging logScopesFlag
flags.Var(&hostlogging, "hostlogging",
"A scope of host functions to log to stderr. "+
"This may be specified multiple times. Supported values: filesystem,random")
"This may be specified multiple times. Supported values: clock,filesystem,random")
cacheDir := cacheDirFlag(flags)
@@ -173,7 +174,7 @@ func doRun(args []string, stdOut io.Writer, stdErr logging.Writer, exit func(cod
wasmExe := filepath.Base(wasmPath)
ctx := maybeHostLogging(context.Background(), hostlogging, stdErr, exit)
ctx := maybeHostLogging(context.Background(), logging.LogScopes(hostlogging), stdErr)
rtc := wazero.NewRuntimeConfig()
if cache := maybeUseCacheDir(cacheDir, stdErr, exit); cache != nil {
@@ -294,25 +295,10 @@ func detectImports(imports []api.FunctionDefinition) (needsWASI, needsGo bool) {
return
}
func maybeHostLogging(ctx context.Context, hostLogging []string, stdErr logging.Writer, exit func(code int)) context.Context {
var scopes logging.LogScopes
for _, h := range hostLogging {
switch h {
case "":
case "random":
scopes |= logging.LogScopeRandom
case "filesystem":
scopes |= logging.LogScopeFilesystem
default:
fmt.Fprintf(stdErr, "invalid hostLogging value: %v\n", h)
exit(1)
}
}
func maybeHostLogging(ctx context.Context, scopes logging.LogScopes, stdErr logging.Writer) context.Context {
if scopes != 0 {
ctx = context.WithValue(ctx, experimental.FunctionListenerFactoryKey{}, logging.NewHostLoggingListenerFactory(stdErr, scopes))
return context.WithValue(ctx, experimental.FunctionListenerFactoryKey{}, logging.NewHostLoggingListenerFactory(stdErr, scopes))
}
return ctx
}
@@ -374,3 +360,24 @@ func (f *sliceFlag) Set(s string) error {
*f = append(*f, s)
return nil
}
type logScopesFlag logging.LogScopes
func (f *logScopesFlag) String() string {
return logging.LogScopes(*f).String()
}
func (f *logScopesFlag) Set(s string) error {
switch s {
case "":
case "clock":
*f |= logScopesFlag(logging.LogScopeClock)
case "filesystem":
*f |= logScopesFlag(logging.LogScopeFilesystem)
case "random":
*f |= logScopesFlag(logging.LogScopeRandom)
default:
return errors.New("not a log scope")
}
return nil
}

View File

@@ -14,6 +14,7 @@ import (
"testing"
"github.com/tetratelabs/wazero/api"
"github.com/tetratelabs/wazero/experimental/logging"
"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
"github.com/tetratelabs/wazero/internal/platform"
"github.com/tetratelabs/wazero/internal/testing/require"
@@ -354,9 +355,9 @@ func TestRun(t *testing.T) {
}
cryptoTest := test{
name: "GOARCH=wasm GOOS=js hostlogging=random and filesystem",
name: "GOARCH=wasm GOOS=js hostlogging=filesystem random",
wasm: wasmCat,
wazeroOpts: []string{"--hostlogging=random", "--hostlogging=filesystem"},
wazeroOpts: []string{"--hostlogging=filesystem", "--hostlogging=random"},
wasmArgs: []string{"/bear.txt"},
expectedStderr: `==> go.runtime.getRandomData(r_len=32)
<==
@@ -526,6 +527,55 @@ func Test_detectImports(t *testing.T) {
}
}
func Test_logScopesFlag(t *testing.T) {
tests := []struct {
name string
values []string
expected logging.LogScopes
}{
{
name: "defaults to none",
expected: logging.LogScopeNone,
},
{
name: "ignores empty",
values: []string{""},
expected: logging.LogScopeNone,
},
{
name: "clock",
values: []string{"clock"},
expected: logging.LogScopeClock,
},
{
name: "filesystem",
values: []string{"filesystem"},
expected: logging.LogScopeFilesystem,
},
{
name: "random",
values: []string{"random"},
expected: logging.LogScopeRandom,
},
{
name: "clock filesystem random",
values: []string{"clock", "filesystem", "random"},
expected: logging.LogScopeClock | logging.LogScopeFilesystem | logging.LogScopeRandom,
},
}
for _, tt := range tests {
tc := tt
t.Run(tc.name, func(t *testing.T) {
f := logScopesFlag(0)
for _, v := range tc.values {
require.NoError(t, f.Set(v))
}
require.Equal(t, tc.expected, logging.LogScopes(f))
})
}
}
func TestHelp(t *testing.T) {
exitCode, _, stdErr := runMain(t, []string{"-h"})
require.Equal(t, 0, exitCode)

View File

@@ -31,6 +31,8 @@ type LogScopes = logging.LogScopes
const (
// LogScopeNone means nothing should be logged
LogScopeNone = logging.LogScopeNone
// LogScopeClock enables logging for functions such as `clock_time_get`.
LogScopeClock = logging.LogScopeClock
// LogScopeFilesystem enables logging for functions such as `path_open`.
// Note: This doesn't log writes to the console.
LogScopeFilesystem = logging.LogScopeFilesystem

View File

@@ -36,8 +36,8 @@ func Test_clockResGet(t *testing.T) {
clockID: ClockIDRealtime,
expectedMemory: expectedMemoryMicro,
expectedLog: `
==> wasi_snapshot_preview1.clock_res_get(id=0,result.resolution=16)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.clock_res_get(id=realtime)
<== (resolution=1000,errno=ESUCCESS)
`,
},
{
@@ -45,8 +45,8 @@ func Test_clockResGet(t *testing.T) {
clockID: ClockIDMonotonic,
expectedMemory: expectedMemoryNano,
expectedLog: `
==> wasi_snapshot_preview1.clock_res_get(id=1,result.resolution=16)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.clock_res_get(id=monotonic)
<== (resolution=1,errno=ESUCCESS)
`,
},
}
@@ -85,8 +85,8 @@ func Test_clockResGet_Unsupported(t *testing.T) {
clockID: 2,
expectedErrno: ErrnoInval,
expectedLog: `
==> wasi_snapshot_preview1.clock_res_get(id=2,result.resolution=16)
<== errno=EINVAL
==> wasi_snapshot_preview1.clock_res_get(id=2)
<== (resolution=,errno=EINVAL)
`,
},
{
@@ -94,8 +94,8 @@ func Test_clockResGet_Unsupported(t *testing.T) {
clockID: 3,
expectedErrno: ErrnoInval,
expectedLog: `
==> wasi_snapshot_preview1.clock_res_get(id=3,result.resolution=16)
<== errno=EINVAL
==> wasi_snapshot_preview1.clock_res_get(id=3)
<== (resolution=,errno=EINVAL)
`,
},
{
@@ -103,12 +103,11 @@ func Test_clockResGet_Unsupported(t *testing.T) {
clockID: 100,
expectedErrno: ErrnoInval,
expectedLog: `
==> wasi_snapshot_preview1.clock_res_get(id=100,result.resolution=16)
<== errno=EINVAL
==> wasi_snapshot_preview1.clock_res_get(id=100)
<== (resolution=,errno=EINVAL)
`,
},
}
for _, tt := range tests {
tc := tt
@@ -141,8 +140,8 @@ func Test_clockTimeGet(t *testing.T) {
'?', // stopped after encoding
},
expectedLog: `
==> wasi_snapshot_preview1.clock_time_get(id=0,precision=0,result.timestamp=16)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.clock_time_get(id=realtime,precision=0)
<== (timestamp=1640995200000000000,errno=ESUCCESS)
`,
},
{
@@ -154,8 +153,8 @@ func Test_clockTimeGet(t *testing.T) {
'?', // stopped after encoding
},
expectedLog: `
==> wasi_snapshot_preview1.clock_time_get(id=1,precision=0,result.timestamp=16)
<== errno=ESUCCESS
==> wasi_snapshot_preview1.clock_time_get(id=monotonic,precision=0)
<== (timestamp=0,errno=ESUCCESS)
`,
},
}
@@ -193,8 +192,8 @@ func Test_clockTimeGet_Unsupported(t *testing.T) {
clockID: 2,
expectedErrno: ErrnoInval,
expectedLog: `
==> wasi_snapshot_preview1.clock_time_get(id=2,precision=0,result.timestamp=16)
<== errno=EINVAL
==> wasi_snapshot_preview1.clock_time_get(id=2,precision=0)
<== (timestamp=,errno=EINVAL)
`,
},
{
@@ -202,8 +201,8 @@ func Test_clockTimeGet_Unsupported(t *testing.T) {
clockID: 3,
expectedErrno: ErrnoInval,
expectedLog: `
==> wasi_snapshot_preview1.clock_time_get(id=3,precision=0,result.timestamp=16)
<== errno=EINVAL
==> wasi_snapshot_preview1.clock_time_get(id=3,precision=0)
<== (timestamp=,errno=EINVAL)
`,
},
{
@@ -211,8 +210,8 @@ func Test_clockTimeGet_Unsupported(t *testing.T) {
clockID: 100,
expectedErrno: ErrnoInval,
expectedLog: `
==> wasi_snapshot_preview1.clock_time_get(id=100,precision=0,result.timestamp=16)
<== errno=EINVAL
==> wasi_snapshot_preview1.clock_time_get(id=100,precision=0)
<== (timestamp=,errno=EINVAL)
`,
},
}
@@ -245,16 +244,16 @@ func Test_clockTimeGet_Errors(t *testing.T) {
name: "resultTimestamp OOM",
resultTimestamp: memorySize,
expectedLog: `
==> wasi_snapshot_preview1.clock_time_get(id=0,precision=0,result.timestamp=65536)
<== errno=EFAULT
==> wasi_snapshot_preview1.clock_time_get(id=realtime,precision=0)
<== (timestamp=,errno=EFAULT)
`,
},
{
name: "resultTimestamp exceeds the maximum valid address by 1",
resultTimestamp: memorySize - 4 + 1, // 4 is the size of uint32, the type of the count of args
expectedLog: `
==> wasi_snapshot_preview1.clock_time_get(id=0,precision=0,result.timestamp=65533)
<== errno=EFAULT
==> wasi_snapshot_preview1.clock_time_get(id=realtime,precision=0)
<== (timestamp=,errno=EFAULT)
`,
},
}

View File

@@ -25,21 +25,10 @@ func Test_crypto(t *testing.T) {
require.Equal(t, `7a0c9f9f0d
`, stdout)
// TODO: Go 1.17 initializes randoms in a different order than Go 1.18,19
// When we move to 1.20, remove the workaround.
if log.String() != `==> go.runtime.getRandomData(r_len=32)
<==
==> go.runtime.getRandomData(r_len=8)
<==
==> go.syscall/js.valueCall(crypto.getRandomValues(r_len=5))
<== (n=5)
` {
require.Equal(t, `==> go.runtime.getRandomData(r_len=8)
<==
==> go.runtime.getRandomData(r_len=32)
<==
==> go.syscall/js.valueCall(crypto.getRandomValues(r_len=5))
<== (n=5)
`, log.String())
}
// Search for the two functions that should be in scope, flexibly, to pass
// go 1.17-19
require.Contains(t, log.String(), `go.runtime.getRandomData(r_len=32)
<==`)
require.Contains(t, log.String(), `==> go.syscall/js.valueCall(crypto.getRandomValues(r_len=5))
<== (n=5)`)
}

View File

@@ -0,0 +1,17 @@
package custom
const (
NameDate = "Date"
NameDateGetTimezoneOffset = "getTimezoneOffset"
)
// DateNameSection are the functions defined in the object named NameDate.
// Results here are those set to the current event object, but effectively are
// results of the host function.
var DateNameSection = map[string]*Names{
NameDateGetTimezoneOffset: {
Name: NameDateGetTimezoneOffset,
ParamNames: []string{},
ResultNames: []string{"tz"},
},
}

View File

@@ -190,5 +190,6 @@ var NameSection = map[string]*Names{
var NameSectionSyscallValueCall = map[string]map[string]*Names{
NameCrypto: CryptoNameSection,
NameDate: DateNameSection,
NameFs: FsNameSection,
}

View File

@@ -18,11 +18,11 @@ import (
// IsInLogScope returns true if the current function is in any of the scopes.
func IsInLogScope(fnd api.FunctionDefinition, scopes logging.LogScopes) bool {
if scopes.IsEnabled(logging.LogScopeRandom) {
if scopes.IsEnabled(logging.LogScopeClock) {
switch fnd.Name() {
case custom.NameRuntimeGetRandomData:
case custom.NameRuntimeNanotime1, custom.NameRuntimeWalltime:
return true
case custom.NameSyscallValueCall: // e.g. crypto.getRandomValues
case custom.NameSyscallValueCall: // e.g. Date.getTimezoneOffset
return true
}
}
@@ -33,6 +33,15 @@ func IsInLogScope(fnd api.FunctionDefinition, scopes logging.LogScopes) bool {
}
}
if scopes.IsEnabled(logging.LogScopeRandom) {
switch fnd.Name() {
case custom.NameRuntimeGetRandomData:
return true
case custom.NameSyscallValueCall: // e.g. crypto.getRandomValues
return true
}
}
return scopes == logging.LogScopeAll
}
@@ -44,14 +53,20 @@ func Config(fnd api.FunctionDefinition, scopes logging.LogScopes) (pSampler logg
pLoggers = []logging.ParamLogger{syscallValueCallParamLogger}
rLoggers = []logging.ResultLogger{syscallValueCallResultLogger}
case custom.NameRuntimeGetRandomData:
_, rLoggers = logging.Config(fnd)
pLoggers = []logging.ParamLogger{syscallGetRandomParamLogger}
pLoggers = []logging.ParamLogger{runtimeGetRandomDataParamLogger}
// no results
case custom.NameRuntimeNanotime1:
// no params
rLoggers = []logging.ResultLogger{runtimeNanotime1ResultLogger}
case custom.NameRuntimeWalltime:
// no params
rLoggers = []logging.ResultLogger{runtimeWalltimeResultLogger}
default: // TODO: make generic logger for gojs
}
return
}
func syscallGetRandomParamLogger(_ context.Context, mod api.Module, w logging.Writer, params []uint64) {
func runtimeGetRandomDataParamLogger(_ context.Context, mod api.Module, w logging.Writer, params []uint64) {
funcName := custom.NameRuntimeGetRandomData
paramNames := custom.NameSection[funcName].ParamNames
paramIdx := 1 /* there are two params, only write the length */
@@ -62,6 +77,28 @@ func syscallGetRandomParamLogger(_ context.Context, mod api.Module, w logging.Wr
writeI32(w, stack.ParamUint32(paramIdx))
}
func runtimeNanotime1ResultLogger(_ context.Context, mod api.Module, w logging.Writer, params, _ []uint64) {
writeResults(w, custom.NameRuntimeNanotime1, mod, params, 0)
}
func runtimeWalltimeResultLogger(_ context.Context, mod api.Module, w logging.Writer, params, _ []uint64) {
writeResults(w, custom.NameRuntimeWalltime, mod, params, 0)
}
func writeResults(w logging.Writer, funcName string, mod api.Module, params []uint64, resultOffset int) {
stack := goos.NewStack(funcName, mod.Memory(), uint32(params[0]))
resultNames := custom.NameSection[funcName].ResultNames
results := make([]interface{}, len(resultNames))
for i := range resultNames {
results[i] = stack.ParamUint32(i + resultOffset)
}
w.WriteByte('(') //nolint
writeVals(w, resultNames, results)
w.WriteByte(')') //nolint
}
type syscallValueCallParamSampler struct {
scopes logging.LogScopes
}
@@ -70,6 +107,10 @@ func (s *syscallValueCallParamSampler) isSampled(ctx context.Context, mod api.Mo
vRef, m, args := syscallValueCallParams(ctx, mod, params)
switch vRef {
case goos.RefJsCrypto:
return logging.LogScopeRandom.IsEnabled(s.scopes)
case goos.RefJsDate:
return logging.LogScopeClock.IsEnabled(s.scopes)
case goos.RefJsfs:
if !logging.LogScopeFilesystem.IsEnabled(s.scopes) {
return false
@@ -81,8 +122,6 @@ func (s *syscallValueCallParamSampler) isSampled(ctx context.Context, mod api.Mo
return fd > sys.FdStderr
}
return true
case goos.RefJsCrypto:
return logging.LogScopeRandom.IsEnabled(s.scopes)
}
return s.scopes == logging.LogScopeAll
@@ -94,6 +133,8 @@ func syscallValueCallParamLogger(ctx context.Context, mod api.Module, w logging.
switch vRef {
case goos.RefJsCrypto:
logSyscallValueCallArgs(w, custom.NameCrypto, m, args)
case goos.RefJsDate:
logSyscallValueCallArgs(w, custom.NameDate, m, args)
case goos.RefJsfs:
logFsParams(m, w, args)
default:
@@ -151,6 +192,10 @@ func syscallValueCallResultLogger(ctx context.Context, mod api.Module, w logging
resultNames = custom.CryptoNameSection[m].ResultNames
rRef := stack.ParamVal(ctx, 6, gojs.LoadValue) // val is after padding
resultVals = []interface{}{rRef}
case goos.RefJsDate:
resultNames = custom.DateNameSection[m].ResultNames
rRef := stack.ParamVal(ctx, 6, gojs.LoadValue) // val is after padding
resultVals = []interface{}{rRef}
case goos.RefJsfs:
resultNames = custom.FsNameSection[m].ResultNames
resultVals = gojs.GetLastEventArgs(ctx)

View File

@@ -4,6 +4,7 @@ import (
"context"
"github.com/tetratelabs/wazero/api"
"github.com/tetratelabs/wazero/internal/gojs/custom"
"github.com/tetratelabs/wazero/internal/gojs/goos"
)
@@ -11,12 +12,12 @@ var (
// jsDateConstructor returns jsDate.
//
// This is defined as `Get("Date")` in zoneinfo_js.go time.initLocal
jsDateConstructor = newJsVal(goos.RefJsDateConstructor, "Date")
jsDateConstructor = newJsVal(goos.RefJsDateConstructor, custom.NameDate)
// jsDate is used inline in zoneinfo_js.go for time.initLocal.
// `.Call("getTimezoneOffset").Int()` returns a timezone offset.
jsDate = newJsVal(goos.RefJsDate, "jsDate").
addFunction("getTimezoneOffset", jsDateGetTimezoneOffset{})
jsDate = newJsVal(goos.RefJsDate, custom.NameDate).
addFunction(custom.NameDateGetTimezoneOffset, jsDateGetTimezoneOffset{})
)
// jsDateGetTimezoneOffset implements jsFn

View File

@@ -1,20 +1,39 @@
package gojs_test
import (
"bytes"
"context"
"testing"
"github.com/tetratelabs/wazero"
"github.com/tetratelabs/wazero/experimental"
"github.com/tetratelabs/wazero/experimental/logging"
"github.com/tetratelabs/wazero/internal/testing/require"
)
func Test_time(t *testing.T) {
t.Parallel()
stdout, stderr, err := compileAndRun(testCtx, "time", wazero.NewModuleConfig())
var log bytes.Buffer
loggingCtx := context.WithValue(testCtx, experimental.FunctionListenerFactoryKey{},
logging.NewHostLoggingListenerFactory(&log, logging.LogScopeClock))
stdout, stderr, err := compileAndRun(loggingCtx, "time", wazero.NewModuleConfig())
require.EqualError(t, err, `module "" closed with exit_code(0)`)
require.Zero(t, stderr)
require.Equal(t, `Local
1ms
`, stdout)
// Search for the three functions that should be in scope, flexibly, to pass
// go 1.17-19
require.Contains(t, log.String(), `==> go.runtime.nanotime1()
<== (nsec=0)`)
require.Contains(t, log.String(), `==> go.runtime.walltime()
<== (sec=1640995200,nsec=0)
`)
require.Contains(t, log.String(), `==> go.syscall/js.valueCall(Date.getTimezoneOffset())
<== (tz=0)
`)
}

View File

@@ -37,14 +37,17 @@ const (
type LogScopes uint64
const (
LogScopeNone = LogScopes(0)
LogScopeFilesystem LogScopes = 1 << iota
LogScopeNone = LogScopes(0)
LogScopeClock LogScopes = 1 << iota
LogScopeFilesystem
LogScopeRandom
LogScopeAll = LogScopes(0xffffffffffffffff)
)
func scopeName(s LogScopes) string {
switch s {
case LogScopeClock:
return "clock"
case LogScopeFilesystem:
return "filesystem"
case LogScopeRandom:

View File

@@ -51,10 +51,11 @@ func TestLogScopes_String(t *testing.T) {
}{
{name: "none", scopes: LogScopeNone, expected: ""},
{name: "any", scopes: LogScopeAll, expected: "all"},
{name: "clock", scopes: LogScopeClock, expected: "clock"},
{name: "filesystem", scopes: LogScopeFilesystem, expected: "filesystem"},
{name: "random", scopes: LogScopeRandom, expected: "random"},
{name: "filesystem|random", scopes: LogScopeFilesystem | LogScopeRandom, expected: "filesystem|random"},
{name: "undefined", scopes: 1 << 3, expected: fmt.Sprintf("<unknown=%d>", (1 << 3))},
{name: "undefined", scopes: 1 << 14, expected: fmt.Sprintf("<unknown=%d>", 1<<14)},
}
for _, tt := range tests {

View File

@@ -14,6 +14,10 @@ import (
var le = binary.LittleEndian
func isClockFunction(fnd api.FunctionDefinition) bool {
return strings.HasPrefix(fnd.Name(), "clock_")
}
func isFilesystemFunction(fnd api.FunctionDefinition) bool {
switch {
case strings.HasPrefix(fnd.Name(), "path_"):
@@ -30,8 +34,8 @@ func isRandomFunction(fnd api.FunctionDefinition) bool {
// IsInLogScope returns true if the current function is in any of the scopes.
func IsInLogScope(fnd api.FunctionDefinition, scopes logging.LogScopes) bool {
if scopes.IsEnabled(logging.LogScopeRandom) {
if isRandomFunction(fnd) {
if scopes.IsEnabled(logging.LogScopeClock) {
if isClockFunction(fnd) {
return true
}
}
@@ -42,6 +46,12 @@ func IsInLogScope(fnd api.FunctionDefinition, scopes logging.LogScopes) bool {
}
}
if scopes.IsEnabled(logging.LogScopeRandom) {
if isRandomFunction(fnd) {
return true
}
}
return scopes == logging.LogScopeAll
}
@@ -83,6 +93,26 @@ func Config(fnd api.FunctionDefinition) (pSampler logging.ParamSampler, pLoggers
continue
}
if strings.HasPrefix(fnd.Name(), "clock_") {
switch name {
case "id":
logger = logClockId(idx).Log
pLoggers = append(pLoggers, logger)
case "result.resolution":
name = resultParamName(name)
logger = logMemI32(idx).Log
rLoggers = append(rLoggers, resultParamLogger(name, logger))
case "result.timestamp":
name = resultParamName(name)
logger = logMemI64(idx).Log
rLoggers = append(rLoggers, resultParamLogger(name, logger))
default:
logger = logging.NewParamLogger(idx, name, fnd.ParamTypes()[idx])
pLoggers = append(pLoggers, logger)
}
continue
}
switch name {
case "fdflags":
logger = logFdflags(idx).Log
@@ -149,6 +179,14 @@ func (i logMemI32) Log(_ context.Context, mod api.Module, w logging.Writer, para
}
}
type logMemI64 uint32
func (i logMemI64) Log(_ context.Context, mod api.Module, w logging.Writer, params []uint64) {
if v, ok := mod.Memory().ReadUint64Le(uint32(params[i])); ok {
writeI64(w, v)
}
}
type logFilestat uint32
func (i logFilestat) Log(_ context.Context, mod api.Module, w logging.Writer, params []uint64) {
@@ -214,6 +252,21 @@ func resultParamLogger(name string, pLogger logging.ParamLogger) logging.ResultL
}
}
type logClockId int
func (i logClockId) Log(_ context.Context, _ api.Module, w logging.Writer, params []uint64) {
id := uint32(params[i])
w.WriteString("id=") //nolint
switch id {
case ClockIDRealtime:
w.WriteString("realtime") //nolint
case ClockIDMonotonic:
w.WriteString("monotonic") //nolint
default:
writeI32(w, id)
}
}
type logFdflags int
func (i logFdflags) Log(_ context.Context, _ api.Module, w logging.Writer, params []uint64) {

View File

@@ -21,8 +21,9 @@ func (f *testFunctionDefinition) Name() string {
}
func TestIsInLogScope(t *testing.T) {
randomGet := &testFunctionDefinition{name: RandomGetName}
clockTimeGet := &testFunctionDefinition{name: ClockTimeGetName}
fdRead := &testFunctionDefinition{name: FdReadName}
randomGet := &testFunctionDefinition{name: RandomGetName}
tests := []struct {
name string
fnd api.FunctionDefinition
@@ -30,32 +31,32 @@ func TestIsInLogScope(t *testing.T) {
expected bool
}{
{
name: "randomGet in LogScopeRandom",
fnd: randomGet,
scopes: logging.LogScopeRandom,
name: "clockTimeGet in LogScopeClock",
fnd: clockTimeGet,
scopes: logging.LogScopeClock,
expected: true,
},
{
name: "randomGet not in LogScopeFilesystem",
fnd: randomGet,
name: "clockTimeGet not in LogScopeFilesystem",
fnd: clockTimeGet,
scopes: logging.LogScopeFilesystem,
expected: false,
},
{
name: "randomGet in LogScopeRandom|LogScopeFilesystem",
fnd: randomGet,
scopes: logging.LogScopeRandom | logging.LogScopeFilesystem,
name: "clockTimeGet in LogScopeClock|LogScopeFilesystem",
fnd: clockTimeGet,
scopes: logging.LogScopeClock | logging.LogScopeFilesystem,
expected: true,
},
{
name: "randomGet in LogScopeAll",
fnd: randomGet,
name: "clockTimeGet in LogScopeAll",
fnd: clockTimeGet,
scopes: logging.LogScopeAll,
expected: true,
},
{
name: "randomGet not in LogScopeNone",
fnd: randomGet,
name: "clockTimeGet not in LogScopeNone",
fnd: clockTimeGet,
scopes: logging.LogScopeNone,
expected: false,
},
@@ -89,6 +90,36 @@ func TestIsInLogScope(t *testing.T) {
scopes: logging.LogScopeNone,
expected: false,
},
{
name: "randomGet in LogScopeRandom",
fnd: randomGet,
scopes: logging.LogScopeRandom,
expected: true,
},
{
name: "randomGet not in LogScopeFilesystem",
fnd: randomGet,
scopes: logging.LogScopeFilesystem,
expected: false,
},
{
name: "randomGet in LogScopeRandom|LogScopeFilesystem",
fnd: randomGet,
scopes: logging.LogScopeRandom | logging.LogScopeFilesystem,
expected: true,
},
{
name: "randomGet in LogScopeAll",
fnd: randomGet,
scopes: logging.LogScopeAll,
expected: true,
},
{
name: "randomGet not in LogScopeNone",
fnd: randomGet,
scopes: logging.LogScopeNone,
expected: false,
},
}
for _, tt := range tests {