]> ruderich.org/simon Gitweb - safcm/safcm.git/blob - remote/ainsl/ainsl_test.go
Use SPDX license identifiers
[safcm/safcm.git] / remote / ainsl / ainsl_test.go
1 // SPDX-License-Identifier: GPL-3.0-or-later
2 // Copyright (C) 2021-2024  Simon Ruderich
3
4 package ainsl
5
6 import (
7         "fmt"
8         "io/fs"
9         "os"
10         "path/filepath"
11         "runtime"
12         "syscall"
13         "testing"
14
15         ft "ruderich.org/simon/safcm/remote/sync/filetest"
16         "ruderich.org/simon/safcm/testutil"
17 )
18
19 func TestHandle(t *testing.T) {
20         cwd, err := os.Getwd()
21         if err != nil {
22                 t.Fatal(err)
23         }
24         defer os.Chdir(cwd) //nolint:errcheck
25
26         err = os.RemoveAll("testdata")
27         if err != nil {
28                 t.Fatal(err)
29         }
30         err = os.Mkdir("testdata", 0700)
31         if err != nil {
32                 t.Fatal(err)
33         }
34
35         // Set umask to test mode for new files
36         umask := syscall.Umask(027)
37         defer syscall.Umask(umask)
38
39         root := ft.File{
40                 Path: ".",
41                 Mode: fs.ModeDir | 0700,
42         }
43         _, uid, _, gid := ft.CurrentUserAndGroup()
44
45         symlinkExists := "\"file\": too many levels of symbolic links"
46         if runtime.GOOS == "freebsd" {
47                 // EMLINK instead of ELOOP
48                 symlinkExists = "\"file\": too many links"
49         }
50
51         tests := []struct {
52                 name       string
53                 path       string
54                 line       string
55                 create     bool
56                 prepare    func()
57                 expFiles   []ft.File
58                 expChanges []string
59                 expErr     error
60         }{
61
62                 // TODO: Add tests for chown and run them only as root
63
64                 {
65                         "missing",
66                         "file",
67                         "line",
68                         false,
69                         nil,
70                         []ft.File{
71                                 root,
72                         },
73                         nil,
74                         fmt.Errorf("\"file\": file does not exist, use -create"),
75                 },
76
77                 {
78                         "missing: create",
79                         "file",
80                         "line",
81                         true,
82                         nil,
83                         []ft.File{
84                                 root,
85                                 {
86                                         Path: "file",
87                                         Mode: 0640,
88                                         Data: []byte("line\n"),
89                                 },
90                         },
91                         []string{
92                                 fmt.Sprintf(`"file": created file (%d/%d -rw-r-----)`, uid, gid),
93                                 `"file": added line "line"`,
94                         },
95                         nil,
96                 },
97                 {
98                         "missing: create (empty line)",
99                         "file",
100                         "",
101                         true,
102                         nil,
103                         []ft.File{
104                                 root,
105                         },
106                         nil,
107                         fmt.Errorf("empty line"),
108                 },
109                 {
110                         "missing: create (newline)",
111                         "file",
112                         "line\n",
113                         true,
114                         nil,
115                         []ft.File{
116                                 root,
117                         },
118                         nil,
119                         fmt.Errorf("line must not contain newlines: \"line\\n\""),
120                 },
121
122                 {
123                         "exists: unchanged",
124                         "file",
125                         "line",
126                         true,
127                         func() {
128                                 ft.CreateFile("file", "line\n", 0641)
129                         },
130                         []ft.File{
131                                 root,
132                                 {
133                                         Path: "file",
134                                         Mode: 0641,
135                                         Data: []byte("line\n"),
136                                 },
137                         },
138                         nil,
139                         nil,
140                 },
141
142                 {
143                         "exists: append",
144                         "file",
145                         "line",
146                         true,
147                         func() {
148                                 ft.CreateFile("file", "existing\n", 0641)
149                         },
150                         []ft.File{
151                                 root,
152                                 {
153                                         Path: "file",
154                                         Mode: 0641,
155                                         Data: []byte("existing\nline\n"),
156                                 },
157                         },
158                         []string{
159                                 `"file": added line "line"`,
160                         },
161                         nil,
162                 },
163                 {
164                         "exists: append (no newline in file)",
165                         "file",
166                         "line",
167                         true,
168                         func() {
169                                 ft.CreateFile("file", "existing", 0641)
170                         },
171                         []ft.File{
172                                 root,
173                                 {
174                                         Path: "file",
175                                         Mode: 0641,
176                                         Data: []byte("existing\nline\n"),
177                                 },
178                         },
179                         []string{
180                                 `"file": added missing trailing newline`,
181                                 `"file": added line "line"`,
182                         },
183                         nil,
184                 },
185                 {
186                         "exists: append (only trailing newline I)",
187                         "file",
188                         "line",
189                         true,
190                         func() {
191                                 ft.CreateFile("file", "first\nline", 0641)
192                         },
193                         []ft.File{
194                                 root,
195                                 {
196                                         Path: "file",
197                                         Mode: 0641,
198                                         Data: []byte("first\nline\n"),
199                                 },
200                         },
201                         []string{
202                                 `"file": added missing trailing newline`,
203                         },
204                         nil,
205                 },
206                 {
207                         "exists: append (only trailing newline II)",
208                         "file",
209                         "first",
210                         true,
211                         func() {
212                                 ft.CreateFile("file", "first\nline", 0641)
213                         },
214                         []ft.File{
215                                 root,
216                                 {
217                                         Path: "file",
218                                         Mode: 0641,
219                                         Data: []byte("first\nline\n"),
220                                 },
221                         },
222                         []string{
223                                 `"file": added missing trailing newline`,
224                         },
225                         nil,
226                 },
227                 {
228                         "exists: append (partial line)",
229                         "file",
230                         "line with spaces",
231                         true,
232                         func() {
233                                 ft.CreateFile("file", "# line with spaces\n", 0641)
234                         },
235                         []ft.File{
236                                 root,
237                                 {
238                                         Path: "file",
239                                         Mode: 0641,
240                                         Data: []byte("# line with spaces\nline with spaces\n"),
241                                 },
242                         },
243                         []string{
244                                 `"file": added line "line with spaces"`,
245                         },
246                         nil,
247                 },
248
249                 {
250                         "exists: symlink",
251                         "file",
252                         "line",
253                         true,
254                         func() {
255                                 ft.CreateSymlink("file", "target")
256                         },
257                         []ft.File{
258                                 root,
259                                 {
260                                         Path: "file",
261                                         Mode: fs.ModeSymlink | 0777,
262                                         Data: []byte("target"),
263                                 },
264                         },
265                         nil,
266                         fmt.Errorf(symlinkExists),
267                 },
268                 {
269                         "exists: fifo",
270                         "file",
271                         "line",
272                         true,
273                         func() {
274                                 ft.CreateFifo("file", 0640)
275                         },
276                         []ft.File{
277                                 root,
278                                 {
279                                         Path: "file",
280                                         Mode: fs.ModeNamedPipe | 0640,
281                                 },
282                         },
283                         nil,
284                         fmt.Errorf("\"file\": not a regular file but p---------"),
285                 },
286         }
287
288         for _, tc := range tests {
289                 t.Run(tc.name, func(t *testing.T) {
290                         // Create separate test directory for each test case
291                         path := filepath.Join(cwd, "testdata", tc.name)
292                         err = os.Mkdir(path, 0700)
293                         if err != nil {
294                                 t.Fatal(err)
295                         }
296                         err = os.Chdir(path)
297                         if err != nil {
298                                 t.Fatal(err)
299                         }
300
301                         if tc.prepare != nil {
302                                 tc.prepare()
303                         }
304
305                         changes, err := handle(tc.path, tc.line, tc.create)
306                         testutil.AssertEqual(t, "changes",
307                                 changes, tc.expChanges)
308                         testutil.AssertErrorEqual(t, "err", err, tc.expErr)
309
310                         files, err := ft.WalkDir(path)
311                         if err != nil {
312                                 t.Fatal(err)
313                         }
314                         testutil.AssertEqual(t, "files", files, tc.expFiles)
315                 })
316         }
317
318         if !t.Failed() {
319                 err = os.RemoveAll(filepath.Join(cwd, "testdata"))
320                 if err != nil {
321                         t.Fatal(err)
322                 }
323         }
324 }