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