Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aos
GitHub Repository: aos/grafana-agent
Path: blob/main/component/module/file/file_test.go
4096 views
1
package file
2
3
import (
4
"context"
5
"os"
6
"path/filepath"
7
"runtime"
8
"strings"
9
"testing"
10
"time"
11
12
"github.com/grafana/agent/component"
13
"github.com/grafana/agent/pkg/cluster"
14
"github.com/grafana/agent/pkg/river"
15
"github.com/grafana/agent/pkg/util"
16
"github.com/prometheus/client_golang/prometheus"
17
"github.com/stretchr/testify/require"
18
)
19
20
func TestModule(t *testing.T) {
21
tempDir := t.TempDir()
22
debugLevelFilePath := filepath.Join(tempDir, "debug_level.txt")
23
os.WriteFile(debugLevelFilePath, []byte("info"), 0664)
24
25
tt := []struct {
26
name string
27
moduleContents string
28
expectedHealthType component.HealthType
29
expectedHealthMessagePrefix string
30
expectedManagedFileHealthType component.HealthType
31
expectedManagedFileHealthMessagePrefix string
32
}{
33
{
34
name: "Good Module",
35
36
moduleContents: `local.file "log_level" {
37
filename = "` + riverEscape(debugLevelFilePath) + `"
38
}`,
39
expectedHealthType: component.HealthTypeHealthy,
40
expectedHealthMessagePrefix: "module content loaded",
41
42
expectedManagedFileHealthType: component.HealthTypeHealthy,
43
expectedManagedFileHealthMessagePrefix: "read file",
44
},
45
}
46
47
for _, tc := range tt {
48
t.Run(tc.name, func(t *testing.T) {
49
moduleFilePath := filepath.Join(tempDir, "module.river")
50
os.WriteFile(moduleFilePath, []byte(tc.moduleContents), 0664)
51
52
opts := component.Options{
53
ID: "module.file.test",
54
Logger: util.TestFlowLogger(t),
55
Clusterer: noOpClusterer(),
56
Registerer: prometheus.NewRegistry(),
57
OnStateChange: func(e component.Exports) {},
58
DataPath: t.TempDir(),
59
}
60
61
moduleFileConfig := `filename = "` + riverEscape(moduleFilePath) + `"`
62
63
var args Arguments
64
require.NoError(t, river.Unmarshal([]byte(moduleFileConfig), &args))
65
66
c, err := New(opts, args)
67
require.NoError(t, err)
68
69
go c.Run(context.Background())
70
require.Eventually(
71
t,
72
func() bool { return tc.expectedHealthType == c.CurrentHealth().Health },
73
5*time.Second,
74
50*time.Millisecond,
75
"did not reach required health status before timeout: %v != %v",
76
tc.expectedHealthType,
77
c.CurrentHealth().Health,
78
)
79
80
require.Equal(t, tc.expectedHealthType, c.CurrentHealth().Health)
81
requirePrefix(t, c.CurrentHealth().Message, tc.expectedHealthMessagePrefix)
82
83
require.Equal(t, tc.expectedManagedFileHealthType, c.managedLocalFile.CurrentHealth().Health)
84
requirePrefix(t, c.managedLocalFile.CurrentHealth().Message, tc.expectedManagedFileHealthMessagePrefix)
85
})
86
}
87
}
88
89
func TestBadFile(t *testing.T) {
90
tt := []struct {
91
name string
92
moduleContents string
93
expectedErrorContains string
94
}{
95
{
96
name: "Bad Module",
97
moduleContents: `this isn't a valid module config`,
98
expectedErrorContains: `expected block label, got IDENT`,
99
},
100
{
101
name: "Bad Component",
102
moduleContents: `local.fake "fake" {}`,
103
expectedErrorContains: `Unrecognized component name "local.fake"`,
104
},
105
{
106
name: "Missing Module",
107
moduleContents: "",
108
expectedErrorContains: `failed to read file:`,
109
},
110
{
111
name: "Logging in Module",
112
moduleContents: "logging {}",
113
expectedErrorContains: `logging block not allowed inside a module`,
114
},
115
{
116
name: "Tracing in Module",
117
moduleContents: "tracing {}",
118
expectedErrorContains: `tracing block not allowed inside a module`,
119
},
120
}
121
122
for _, tc := range tt {
123
t.Run(tc.name, func(t *testing.T) {
124
moduleFilePath := filepath.Join(t.TempDir(), "module.river")
125
if tc.moduleContents != "" {
126
os.WriteFile(moduleFilePath, []byte(tc.moduleContents), 0664)
127
}
128
129
moduleFileConfig := `filename = "` + riverEscape(moduleFilePath) + `"`
130
131
var args Arguments
132
require.NoError(t, river.Unmarshal([]byte(moduleFileConfig), &args))
133
134
opts := component.Options{
135
ID: "module.file.test",
136
Logger: util.TestFlowLogger(t),
137
Clusterer: noOpClusterer(),
138
Registerer: prometheus.NewRegistry(),
139
OnStateChange: func(e component.Exports) {},
140
DataPath: t.TempDir(),
141
}
142
143
_, err := New(opts, args)
144
require.ErrorContains(t, err, tc.expectedErrorContains)
145
})
146
}
147
}
148
149
func riverEscape(filePath string) string {
150
if runtime.GOOS == "windows" {
151
return strings.Replace(filePath, `\`, `\\`, -1)
152
}
153
154
return filePath
155
}
156
157
func requirePrefix(t *testing.T, s string, prefix string) {
158
require.True(
159
t,
160
strings.HasPrefix(s, prefix),
161
"expected '%v' to have '%v' prefix",
162
s,
163
prefix,
164
)
165
}
166
167
func noOpClusterer() *cluster.Clusterer {
168
return &cluster.Clusterer{Node: cluster.NewLocalNode("")}
169
}
170
171