code.gitea.io/gitea@v1.22.3/modules/test/logchecker.go (about) 1 // Copyright 2023 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package test 5 6 import ( 7 "context" 8 "fmt" 9 "strings" 10 "sync" 11 "sync/atomic" 12 "time" 13 14 "code.gitea.io/gitea/modules/log" 15 ) 16 17 type LogChecker struct { 18 *log.EventWriterBaseImpl 19 20 filterMessages []string 21 filtered []bool 22 23 stopMark string 24 stopped bool 25 26 mu sync.Mutex 27 } 28 29 func (lc *LogChecker) Run(ctx context.Context) { 30 for { 31 select { 32 case <-ctx.Done(): 33 return 34 case event, ok := <-lc.Queue: 35 if !ok { 36 return 37 } 38 lc.checkLogEvent(event) 39 } 40 } 41 } 42 43 func (lc *LogChecker) checkLogEvent(event *log.EventFormatted) { 44 lc.mu.Lock() 45 defer lc.mu.Unlock() 46 for i, msg := range lc.filterMessages { 47 if strings.Contains(event.Origin.MsgSimpleText, msg) { 48 lc.filtered[i] = true 49 } 50 } 51 if strings.Contains(event.Origin.MsgSimpleText, lc.stopMark) { 52 lc.stopped = true 53 } 54 } 55 56 var checkerIndex int64 57 58 func NewLogChecker(namePrefix string) (logChecker *LogChecker, cancel func()) { 59 logger := log.GetManager().GetLogger(namePrefix) 60 newCheckerIndex := atomic.AddInt64(&checkerIndex, 1) 61 writerName := namePrefix + "-" + fmt.Sprint(newCheckerIndex) 62 63 lc := &LogChecker{} 64 lc.EventWriterBaseImpl = log.NewEventWriterBase(writerName, "test-log-checker", log.WriterMode{}) 65 logger.AddWriters(lc) 66 return lc, func() { _ = logger.RemoveWriter(writerName) } 67 } 68 69 // Filter will make the `Check` function to check if these logs are outputted. 70 func (lc *LogChecker) Filter(msgs ...string) *LogChecker { 71 lc.mu.Lock() 72 defer lc.mu.Unlock() 73 lc.filterMessages = make([]string, len(msgs)) 74 copy(lc.filterMessages, msgs) 75 lc.filtered = make([]bool, len(lc.filterMessages)) 76 return lc 77 } 78 79 func (lc *LogChecker) StopMark(msg string) *LogChecker { 80 lc.mu.Lock() 81 defer lc.mu.Unlock() 82 lc.stopMark = msg 83 lc.stopped = false 84 return lc 85 } 86 87 // Check returns the filtered slice and whether the stop mark is reached. 88 func (lc *LogChecker) Check(d time.Duration) (filtered []bool, stopped bool) { 89 stop := time.Now().Add(d) 90 91 for { 92 lc.mu.Lock() 93 stopped = lc.stopped 94 lc.mu.Unlock() 95 96 if time.Now().After(stop) || stopped { 97 lc.mu.Lock() 98 f := make([]bool, len(lc.filtered)) 99 copy(f, lc.filtered) 100 lc.mu.Unlock() 101 return f, stopped 102 } 103 time.Sleep(10 * time.Millisecond) 104 } 105 }