Fix logging tests

Signed-off-by: Steffen Vogel <post@steffenvogel.de>
This commit is contained in:
Steffen Vogel
2023-06-21 08:56:09 +02:00
parent 8e4961e1f7
commit c8e5858314
28 changed files with 250 additions and 186 deletions

View File

@@ -27,12 +27,11 @@ import (
) )
func TestSuite(t *testing.T) { func TestSuite(t *testing.T) {
test.SetupLogging()
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
RunSpecs(t, "Config Suite") RunSpecs(t, "Config Suite")
} }
var _ = test.SetupLogging()
var _ = Context("config", func() { var _ = Context("config", func() {
mkTempFile := func(contents string) *os.File { mkTempFile := func(contents string) *os.File {
dir := GinkgoT().TempDir() dir := GinkgoT().TempDir()

View File

@@ -14,12 +14,11 @@ import (
) )
func TestSuite(t *testing.T) { func TestSuite(t *testing.T) {
test.SetupLogging()
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
RunSpecs(t, "Crypto Suite") RunSpecs(t, "Crypto Suite")
} }
var _ = test.SetupLogging()
var _ = Describe("nonce", func() { var _ = Describe("nonce", func() {
It("can generate a valid nonce", func() { It("can generate a valid nonce", func() {
nonce, err := crypto.GetNonce(100) nonce, err := crypto.GetNonce(100)

View File

@@ -14,12 +14,11 @@ import (
) )
func TestSuite(t *testing.T) { func TestSuite(t *testing.T) {
test.SetupLogging()
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
RunSpecs(t, "Watcher Suite") RunSpecs(t, "Watcher Suite")
} }
var _ = test.SetupLogging()
var _ = BeforeSuite(func() { var _ = BeforeSuite(func() {
if !osx.HasAdminPrivileges() { if !osx.HasAdminPrivileges() {
Skip("Insufficient privileges") Skip("Insufficient privileges")

View File

@@ -14,12 +14,11 @@ import (
) )
func TestSuite(t *testing.T) { func TestSuite(t *testing.T) {
test.SetupLogging()
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
RunSpecs(t, "Device Suite") RunSpecs(t, "Device Suite")
} }
var _ = test.SetupLogging()
var _ = BeforeSuite(func() { var _ = BeforeSuite(func() {
if !osx.HasAdminPrivileges() { if !osx.HasAdminPrivileges() {
Skip("Insufficient privileges") Skip("Insufficient privileges")

View File

@@ -13,8 +13,7 @@ import (
) )
func TestSuite(t *testing.T) { func TestSuite(t *testing.T) {
test.SetupLogging()
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
RunSpecs(t, "ICE Suite") RunSpecs(t, "ICE Suite")
} }
var _ = test.SetupLogging()

View File

@@ -15,6 +15,8 @@ import (
"strings" "strings"
"go.uber.org/zap" "go.uber.org/zap"
"github.com/stv0g/cunicu/pkg/log"
) )
var ( var (
@@ -204,7 +206,7 @@ func getRouteMTU(ip net.IP) (int, error) {
} }
func run(args ...string) (string, error) { func run(args ...string) (string, error) {
cmd := exec.Command(args[0], args[1:]...) cmd := exec.Command(args[0], args[1:]...) //nolint:gosec
out, err := cmd.CombinedOutput() out, err := cmd.CombinedOutput()
outStr := string(out) outStr := string(out)

View File

@@ -7,12 +7,14 @@ import (
"testing" "testing"
osx "github.com/stv0g/cunicu/pkg/os" osx "github.com/stv0g/cunicu/pkg/os"
"github.com/stv0g/cunicu/test"
. "github.com/onsi/ginkgo/v2" . "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
) )
func TestSuite(t *testing.T) { func TestSuite(t *testing.T) {
test.SetupLogging()
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
RunSpecs(t, "Link Suite") RunSpecs(t, "Link Suite")
} }

View File

@@ -8,6 +8,8 @@ import (
"strconv" "strconv"
"go.uber.org/zap" "go.uber.org/zap"
"github.com/stv0g/cunicu/pkg/log"
) )
type WindowsLink struct { type WindowsLink struct {

View File

@@ -63,6 +63,11 @@ var (
} }
) )
func ResetWidths() {
widthLevel.Store(0)
widthName.Store(0)
}
func ColorLevel(l zapcore.Level) string { func ColorLevel(l zapcore.Level) string {
if color, ok := ColorLevels[l]; ok { if color, ok := ColorLevels[l]; ok {
return color return color
@@ -74,14 +79,39 @@ func ColorLevel(l zapcore.Level) string {
} }
type encoderConfig struct { type encoderConfig struct {
zapcore.EncoderConfig
ColorTime string ColorTime string
ColorContext string ColorContext string
ColorStacktrace string ColorStacktrace string
ColorName string ColorName string
ColorCaller string ColorCaller string
ColorLevel func(lvl zapcore.Level) string ColorLevel func(lvl zapcore.Level) string
Function bool
Message bool
Time bool
Context bool
Stacktrace bool
Name bool
Caller bool
Level bool
// Configure the primitive representations of common complex types. For
// example, some users may want all time.Times serialized as floating-point
// seconds since epoch, while others may prefer ISO8601 strings.
EncodeLevel zapcore.LevelEncoder
EncodeTime zapcore.TimeEncoder
EncodeDuration zapcore.DurationEncoder
EncodeCaller zapcore.CallerEncoder
// Unlike the other primitive type encoders, EncodeName is optional. The
// zero value falls back to FullNameEncoder.
EncodeName zapcore.NameEncoder
// Configures the field separator used by the console encoder. Defaults
// to tab.
ConsoleSeparator string
LineEnding string
} }
type encoder struct { type encoder struct {
@@ -434,7 +464,7 @@ func (e *encoder) appendReflection(value any) error {
rvalue := reflect.ValueOf(value) rvalue := reflect.ValueOf(value)
switch rvalue.Kind() { switch rvalue.Kind() {
case reflect.Chan, reflect.Func: case reflect.Chan, reflect.Func:
e.AppendString(fmt.Sprintf("%s(%d)", rvalue.Type(), rvalue.Pointer())) e.AppendString(fmt.Sprintf("%T(%p)", value, value))
case reflect.Struct: case reflect.Struct:
return e.appendReflectedStruct(rvalue) return e.appendReflectedStruct(rvalue)
case reflect.Map: case reflect.Map:
@@ -613,7 +643,7 @@ func (e *encoder) EncodeEntry(ent zapcore.Entry, fields []zapcore.Field) (*buffe
defer putEncoder(f) defer putEncoder(f)
// Time // Time
if f.TimeKey != "" && f.EncodeTime != nil { if f.Time && f.EncodeTime != nil {
f.addSeparator(e.fieldSeparator) f.addSeparator(e.fieldSeparator)
f.colored(e.ColorTime, func() { f.colored(e.ColorTime, func() {
f.EncodeTime(ent.Time, f) f.EncodeTime(ent.Time, f)
@@ -621,17 +651,24 @@ func (e *encoder) EncodeEntry(ent zapcore.Entry, fields []zapcore.Field) (*buffe
} }
// Level // Level
if f.LevelKey != "" && f.EncodeLevel != nil { if f.Level && f.EncodeLevel != nil {
f.addSeparator(e.fieldSeparator) cb := func() {
f.colored(e.ColorLevel(ent.Level), func() {
f.aligned(&widthLevel, func() { f.aligned(&widthLevel, func() {
f.EncodeLevel(ent.Level, f) f.EncodeLevel(ent.Level, f)
}) })
}) }
f.addSeparator(e.fieldSeparator)
if e.ColorLevel != nil {
f.colored(e.ColorLevel(ent.Level), cb)
} else {
cb()
}
} }
// Name // Name
if ent.LoggerName != "" && f.NameKey != "" { if f.Name && ent.LoggerName != "" {
nameEncoder := f.EncodeName nameEncoder := f.EncodeName
if nameEncoder == nil { if nameEncoder == nil {
// Fall back to FullNameEncoder for backward compatibility. // Fall back to FullNameEncoder for backward compatibility.
@@ -647,14 +684,14 @@ func (e *encoder) EncodeEntry(ent zapcore.Entry, fields []zapcore.Field) (*buffe
} }
if ent.Caller.Defined { if ent.Caller.Defined {
if f.CallerKey != "" && f.EncodeCaller != nil { if f.Caller && f.EncodeCaller != nil {
f.addSeparator(e.fieldSeparator) f.addSeparator(e.fieldSeparator)
f.colored(e.ColorCaller, func() { f.colored(e.ColorCaller, func() {
f.EncodeCaller(ent.Caller, f) f.EncodeCaller(ent.Caller, f)
}) })
} }
if f.FunctionKey != "" { if f.Function {
f.addSeparator(e.fieldSeparator) f.addSeparator(e.fieldSeparator)
f.colored(e.ColorCaller, func() { f.colored(e.ColorCaller, func() {
f.AppendString(ent.Caller.Function) f.AppendString(ent.Caller.Function)
@@ -663,7 +700,7 @@ func (e *encoder) EncodeEntry(ent zapcore.Entry, fields []zapcore.Field) (*buffe
} }
// Add the message itself. // Add the message itself.
if f.MessageKey != "" { if f.Message {
f.addSeparator(e.fieldSeparator) f.addSeparator(e.fieldSeparator)
f.AppendString(ent.Message) f.AppendString(ent.Message)
} }
@@ -688,7 +725,7 @@ func (e *encoder) EncodeEntry(ent zapcore.Entry, fields []zapcore.Field) (*buffe
}) })
} }
if f.StacktraceKey != "" && ent.Stack != "" { if f.Stacktrace && ent.Stack != "" {
f.addSeparator(e.fieldSeparator) f.addSeparator(e.fieldSeparator)
f.colored(e.ColorStacktrace, func() { f.colored(e.ColorStacktrace, func() {
f.buf.AppendString(ent.Stack) f.buf.AppendString(ent.Stack)

View File

@@ -38,6 +38,10 @@ func (j jsonMarshaler) MarshalJSON() ([]byte, error) { return []byte(j), nil }
func (t failedMarshaler) MarshalText() ([]byte, error) { return []byte(t), errWelp } func (t failedMarshaler) MarshalText() ([]byte, error) { return []byte(t), errWelp }
var _ = Context("encoder", func() { var _ = Context("encoder", func() {
BeforeEach(func() {
ResetWidths()
})
DescribeTable("key", DescribeTable("key",
func( func(
key string, key string,
@@ -177,7 +181,7 @@ var _ = Context("encoder", func() {
}, },
Entry("nil", "<nil>", nil), Entry("nil", "<nil>", nil),
Entry("error", "welp", errWelp), Entry("error", "welp", errWelp),
Entry("bytes", "bytes", []byte("bytes")), Entry("bytes", "Ynl0ZXM=", []byte("bytes")),
Entry("stringer", "my-stringer", stringer("my-stringer")), Entry("stringer", "my-stringer", stringer("my-stringer")),
Entry("text marshaler", "marshaled-text", textMarshaler("marshaled-text")), Entry("text marshaler", "marshaled-text", textMarshaler("marshaled-text")),
Entry("json marshaler", `{"json":"data"}`, jsonMarshaler(`{"json":"data"}`)), Entry("json marshaler", `{"json":"data"}`, jsonMarshaler(`{"json":"data"}`)),
@@ -413,8 +417,10 @@ var _ = Context("encoder", func() {
}) })
Describe("EncodeEntry", func() { Describe("EncodeEntry", func() {
It("empty config with field", func() { DescribeTable("empty config with field", func(color, expected string) {
enc := newEncoder(encoderConfig{}) enc := newEncoder(encoderConfig{
ColorContext: color,
})
enc.AddString("x", "y") enc.AddString("x", "y")
@@ -427,8 +433,11 @@ var _ = Context("encoder", func() {
) )
Expect(err).To(Succeed()) Expect(err).To(Succeed())
Expect(buf.String()).To(Equal(tty.Mods("x=y a=b c=d", ColorContext) + "\n")) Expect(buf.String()).To(Equal(expected))
}) },
Entry("with color", ColorContext, tty.Mods("x=y a=b c=d", ColorContext)+"\n"),
Entry("without color", "", "x=y a=b c=d\n"),
)
DescribeTable("with config", DescribeTable("with config",
func( func(
@@ -468,61 +477,109 @@ var _ = Context("encoder", func() {
}, },
Entry("empty", Entry("empty",
"", "",
zapcore.EncoderConfig{}, encoderConfig{},
nil, nil,
nil, nil,
), ),
Entry("empty with fields", Entry("empty with fields",
"key=value",
encoderConfig{},
nil,
[]zapcore.Field{zap.String("key", "value")},
),
Entry("empty with fields and color",
tty.Mods("key=value", ColorContext), tty.Mods("key=value", ColorContext),
zapcore.EncoderConfig{}, encoderConfig{ColorContext: ColorContext},
nil, nil,
[]zapcore.Field{zap.String("key", "value")}, []zapcore.Field{zap.String("key", "value")},
), ),
Entry("empty with context", Entry("empty with context",
"message\tcontext=value field=value",
encoderConfig{Message: true},
func(enc zapcore.Encoder) { enc.AddString("context", "value") },
[]zapcore.Field{zap.String("field", "value")},
),
Entry("empty with context and color",
"message\t"+tty.Mods("context=value field=value", ColorContext), "message\t"+tty.Mods("context=value field=value", ColorContext),
zapcore.EncoderConfig{MessageKey: "M"}, encoderConfig{Message: true, ColorContext: ColorContext},
func(enc zapcore.Encoder) { enc.AddString("context", "value") }, func(enc zapcore.Encoder) { enc.AddString("context", "value") },
[]zapcore.Field{zap.String("field", "value")}, []zapcore.Field{zap.String("field", "value")},
), ),
Entry("EncodeTime", Entry("EncodeTime",
"1000000001",
encoderConfig{Time: true, EncodeTime: zapcore.EpochNanosTimeEncoder},
nil,
nil,
),
Entry("EncodeTime with color",
tty.Mods("1000000001", ColorTime), tty.Mods("1000000001", ColorTime),
zapcore.EncoderConfig{TimeKey: "T", EncodeTime: zapcore.EpochNanosTimeEncoder}, encoderConfig{Time: true, EncodeTime: zapcore.EpochNanosTimeEncoder, ColorTime: ColorTime},
nil, nil,
nil, nil,
), ),
Entry("EncodeLevel", Entry("EncodeLevel",
"debug",
encoderConfig{Level: true, EncodeLevel: zapcore.LowercaseLevelEncoder},
nil,
nil,
),
Entry("EncodeLevel with color",
tty.Mods("debug", ColorLevels[zapcore.DebugLevel]), tty.Mods("debug", ColorLevels[zapcore.DebugLevel]),
zapcore.EncoderConfig{LevelKey: "L", EncodeLevel: zapcore.LowercaseLevelEncoder}, encoderConfig{Level: true, EncodeLevel: zapcore.LowercaseLevelEncoder, ColorLevel: ColorLevel},
nil, nil,
nil, nil,
), ),
Entry("EncodeName", Entry("EncodeName",
"test",
encoderConfig{Name: true, EncodeName: zapcore.FullNameEncoder},
nil,
nil,
),
Entry("EncodeName with color",
tty.Mods("test", ColorName), tty.Mods("test", ColorName),
zapcore.EncoderConfig{NameKey: "N", EncodeName: zapcore.FullNameEncoder}, encoderConfig{Name: true, EncodeName: zapcore.FullNameEncoder, ColorName: ColorName},
nil, nil,
nil, nil,
), ),
Entry("EncodeCaller", Entry("EncodeCaller",
"arthur/philip/dent/h2g2.go:42",
encoderConfig{Caller: true, EncodeCaller: zapcore.FullCallerEncoder},
nil,
nil,
),
Entry("EncodeCalle with color",
tty.Mods("arthur/philip/dent/h2g2.go:42", ColorCaller), tty.Mods("arthur/philip/dent/h2g2.go:42", ColorCaller),
zapcore.EncoderConfig{CallerKey: "C", EncodeCaller: zapcore.FullCallerEncoder}, encoderConfig{Caller: true, EncodeCaller: zapcore.FullCallerEncoder, ColorCaller: ColorCaller},
nil, nil,
nil, nil,
), ),
Entry("EncodeMessage", Entry("EncodeMessage",
"message", "message",
zapcore.EncoderConfig{MessageKey: "M"}, encoderConfig{Message: true},
nil, nil,
nil, nil,
), ),
Entry("StracktraceKey", Entry("EncodeMessage with color",
"message",
encoderConfig{Message: true},
nil,
nil,
),
Entry("Stracktrace",
"stacktrace\nwith multiple lines\n\tand tabs\n",
encoderConfig{Stacktrace: true},
nil,
nil,
),
Entry("Stracktrace with color",
tty.Mods("stacktrace\nwith multiple lines\n\tand tabs\n", ColorStacktrace), tty.Mods("stacktrace\nwith multiple lines\n\tand tabs\n", ColorStacktrace),
zapcore.EncoderConfig{StacktraceKey: "S"}, encoderConfig{Stacktrace: true, ColorStacktrace: ColorStacktrace},
nil, nil,
nil, nil,
), ),
Entry("LineEnding", Entry("LineEnding",
"", "",
zapcore.EncoderConfig{LineEnding: "<EOL>"}, encoderConfig{LineEnding: "<EOL>"},
nil, nil,
nil, nil,
), ),
@@ -536,7 +593,7 @@ var _ = Context("encoder", func() {
expected string, expected string,
timeEncoder zapcore.TimeEncoder, timeEncoder zapcore.TimeEncoder,
) { ) {
enc := newEncoder(encoderConfig{EncoderConfig: zapcore.EncoderConfig{EncodeTime: timeEncoder}}) enc := newEncoder(encoderConfig{EncodeTime: timeEncoder})
enc.quote = '"' enc.quote = '"'
enc.AddTime("ts", ts) enc.AddTime("ts", ts)
@@ -555,7 +612,7 @@ var _ = Context("encoder", func() {
expected string, expected string,
durationEncoder zapcore.DurationEncoder, durationEncoder zapcore.DurationEncoder,
) { ) {
enc := newEncoder(encoderConfig{EncoderConfig: zapcore.EncoderConfig{EncodeDuration: durationEncoder}}) enc := newEncoder(encoderConfig{EncodeDuration: durationEncoder})
enc.quote = '"' enc.quote = '"'
enc.AddDuration("duration", duration) enc.AddDuration("duration", duration)

View File

@@ -80,7 +80,7 @@ var _ = Describe("filter", func() {
defer logger.Sync() //nolint:errcheck defer logger.Sync() //nolint:errcheck
rule := new(log.AtomicFilterRule) rule := new(log.AtomicFilterRule)
rule.Store(log.NewFilterRule(log.MustParseRules("demo*"))) rule.Store(log.NewFilterRule(log.MustParseRules("*:demo*")))
logger = logger.WithOptions(zap.WrapCore(func(c zapcore.Core) zapcore.Core { logger = logger.WithOptions(zap.WrapCore(func(c zapcore.Core) zapcore.Core {
return log.NewFilteredCore(c, rule) return log.NewFilteredCore(c, rule)
@@ -96,7 +96,7 @@ var _ = Describe("filter", func() {
}) })
It("new logger", func() { It("new logger", func() {
logger, logs := makeLogger(log.MustParseRules("demo*")) logger, logs := makeLogger(log.MustParseRules("*:demo*"))
defer logger.Sync() //nolint:errcheck defer logger.Sync() //nolint:errcheck
logger.Debug("hello world!") logger.Debug("hello world!")
@@ -141,8 +141,8 @@ var _ = Describe("filter", func() {
logger.Debug("hello multiverse!") logger.Debug("hello multiverse!")
Expect(logs.All()).To(HaveExactElements( Expect(logs.All()).To(HaveExactElements(
MatchEntry(zapcore.Entry{Message: "hello city!"}), MatchEntry(zapcore.Entry{Message: "hello planet!"}),
MatchEntry(zapcore.Entry{Message: "hello solar system!"}), MatchEntry(zapcore.Entry{Message: "hello multiverse!"}),
)) ))
}) })
@@ -396,29 +396,27 @@ var _ = Describe("filter", func() {
}, },
Entry("empty", "", "", nil), Entry("empty", "", "", nil),
Entry("everything", "*", everything, nil), Entry("everything", "*", everything, nil),
Entry("debug+", "debug+:*", everything, nil), Entry("debug+", "debug:*", everything, nil),
Entry("all-debug", "debug:*", allDebug, nil), Entry("all-debug", "=debug:*", allDebug, nil),
Entry("all-info", "info:*", allInfo, nil), Entry("all-info", "=info:*", allInfo, nil),
Entry("all-warn", "warn:*", allWarn, nil), Entry("all-warn", "=warn:*", allWarn, nil),
Entry("all-error", "error:*", allError, nil), Entry("all-error", "=error:*", allError, nil),
Entry("all-info-and-warn-1", "info,warn:*", "bcfgjknorsvwz034", nil), Entry("all-info-and-warn-1", "=info,=warn:*", "bcfgjknorsvwz034", nil),
Entry("all-info-and-warn-2", "info:* warn:*", "bcfgjknorsvwz034", nil), Entry("all-info-and-warn-2", "=info:* =warn:*", "bcfgjknorsvwz034", nil),
Entry("warn+", "warn+:*", "cdghklopstwx0145", nil), Entry("warn+", "warn:*", "cdghklopstwx0145", nil),
Entry("redundant-1", "info,info:* info:*", allInfo, nil), Entry("redundant-1", "=info,=info:* =info:*", allInfo, nil),
Entry("redundant-2", "* *:* info:*", everything, nil), Entry("redundant-2", "* *:* =info:*", everything, nil),
Entry("foo-ns", "foo", "efgh", nil), Entry("foo-ns", "*:foo", "efgh", nil),
Entry("foo-ns-wildcard", "*:foo", "efgh", nil), Entry("foo-ns-debug,info", "=debug,=info:foo", "ef", nil),
Entry("foo-ns-debug,info", "debug,info:foo", "ef", nil), Entry("foo.star-ns", "*:foo.*", "qrstuvwx", nil),
Entry("foo.star-ns", "foo.*", "qrstuvwx", nil), Entry("foo.star-ns-debug,info", "=debug,=info:foo.*", "qruv", nil),
Entry("foo.star-ns-wildcard", "*:foo.*", "qrstuvwx", nil), Entry("all-in-one", "*:foo =debug:foo.* =info,=warn:bar error:*", "defghjklpqtux15", nil),
Entry("foo.star-ns-debug,info", "debug,info:foo.*", "qruv", nil), Entry("exclude-1", "=info:test,foo*,-foo.foo", "fr", nil),
Entry("all-in-one", "*:foo debug:foo.* info,warn:bar error:*", "defghjklpqtux15", nil), Entry("exclude-2", "=info:test,foo*,-*.foo", "fr", nil),
Entry("exclude-1", "info:test,foo*,-foo.foo", "fr", nil), Entry("exclude-3", "*:test,*.foo,-foo.*", "yz012345", nil),
Entry("exclude-2", "info:test,foo*,-*.foo", "fr", nil), Entry("exclude-4", "*:*,-foo,-bar", "abcdmnopqrstuvwxyz012345", nil),
Entry("exclude-3", "test,*.foo,-foo.*", "yz012345", nil), Entry("exclude-5", "*:foo*,bar*,-foo.foo,-bar.foo", "efghijklqrst", nil),
Entry("exclude-4", "*,-foo,-bar", "abcdmnopqrstuvwxyz012345", nil), Entry("exclude-6", "*:foo*,-foo.foo,bar*,-bar.foo", "efghijklqrst", nil),
Entry("exclude-5", "foo*,bar*,-foo.foo,-bar.foo", "efghijklqrst", nil),
Entry("exclude-6", "foo*,-foo.foo,bar*,-bar.foo", "efghijklqrst", nil),
Entry("invalid-left", "invalid:*", "", log.ErrUnsupportedKeyword), Entry("invalid-left", "invalid:*", "", log.ErrUnsupportedKeyword),
Entry("missing-left", ":*", "", log.ErrBadSyntax), Entry("missing-left", ":*", "", log.ErrBadSyntax),
Entry("missing-right", ":*", "", log.ErrBadSyntax), Entry("missing-right", ":*", "", log.ErrBadSyntax),
@@ -451,35 +449,35 @@ var _ = Describe("filter", func() {
Expect(entry).To(BeNil()) Expect(entry).To(BeNil())
} }
}, },
Entry(nil, "", "", false), Entry("1", "", "", false),
Entry(nil, "", "foo", false), Entry("2", "", "foo", false),
Entry(nil, "*", "", true), Entry("3", "*", "", true),
Entry(nil, "*", "foo", true), Entry("4", "*", "foo", true),
Entry(nil, "*:foo", "", false), Entry("5", "*:foo", "", false),
Entry(nil, "*:foo", "foo", true), Entry("6", "*:foo", "foo", true),
Entry(nil, "*:foo", "bar", false), Entry("7", "*:foo", "bar", false),
) )
DescribeTable("any level", DescribeTable("any level",
func(name string, expected bool) { func(name string, expected bool) {
logger, _ := makeLogger(log.MustParseRules("debug:*.* info:demo*")) logger, _ := makeLogger(log.MustParseRules("=debug:*.* =info:demo*"))
if name != "" { if name != "" {
logger = logger.Named(name) logger = logger.Named(name)
} }
Expect(log.CheckAnyLevel(logger)).To(Equal(expected)) Expect(log.CheckAnyLevel(logger)).To(Equal(expected))
}, },
Entry(nil, "", false), Entry("1", "", false),
Entry(nil, "demo", true), Entry("2", "demo", true),
Entry(nil, "blahdemo", false), Entry("3", "blahdemo", false),
Entry(nil, "demoblah", true), Entry("4", "demoblah", true),
Entry(nil, "blah", false), Entry("5", "blah", false),
Entry(nil, "blah.blah", true), Entry("6", "blah.blah", true),
) )
DescribeTable("level", DescribeTable("level",
func(name string, lvl zapcore.Level, expected bool) { func(name string, lvl zapcore.Level, expected bool) {
logger, _ := makeLogger(log.MustParseRules("debug:*.* info:demo*")) logger, _ := makeLogger(log.MustParseRules("=debug:*.* =info:demo*"))
if name != "" { if name != "" {
logger = logger.Named(name) logger = logger.Named(name)
@@ -487,18 +485,18 @@ var _ = Describe("filter", func() {
Expect(log.CheckLevel(logger, lvl)).To(Equal(expected)) Expect(log.CheckLevel(logger, lvl)).To(Equal(expected))
}, },
Entry(nil, "", zap.DebugLevel, false), Entry("1", "", zap.DebugLevel, false),
Entry(nil, "demo", zap.DebugLevel, false), Entry("2", "demo", zap.DebugLevel, false),
Entry(nil, "blahdemo", zap.DebugLevel, false), Entry("3", "blahdemo", zap.DebugLevel, false),
Entry(nil, "demoblah", zap.DebugLevel, false), Entry("4", "demoblah", zap.DebugLevel, false),
Entry(nil, "blah", zap.DebugLevel, false), Entry("5", "blah", zap.DebugLevel, false),
Entry(nil, "blah.blah", zap.DebugLevel, true), Entry("6", "blah.blah", zap.DebugLevel, true),
Entry(nil, "", zap.InfoLevel, false), Entry("7", "", zap.InfoLevel, false),
Entry(nil, "demo", zap.InfoLevel, true), Entry("8", "demo", zap.InfoLevel, true),
Entry(nil, "blahdemo", zap.InfoLevel, false), Entry("9", "blahdemo", zap.InfoLevel, false),
Entry(nil, "demoblah", zap.InfoLevel, true), Entry("10", "demoblah", zap.InfoLevel, true),
Entry(nil, "blah", zap.InfoLevel, false), Entry("11", "blah", zap.InfoLevel, false),
Entry(nil, "blah.blah", zap.InfoLevel, false), Entry("12", "blah.blah", zap.InfoLevel, false),
) )
}) })
@@ -524,7 +522,7 @@ var _ = Describe("filter", func() {
}) })
It("Check", func() { It("Check", func() {
logger, logs := makeLogger(log.MustParseRules("debug:* info:demo*")) logger, logs := makeLogger(log.MustParseRules("=debug:* =info:demo*"))
defer logger.Sync() //nolint:errcheck defer logger.Sync() //nolint:errcheck
ce := logger.Check(zap.DebugLevel, "a") ce := logger.Check(zap.DebugLevel, "a")

View File

@@ -7,6 +7,7 @@ package log
import ( import (
"os" "os"
"github.com/onsi/ginkgo/v2"
"go.uber.org/zap" "go.uber.org/zap"
"go.uber.org/zap/zapcore" "go.uber.org/zap/zapcore"
"google.golang.org/grpc/grpclog" "google.golang.org/grpc/grpclog"
@@ -25,10 +26,13 @@ func DebugLevel(verbosity int) Level {
} }
func openSink(path string) zapcore.WriteSyncer { func openSink(path string) zapcore.WriteSyncer {
if path == "stdout" { switch path {
case "stdout":
return os.Stdout return os.Stdout
} else if path == "stderr" { case "stderr":
return os.Stderr return os.Stderr
case "ginkgo":
return &ginkgoSyncWriter{ginkgo.GinkgoWriter}
} }
f, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0o644) f, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0o644)
@@ -45,21 +49,20 @@ func (e *alwaysEnabled) Enabled(zapcore.Level) bool { return true }
func SetupLogging(rule string, paths []string, color bool) (logger *Logger, err error) { func SetupLogging(rule string, paths []string, color bool) (logger *Logger, err error) {
cfg := encoderConfig{ cfg := encoderConfig{
EncoderConfig: zapcore.EncoderConfig{ Time: true,
TimeKey: "T", Level: true,
LevelKey: "L", Name: true,
NameKey: "N", Message: true,
CallerKey: "C",
FunctionKey: zapcore.OmitKey,
MessageKey: "M",
StacktraceKey: "S",
ConsoleSeparator: " ", ConsoleSeparator: " ",
LineEnding: zapcore.DefaultLineEnding, LineEnding: zapcore.DefaultLineEnding,
EncodeTime: zapcore.TimeEncoderOfLayout("15:04:05.000000"), EncodeTime: zapcore.TimeEncoderOfLayout("15:04:05.000000"),
EncodeDuration: zapcore.StringDurationEncoder, EncodeDuration: zapcore.StringDurationEncoder,
EncodeCaller: zapcore.ShortCallerEncoder, EncodeCaller: zapcore.ShortCallerEncoder,
EncodeLevel: levelEncoder, EncodeLevel: levelEncoder,
}, }
if rule == "" {
rule = "*"
} }
if color { if color {
@@ -69,10 +72,6 @@ func SetupLogging(rule string, paths []string, color bool) (logger *Logger, err
cfg.ColorName = ColorName cfg.ColorName = ColorName
cfg.ColorCaller = ColorCaller cfg.ColorCaller = ColorCaller
cfg.ColorLevel = ColorLevel cfg.ColorLevel = ColorLevel
} else {
cfg.ColorLevel = func(lvl zapcore.Level) string {
return ""
}
} }
wss := []zapcore.WriteSyncer{} wss := []zapcore.WriteSyncer{}
@@ -89,10 +88,6 @@ func SetupLogging(rule string, paths []string, color bool) (logger *Logger, err
enc := newEncoder(cfg) enc := newEncoder(cfg)
core := zapcore.NewCore(enc, ws, &alwaysEnabled{}) core := zapcore.NewCore(enc, ws, &alwaysEnabled{})
if rule == "" {
rule = "*"
}
filterRule, err := ParseFilterRule(rule) filterRule, err := ParseFilterRule(rule)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -8,7 +8,6 @@ import (
stdlog "log" stdlog "log"
"os" "os"
"path/filepath" "path/filepath"
"regexp"
"testing" "testing"
"github.com/pion/zapion" "github.com/pion/zapion"
@@ -16,7 +15,6 @@ import (
"google.golang.org/grpc/grpclog" "google.golang.org/grpc/grpclog"
"github.com/stv0g/cunicu/pkg/log" "github.com/stv0g/cunicu/pkg/log"
"github.com/stv0g/cunicu/pkg/tty"
. "github.com/onsi/ginkgo/v2" . "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
@@ -43,11 +41,13 @@ var _ = Context("log", Label("broken-on-windows"), func() {
os.Setenv("GRPC_GO_LOG_VERBOSITY_LEVEL", "2") os.Setenv("GRPC_GO_LOG_VERBOSITY_LEVEL", "2")
os.Setenv("GRPC_GO_LOG_SEVERITY_LEVEL", lvl.String()) os.Setenv("GRPC_GO_LOG_SEVERITY_LEVEL", lvl.String())
os.Setenv("PION_LOG", lvl.String()) os.Setenv("PION_LOG", lvl.String())
log.ResetWidths()
}) })
JustBeforeEach(func() { JustBeforeEach(func() {
var err error var err error
logger, err = log.SetupLogging("", []string{logPath}, true) logger, err = log.SetupLogging("", []string{logPath}, false)
Expect(err).To(Succeed()) Expect(err).To(Succeed())
}) })
@@ -96,9 +96,9 @@ var _ = Context("log", Label("broken-on-windows"), func() {
Expect(err).To(Succeed(), "Failed to read standard log contents: %s", err) Expect(err).To(Succeed(), "Failed to read standard log contents: %s", err)
Expect(logContents).NotTo(BeEmpty()) Expect(logContents).NotTo(BeEmpty())
regexTime := regexpQuoteColor(`\d{2}:\d{2}:\d{2}.\d{6}`, log.ColorTime) + " " regexTime := `\d{2}:\d{2}:\d{2}.\d{6} `
regexLevel := regexpQuoteColor(lvl.String(), log.ColorLevel(lvl)) + " " regexLevel := lvl.String() + " "
regexName := regexpQuoteColor(name, log.ColorName) + " " regexName := name + " "
var regex string var regex string
if name != "" { if name != "" {
@@ -110,11 +110,3 @@ var _ = Context("log", Label("broken-on-windows"), func() {
Expect(string(logContents)).To(MatchRegexp(regex), "Log output '%s' does not match regex '%s'", logContents, regex) Expect(string(logContents)).To(MatchRegexp(regex), "Log output '%s' does not match regex '%s'", logContents, regex)
}) })
}) })
func regexpQuoteColor(str, color string) string {
if color == "" {
return str
}
return regexp.QuoteMeta(color) + str + regexp.QuoteMeta(tty.Reset)
}

18
pkg/log/sink_ginkgo.go Normal file
View File

@@ -0,0 +1,18 @@
// SPDX-FileCopyrightText: 2023 Steffen Vogel <post@steffenvogel.de>
// SPDX-License-Identifier: Apache-2.0
package log
import "github.com/onsi/ginkgo/v2"
type ginkgoSyncWriter struct {
ginkgo.GinkgoWriterInterface
}
func (w *ginkgoSyncWriter) Close() error {
return nil
}
func (w *ginkgoSyncWriter) Sync() error {
return nil
}

View File

@@ -15,12 +15,11 @@ import (
) )
func TestSuite(t *testing.T) { func TestSuite(t *testing.T) {
test.SetupLogging()
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
RunSpecs(t, "Network Suite") RunSpecs(t, "Network Suite")
} }
var _ = test.SetupLogging()
var _ = Context("endpoint comparisons", func() { var _ = Context("endpoint comparisons", func() {
It("to be equal", func() { It("to be equal", func() {
a := net.UDPAddr{ a := net.UDPAddr{

View File

@@ -13,8 +13,7 @@ import (
) )
func TestSuite(t *testing.T) { func TestSuite(t *testing.T) {
test.SetupLogging()
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
RunSpecs(t, "Protobuf Suite") RunSpecs(t, "Protobuf Suite")
} }
var _ = test.SetupLogging()

View File

@@ -18,12 +18,11 @@ import (
) )
func TestSuite(t *testing.T) { func TestSuite(t *testing.T) {
test.SetupLogging()
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
RunSpecs(t, "Protobuf Suite") RunSpecs(t, "Protobuf Suite")
} }
var _ = test.SetupLogging()
var _ = Describe("message encryption", func() { var _ = Describe("message encryption", func() {
var c epdiscproto.Candidate var c epdiscproto.Candidate
var ourKP, theirKP *crypto.KeyPair var ourKP, theirKP *crypto.KeyPair

View File

@@ -188,7 +188,7 @@ func extractToFile(buf []byte, filename, target string) (int64, error) {
return -1, err return -1, err
} }
n, err := io.Copy(dest, rd) n, err := io.Copy(dest, rd) //nolint:gosec
if err != nil { if err != nil {
_ = dest.Close() _ = dest.Close()
_ = os.Remove(dest.Name()) _ = os.Remove(dest.Name())

View File

@@ -8,6 +8,7 @@ import (
"testing" "testing"
"github.com/stv0g/cunicu/pkg/buildinfo" "github.com/stv0g/cunicu/pkg/buildinfo"
"github.com/stv0g/cunicu/pkg/log"
"github.com/stv0g/cunicu/pkg/selfupdate" "github.com/stv0g/cunicu/pkg/selfupdate"
"github.com/stv0g/cunicu/test" "github.com/stv0g/cunicu/test"
@@ -16,14 +17,13 @@ import (
) )
func TestSuite(t *testing.T) { func TestSuite(t *testing.T) {
test.SetupLogging()
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
RunSpecs(t, "Self-update Suite") RunSpecs(t, "Self-update Suite")
} }
var logger = test.SetupLogging()
var _ = It("self-update", Pending, func() { var _ = It("self-update", Pending, func() {
logger := logger.Named("self-update") logger := log.Global.Named("self-update")
output := filepath.Join(GinkgoT().TempDir(), "cunicu") output := filepath.Join(GinkgoT().TempDir(), "cunicu")

View File

@@ -16,12 +16,11 @@ import (
) )
func TestSuite(t *testing.T) { func TestSuite(t *testing.T) {
test.SetupLogging()
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
RunSpecs(t, "gRPC Backend Suite") RunSpecs(t, "gRPC Backend Suite")
} }
var _ = test.SetupLogging()
var _ = Describe("gRPC backend", func() { var _ = Describe("gRPC backend", func() {
var svr *grpc.Server var svr *grpc.Server
var l *net.TCPListener var l *net.TCPListener

View File

@@ -16,12 +16,11 @@ import (
) )
func TestSuite(t *testing.T) { func TestSuite(t *testing.T) {
test.SetupLogging()
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
RunSpecs(t, "In-Process Backend Suite") RunSpecs(t, "In-Process Backend Suite")
} }
var _ = test.SetupLogging()
var _ = Describe("inprocess backend", func() { var _ = Describe("inprocess backend", func() {
u := url.URL{ u := url.URL{
Scheme: "inprocess", Scheme: "inprocess",

View File

@@ -13,8 +13,7 @@ import (
) )
func TestSuite(t *testing.T) { func TestSuite(t *testing.T) {
test.SetupLogging()
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
RunSpecs(t, "Signaling Suite") RunSpecs(t, "Signaling Suite")
} }
var _ = test.SetupLogging()

View File

@@ -16,12 +16,11 @@ import (
) )
func TestSuite(t *testing.T) { func TestSuite(t *testing.T) {
test.SetupLogging()
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
RunSpecs(t, "TTY Suite") RunSpecs(t, "TTY Suite")
} }
var _ = test.SetupLogging()
var _ = Context("IsATTY", func() { var _ = Context("IsATTY", func() {
if test.IsCI() { if test.IsCI() {
It("is false in CI runners", func() { It("is false in CI runners", func() {

View File

@@ -16,12 +16,11 @@ import (
) )
func TestSuite(t *testing.T) { func TestSuite(t *testing.T) {
test.SetupLogging()
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
RunSpecs(t, "Slices Suite") RunSpecs(t, "Slices Suite")
} }
var _ = test.SetupLogging()
var _ = Context("slice", func() { var _ = Context("slice", func() {
var s []int var s []int

View File

@@ -13,8 +13,7 @@ import (
) )
func TestSuite(t *testing.T) { func TestSuite(t *testing.T) {
test.SetupLogging()
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
RunSpecs(t, "Types Suite") RunSpecs(t, "Types Suite")
} }
var _ = test.SetupLogging()

View File

@@ -13,8 +13,7 @@ import (
) )
func TestSuite(t *testing.T) { func TestSuite(t *testing.T) {
test.SetupLogging()
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
RunSpecs(t, "WireGuard Suite") RunSpecs(t, "WireGuard Suite")
} }
var _ = test.SetupLogging()

View File

@@ -6,30 +6,15 @@ package test
import ( import (
"fmt" "fmt"
"net/url"
"os" "os"
"path/filepath" "path/filepath"
"strings"
"github.com/onsi/ginkgo/v2" "github.com/onsi/ginkgo/v2"
"go.uber.org/zap"
"github.com/stv0g/cunicu/pkg/log" "github.com/stv0g/cunicu/pkg/log"
"github.com/stv0g/cunicu/pkg/tty" "github.com/stv0g/cunicu/pkg/tty"
) )
type writerWrapper struct {
ginkgo.GinkgoWriterInterface
}
func (w *writerWrapper) Close() error {
return nil
}
func (w *writerWrapper) Sync() error {
return nil
}
func SetupLogging() *log.Logger { func SetupLogging() *log.Logger {
logger, err := SetupLoggingWithFile("", false) logger, err := SetupLoggingWithFile("", false)
if err != nil { if err != nil {
@@ -40,15 +25,7 @@ func SetupLogging() *log.Logger {
} }
func SetupLoggingWithFile(fn string, truncate bool) (*log.Logger, error) { func SetupLoggingWithFile(fn string, truncate bool) (*log.Logger, error) {
if err := zap.RegisterSink("ginkgo", func(u *url.URL) (zap.Sink, error) { outputPaths := []string{"ginkgo"}
return &writerWrapper{
GinkgoWriterInterface: ginkgo.GinkgoWriter,
}, nil
}); err != nil && !strings.Contains(err.Error(), "already registered") {
panic(err)
}
outputPaths := []string{"ginkgo:"}
if fn != "" { if fn != "" {
// Create parent directories for log file // Create parent directories for log file

View File

@@ -14,12 +14,11 @@ import (
) )
func TestSuite(t *testing.T) { func TestSuite(t *testing.T) {
test.SetupLogging()
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
RunSpecs(t, "Test Helper Suite") RunSpecs(t, "Test Helper Suite")
} }
var _ = test.SetupLogging()
var _ = Describe("entropy", func() { var _ = Describe("entropy", func() {
Specify("that the entropy of an empty slice is zero", func() { Specify("that the entropy of an empty slice is zero", func() {
Expect(test.Entropy([]byte{})).To(BeNumerically("==", 0)) Expect(test.Entropy([]byte{})).To(BeNumerically("==", 0))