From 7d0ed8e9c1250bbdccb4a77e3a52d41b1da7439d Mon Sep 17 00:00:00 2001 From: Dan Gottlieb Date: Thu, 13 Jun 2024 13:59:03 -0400 Subject: [PATCH] RSDK-7917: Only output `TestReconfigureParity` logs on failure. (#4076) --- logging/logging.go | 33 +++++++++++++++++++++++++++++ robot/impl/resource_manager_test.go | 8 ++++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/logging/logging.go b/logging/logging.go index 8f723a2d174..aba0ef32c48 100644 --- a/logging/logging.go +++ b/logging/logging.go @@ -8,6 +8,7 @@ import ( "go.uber.org/zap" "go.uber.org/zap/zapcore" "go.uber.org/zap/zaptest/observer" + "go.viam.com/utils" ) var ( @@ -110,3 +111,35 @@ func NewObservedTestLogger(tb testing.TB) (Logger, *observer.ObservedLogs) { return logger, observedLogs } + +// MemLogger stores test logs in memory. And can write them on request with `OutputLogs`. +type MemLogger struct { + Logger + + tb testing.TB + observer *observer.ObservedLogs +} + +// OutputLogs writes in-memory logs to the test object MemLogger was constructed with. +func (memLogger *MemLogger) OutputLogs() { + appender := NewTestAppender(memLogger.tb) + for _, loggedEntry := range memLogger.observer.All() { + utils.UncheckedError(appender.Write(loggedEntry.Entry, loggedEntry.Context)) + } +} + +// NewInMemoryLogger creates a MemLogger that can be used to buffer test logs and output them on +// command. This is handy if a test is noisy, but the output is useful when the test fails. +func NewInMemoryLogger(tb testing.TB) *MemLogger { + observerCore, observedLogs := observer.New(zap.LevelEnablerFunc(zapcore.DebugLevel.Enabled)) + logger := &impl{ + name: "", + level: NewAtomicLevelAt(DEBUG), + appenders: []Appender{ + observerCore, + }, + testHelper: tb.Helper, + } + + return &MemLogger{logger, tb, observedLogs} +} diff --git a/robot/impl/resource_manager_test.go b/robot/impl/resource_manager_test.go index a893ea5d293..d06185af91b 100644 --- a/robot/impl/resource_manager_test.go +++ b/robot/impl/resource_manager_test.go @@ -1838,13 +1838,19 @@ func TestReconfigureParity(t *testing.T) { "data/diff_config_deps11.json", "data/diff_config_deps12.json", } - logger := logging.NewTestLogger(t) ctx := context.Background() testReconfigureParity := func(t *testing.T, initCfg, updateCfg string) { name := fmt.Sprintf("%s -> %s", initCfg, updateCfg) t.Run(name, func(t *testing.T) { t.Parallel() + // Capture logs for this sub-test run. Only output the logs if the test fails. + logger := logging.NewInMemoryLogger(t) + defer func() { + if t.Failed() { + logger.OutputLogs() + } + }() // Configuration may mutate `*config.Config`, so we read it from // file each time.