Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aos
GitHub Repository: aos/grafana-agent
Path: blob/main/pkg/river/parser/parser_test.go
4096 views
1
package parser
2
3
import (
4
"io/fs"
5
"os"
6
"path/filepath"
7
"testing"
8
9
"github.com/stretchr/testify/require"
10
)
11
12
func FuzzParser(f *testing.F) {
13
filepath.WalkDir("./testdata/valid", func(path string, d fs.DirEntry, _ error) error {
14
if d.IsDir() {
15
return nil
16
}
17
18
bb, err := os.ReadFile(path)
19
require.NoError(f, err)
20
f.Add(bb)
21
return nil
22
})
23
24
f.Fuzz(func(t *testing.T, input []byte) {
25
p := newParser(t.Name(), input)
26
27
_ = p.ParseFile()
28
if len(p.diags) > 0 {
29
t.SkipNow()
30
}
31
})
32
}
33
34
// TestValid parses every *.river file in testdata, which is expected to be
35
// valid.
36
func TestValid(t *testing.T) {
37
filepath.WalkDir("./testdata/valid", func(path string, d fs.DirEntry, _ error) error {
38
if d.IsDir() {
39
return nil
40
}
41
42
t.Run(filepath.Base(path), func(t *testing.T) {
43
bb, err := os.ReadFile(path)
44
require.NoError(t, err)
45
46
p := newParser(path, bb)
47
48
res := p.ParseFile()
49
require.NotNil(t, res)
50
require.Len(t, p.diags, 0)
51
})
52
53
return nil
54
})
55
}
56
57
func TestParseExpressions(t *testing.T) {
58
tt := map[string]string{
59
"literal number": `10`,
60
"literal float": `15.0`,
61
"literal string": `"Hello, world!"`,
62
"literal ident": `some_ident`,
63
"literal null": `null`,
64
"literal true": `true`,
65
"literal false": `false`,
66
67
"empty array": `[]`,
68
"array one element": `[1]`,
69
"array many elements": `[0, 1, 2, 3]`,
70
"array trailing comma": `[0, 1, 2, 3,]`,
71
"nested array": `[[0, 1, 2], [3, 4, 5]]`,
72
"array multiline": `[
73
0,
74
1,
75
2,
76
]`,
77
78
"empty object": `{}`,
79
"object one field": `{ field_a = 5 }`,
80
"object multiple fields": `{ field_a = 5, field_b = 10 }`,
81
"object trailing comma": `{ field_a = 5, field_b = 10, }`,
82
"nested objects": `{ field_a = { nested_field = 100 } }`,
83
"object multiline": `{
84
field_a = 5,
85
field_b = 10,
86
}`,
87
88
"unary not": `!true`,
89
"unary neg": `-5`,
90
91
"math": `1 + 2 - 3 * 4 / 5 % 6`,
92
"compare ops": `1 == 2 != 3 < 4 > 5 <= 6 >= 7`,
93
"logical ops": `true || false && true`,
94
"pow operator": "1 ^ 2 ^ 3",
95
96
"field access": `a.b.c.d`,
97
"element access": `a[0][1][2]`,
98
99
"call no args": `a()`,
100
"call one arg": `a(1)`,
101
"call multiple args": `a(1,2,3)`,
102
"call with trailing comma": `a(1,2,3,)`,
103
"call multiline": `a(
104
1,
105
2,
106
3,
107
)`,
108
109
"parens": `(1 + 5) * 100`,
110
111
"mixed expression": `(a.b.c)(1, 3 * some_list[magic_index * 2]).resulting_field`,
112
}
113
114
for name, input := range tt {
115
t.Run(name, func(t *testing.T) {
116
p := newParser(name, []byte(input))
117
118
res := p.ParseExpression()
119
require.NotNil(t, res)
120
require.Len(t, p.diags, 0)
121
})
122
}
123
}
124
125