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