]> ruderich.org/simon Gitweb - safcm/safcm.git/blob - cmd/safcm/sync_changes_test.go
76a016834b87d8a09d68547bcea26720511b13a4
[safcm/safcm.git] / cmd / safcm / sync_changes_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 main
17
18 import (
19         "io/fs"
20         "testing"
21
22         "github.com/google/go-cmp/cmp"
23
24         "ruderich.org/simon/safcm"
25         "ruderich.org/simon/safcm/cmd/safcm/config"
26 )
27
28 func TestFormatFileChanges(t *testing.T) {
29         tests := []struct {
30                 name    string
31                 dryRun  bool
32                 changes []safcm.FileChange
33                 exp     string
34         }{
35
36                 {
37                         "regular",
38                         false,
39                         []safcm.FileChange{
40                                 {
41                                         Path:    "created: file",
42                                         Created: true,
43                                         New: safcm.FileChangeInfo{
44                                                 Mode:  0644,
45                                                 User:  "user",
46                                                 Uid:   1000,
47                                                 Group: "group",
48                                                 Gid:   2000,
49                                         },
50                                 },
51                                 {
52                                         Path:    "created: link",
53                                         Created: true,
54                                         New: safcm.FileChangeInfo{
55                                                 Mode:  fs.ModeSymlink | 0777,
56                                                 User:  "user",
57                                                 Uid:   1000,
58                                                 Group: "group",
59                                                 Gid:   2000,
60                                         },
61                                 },
62                                 {
63                                         Path: "type change: file -> dir",
64                                         Old: safcm.FileChangeInfo{
65                                                 Mode:  0751,
66                                                 User:  "user",
67                                                 Uid:   1000,
68                                                 Group: "group",
69                                                 Gid:   2000,
70                                         },
71                                         New: safcm.FileChangeInfo{
72                                                 Mode:  fs.ModeDir | 0751,
73                                                 User:  "user",
74                                                 Uid:   1000,
75                                                 Group: "group",
76                                                 Gid:   2000,
77                                         },
78                                         DataDiff: `@@ -1,2 +1 @@
79 -content
80  
81 `,
82                                 },
83                                 {
84                                         Path: "user change",
85                                         Old: safcm.FileChangeInfo{
86                                                 Mode:  0755,
87                                                 User:  "user",
88                                                 Uid:   1000,
89                                                 Group: "group",
90                                                 Gid:   2000,
91                                         },
92                                         New: safcm.FileChangeInfo{
93                                                 Mode:  0755,
94                                                 User:  "user2",
95                                                 Uid:   1001,
96                                                 Group: "group",
97                                                 Gid:   2000,
98                                         },
99                                 },
100                                 {
101                                         Path: "group change",
102                                         Old: safcm.FileChangeInfo{
103                                                 Mode:  0755,
104                                                 User:  "user",
105                                                 Uid:   1000,
106                                                 Group: "group",
107                                                 Gid:   2000,
108                                         },
109                                         New: safcm.FileChangeInfo{
110                                                 Mode:  0755,
111                                                 User:  "user",
112                                                 Uid:   1000,
113                                                 Group: "group2",
114                                                 Gid:   2001,
115                                         },
116                                 },
117                                 {
118                                         Path: "mode change",
119                                         Old: safcm.FileChangeInfo{
120                                                 Mode:  0755,
121                                                 User:  "user",
122                                                 Uid:   1000,
123                                                 Group: "group",
124                                                 Gid:   2000,
125                                         },
126                                         New: safcm.FileChangeInfo{
127                                                 Mode:  0750,
128                                                 User:  "user",
129                                                 Uid:   1000,
130                                                 Group: "group",
131                                                 Gid:   2000,
132                                         },
133                                 },
134                                 {
135                                         Path: "mode change (setuid)",
136                                         Old: safcm.FileChangeInfo{
137                                                 Mode:  0755,
138                                                 User:  "user",
139                                                 Uid:   1000,
140                                                 Group: "group",
141                                                 Gid:   2000,
142                                         },
143                                         New: safcm.FileChangeInfo{
144                                                 Mode:  0755 | fs.ModeSetuid,
145                                                 User:  "user",
146                                                 Uid:   1000,
147                                                 Group: "group",
148                                                 Gid:   2000,
149                                         },
150                                 },
151                                 {
152                                         Path: "content change",
153                                         Old: safcm.FileChangeInfo{
154                                                 Mode:  0644,
155                                                 User:  "user",
156                                                 Uid:   1000,
157                                                 Group: "group",
158                                                 Gid:   2000,
159                                         },
160                                         New: safcm.FileChangeInfo{
161                                                 Mode:  0644,
162                                                 User:  "user",
163                                                 Uid:   1000,
164                                                 Group: "group",
165                                                 Gid:   2000,
166                                         },
167                                         DataDiff: `@@ -1,2 +1,2 @@
168 -old content
169 +content
170  
171 `,
172                                 },
173                                 {
174                                         Path: "multiple changes",
175                                         Old: safcm.FileChangeInfo{
176                                                 Mode:  0644,
177                                                 User:  "user",
178                                                 Uid:   1000,
179                                                 Group: "group",
180                                                 Gid:   2000,
181                                         },
182                                         New: safcm.FileChangeInfo{
183                                                 Mode:  fs.ModeDir | 0755,
184                                                 User:  "user2",
185                                                 Uid:   1001,
186                                                 Group: "group2",
187                                                 Gid:   2001,
188                                         },
189                                         DataDiff: `@@ -1,2 +1 @@
190 -content
191  
192 `,
193                                 },
194                         },
195                         `changed 9 file(s):
196 "created: file": created, file, user(1000) group(2000), 0644
197 "created: link": created, symlink, user(1000) group(2000), 0777
198 "type change: file -> dir": file -> dir
199    @@ -1,2 +1 @@
200    -content
201     
202 "user change": user(1000) group(2000) -> user2(1001) group(2000)
203 "group change": user(1000) group(2000) -> user(1000) group2(2001)
204 "mode change": 0755 -> 0750
205 "mode change (setuid)": 0755 -> 04755
206 "content change":
207    @@ -1,2 +1,2 @@
208    -old content
209    +content
210     
211 "multiple changes": file -> dir, user(1000) group(2000) -> user2(1001) group2(2001), 0644 -> 0755
212    @@ -1,2 +1 @@
213    -content
214     
215 `,
216                 },
217
218                 {
219                         "dry-run",
220                         true,
221                         []safcm.FileChange{
222                                 {
223                                         Path:    "file",
224                                         Created: true,
225                                         New: safcm.FileChangeInfo{
226                                                 Mode:  0644,
227                                                 User:  "user",
228                                                 Uid:   1000,
229                                                 Group: "group",
230                                                 Gid:   2000,
231                                         },
232                                 },
233                         },
234                         `changed 1 file(s): (dry-run)
235 "file": created, file, user(1000) group(2000), 0644
236 `,
237                 },
238
239                 {
240                         "escaping",
241                         false,
242                         []safcm.FileChange{
243                                 {
244                                         Path:    "\x00",
245                                         Created: true,
246                                         New: safcm.FileChangeInfo{
247                                                 Mode:  0xFFFFFFFF,
248                                                 User:  "\x01",
249                                                 Uid:   -1,
250                                                 Group: "\x02",
251                                                 Gid:   -2,
252                                         },
253                                         DataDiff: "\x03",
254                                 },
255                                 {
256                                         Path: "\x00",
257                                         Old: safcm.FileChangeInfo{
258                                                 Mode:  0x00000000,
259                                                 User:  "\x01",
260                                                 Uid:   -1,
261                                                 Group: "\x02",
262                                                 Gid:   -2,
263                                         },
264                                         New: safcm.FileChangeInfo{
265                                                 Mode:  0xFFFFFFFF,
266                                                 User:  "\x03",
267                                                 Uid:   -3,
268                                                 Group: "\x04",
269                                                 Gid:   -4,
270                                         },
271                                         DataDiff: "\x05",
272                                 },
273                         },
274                         `changed 2 file(s):
275 "\x00": created, invalid type dLDpSc?---------, \x01(-1) \x02(-2), 07777
276    \x03
277    \ No newline at end of file
278 "\x00": file -> invalid type dLDpSc?---------, \x01(-1) \x02(-2) -> \x03(-3) \x04(-4), 0 -> 07777
279    \x05
280    \ No newline at end of file
281 `,
282                 },
283         }
284
285         for _, tc := range tests {
286                 s := &Sync{
287                         config: &config.Config{
288                                 DryRun: tc.dryRun,
289                         },
290                 }
291
292                 res := s.formatFileChanges(tc.changes)
293                 if tc.exp != res {
294                         t.Errorf("%s: res: %s", tc.name,
295                                 cmp.Diff(tc.exp, res))
296                 }
297         }
298 }
299
300 func TestFormatPackageChanges(t *testing.T) {
301         tests := []struct {
302                 name    string
303                 dryRun  bool
304                 changes []safcm.PackageChange
305                 exp     string
306         }{
307
308                 {
309                         "regular",
310                         false,
311                         []safcm.PackageChange{
312                                 {
313                                         Name: "package-one",
314                                 },
315                                 {
316                                         Name: "package-two",
317                                 },
318                         },
319                         `installed 2 package(s):
320 "package-one"
321 "package-two"
322 `,
323                 },
324
325                 {
326                         "dry-run",
327                         true,
328                         []safcm.PackageChange{
329                                 {
330                                         Name: "package-one",
331                                 },
332                                 {
333                                         Name: "package-two",
334                                 },
335                         },
336                         `installed 2 package(s): (dry-run)
337 "package-one"
338 "package-two"
339 `,
340                 },
341
342                 {
343                         "escaping",
344                         false,
345                         []safcm.PackageChange{
346                                 {
347                                         Name: "\x00",
348                                 },
349                         },
350                         `installed 1 package(s):
351 "\x00"
352 `,
353                 },
354         }
355
356         for _, tc := range tests {
357                 s := &Sync{
358                         config: &config.Config{
359                                 DryRun: tc.dryRun,
360                         },
361                 }
362
363                 res := s.formatPackageChanges(tc.changes)
364                 if tc.exp != res {
365                         t.Errorf("%s: res: %s", tc.name,
366                                 cmp.Diff(tc.exp, res))
367                 }
368         }
369 }
370
371 func TestFormatServiceChanges(t *testing.T) {
372         tests := []struct {
373                 name    string
374                 dryRun  bool
375                 changes []safcm.ServiceChange
376                 exp     string
377         }{
378
379                 {
380                         "regular",
381                         false,
382                         []safcm.ServiceChange{
383                                 {
384                                         Name:    "service-one",
385                                         Started: true,
386                                 },
387                                 {
388                                         Name:    "service-two",
389                                         Enabled: true,
390                                 },
391                                 {
392                                         Name:    "service-three",
393                                         Started: true,
394                                         Enabled: true,
395                                 },
396                         },
397                         `modified 3 service(s):
398 "service-one": started
399 "service-two": enabled
400 "service-three": started, enabled
401 `,
402                 },
403
404                 {
405                         "dry-run",
406                         true,
407                         []safcm.ServiceChange{
408                                 {
409                                         Name:    "service-one",
410                                         Started: true,
411                                 },
412                                 {
413                                         Name:    "service-two",
414                                         Enabled: true,
415                                 },
416                                 {
417                                         Name:    "service-three",
418                                         Started: true,
419                                         Enabled: true,
420                                 },
421                         },
422                         `modified 3 service(s): (dry-run)
423 "service-one": started
424 "service-two": enabled
425 "service-three": started, enabled
426 `,
427                 },
428
429                 {
430                         "escaping",
431                         false,
432                         []safcm.ServiceChange{
433                                 {
434                                         Name: "\x00",
435                                 },
436                                 {
437                                         Name:    "\x01",
438                                         Started: true,
439                                         Enabled: true,
440                                 },
441                         },
442                         `modified 2 service(s):
443 "\x00": 
444 "\x01": started, enabled
445 `,
446                 },
447         }
448
449         for _, tc := range tests {
450                 s := &Sync{
451                         config: &config.Config{
452                                 DryRun: tc.dryRun,
453                         },
454                 }
455
456                 res := s.formatServiceChanges(tc.changes)
457                 if tc.exp != res {
458                         t.Errorf("%s: res: %s", tc.name,
459                                 cmp.Diff(tc.exp, res))
460                 }
461         }
462 }
463
464 func TestFormatCommandChanges(t *testing.T) {
465         tests := []struct {
466                 name    string
467                 dryRun  bool
468                 changes []safcm.CommandChange
469                 exp     string
470         }{
471
472                 {
473                         "regular",
474                         false,
475                         []safcm.CommandChange{
476                                 {
477                                         Command: "fake command",
478                                         Output:  "fake output",
479                                 },
480                                 {
481                                         Command: "fake command with no output",
482                                 },
483                                 {
484                                         Command: "fake command with newline",
485                                         Output:  "fake output\n",
486                                 },
487                                 {
488                                         Command: "fake command with more output",
489                                         Output:  "fake out\nfake put\nfake\n",
490                                 },
491                                 {
492                                         Command: "fake failed command",
493                                         Output:  "fake output",
494                                         Error:   "fake error",
495                                 },
496                         },
497                         `executed 5 command(s):
498 "fake command":
499    > fake output
500    > \ No newline at end of file
501 "fake command with no output"
502 "fake command with newline":
503    > fake output
504 "fake command with more output":
505    > fake out
506    > fake put
507    > fake
508 "fake failed command", failed: "fake error":
509    > fake output
510    > \ No newline at end of file
511 `,
512                 },
513
514                 {
515                         "dry-run",
516                         true,
517                         []safcm.CommandChange{
518                                 {
519                                         Command: "fake command",
520                                         Output:  "fake output",
521                                 },
522                         },
523                         `executed 1 command(s): (dry-run)
524 "fake command":
525    > fake output
526    > \ No newline at end of file
527 `,
528                 },
529
530                 {
531                         "escaping",
532                         false,
533                         []safcm.CommandChange{
534                                 {
535                                         Command: "\x00",
536                                         Trigger: "\x01",
537                                         Output:  "\x02",
538                                         Error:   "\x03",
539                                 },
540                         },
541                         `executed 1 command(s):
542 "\x00", trigger for "\x01", failed: "\x03":
543    > \x02
544    > \ No newline at end of file
545 `,
546                 },
547         }
548
549         for _, tc := range tests {
550                 s := &Sync{
551                         config: &config.Config{
552                                 DryRun: tc.dryRun,
553                         },
554                 }
555
556                 res := s.formatCommandChanges(tc.changes)
557                 if tc.exp != res {
558                         t.Errorf("%s: res: %s", tc.name,
559                                 cmp.Diff(tc.exp, res))
560                 }
561         }
562 }