1 package sources_test
2
3 import (
4 "os"
5 "path/filepath"
6 "testing"
7
8 "github.com/stretchr/testify/assert"
9
10 "github.com/cybertec-postgresql/pgwatch/v3/internal/sources"
11 )
12
13
14 const sampleEntriesNumber = 4
15
16 const (
17 contribDir = "../../contrib/"
18 sampleFile = "../../contrib/sample.sources.yaml"
19 )
20
21 func TestNewYAMLSourcesReaderWriter(t *testing.T) {
22 a := assert.New(t)
23 yamlrw, err := sources.NewYAMLSourcesReaderWriter(ctx, sampleFile)
24 a.NoError(err)
25 a.NotNil(t, yamlrw)
26 }
27
28 func TestYAMLGetMonitoredDatabases(t *testing.T) {
29 a := assert.New(t)
30
31 t.Run("single file", func(*testing.T) {
32 yamlrw, err := sources.NewYAMLSourcesReaderWriter(ctx, sampleFile)
33 a.NoError(err)
34
35 dbs, err := yamlrw.GetSources()
36 a.NoError(err)
37 a.Len(dbs, sampleEntriesNumber)
38 })
39
40 t.Run("nonexistent file", func(*testing.T) {
41 yamlrw, err := sources.NewYAMLSourcesReaderWriter(ctx, "nonexistent.yaml")
42 a.NoError(err)
43 dbs, err := yamlrw.GetSources()
44 a.Error(err)
45 a.Nil(dbs)
46 })
47
48 t.Run("garbage file", func(*testing.T) {
49 yamlrw, err := sources.NewYAMLSourcesReaderWriter(ctx, filepath.Join(contribDir, "yaml.go"))
50 a.NoError(err)
51 dbs, err := yamlrw.GetSources()
52 a.Error(err)
53 a.Nil(dbs)
54 })
55
56 t.Run("duplicate in single file", func(t *testing.T) {
57 tmpFile := filepath.Join(t.TempDir(), "duplicate.yaml")
58 yamlContent := `
59 - name: test1
60 conn_str: postgresql://localhost/test1
61 - name: test2
62 conn_str: postgresql://localhost/test2
63 - name: test1
64 conn_str: postgresql://localhost/test1_duplicate
65 `
66 err := os.WriteFile(tmpFile, []byte(yamlContent), 0644)
67 a.NoError(err)
68 yamlrw, err := sources.NewYAMLSourcesReaderWriter(ctx, tmpFile)
69 a.NoError(err)
70
71 dbs, err := yamlrw.GetSources()
72 a.Error(err)
73 a.Nil(dbs)
74 })
75
76 t.Run("duplicates across files", func(t *testing.T) {
77 tmpDir := t.TempDir()
78 yamlContent1 := `
79 - name: test1
80 conn_str: postgresql://localhost/test1
81 - name: test2
82 conn_str: postgresql://localhost/test2
83 `
84 err := os.WriteFile(filepath.Join(tmpDir, "sources1.yaml"), []byte(yamlContent1), 0644)
85 a.NoError(err)
86
87 yamlContent2 := `
88 - name: test1
89 conn_str: postgresql://localhost/test1_duplicate
90 `
91 err = os.WriteFile(filepath.Join(tmpDir, "sources2.yaml"), []byte(yamlContent2), 0644)
92 a.NoError(err)
93 yamlrw, err := sources.NewYAMLSourcesReaderWriter(ctx, tmpDir)
94 a.NoError(err)
95
96 dbs, err := yamlrw.GetSources()
97 a.Error(err)
98 a.Nil(dbs)
99 })
100 }
101
102 func TestYAMLDeleteDatabase(t *testing.T) {
103 a := assert.New(t)
104
105 t.Run("happy path", func(*testing.T) {
106 data, err := os.ReadFile(sampleFile)
107 a.NoError(err)
108 tmpSampleFile := filepath.Join(t.TempDir(), "sample.sources.yaml")
109 err = os.WriteFile(tmpSampleFile, data, 0644)
110 a.NoError(err)
111 defer os.Remove(tmpSampleFile)
112
113 yamlrw, err := sources.NewYAMLSourcesReaderWriter(ctx, tmpSampleFile)
114 a.NoError(err)
115
116 err = yamlrw.DeleteSource("test1")
117 a.NoError(err)
118
119 dbs, err := yamlrw.GetSources()
120 a.NoError(err)
121 a.Len(dbs, sampleEntriesNumber-1)
122 })
123
124 t.Run("nonexistent file", func(*testing.T) {
125 yamlrw, err := sources.NewYAMLSourcesReaderWriter(ctx, "nonexistent.yaml")
126 a.NoError(err)
127 err = yamlrw.DeleteSource("test1")
128 a.Error(err)
129 })
130 }
131
132 func TestYAMLUpdateDatabase(t *testing.T) {
133 a := assert.New(t)
134
135 t.Run("happy path", func(*testing.T) {
136 data, err := os.ReadFile(sampleFile)
137 a.NoError(err)
138 tmpSampleFile := filepath.Join(t.TempDir(), "sample.sources.yaml")
139 err = os.WriteFile(tmpSampleFile, data, 0644)
140 a.NoError(err)
141 defer os.Remove(tmpSampleFile)
142
143 yamlrw, err := sources.NewYAMLSourcesReaderWriter(ctx, tmpSampleFile)
144 a.NoError(err)
145
146
147 md := sources.Source{}
148 md.Name = "test1"
149 md.ConnStr = "postgresql://localhost/test1"
150 err = yamlrw.UpdateSource(md)
151 a.NoError(err)
152
153
154 md = sources.Source{}
155 md.Name = "test5"
156 md.ConnStr = "postgresql://localhost/test5"
157 err = yamlrw.UpdateSource(md)
158 a.NoError(err)
159
160 dbs, err := yamlrw.GetSources()
161 a.NoError(err)
162 a.Len(dbs, sampleEntriesNumber+1)
163 dbs[0].ConnStr = "postgresql://localhost/test1"
164 dbs[sampleEntriesNumber].ConnStr = "postgresql://localhost/test5"
165 })
166
167 t.Run("nonexistent file", func(*testing.T) {
168 yamlrw, err := sources.NewYAMLSourcesReaderWriter(ctx, "")
169 a.NoError(err)
170 err = yamlrw.UpdateSource(sources.Source{})
171 a.Error(err)
172 })
173 }
174
175 func TestYAMLCreateSource(t *testing.T) {
176 a := assert.New(t)
177
178 t.Run("happy_path", func(*testing.T) {
179 data, err := os.ReadFile(sampleFile)
180 a.NoError(err)
181 tmpSampleFile := filepath.Join(t.TempDir(), "sample.sources.yaml")
182 err = os.WriteFile(tmpSampleFile, data, 0644)
183 a.NoError(err)
184 defer os.Remove(tmpSampleFile)
185
186 yamlrw, err := sources.NewYAMLSourcesReaderWriter(ctx, tmpSampleFile)
187 a.NoError(err)
188
189
190 md := sources.Source{
191 Name: "new_source",
192 ConnStr: "postgresql://localhost/new_db",
193 Kind: sources.SourcePostgres,
194 }
195 err = yamlrw.CreateSource(md)
196 a.NoError(err)
197
198
199 dbs, err := yamlrw.GetSources()
200 a.NoError(err)
201 a.Len(dbs, sampleEntriesNumber+1)
202
203
204 err = yamlrw.CreateSource(md)
205 a.Error(err)
206 a.ErrorIs(sources.ErrSourceExists, err)
207 })
208
209 t.Run("duplicate_source", func(*testing.T) {
210 data, err := os.ReadFile(sampleFile)
211 a.NoError(err)
212 tmpSampleFile := filepath.Join(t.TempDir(), "sample.sources.yaml")
213 err = os.WriteFile(tmpSampleFile, data, 0644)
214 a.NoError(err)
215 defer os.Remove(tmpSampleFile)
216
217 yamlrw, err := sources.NewYAMLSourcesReaderWriter(ctx, tmpSampleFile)
218 a.NoError(err)
219
220
221 md := sources.Source{
222 Name: "test1",
223 ConnStr: "postgresql://localhost/test1",
224 Kind: sources.SourcePostgres,
225 }
226 err = yamlrw.CreateSource(md)
227 a.Error(err)
228 a.ErrorIs(sources.ErrSourceExists, err)
229 })
230 }
231