diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 371bd29f..11aecceb 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -4,7 +4,7 @@ jobs: test: strategy: matrix: - go-version: [1.15, 1.16, 1.17] + go-version: [1.15, 1.16, 1.17, 1.18] platform: [ubuntu-latest, macos-latest, windows-latest] runs-on: ${{ matrix.platform }} steps: diff --git a/examples/benchmarks/benchmarks_test.go b/examples/benchmarks/benchmarks_test.go index 3105abaf..a343efe0 100644 --- a/examples/benchmarks/benchmarks_test.go +++ b/examples/benchmarks/benchmarks_test.go @@ -91,6 +91,33 @@ func BenchmarkOutput(b *testing.B) { "fail-verbosity-check": func(value interface{}) { klog.V(verbosityThreshold+1).InfoS("test", "key", value) }, + "non-standard-int-key-check": func(value interface{}) { + klog.InfoS("test", 1, value) + }, + "non-standard-struct-key-check": func(value interface{}) { + klog.InfoS("test", struct{ key string }{"test"}, value) + }, + "non-standard-map-key-check": func(value interface{}) { + klog.InfoS("test", map[string]bool{"key": true}, value) + }, + "pass-verbosity-non-standard-int-key-check": func(value interface{}) { + klog.V(verbosityThreshold).InfoS("test", 1, value) + }, + "pass-verbosity-non-standard-struct-key-check": func(value interface{}) { + klog.V(verbosityThreshold).InfoS("test", struct{ key string }{"test"}, value) + }, + "pass-verbosity-non-standard-map-key-check": func(value interface{}) { + klog.V(verbosityThreshold).InfoS("test", map[string]bool{"key": true}, value) + }, + "fail-verbosity-non-standard-int-key-check": func(value interface{}) { + klog.V(verbosityThreshold+1).InfoS("test", 1, value) + }, + "fail-verbosity-non-standard-struct-key-check": func(value interface{}) { + klog.V(verbosityThreshold+1).InfoS("test", struct{ key string }{"test"}, value) + }, + "fail-verbosity-non-standard-map-key-check": func(value interface{}) { + klog.V(verbosityThreshold+1).InfoS("test", map[string]bool{"key": true}, value) + }, } for name, config := range configs { diff --git a/examples/output_test/output_test.go b/examples/output_test/output_test.go index b4170121..ac10f92f 100644 --- a/examples/output_test/output_test.go +++ b/examples/output_test/output_test.go @@ -63,7 +63,7 @@ func TestTextloggerOutput(t *testing.T) { }) } -// TestTextloggerOutput tests the zapr, directly and as backend. +// TestZaprOutput tests the zapr, directly and as backend. func TestZaprOutput(t *testing.T) { newLogger := func(out io.Writer, v int, vmodule string) logr.Logger { return newZaprLogger(out, v) @@ -121,6 +121,18 @@ func TestKlogrStackZapr(t *testing.T) { `I output.go:] "both odd" basekey1="basevar1" basekey2="(MISSING)" akey="avalue" akey2="(MISSING)" `: `{"caller":"test/output.go:","msg":"both odd","v":0,"basekey1":"basevar1","basekey2":"(MISSING)","akey":"avalue","akey2":"(MISSING)"} +`, + `I output.go:] "integer keys" %!s(int=1)="value" %!s(int=2)="value2" akey="avalue" akey2="(MISSING)" +`: `{"caller":"test/output.go:","msg":"non-string key argument passed to logging, ignoring all later arguments","invalid key":1} +{"caller":"test/output.go:","msg":"integer keys","v":0} +`, + `I output.go:] "struct keys" {name}="value" test="other value" key="val" +`: `{"caller":"test/output.go:","msg":"non-string key argument passed to logging, ignoring all later arguments","invalid key":{}} +{"caller":"test/output.go:","msg":"struct keys","v":0} +`, + `I output.go:] "map keys" map[test:%!s(bool=true)]="test" +`: `{"caller":"test/output.go:","msg":"non-string key argument passed to logging, ignoring all later arguments","invalid key":{"test":true}} +{"caller":"test/output.go:","msg":"map keys","v":0} `, } { mapping[key] = value @@ -172,6 +184,18 @@ func TestKlogrInternalStackZapr(t *testing.T) { `I output.go:] "both odd" basekey1="basevar1" basekey2="(MISSING)" akey="avalue" akey2="(MISSING)" `: `{"caller":"test/output.go:","msg":"both odd","v":0,"basekey1":"basevar1","basekey2":"(MISSING)","akey":"avalue","akey2":"(MISSING)"} +`, + `I output.go:] "integer keys" %!s(int=1)="value" %!s(int=2)="value2" akey="avalue" akey2="(MISSING)" +`: `{"caller":"test/output.go:","msg":"non-string key argument passed to logging, ignoring all later arguments","invalid key":1} +{"caller":"test/output.go:","msg":"integer keys","v":0} +`, + `I output.go:] "struct keys" {name}="value" test="other value" key="val" +`: `{"caller":"test/output.go:","msg":"non-string key argument passed to logging, ignoring all later arguments","invalid key":{}} +{"caller":"test/output.go:","msg":"struct keys","v":0} +`, + `I output.go:] "map keys" map[test:%!s(bool=true)]="test" +`: `{"caller":"test/output.go:","msg":"non-string key argument passed to logging, ignoring all later arguments","invalid key":{"test":true}} +{"caller":"test/output.go:","msg":"map keys","v":0} `, } { mapping[key] = value diff --git a/test/output.go b/test/output.go index 673e40c5..775571f2 100644 --- a/test/output.go +++ b/test/output.go @@ -365,6 +365,27 @@ I output.go:] "test" firstKey=1 secondKey=3 text: "marshaler recursion", values: []interface{}{"obj", recursiveMarshaler{}}, expectedOutput: `I output.go:] "marshaler recursion" obj={} +`, + }, + "handle integer keys": { + withValues: []interface{}{1, "value", 2, "value2"}, + text: "integer keys", + values: []interface{}{"akey", "avalue", "akey2"}, + expectedOutput: `I output.go:] "integer keys" %!s(int=1)="value" %!s(int=2)="value2" akey="avalue" akey2="(MISSING)" +`, + }, + "struct keys": { + withValues: []interface{}{struct{ name string }{"name"}, "value", "test", "other value"}, + text: "struct keys", + values: []interface{}{"key", "val"}, + expectedOutput: `I output.go:] "struct keys" {name}="value" test="other value" key="val" +`, + }, + "map keys": { + withValues: []interface{}{}, + text: "map keys", + values: []interface{}{map[string]bool{"test": true}, "test"}, + expectedOutput: `I output.go:] "map keys" map[test:%!s(bool=true)]="test" `, }, } diff --git a/test/zapr.go b/test/zapr.go index 32a82e68..427d1f78 100644 --- a/test/zapr.go +++ b/test/zapr.go @@ -217,6 +217,21 @@ I output.go:] "odd WithValues" keyWithoutValue="(MISSING)" // klog.V(1).InfoS `I output.go:] "hello" what="one world" `: `{"caller":"test/output.go:","msg":"hello","v":1,"what":"one world"} +`, + + `I output.go:] "integer keys" %!s(int=1)="value" %!s(int=2)="value2" akey="avalue" akey2="(MISSING)" +`: `{"caller":"test/output.go:","msg":"non-string key argument passed to logging, ignoring all later arguments","invalid key":1} +{"caller":"test/output.go:","msg":"odd number of arguments passed as key-value pairs for logging","ignored key":"akey2"} +{"caller":"test/output.go:","msg":"integer keys","v":0,"akey":"avalue"} +`, + + `I output.go:] "struct keys" {name}="value" test="other value" key="val" +`: `{"caller":"test/output.go:","msg":"non-string key argument passed to logging, ignoring all later arguments","invalid key":{}} +{"caller":"test/output.go:","msg":"struct keys","v":0,"key":"val"} +`, + `I output.go:] "map keys" map[test:%!s(bool=true)]="test" +`: `{"caller":"test/output.go:","msg":"non-string key argument passed to logging, ignoring all later arguments","invalid key":{"test":true}} +{"caller":"test/output.go:","msg":"map keys","v":0} `, } } @@ -291,6 +306,18 @@ I output.go:] "test" firstKey=1 secondKey=3 {"caller":"test/output.go:","msg":"test","v":0,"firstKey":1,"secondKey":2} {"caller":"test/output.go:","msg":"test","v":0,"firstKey":1} {"caller":"test/output.go:","msg":"test","v":0,"firstKey":1,"secondKey":3} +`, + `I output.go:] "integer keys" %!s(int=1)="value" %!s(int=2)="value2" akey="avalue" akey2="(MISSING)" +`: `{"caller":"test/output.go:","msg":"non-string key argument passed to logging, ignoring all later arguments","invalid key":1} +{"caller":"test/output.go:","msg":"integer keys","v":0} +`, + `I output.go:] "struct keys" {name}="value" test="other value" key="val" +`: `{"caller":"test/output.go:","msg":"non-string key argument passed to logging, ignoring all later arguments","invalid key":{}} +{"caller":"test/output.go:","msg":"struct keys","v":0} +`, + `I output.go:] "map keys" map[test:%!s(bool=true)]="test" +`: `{"caller":"test/output.go:","msg":"non-string key argument passed to logging, ignoring all later arguments","invalid key":{"test":true}} +{"caller":"test/output.go:","msg":"map keys","v":0} `, } { mapping[key] = value