Dragonfly2
554 строки · 16.7 Кб
1/*
2* Copyright 2023 The Dragonfly Authors
3*
4* Licensed under the Apache License, Version 2.0 (the "License");
5* you may not use this file except in compliance with the License.
6* You may obtain a copy of the License at
7*
8* http://www.apache.org/licenses/LICENSE-2.0
9*
10* Unless required by applicable law or agreed to in writing, software
11* distributed under the License is distributed on an "AS IS" BASIS,
12* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13* See the License for the specific language governing permissions and
14* limitations under the License.
15*/
16
17package storage
18
19import (
20"fmt"
21"io/fs"
22"os"
23"path/filepath"
24"reflect"
25"regexp"
26"testing"
27
28"github.com/gocarina/gocsv"
29"github.com/stretchr/testify/assert"
30"github.com/stretchr/testify/require"
31
32schedulerstorage "d7y.io/dragonfly/v2/scheduler/storage"
33)
34
35var mockModelKey = "bar"
36
37func TestStorage_New(t *testing.T) {
38tests := []struct {
39name string
40baseDir string
41expect func(t *testing.T, s Storage)
42}{
43{
44name: "new storage",
45baseDir: os.TempDir(),
46expect: func(t *testing.T, s Storage) {
47assert := assert.New(t)
48assert.Equal(reflect.TypeOf(s).Elem().Name(), "storage")
49},
50},
51}
52
53for _, tc := range tests {
54t.Run(tc.name, func(t *testing.T) {
55tc.expect(t, New(tc.baseDir))
56})
57}
58}
59
60func TestStorage_ListDownload(t *testing.T) {
61require := require.New(t)
62testData, err := os.ReadFile("./testdata/download.csv")
63require.Nil(err, "load test file")
64
65tests := []struct {
66name string
67baseDir string
68mock func(t *testing.T, s Storage, baseDir, modelKey string, download []byte)
69expect func(t *testing.T, s Storage, baseDir, modelKey string, download []byte)
70}{
71{
72name: "empty csv file given",
73baseDir: os.TempDir(),
74mock: func(t *testing.T, s Storage, baseDir, modelKey string, download []byte) {
75file, err := os.OpenFile(filepath.Join(baseDir, "download_bar.csv"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
76if err != nil {
77t.Fatal(err)
78}
79defer file.Close()
80},
81expect: func(t *testing.T, s Storage, baseDir, modelKey string, download []byte) {
82assert := assert.New(t)
83_, err := s.ListDownload(modelKey)
84assert.EqualError(err, "empty csv file given")
85},
86},
87{
88name: "get file failed",
89baseDir: os.TempDir(),
90mock: func(t *testing.T, s Storage, baseDir, modelKey string, download []byte) {
91file, err := os.OpenFile(filepath.Join(baseDir, "download_bar.csv"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
92if err != nil {
93t.Fatal(err)
94}
95defer file.Close()
96
97if _, err = file.Write(download); err != nil {
98t.Fatal(err)
99}
100s.(*storage).baseDir = "bas"
101},
102expect: func(t *testing.T, s Storage, baseDir, modelKey string, download []byte) {
103assert := assert.New(t)
104_, err := s.ListDownload(modelKey)
105assert.EqualError(err, "open bas/download_bar.csv: no such file or directory")
106s.(*storage).baseDir = baseDir
107},
108},
109{
110name: "list downloads of a file",
111baseDir: os.TempDir(),
112mock: func(t *testing.T, s Storage, baseDir, modelKey string, download []byte) {
113file, err := os.OpenFile(filepath.Join(baseDir, "download_bar.csv"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
114if err != nil {
115t.Fatal(err)
116}
117defer file.Close()
118
119if _, err = file.Write(download); err != nil {
120t.Fatal(err)
121}
122},
123expect: func(t *testing.T, s Storage, baseDir, modelKey string, download []byte) {
124assert := assert.New(t)
125list, err := s.ListDownload(modelKey)
126assert.NoError(err)
127assert.Equal(len(list), 1)
128},
129},
130}
131
132for _, tc := range tests {
133t.Run(tc.name, func(t *testing.T) {
134s := New(tc.baseDir)
135tc.mock(t, s, tc.baseDir, mockModelKey, testData)
136tc.expect(t, s, tc.baseDir, mockModelKey, testData)
137if err := s.ClearDownload(mockModelKey); err != nil {
138t.Fatal(err)
139}
140})
141}
142}
143
144func TestStorage_ListNetworkTopology(t *testing.T) {
145require := require.New(t)
146testData, err := os.ReadFile("./testdata/networktopology.csv")
147require.Nil(err, "load test file")
148
149tests := []struct {
150name string
151baseDir string
152mock func(t *testing.T, s Storage, baseDir, modelKey string, networkTopology []byte)
153expect func(t *testing.T, s Storage, baseDir, modelKey string, networkTopology []byte)
154}{
155{
156name: "empty csv file given",
157baseDir: os.TempDir(),
158mock: func(t *testing.T, s Storage, baseDir, modelKey string, networkTopology []byte) {
159file, err := os.OpenFile(filepath.Join(baseDir, "networktopology_bar.csv"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
160if err != nil {
161t.Fatal(err)
162}
163defer file.Close()
164},
165expect: func(t *testing.T, s Storage, baseDir, modelKey string, networkTopology []byte) {
166assert := assert.New(t)
167_, err := s.ListNetworkTopology(modelKey)
168assert.EqualError(err, "empty csv file given")
169},
170},
171{
172name: "get file failed",
173baseDir: os.TempDir(),
174mock: func(t *testing.T, s Storage, baseDir, modelKey string, networkTopology []byte) {
175file, err := os.OpenFile(filepath.Join(baseDir, "networktopology_bar.csv"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
176if err != nil {
177t.Fatal(err)
178}
179defer file.Close()
180
181if _, err = file.Write(networkTopology); err != nil {
182t.Fatal(err)
183}
184s.(*storage).baseDir = "foo"
185},
186expect: func(t *testing.T, s Storage, baseDir, modelKey string, networkTopology []byte) {
187assert := assert.New(t)
188_, err := s.ListNetworkTopology(modelKey)
189assert.EqualError(err, "open foo/networktopology_bar.csv: no such file or directory")
190s.(*storage).baseDir = baseDir
191},
192},
193{
194name: "list network topologies of a file",
195baseDir: os.TempDir(),
196mock: func(t *testing.T, s Storage, baseDir, modelKey string, networkTopology []byte) {
197file, err := os.OpenFile(filepath.Join(baseDir, "networktopology_bar.csv"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
198if err != nil {
199t.Fatal(err)
200}
201defer file.Close()
202
203if _, err = file.Write(networkTopology); err != nil {
204t.Fatal(err)
205}
206},
207expect: func(t *testing.T, s Storage, baseDir, modelKey string, networkTopology []byte) {
208assert := assert.New(t)
209list, err := s.ListNetworkTopology(modelKey)
210assert.NoError(err)
211assert.Equal(len(list), 1)
212},
213},
214}
215
216for _, tc := range tests {
217t.Run(tc.name, func(t *testing.T) {
218s := New(tc.baseDir)
219tc.mock(t, s, tc.baseDir, mockModelKey, testData)
220tc.expect(t, s, tc.baseDir, mockModelKey, testData)
221if err := s.ClearNetworkTopology(mockModelKey); err != nil {
222t.Fatal(err)
223}
224})
225}
226}
227
228func TestStorage_OpenDownload(t *testing.T) {
229require := require.New(t)
230testData, err := os.ReadFile("./testdata/download.csv")
231require.Nil(err, "load test file")
232
233tests := []struct {
234name string
235baseDir string
236mock func(t *testing.T, s Storage, baseDir, modelKey string, download []byte)
237expect func(t *testing.T, s Storage, baseDir, modelKey string, download []byte)
238}{
239{
240name: "open file failed",
241baseDir: os.TempDir(),
242mock: func(t *testing.T, s Storage, baseDir, modelKey string, download []byte) {
243file, err := os.OpenFile(filepath.Join(baseDir, "download_bar.csv"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
244if err != nil {
245t.Fatal(err)
246}
247defer file.Close()
248s.(*storage).baseDir = "baw"
249},
250expect: func(t *testing.T, s Storage, baseDir, modelKey string, download []byte) {
251assert := assert.New(t)
252_, err := s.OpenDownload(modelKey)
253assert.EqualError(err, "open baw/download_bar.csv: no such file or directory")
254s.(*storage).baseDir = baseDir
255},
256},
257{
258name: "open storage with downloads of a file",
259baseDir: os.TempDir(),
260mock: func(t *testing.T, s Storage, baseDir, modelKey string, download []byte) {
261file, err := os.OpenFile(filepath.Join(baseDir, "download_bar.csv"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
262if err != nil {
263t.Fatal(err)
264}
265defer file.Close()
266
267if _, err = file.Write(download); err != nil {
268t.Fatal(err)
269}
270},
271expect: func(t *testing.T, s Storage, baseDir, modelKey string, download []byte) {
272assert := assert.New(t)
273readCloser, err := s.OpenDownload(modelKey)
274assert.NoError(err)
275
276var downloads []schedulerstorage.Download
277assert.NoError(gocsv.UnmarshalWithoutHeaders(readCloser, &downloads))
278assert.Equal(len(downloads), 1)
279},
280},
281}
282
283for _, tc := range tests {
284t.Run(tc.name, func(t *testing.T) {
285s := New(tc.baseDir)
286tc.mock(t, s, tc.baseDir, mockModelKey, testData)
287tc.expect(t, s, tc.baseDir, mockModelKey, testData)
288if err := s.ClearDownload(mockModelKey); err != nil {
289t.Fatal(err)
290}
291})
292}
293}
294
295func TestStorage_OpenNetworkTopology(t *testing.T) {
296require := require.New(t)
297testData, err := os.ReadFile("./testdata/networktopology.csv")
298require.Nil(err, "load test file")
299
300tests := []struct {
301name string
302baseDir string
303mock func(t *testing.T, s Storage, baseDir, modelKey string, networkTopology []byte)
304expect func(t *testing.T, s Storage, baseDir, modelKey string, networkTopology []byte)
305}{
306{
307name: "open file failed",
308baseDir: os.TempDir(),
309mock: func(t *testing.T, s Storage, baseDir, modelKey string, networkTopology []byte) {
310file, err := os.OpenFile(filepath.Join(baseDir, "networktopology_bar.csv"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
311if err != nil {
312t.Fatal(err)
313}
314defer file.Close()
315s.(*storage).baseDir = "bas"
316},
317expect: func(t *testing.T, s Storage, baseDir, modelKey string, networkTopology []byte) {
318assert := assert.New(t)
319_, err := s.OpenNetworkTopology(modelKey)
320assert.EqualError(err, "open bas/networktopology_bar.csv: no such file or directory")
321s.(*storage).baseDir = baseDir
322},
323},
324{
325name: "open storage with network topologies of a file",
326baseDir: os.TempDir(),
327mock: func(t *testing.T, s Storage, baseDir, modelKey string, networkTopology []byte) {
328file, err := os.OpenFile(filepath.Join(baseDir, "networktopology_bar.csv"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
329if err != nil {
330t.Fatal(err)
331}
332defer file.Close()
333
334if _, err = file.Write(networkTopology); err != nil {
335t.Fatal(err)
336}
337},
338expect: func(t *testing.T, s Storage, baseDir, modelKey string, networkTopology []byte) {
339assert := assert.New(t)
340readCloser, err := s.OpenNetworkTopology(modelKey)
341assert.NoError(err)
342
343var networkTopologies []schedulerstorage.NetworkTopology
344assert.NoError(gocsv.UnmarshalWithoutHeaders(readCloser, &networkTopologies))
345assert.Equal(len(networkTopologies), 1)
346},
347},
348}
349
350for _, tc := range tests {
351t.Run(tc.name, func(t *testing.T) {
352s := New(tc.baseDir)
353tc.mock(t, s, tc.baseDir, mockModelKey, testData)
354tc.expect(t, s, tc.baseDir, mockModelKey, testData)
355if err := s.ClearNetworkTopology(mockModelKey); err != nil {
356t.Fatal(err)
357}
358})
359}
360}
361
362func TestStorage_ClearDownload(t *testing.T) {
363tests := []struct {
364name string
365baseDir string
366mock func(t *testing.T, s Storage, baseDir, modelKey string)
367expect func(t *testing.T, s Storage, baseDir, modelKey string)
368}{
369{
370name: "clear file",
371baseDir: os.TempDir(),
372mock: func(t *testing.T, s Storage, baseDir, modelKey string) {
373file, err := os.OpenFile(filepath.Join(baseDir, "download_bar.csv"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
374if err != nil {
375t.Fatal(err)
376}
377defer file.Close()
378},
379expect: func(t *testing.T, s Storage, baseDir, modelKey string) {
380assert := assert.New(t)
381assert.NoError(s.ClearDownload(modelKey))
382fileInfos, err := os.ReadDir(filepath.Join(baseDir))
383assert.NoError(err)
384
385var backups []fs.FileInfo
386re := regexp.MustCompile(fmt.Sprintf("%s_%s", DownloadFilePrefix, modelKey))
387
388for _, fileInfo := range fileInfos {
389if !fileInfo.IsDir() && re.MatchString(fileInfo.Name()) {
390info, _ := fileInfo.Info()
391backups = append(backups, info)
392}
393}
394assert.Equal(len(backups), 0)
395},
396},
397{
398name: "open file failed",
399baseDir: os.TempDir(),
400mock: func(t *testing.T, s Storage, baseDir, modelKey string) {
401file, err := os.OpenFile(filepath.Join(baseDir, "download_bar.csv"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
402if err != nil {
403t.Fatal(err)
404}
405defer file.Close()
406s.(*storage).baseDir = "baz"
407},
408expect: func(t *testing.T, s Storage, baseDir, modelKey string) {
409assert := assert.New(t)
410assert.EqualError(s.ClearDownload(modelKey), "remove baz/download_bar.csv: no such file or directory")
411
412s.(*storage).baseDir = baseDir
413assert.NoError(s.ClearDownload(modelKey))
414},
415},
416}
417
418for _, tc := range tests {
419t.Run(tc.name, func(t *testing.T) {
420s := New(tc.baseDir)
421tc.mock(t, s, tc.baseDir, mockModelKey)
422tc.expect(t, s, tc.baseDir, mockModelKey)
423})
424}
425}
426
427func TestStorage_ClearNetworkTopology(t *testing.T) {
428tests := []struct {
429name string
430baseDir string
431mock func(t *testing.T, s Storage, baseDir, modelKey string)
432expect func(t *testing.T, s Storage, baseDir, modelKey string)
433}{
434{
435name: "clear file",
436baseDir: os.TempDir(),
437mock: func(t *testing.T, s Storage, baseDir, modelKey string) {
438file, err := os.OpenFile(filepath.Join(baseDir, "networktopology_bar.csv"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
439if err != nil {
440t.Fatal(err)
441}
442defer file.Close()
443},
444expect: func(t *testing.T, s Storage, baseDir, modelKey string) {
445assert := assert.New(t)
446assert.NoError(s.ClearNetworkTopology(modelKey))
447fileInfos, err := os.ReadDir(filepath.Join(baseDir))
448assert.NoError(err)
449
450var backups []fs.FileInfo
451re := regexp.MustCompile(fmt.Sprintf("%s_%s", NetworkTopologyFilePrefix, modelKey))
452for _, fileInfo := range fileInfos {
453if !fileInfo.IsDir() && re.MatchString(fileInfo.Name()) {
454info, _ := fileInfo.Info()
455backups = append(backups, info)
456}
457}
458assert.Equal(len(backups), 0)
459},
460},
461{
462name: "open file failed",
463baseDir: os.TempDir(),
464mock: func(t *testing.T, s Storage, baseDir, modelKey string) {
465file, err := os.OpenFile(filepath.Join(baseDir, "networktopology_bar.csv"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
466if err != nil {
467t.Fatal(err)
468}
469defer file.Close()
470s.(*storage).baseDir = "baz"
471},
472expect: func(t *testing.T, s Storage, baseDir, modelKey string) {
473assert := assert.New(t)
474assert.EqualError(s.ClearNetworkTopology(modelKey), "remove baz/networktopology_bar.csv: no such file or directory")
475s.(*storage).baseDir = baseDir
476assert.NoError(s.ClearNetworkTopology(modelKey))
477},
478},
479}
480
481for _, tc := range tests {
482t.Run(tc.name, func(t *testing.T) {
483s := New(tc.baseDir)
484tc.mock(t, s, tc.baseDir, mockModelKey)
485tc.expect(t, s, tc.baseDir, mockModelKey)
486})
487}
488}
489
490func TestStorage_Clear(t *testing.T) {
491tests := []struct {
492name string
493baseDir string
494mock func(t *testing.T, s Storage, baseDir string)
495expect func(t *testing.T, s Storage, baseDir string)
496}{
497{
498name: "clear file",
499baseDir: os.TempDir(),
500mock: func(t *testing.T, s Storage, baseDir string) {
501s.(*storage).baseDir = filepath.Join(baseDir, "bae")
502if err := os.MkdirAll(s.(*storage).baseDir, fs.FileMode(0700)); err != nil {
503t.Fatal(err)
504}
505
506downloadFile, err := os.OpenFile(filepath.Join(s.(*storage).baseDir, "download_bar.csv"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
507if err != nil {
508t.Fatal(err)
509}
510defer downloadFile.Close()
511
512networkTopologyFile, err := os.OpenFile(filepath.Join(s.(*storage).baseDir, "networktopology_bar.csv"), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
513if err != nil {
514t.Fatal(err)
515}
516defer networkTopologyFile.Close()
517},
518expect: func(t *testing.T, s Storage, baseDir string) {
519assert := assert.New(t)
520assert.NoError(s.Clear())
521_, err := os.Stat(filepath.Join(baseDir, "bae"))
522assert.EqualError(err, fmt.Sprintf("stat %s: no such file or directory", filepath.Join(baseDir, "bae")))
523},
524},
525}
526
527for _, tc := range tests {
528t.Run(tc.name, func(t *testing.T) {
529s := New(tc.baseDir)
530tc.mock(t, s, tc.baseDir)
531tc.expect(t, s, tc.baseDir)
532})
533}
534}
535
536func TestStorage_downloadFilename(t *testing.T) {
537baseDir := os.TempDir()
538s := New(baseDir)
539
540filename := s.(*storage).downloadFilename(mockModelKey)
541re := regexp.MustCompile(fmt.Sprintf("%s_%s.%s$", DownloadFilePrefix, mockModelKey, CSVFileExt))
542assert := assert.New(t)
543assert.True(re.MatchString(filename))
544}
545
546func TestStorage_networkTopologyFilename(t *testing.T) {
547baseDir := os.TempDir()
548s := New(baseDir)
549
550filename := s.(*storage).networkTopologyFilename(mockModelKey)
551re := regexp.MustCompile(fmt.Sprintf("%s_%s.%s$", NetworkTopologyFilePrefix, mockModelKey, CSVFileExt))
552assert := assert.New(t)
553assert.True(re.MatchString(filename))
554}
555