aboutsummaryrefslogtreecommitdiffstats
path: root/modules/test
diff options
context:
space:
mode:
authorwxiaoguang <wxiaoguang@gmail.com>2023-04-22 04:32:25 +0800
committerGitHub <noreply@github.com>2023-04-21 16:32:25 -0400
commit911975059a50e71632d33567da7000a97aa28f22 (patch)
tree336ccc3a6ca64ab0967daf4cbbd8f908f4dac078 /modules/test
parent65fe0fb22cfb264f0b756065d0c3ce7a17d7e55b (diff)
downloadgitea-911975059a50e71632d33567da7000a97aa28f22.tar.gz
gitea-911975059a50e71632d33567da7000a97aa28f22.zip
Improve test logger (#24235)
Before, there was a `log/buffer.go`, but that design is not general, and it introduces a lot of irrelevant `Content() (string, error) ` and `return "", fmt.Errorf("not supported")` . And the old `log/buffer.go` is difficult to use, developers have to write a lot of `Contains` and `Sleep` code. The new `LogChecker` is designed to be a general approach to help to assert some messages appearing or not appearing in logs.
Diffstat (limited to 'modules/test')
-rw-r--r--modules/test/logchecker.go116
-rw-r--r--modules/test/logchecker_test.go47
2 files changed, 163 insertions, 0 deletions
diff --git a/modules/test/logchecker.go b/modules/test/logchecker.go
new file mode 100644
index 0000000000..8f8c753c76
--- /dev/null
+++ b/modules/test/logchecker.go
@@ -0,0 +1,116 @@
+// Copyright 2023 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package test
+
+import (
+ "strconv"
+ "strings"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ "code.gitea.io/gitea/modules/log"
+)
+
+type LogChecker struct {
+ logger *log.MultiChannelledLogger
+ loggerName string
+ eventLoggerName string
+
+ filterMessages []string
+ filtered []bool
+
+ stopMark string
+ stopped bool
+
+ mu sync.Mutex
+}
+
+func (lc *LogChecker) LogEvent(event *log.Event) error {
+ lc.mu.Lock()
+ defer lc.mu.Unlock()
+ for i, msg := range lc.filterMessages {
+ if strings.Contains(event.GetMsg(), msg) {
+ lc.filtered[i] = true
+ }
+ }
+ if strings.Contains(event.GetMsg(), lc.stopMark) {
+ lc.stopped = true
+ }
+ return nil
+}
+
+func (lc *LogChecker) Close() {}
+
+func (lc *LogChecker) Flush() {}
+
+func (lc *LogChecker) GetLevel() log.Level {
+ return log.TRACE
+}
+
+func (lc *LogChecker) GetStacktraceLevel() log.Level {
+ return log.NONE
+}
+
+func (lc *LogChecker) GetName() string {
+ return lc.eventLoggerName
+}
+
+func (lc *LogChecker) ReleaseReopen() error {
+ return nil
+}
+
+var checkerIndex int64
+
+func NewLogChecker(loggerName string) (logChecker *LogChecker, cancel func()) {
+ logger := log.GetLogger(loggerName)
+ newCheckerIndex := atomic.AddInt64(&checkerIndex, 1)
+ lc := &LogChecker{
+ logger: logger,
+ loggerName: loggerName,
+ eventLoggerName: "TestLogChecker-" + strconv.FormatInt(newCheckerIndex, 10),
+ }
+ if err := logger.AddLogger(lc); err != nil {
+ panic(err) // it's impossible
+ }
+ return lc, func() { _, _ = logger.DelLogger(lc.GetName()) }
+}
+
+// Filter will make the `Check` function to check if these logs are outputted.
+func (lc *LogChecker) Filter(msgs ...string) *LogChecker {
+ lc.mu.Lock()
+ defer lc.mu.Unlock()
+ lc.filterMessages = make([]string, len(msgs))
+ copy(lc.filterMessages, msgs)
+ lc.filtered = make([]bool, len(lc.filterMessages))
+ return lc
+}
+
+func (lc *LogChecker) StopMark(msg string) *LogChecker {
+ lc.mu.Lock()
+ defer lc.mu.Unlock()
+ lc.stopMark = msg
+ lc.stopped = false
+ return lc
+}
+
+// Check returns the filtered slice and whether the stop mark is reached.
+func (lc *LogChecker) Check(d time.Duration) (filtered []bool, stopped bool) {
+ stop := time.Now().Add(d)
+
+ for {
+ lc.mu.Lock()
+ stopped = lc.stopped
+ lc.mu.Unlock()
+
+ if time.Now().After(stop) || stopped {
+ lc.mu.Lock()
+ f := make([]bool, len(lc.filtered))
+ copy(f, lc.filtered)
+ lc.mu.Unlock()
+ return f, stopped
+ }
+ time.Sleep(10 * time.Millisecond)
+ }
+}
diff --git a/modules/test/logchecker_test.go b/modules/test/logchecker_test.go
new file mode 100644
index 0000000000..1ed7f427f4
--- /dev/null
+++ b/modules/test/logchecker_test.go
@@ -0,0 +1,47 @@
+// Copyright 2023 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package test
+
+import (
+ "testing"
+ "time"
+
+ "code.gitea.io/gitea/modules/log"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestLogChecker(t *testing.T) {
+ _ = log.NewLogger(1000, "console", "console", `{"level":"info","stacktracelevel":"NONE","stderr":true}`)
+
+ lc, cleanup := NewLogChecker(log.DEFAULT)
+ defer cleanup()
+
+ lc.Filter("First", "Third").StopMark("End")
+ log.Info("test")
+
+ filtered, stopped := lc.Check(100 * time.Millisecond)
+ assert.EqualValues(t, []bool{false, false}, filtered)
+ assert.EqualValues(t, false, stopped)
+
+ log.Info("First")
+ filtered, stopped = lc.Check(100 * time.Millisecond)
+ assert.EqualValues(t, []bool{true, false}, filtered)
+ assert.EqualValues(t, false, stopped)
+
+ log.Info("Second")
+ filtered, stopped = lc.Check(100 * time.Millisecond)
+ assert.EqualValues(t, []bool{true, false}, filtered)
+ assert.EqualValues(t, false, stopped)
+
+ log.Info("Third")
+ filtered, stopped = lc.Check(100 * time.Millisecond)
+ assert.EqualValues(t, []bool{true, true}, filtered)
+ assert.EqualValues(t, false, stopped)
+
+ log.Info("End")
+ filtered, stopped = lc.Check(100 * time.Millisecond)
+ assert.EqualValues(t, []bool{true, true}, filtered)
+ assert.EqualValues(t, true, stopped)
+}