blob: 315dbc333c175104df44d4a60761a5b30b3e5498 [file] [log] [blame]
Serge Bazanski5faa2fc2020-09-07 14:09:30 +02001// Copyright 2020 The Monogon Project Authors.
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
17package logtree
18
19import (
20 "fmt"
21 "strings"
22 "testing"
23 "time"
24)
25
Serge Bazanski12971d62020-11-17 12:12:58 +010026func expect(tree *LogTree, t *testing.T, dn DN, entries ...string) string {
27 t.Helper()
28 res, err := tree.Read(dn, WithChildren(), WithBacklog(BacklogAllAvailable))
29 if err != nil {
30 t.Fatalf("Read: %v", err)
31 }
32 if want, got := len(entries), len(res.Backlog); want != got {
33 t.Fatalf("wanted %v backlog entries, got %v", want, got)
34 }
35 got := make(map[string]bool)
36 for _, entry := range res.Backlog {
37 if entry.Leveled != nil {
38 got[entry.Leveled.MessagesJoined()] = true
39 }
40 if entry.Raw != nil {
41 got[entry.Raw.Data] = true
42 }
43 }
44 for _, entry := range entries {
45 if !got[entry] {
46 return fmt.Sprintf("missing entry %q", entry)
47 }
48 }
49 return ""
50}
51
52func TestMultiline(t *testing.T) {
53 tree := New()
54 // Two lines in a single message.
55 tree.MustLeveledFor("main").Info("foo\nbar")
56 // Two lines in a single message with a hanging newline that should get stripped.
57 tree.MustLeveledFor("main").Info("one\ntwo\n")
58
59 if res := expect(tree, t, "main", "foo\nbar", "one\ntwo"); res != "" {
60 t.Errorf("retrieval at main failed: %s", res)
61 }
62}
63
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020064func TestBacklog(t *testing.T) {
65 tree := New()
66 tree.MustLeveledFor("main").Info("hello, main!")
67 tree.MustLeveledFor("main.foo").Info("hello, main.foo!")
68 tree.MustLeveledFor("main.bar").Info("hello, main.bar!")
69 tree.MustLeveledFor("aux").Info("hello, aux!")
Serge Bazanskif68153c2020-10-26 13:54:37 +010070 // No newline at the last entry - shouldn't get propagated to the backlog.
71 fmt.Fprintf(tree.MustRawFor("aux.process"), "processing foo\nprocessing bar\nbaz")
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020072
Serge Bazanski12971d62020-11-17 12:12:58 +010073 if res := expect(tree, t, "main", "hello, main!", "hello, main.foo!", "hello, main.bar!"); res != "" {
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020074 t.Errorf("retrieval at main failed: %s", res)
75 }
Serge Bazanski12971d62020-11-17 12:12:58 +010076 if res := expect(tree, t, "", "hello, main!", "hello, main.foo!", "hello, main.bar!", "hello, aux!", "processing foo", "processing bar"); res != "" {
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020077 t.Errorf("retrieval at root failed: %s", res)
78 }
Serge Bazanski12971d62020-11-17 12:12:58 +010079 if res := expect(tree, t, "aux", "hello, aux!", "processing foo", "processing bar"); res != "" {
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020080 t.Errorf("retrieval at aux failed: %s", res)
81 }
82}
83
84func TestStream(t *testing.T) {
85 tree := New()
86 tree.MustLeveledFor("main").Info("hello, backlog")
Serge Bazanskif68153c2020-10-26 13:54:37 +010087 fmt.Fprintf(tree.MustRawFor("main.process"), "hello, raw backlog\n")
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020088
Serge Bazanskif68153c2020-10-26 13:54:37 +010089 res, err := tree.Read("", WithBacklog(BacklogAllAvailable), WithChildren(), WithStream())
90 if err != nil {
91 t.Fatalf("Read: %v", err)
92 }
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020093 defer res.Close()
Serge Bazanskif68153c2020-10-26 13:54:37 +010094 if want, got := 2, len(res.Backlog); want != got {
Serge Bazanski5faa2fc2020-09-07 14:09:30 +020095 t.Errorf("wanted %d backlog item, got %d", want, got)
96 }
97
98 tree.MustLeveledFor("main").Info("hello, stream")
Serge Bazanskif68153c2020-10-26 13:54:37 +010099 fmt.Fprintf(tree.MustRawFor("main.raw"), "hello, raw stream\n")
Serge Bazanski5faa2fc2020-09-07 14:09:30 +0200100
Serge Bazanskif68153c2020-10-26 13:54:37 +0100101 entries := make(map[string]bool)
102 timeout := time.After(time.Second * 1)
103 for {
104 done := false
105 select {
106 case <-timeout:
107 done = true
108 case p := <-res.Stream:
109 if p.Leveled != nil {
Serge Bazanski12971d62020-11-17 12:12:58 +0100110 entries[p.Leveled.MessagesJoined()] = true
Serge Bazanskif68153c2020-10-26 13:54:37 +0100111 }
112 if p.Raw != nil {
113 entries[p.Raw.Data] = true
114 }
Serge Bazanski5faa2fc2020-09-07 14:09:30 +0200115 }
Serge Bazanskif68153c2020-10-26 13:54:37 +0100116 if done {
117 break
118 }
119 }
120 if entry := "hello, stream"; !entries[entry] {
121 t.Errorf("Missing entry %q", entry)
122 }
123 if entry := "hello, raw stream"; !entries[entry] {
124 t.Errorf("Missing entry %q", entry)
Serge Bazanski5faa2fc2020-09-07 14:09:30 +0200125 }
126}
127
128func TestVerbose(t *testing.T) {
129 tree := New()
130
131 tree.MustLeveledFor("main").V(10).Info("this shouldn't get logged")
132
Serge Bazanskif68153c2020-10-26 13:54:37 +0100133 reader, err := tree.Read("", WithBacklog(BacklogAllAvailable), WithChildren())
134 if err != nil {
135 t.Fatalf("Read: %v", err)
136 }
Serge Bazanski5faa2fc2020-09-07 14:09:30 +0200137 if want, got := 0, len(reader.Backlog); want != got {
138 t.Fatalf("expected nothing to be logged, got %+v", reader.Backlog)
139 }
140
141 tree.SetVerbosity("main", 10)
142 tree.MustLeveledFor("main").V(10).Info("this should get logged")
143
Serge Bazanskif68153c2020-10-26 13:54:37 +0100144 reader, err = tree.Read("", WithBacklog(BacklogAllAvailable), WithChildren())
145 if err != nil {
146 t.Fatalf("Read: %v", err)
147 }
Serge Bazanski5faa2fc2020-09-07 14:09:30 +0200148 if want, got := 1, len(reader.Backlog); want != got {
149 t.Fatalf("expected %d entries to get logged, got %d", want, got)
150 }
151}
152
153func TestMetadata(t *testing.T) {
154 tree := New()
155 tree.MustLeveledFor("main").Error("i am an error")
156 tree.MustLeveledFor("main").Warning("i am a warning")
157 tree.MustLeveledFor("main").Info("i am informative")
158 tree.MustLeveledFor("main").V(0).Info("i am a zero-level debug")
159
Serge Bazanskif68153c2020-10-26 13:54:37 +0100160 reader, err := tree.Read("", WithChildren(), WithBacklog(BacklogAllAvailable))
161 if err != nil {
162 t.Fatalf("Read: %v", err)
163 }
Serge Bazanski5faa2fc2020-09-07 14:09:30 +0200164 if want, got := 4, len(reader.Backlog); want != got {
165 t.Fatalf("expected %d entries, got %d", want, got)
166 }
167
168 for _, te := range []struct {
169 ix int
170 severity Severity
171 message string
172 }{
173 {0, ERROR, "i am an error"},
174 {1, WARNING, "i am a warning"},
175 {2, INFO, "i am informative"},
176 {3, INFO, "i am a zero-level debug"},
177 } {
178 p := reader.Backlog[te.ix]
Serge Bazanskif68153c2020-10-26 13:54:37 +0100179 if want, got := te.severity, p.Leveled.Severity(); want != got {
Serge Bazanski5faa2fc2020-09-07 14:09:30 +0200180 t.Errorf("wanted element %d to have severity %s, got %s", te.ix, want, got)
181 }
Serge Bazanski12971d62020-11-17 12:12:58 +0100182 if want, got := te.message, p.Leveled.MessagesJoined(); want != got {
Serge Bazanski5faa2fc2020-09-07 14:09:30 +0200183 t.Errorf("wanted element %d to have message %q, got %q", te.ix, want, got)
184 }
Serge Bazanskif68153c2020-10-26 13:54:37 +0100185 if want, got := "logtree_test.go", strings.Split(p.Leveled.Location(), ":")[0]; want != got {
Serge Bazanski5faa2fc2020-09-07 14:09:30 +0200186 t.Errorf("wanted element %d to have file %q, got %q", te.ix, want, got)
187 }
188 }
189}
190
191func TestSeverity(t *testing.T) {
192 tree := New()
193 tree.MustLeveledFor("main").Error("i am an error")
194 tree.MustLeveledFor("main").Warning("i am a warning")
195 tree.MustLeveledFor("main").Info("i am informative")
196 tree.MustLeveledFor("main").V(0).Info("i am a zero-level debug")
197
Serge Bazanskif68153c2020-10-26 13:54:37 +0100198 reader, err := tree.Read("main", WithBacklog(BacklogAllAvailable), LeveledWithMinimumSeverity(WARNING))
199 if err != nil {
200 t.Fatalf("Read: %v", err)
201 }
Serge Bazanski5faa2fc2020-09-07 14:09:30 +0200202 if want, got := 2, len(reader.Backlog); want != got {
203 t.Fatalf("wanted %d entries, got %d", want, got)
204 }
Serge Bazanski12971d62020-11-17 12:12:58 +0100205 if want, got := "i am an error", reader.Backlog[0].Leveled.MessagesJoined(); want != got {
Serge Bazanski5faa2fc2020-09-07 14:09:30 +0200206 t.Fatalf("wanted entry %q, got %q", want, got)
207 }
Serge Bazanski12971d62020-11-17 12:12:58 +0100208 if want, got := "i am a warning", reader.Backlog[1].Leveled.MessagesJoined(); want != got {
Serge Bazanski5faa2fc2020-09-07 14:09:30 +0200209 t.Fatalf("wanted entry %q, got %q", want, got)
210 }
211}
Serge Bazanskid9775a62022-02-15 13:28:55 +0100212
213func TestAddedStackDepth(t *testing.T) {
214 tree := New()
215 helper := func(msg string) {
216 tree.MustLeveledFor("main").WithAddedStackDepth(1).Infof("oh no: %s", msg)
217 }
218
219 // The next three lines are tested to be next to each other.
220 helper("it failed")
221 tree.MustLeveledFor("main").Infof("something else")
222
223 reader, err := tree.Read("main", WithBacklog(BacklogAllAvailable))
224 if err != nil {
225 t.Fatalf("Read: %v", err)
226 }
227 if want, got := 2, len(reader.Backlog); want != got {
228 t.Fatalf("wanted %d entries, got %d", want, got)
229 }
230 if want, got := "oh no: it failed", reader.Backlog[0].Leveled.MessagesJoined(); want != got {
231 t.Errorf("wanted entry %q, got %q", want, got)
232 }
233 if want, got := "something else", reader.Backlog[1].Leveled.MessagesJoined(); want != got {
234 t.Errorf("wanted entry %q, got %q", want, got)
235 }
236 if first, second := reader.Backlog[0].Leveled.line, reader.Backlog[1].Leveled.line; first+1 != second {
237 t.Errorf("first entry at %d, second at %d, wanted one after the other", first, second)
238 }
239}