1
2
3
4
5
6
7 package integration
8
9 import (
10 "context"
11 "fmt"
12
13 "go.mongodb.org/mongo-driver/internal/logger"
14 "go.mongodb.org/mongo-driver/mongo/integration/mtest"
15 )
16
17 type testLogSink struct {
18 logs chan func() (int, string, []interface{})
19 bufferSize int
20 logsCount int
21 errsCh chan error
22 }
23
24 type logValidator func(order int, lvl int, msg string, kv ...interface{}) error
25
26 func newTestLogSink(ctx context.Context, mt *mtest.T, bufferSize int, validator logValidator) *testLogSink {
27 mt.Helper()
28
29 sink := &testLogSink{
30 logs: make(chan func() (int, string, []interface{}), bufferSize),
31 errsCh: make(chan error, bufferSize),
32 bufferSize: bufferSize,
33 }
34
35 go func() {
36 order := 0
37 for log := range sink.logs {
38 select {
39 case <-ctx.Done():
40 sink.errsCh <- ctx.Err()
41
42 return
43 default:
44 }
45
46 level, msg, args := log()
47 if err := validator(order, level, msg, args...); err != nil {
48 sink.errsCh <- fmt.Errorf("invalid log at position %d, level %d, and msg %q: %w", order,
49 level, msg, err)
50 }
51
52 order++
53 }
54
55 close(sink.errsCh)
56 }()
57
58 return sink
59 }
60
61 func (sink *testLogSink) Info(level int, msg string, keysAndValues ...interface{}) {
62 sink.logs <- func() (int, string, []interface{}) {
63 return level, msg, keysAndValues
64 }
65
66 if sink.logsCount++; sink.logsCount == sink.bufferSize {
67 close(sink.logs)
68 }
69 }
70
71 func (sink *testLogSink) Error(err error, msg string, keysAndValues ...interface{}) {
72 keysAndValues = append(keysAndValues, "error", err)
73 sink.Info(int(logger.LevelInfo), msg, keysAndValues)
74 }
75
76 func (sink *testLogSink) errs() <-chan error {
77 return sink.errsCh
78 }
79
80 func findLogValue(mt *mtest.T, key string, values ...interface{}) interface{} {
81 mt.Helper()
82
83 for i := 0; i < len(values); i += 2 {
84 if values[i] == key {
85 return values[i+1]
86 }
87 }
88
89 return nil
90 }
91
92 type truncValidator func(values ...interface{}) error
93
94
95
96
97
98
99 func newTruncValidator(mt *mtest.T, key string, cond func(string) error) truncValidator {
100 mt.Helper()
101
102 return func(values ...interface{}) error {
103 cmd := findLogValue(mt, key, values...)
104 if cmd == nil {
105 return fmt.Errorf("%q not found in keys and values", key)
106 }
107
108 cmdStr, ok := cmd.(string)
109
110 if !ok {
111 return fmt.Errorf("command is not a string")
112 }
113
114 return cond(cmdStr)
115 }
116 }
117
View as plain text