Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aos
GitHub Repository: aos/grafana-agent
Path: blob/main/component/common/loki/positions/positions_test.go
4096 views
1
package positions
2
3
// This code is copied from Promtail. The positions package allows logging
4
// components to keep track of read file offsets on disk and continue from the
5
// same place in case of a restart.
6
7
import (
8
"os"
9
"strings"
10
"testing"
11
"time"
12
13
"github.com/go-kit/log"
14
"github.com/stretchr/testify/require"
15
16
util_log "github.com/grafana/loki/pkg/util/log"
17
)
18
19
func tempFilename(t *testing.T) string {
20
t.Helper()
21
22
temp, err := os.CreateTemp("", "positions")
23
if err != nil {
24
t.Fatal("tempFilename:", err)
25
}
26
err = temp.Close()
27
if err != nil {
28
t.Fatal("tempFilename:", err)
29
}
30
31
name := temp.Name()
32
err = os.Remove(name)
33
if err != nil {
34
t.Fatal("tempFilename:", err)
35
}
36
37
return name
38
}
39
40
func TestReadPositionsOK(t *testing.T) {
41
temp := tempFilename(t)
42
defer func() {
43
_ = os.Remove(temp)
44
}()
45
46
yaml := []byte(`
47
positions:
48
? path: /tmp/random.log
49
labels: '{job="tmp"}'
50
: "17623"
51
`)
52
err := os.WriteFile(temp, yaml, 0644)
53
if err != nil {
54
t.Fatal(err)
55
}
56
57
pos, err := readPositionsFile(Config{
58
PositionsFile: temp,
59
}, log.NewNopLogger())
60
61
require.NoError(t, err)
62
require.Equal(t, "17623", pos[Entry{
63
Path: "/tmp/random.log",
64
Labels: `{job="tmp"}`,
65
}])
66
}
67
68
func TestReadPositionsEmptyFile(t *testing.T) {
69
temp := tempFilename(t)
70
defer func() {
71
_ = os.Remove(temp)
72
}()
73
74
yaml := []byte(``)
75
err := os.WriteFile(temp, yaml, 0644)
76
if err != nil {
77
t.Fatal(err)
78
}
79
80
pos, err := readPositionsFile(Config{
81
PositionsFile: temp,
82
}, log.NewNopLogger())
83
84
require.NoError(t, err)
85
require.NotNil(t, pos)
86
}
87
88
func TestReadPositionsFromDir(t *testing.T) {
89
temp := tempFilename(t)
90
err := os.Mkdir(temp, 0644)
91
if err != nil {
92
t.Fatal(err)
93
}
94
95
defer func() {
96
_ = os.Remove(temp)
97
}()
98
99
_, err = readPositionsFile(Config{
100
PositionsFile: temp,
101
}, log.NewNopLogger())
102
103
require.Error(t, err)
104
require.True(t, strings.Contains(err.Error(), temp)) // error must contain filename
105
}
106
107
func TestReadPositionsFromBadYaml(t *testing.T) {
108
temp := tempFilename(t)
109
defer func() {
110
_ = os.Remove(temp)
111
}()
112
113
badYaml := []byte(`
114
positions:
115
? path: /tmp/random.log
116
labels: "{}"
117
: "176
118
`)
119
err := os.WriteFile(temp, badYaml, 0644)
120
if err != nil {
121
t.Fatal(err)
122
}
123
124
_, err = readPositionsFile(Config{
125
PositionsFile: temp,
126
}, log.NewNopLogger())
127
128
require.Error(t, err)
129
require.True(t, strings.Contains(err.Error(), temp)) // error must contain filename
130
}
131
132
func TestReadPositionsFromBadYamlIgnoreCorruption(t *testing.T) {
133
temp := tempFilename(t)
134
defer func() {
135
_ = os.Remove(temp)
136
}()
137
138
badYaml := []byte(`
139
positions:
140
? path: /tmp/random.log
141
labels: "{}"
142
: "176
143
`)
144
err := os.WriteFile(temp, badYaml, 0644)
145
if err != nil {
146
t.Fatal(err)
147
}
148
149
out, err := readPositionsFile(Config{
150
PositionsFile: temp,
151
IgnoreInvalidYaml: true,
152
}, log.NewNopLogger())
153
154
require.NoError(t, err)
155
require.Equal(t, map[Entry]string{}, out)
156
}
157
158
func Test_ReadOnly(t *testing.T) {
159
temp := tempFilename(t)
160
defer func() {
161
_ = os.Remove(temp)
162
}()
163
yaml := []byte(`
164
positions:
165
? path: /tmp/random.log
166
labels: '{job="tmp"}'
167
: "17623"
168
`)
169
err := os.WriteFile(temp, yaml, 0644)
170
if err != nil {
171
t.Fatal(err)
172
}
173
p, err := New(util_log.Logger, Config{
174
SyncPeriod: 20 * time.Second,
175
PositionsFile: temp,
176
ReadOnly: true,
177
})
178
if err != nil {
179
t.Fatal(err)
180
}
181
defer p.Stop()
182
p.Put("/foo/bar/f", "", 12132132)
183
p.PutString("/foo/f", "", "100")
184
pos, err := p.Get("/tmp/random.log", `{job="tmp"}`)
185
if err != nil {
186
t.Fatal(err)
187
}
188
require.Equal(t, int64(17623), pos)
189
p.(*positions).save()
190
out, err := readPositionsFile(Config{
191
PositionsFile: temp,
192
IgnoreInvalidYaml: true,
193
ReadOnly: true,
194
}, log.NewNopLogger())
195
196
require.NoError(t, err)
197
require.Equal(t, map[Entry]string{
198
{Path: "/tmp/random.log", Labels: `{job="tmp"}`}: "17623",
199
}, out)
200
}
201
202
func TestWriteEmptyLabels(t *testing.T) {
203
temp := tempFilename(t)
204
defer func() {
205
_ = os.Remove(temp)
206
}()
207
yaml := []byte(`
208
positions:
209
? path: /tmp/initial.log
210
labels: '{job="tmp"}'
211
: "10030"
212
`)
213
err := os.WriteFile(temp, yaml, 0644)
214
if err != nil {
215
t.Fatal(err)
216
}
217
p, err := New(util_log.Logger, Config{
218
SyncPeriod: 20 * time.Second,
219
PositionsFile: temp,
220
})
221
if err != nil {
222
t.Fatal(err)
223
}
224
defer p.Stop()
225
p.Put("/tmp/foo/nolabels.log", "", 10040)
226
p.Put("/tmp/foo/emptylabels.log", "{}", 10050)
227
p.PutString("/tmp/bar/nolabels.log", "", "10060")
228
p.PutString("/tmp/bar/emptylabels.log", "{}", "10070")
229
pos, err := p.Get("/tmp/initial.log", `{job="tmp"}`)
230
if err != nil {
231
t.Fatal(err)
232
}
233
require.Equal(t, int64(10030), pos)
234
p.(*positions).save()
235
out, err := readPositionsFile(Config{
236
PositionsFile: temp,
237
IgnoreInvalidYaml: true,
238
ReadOnly: false,
239
}, log.NewNopLogger())
240
241
require.NoError(t, err)
242
require.Equal(t, map[Entry]string{
243
{Path: "/tmp/initial.log", Labels: `{job="tmp"}`}: "10030",
244
{Path: "/tmp/bar/emptylabels.log", Labels: `{}`}: "10070",
245
{Path: "/tmp/bar/nolabels.log", Labels: ""}: "10060",
246
{Path: "/tmp/foo/emptylabels.log", Labels: `{}`}: "10050",
247
{Path: "/tmp/foo/nolabels.log", Labels: ""}: "10040",
248
}, out)
249
}
250
251
func TestReadEmptyLabels(t *testing.T) {
252
temp := tempFilename(t)
253
defer func() {
254
_ = os.Remove(temp)
255
}()
256
257
yaml := []byte(`
258
positions:
259
? path: /tmp/nolabels.log
260
labels: ''
261
: "10020"
262
? path: /tmp/emptylabels.log
263
labels: '{}'
264
: "10030"
265
? path: /tmp/missinglabels.log
266
: "10040"
267
`)
268
err := os.WriteFile(temp, yaml, 0644)
269
if err != nil {
270
t.Fatal(err)
271
}
272
273
pos, err := readPositionsFile(Config{
274
PositionsFile: temp,
275
}, log.NewNopLogger())
276
277
require.NoError(t, err)
278
require.Equal(t, "10020", pos[Entry{
279
Path: "/tmp/nolabels.log",
280
Labels: ``,
281
}])
282
require.Equal(t, "10030", pos[Entry{
283
Path: "/tmp/emptylabels.log",
284
Labels: `{}`,
285
}])
286
require.Equal(t, "10040", pos[Entry{
287
Path: "/tmp/missinglabels.log",
288
Labels: ``,
289
}])
290
}
291
292