Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aos
GitHub Repository: aos/grafana-agent
Path: blob/main/pkg/river/diag/printer_test.go
4096 views
1
package diag_test
2
3
import (
4
"bytes"
5
"fmt"
6
"testing"
7
8
"github.com/grafana/agent/pkg/river/diag"
9
"github.com/grafana/agent/pkg/river/token"
10
"github.com/stretchr/testify/require"
11
)
12
13
func TestFprint(t *testing.T) {
14
// In all tests below, the filename is "testfile" and the severity is an
15
// error.
16
17
tt := []struct {
18
name string
19
input string
20
start, end token.Position
21
diag diag.Diagnostic
22
expect string
23
}{
24
{
25
name: "highlight on same line",
26
start: token.Position{Line: 2, Column: 2},
27
end: token.Position{Line: 2, Column: 5},
28
input: `test.block "label" {
29
attr = 1
30
other_attr = 2
31
}`,
32
expect: `Error: testfile:2:2: synthetic error
33
34
1 | test.block "label" {
35
2 | attr = 1
36
| ^^^^
37
3 | other_attr = 2
38
`,
39
},
40
41
{
42
name: "end positions should be optional",
43
start: token.Position{Line: 1, Column: 4},
44
input: `foo,bar`,
45
expect: `Error: testfile:1:4: synthetic error
46
47
1 | foo,bar
48
| ^
49
`,
50
},
51
52
{
53
name: "padding should be inserted to fit line numbers of different lengths",
54
start: token.Position{Line: 9, Column: 1},
55
end: token.Position{Line: 9, Column: 6},
56
input: `LINE_1
57
LINE_2
58
LINE_3
59
LINE_4
60
LINE_5
61
LINE_6
62
LINE_7
63
LINE_8
64
LINE_9
65
LINE_10
66
LINE_11`,
67
expect: `Error: testfile:9:1: synthetic error
68
69
8 | LINE_8
70
9 | LINE_9
71
| ^^^^^^
72
10 | LINE_10
73
`,
74
},
75
76
{
77
name: "errors which cross multiple lines can be printed from start of line",
78
start: token.Position{Line: 2, Column: 1},
79
end: token.Position{Line: 6, Column: 7},
80
input: `FILE_BEGIN
81
START
82
TEXT
83
TEXT
84
TEXT
85
DONE after
86
FILE_END`,
87
expect: `Error: testfile:2:1: synthetic error
88
89
1 | FILE_BEGIN
90
2 | START
91
| _^^^^^
92
3 | | TEXT
93
4 | | TEXT
94
5 | | TEXT
95
6 | | DONE after
96
| |_____________^^^^
97
7 | FILE_END
98
`,
99
},
100
101
{
102
name: "errors which cross multiple lines can be printed from middle of line",
103
start: token.Position{Line: 2, Column: 8},
104
end: token.Position{Line: 6, Column: 7},
105
input: `FILE_BEGIN
106
before START
107
TEXT
108
TEXT
109
TEXT
110
DONE after
111
FILE_END`,
112
expect: `Error: testfile:2:8: synthetic error
113
114
1 | FILE_BEGIN
115
2 | before START
116
| ________^^^^^
117
3 | | TEXT
118
4 | | TEXT
119
5 | | TEXT
120
6 | | DONE after
121
| |_____________^^^^
122
7 | FILE_END
123
`,
124
},
125
}
126
127
for _, tc := range tt {
128
t.Run(tc.name, func(t *testing.T) {
129
files := map[string][]byte{
130
"testfile": []byte(tc.input),
131
}
132
133
tc.start.Filename = "testfile"
134
tc.end.Filename = "testfile"
135
136
diags := diag.Diagnostics{{
137
Severity: diag.SeverityLevelError,
138
StartPos: tc.start,
139
EndPos: tc.end,
140
Message: "synthetic error",
141
}}
142
143
var buf bytes.Buffer
144
_ = diag.Fprint(&buf, files, diags)
145
requireEqualStrings(t, tc.expect, buf.String())
146
})
147
}
148
}
149
150
func TestFprint_MultipleDiagnostics(t *testing.T) {
151
fileA := `old_field = 15
152
3 & 4`
153
fileB := `old_field = 22`
154
155
files := map[string][]byte{
156
"file_a": []byte(fileA),
157
"file_b": []byte(fileB),
158
}
159
160
diags := diag.Diagnostics{
161
{
162
Severity: diag.SeverityLevelWarn,
163
StartPos: token.Position{Filename: "file_a", Line: 1, Column: 1},
164
EndPos: token.Position{Filename: "file_a", Line: 1, Column: 9},
165
Message: "old_field is deprecated",
166
},
167
{
168
Severity: diag.SeverityLevelError,
169
StartPos: token.Position{Filename: "file_a", Line: 2, Column: 3},
170
Message: "unrecognized operator &",
171
},
172
{
173
Severity: diag.SeverityLevelWarn,
174
StartPos: token.Position{Filename: "file_b", Line: 1, Column: 1},
175
EndPos: token.Position{Filename: "file_b", Line: 1, Column: 9},
176
Message: "old_field is deprecated",
177
},
178
}
179
180
expect := `Warning: file_a:1:1: old_field is deprecated
181
182
1 | old_field = 15
183
| ^^^^^^^^^
184
2 | 3 & 4
185
186
Error: file_a:2:3: unrecognized operator &
187
188
1 | old_field = 15
189
2 | 3 & 4
190
| ^
191
192
Warning: file_b:1:1: old_field is deprecated
193
194
1 | old_field = 22
195
| ^^^^^^^^^
196
`
197
198
var buf bytes.Buffer
199
_ = diag.Fprint(&buf, files, diags)
200
requireEqualStrings(t, expect, buf.String())
201
}
202
203
// requireEqualStrings is like require.Equal with two strings but it
204
// pretty-prints multiline strings to make it easier to compare.
205
func requireEqualStrings(t *testing.T, expected, actual string) {
206
if expected == actual {
207
return
208
}
209
210
msg := fmt.Sprintf(
211
"Not equal:\n"+
212
"raw expected: %#v\n"+
213
"raw actual : %#v\n"+
214
"\n"+
215
"expected:\n%s\n"+
216
"actual:\n%s\n",
217
expected, actual,
218
expected, actual,
219
)
220
221
require.Fail(t, msg)
222
}
223
224