1 // Copyright (C) 2021 Simon Ruderich
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.
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.
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/>.
22 "ruderich.org/simon/safcm"
23 "ruderich.org/simon/safcm/cmd/safcm/config"
24 "ruderich.org/simon/safcm/testutil"
27 func TestFormatChanges(t *testing.T) {
32 resp safcm.MsgSyncResp
36 // Just a few basic tests and border cases; see the other
37 // tests for more detailed tests of each format function
52 FileChanges: []safcm.FileChange{
56 New: safcm.FileChangeInfo{
65 PackageChanges: []safcm.PackageChange{
73 ServiceChanges: []safcm.ServiceChange{
83 Name: "service-three",
88 CommandChanges: []safcm.CommandChange{
90 Command: "fake command",
91 Output: "fake output",
94 Command: "fake command with no output",
98 "\nchanged 1 file(s):\n\"created\": created, file, user(1000) group(2000), 0644\n\ninstalled 2 package(s):\n\"package-one\"\n\"package-two\"\n\nmodified 3 service(s):\n\"service-one\": started\n\"service-two\": enabled\n\"service-three\": started, enabled\n\nexecuted 2 command(s):\n\"fake command\":\n > fake output\n > \\ No newline at end of file\n\"fake command with no output\"\n",
102 for _, tc := range tests {
103 t.Run(tc.name, func(t *testing.T) {
105 config: &config.Config{
111 res := s.formatChanges(tc.resp)
112 testutil.AssertEqual(t, "res", res, tc.exp)
117 func TestFormatFileChanges(t *testing.T) {
122 changes []safcm.FileChange
132 Path: "created: file",
134 New: safcm.FileChangeInfo{
143 Path: "created: link",
145 New: safcm.FileChangeInfo{
146 Mode: fs.ModeSymlink | 0777,
154 Path: "type change: file -> dir",
155 Old: safcm.FileChangeInfo{
162 New: safcm.FileChangeInfo{
163 Mode: fs.ModeDir | 0751,
169 DataDiff: `@@ -1,2 +1 @@
176 Old: safcm.FileChangeInfo{
183 New: safcm.FileChangeInfo{
192 Path: "group change",
193 Old: safcm.FileChangeInfo{
200 New: safcm.FileChangeInfo{
210 Old: safcm.FileChangeInfo{
217 New: safcm.FileChangeInfo{
226 Path: "mode change (setuid)",
227 Old: safcm.FileChangeInfo{
234 New: safcm.FileChangeInfo{
235 Mode: 0755 | fs.ModeSetuid,
243 Path: "content change",
244 Old: safcm.FileChangeInfo{
251 New: safcm.FileChangeInfo{
258 DataDiff: `@@ -1,2 +1,2 @@
265 Path: "multiple changes",
266 Old: safcm.FileChangeInfo{
273 New: safcm.FileChangeInfo{
274 Mode: fs.ModeDir | 0755,
280 DataDiff: `@@ -1,2 +1 @@
287 "created: file": created, file, user(1000) group(2000), 0644
288 "created: link": created, symlink, user(1000) group(2000), 0777
289 "type change: file -> dir": file -> dir
293 "user change": user(1000) group(2000) -> user2(1001) group(2000)
294 "group change": user(1000) group(2000) -> user(1000) group2(2001)
295 "mode change": 0755 -> 0750
296 "mode change (setuid)": 0755 -> 04755
302 "multiple changes": file -> dir, user(1000) group(2000) -> user2(1001) group2(2001), 0644 -> 0755
315 Path: "created: file",
317 New: safcm.FileChangeInfo{
326 Path: "created: link",
328 New: safcm.FileChangeInfo{
329 Mode: fs.ModeSymlink | 0777,
337 Path: "type change: file -> dir",
338 Old: safcm.FileChangeInfo{
345 New: safcm.FileChangeInfo{
346 Mode: fs.ModeDir | 0751,
352 DataDiff: `@@ -1,2 +1 @@
359 Old: safcm.FileChangeInfo{
366 New: safcm.FileChangeInfo{
375 Path: "group change",
376 Old: safcm.FileChangeInfo{
383 New: safcm.FileChangeInfo{
393 Old: safcm.FileChangeInfo{
400 New: safcm.FileChangeInfo{
409 Path: "mode change (setuid)",
410 Old: safcm.FileChangeInfo{
417 New: safcm.FileChangeInfo{
418 Mode: 0755 | fs.ModeSetuid,
426 Path: "content change",
427 Old: safcm.FileChangeInfo{
434 New: safcm.FileChangeInfo{
441 DataDiff: `@@ -1,2 +1,2 @@
448 Path: "multiple changes",
449 Old: safcm.FileChangeInfo{
456 New: safcm.FileChangeInfo{
457 Mode: fs.ModeDir | 0755,
463 DataDiff: `@@ -1,2 +1 @@
469 "changed 9 file(s):\n\x1b[36m\"created: file\"\x1b[0m: \x1b[32mcreated\x1b[0m, file, user(1000) group(2000), 0644\n\x1b[36m\"created: link\"\x1b[0m: \x1b[32mcreated\x1b[0m, symlink, user(1000) group(2000), 0777\n\x1b[36m\"type change: file -> dir\"\x1b[0m: file -> dir\n @@ -1,2 +1 @@\n\x1b[31m -content\x1b[0m\n \n\x1b[36m\"user change\"\x1b[0m: user(1000) group(2000) -> user2(1001) group(2000)\n\x1b[36m\"group change\"\x1b[0m: user(1000) group(2000) -> user(1000) group2(2001)\n\x1b[36m\"mode change\"\x1b[0m: 0755 -> 0750\n\x1b[36m\"mode change (setuid)\"\x1b[0m: 0755 -> 04755\n\x1b[36m\"content change\"\x1b[0m:\n @@ -1,2 +1,2 @@\n\x1b[31m -old content\x1b[0m\n\x1b[32m +content\x1b[0m\n \n\x1b[36m\"multiple changes\"\x1b[0m: file -> dir, user(1000) group(2000) -> user2(1001) group2(2001), 0644 -> 0755\n @@ -1,2 +1 @@\n\x1b[31m -content\x1b[0m\n \n",
480 New: safcm.FileChangeInfo{
489 `changed 1 file(s): (dry-run)
490 "file": created, file, user(1000) group(2000), 0644
502 New: safcm.FileChangeInfo{
511 "changed 1 file(s): (dry-run)\n\x1B[36m\"file\"\x1B[0m: \x1B[32mcreated\x1B[0m, file, user(1000) group(2000), 0644\n",
522 New: safcm.FileChangeInfo{
533 Old: safcm.FileChangeInfo{
540 New: safcm.FileChangeInfo{
551 "\x00": created, invalid type dLDpSc?---------, \x01(-1) \x02(-2), 07777
553 \ No newline at end of file
554 "\x00": file -> invalid type dLDpSc?---------, \x01(-1) \x02(-2) -> \x03(-3) \x04(-4), 0 -> 07777
556 \ No newline at end of file
568 New: safcm.FileChangeInfo{
579 Old: safcm.FileChangeInfo{
586 New: safcm.FileChangeInfo{
596 "changed 2 file(s):\n\x1b[36m\"\\x00\"\x1b[0m: \x1b[32mcreated\x1b[0m, invalid type dLDpSc?---------, \\x01(-1) \\x02(-2), 07777\n \\x03\n \\ No newline at end of file\n\x1b[36m\"\\x00\"\x1b[0m: file -> invalid type dLDpSc?---------, \\x01(-1) \\x02(-2) -> \\x03(-3) \\x04(-4), 0 -> 07777\n \\x05\n \\ No newline at end of file\n",
600 for _, tc := range tests {
601 t.Run(tc.name, func(t *testing.T) {
603 config: &config.Config{
609 res := s.formatFileChanges(tc.changes)
610 testutil.AssertEqual(t, "res", res, tc.exp)
615 func TestFormatPackageChanges(t *testing.T) {
620 changes []safcm.PackageChange
628 []safcm.PackageChange{
636 `installed 2 package(s):
646 []safcm.PackageChange{
654 "installed 2 package(s):\n\x1b[36m\"package-one\"\x1b[0m\n\x1b[36m\"package-two\"\x1b[0m\n",
661 []safcm.PackageChange{
669 `installed 2 package(s): (dry-run)
679 []safcm.PackageChange{
687 "installed 2 package(s): (dry-run)\n\x1b[36m\"package-one\"\x1b[0m\n\x1b[36m\"package-two\"\x1b[0m\n",
694 []safcm.PackageChange{
699 `installed 1 package(s):
708 []safcm.PackageChange{
713 "installed 1 package(s):\n\x1b[36m\"\\x00\"\x1b[0m\n",
717 for _, tc := range tests {
718 t.Run(tc.name, func(t *testing.T) {
720 config: &config.Config{
726 res := s.formatPackageChanges(tc.changes)
727 testutil.AssertEqual(t, "res", res, tc.exp)
732 func TestFormatServiceChanges(t *testing.T) {
737 changes []safcm.ServiceChange
745 []safcm.ServiceChange{
755 Name: "service-three",
760 `modified 3 service(s):
761 "service-one": started
762 "service-two": enabled
763 "service-three": started, enabled
771 []safcm.ServiceChange{
781 Name: "service-three",
786 "modified 3 service(s):\n\x1b[36m\"service-one\"\x1b[0m: started\n\x1b[36m\"service-two\"\x1b[0m: enabled\n\x1b[36m\"service-three\"\x1b[0m: started, enabled\n",
793 []safcm.ServiceChange{
803 Name: "service-three",
808 `modified 3 service(s): (dry-run)
809 "service-one": started
810 "service-two": enabled
811 "service-three": started, enabled
819 []safcm.ServiceChange{
829 Name: "service-three",
834 "modified 3 service(s): (dry-run)\n\x1b[36m\"service-one\"\x1b[0m: started\n\x1b[36m\"service-two\"\x1b[0m: enabled\n\x1b[36m\"service-three\"\x1b[0m: started, enabled\n",
841 []safcm.ServiceChange{
851 `modified 2 service(s):
853 "\x01": started, enabled
861 []safcm.ServiceChange{
871 "modified 2 service(s):\n\x1b[36m\"\\x00\"\x1b[0m: \n\x1b[36m\"\\x01\"\x1b[0m: started, enabled\n",
875 for _, tc := range tests {
876 t.Run(tc.name, func(t *testing.T) {
878 config: &config.Config{
884 res := s.formatServiceChanges(tc.changes)
885 testutil.AssertEqual(t, "res", res, tc.exp)
890 func TestFormatCommandChanges(t *testing.T) {
896 changes []safcm.CommandChange
905 []safcm.CommandChange{
907 Command: "fake command",
908 Output: "fake output",
911 Command: "fake command with no output",
914 Command: "fake command with newline",
915 Output: "fake output\n",
918 Command: "fake command with more output",
919 Output: "fake out\nfake put\nfake\n",
922 Command: "fake failed command",
923 Output: "fake output",
927 `executed 5 command(s):
930 > \ No newline at end of file
931 "fake command with no output"
932 "fake command with newline":
934 "fake command with more output":
938 "fake failed command", failed: "fake error":
940 > \ No newline at end of file
949 []safcm.CommandChange{
951 Command: "fake command",
952 Output: "fake output",
955 Command: "fake command with no output",
958 Command: "fake command with newline",
959 Output: "fake output\n",
962 Command: "fake command with more output",
963 Output: "fake out\nfake put\nfake\n",
966 Command: "fake failed command",
967 Output: "fake output",
971 "executed 5 command(s):\n\x1b[36m\"fake command\"\x1b[0m:\n > fake output\n > \\ No newline at end of file\n\x1b[36m\"fake command with no output\"\x1b[0m\n\x1b[36m\"fake command with newline\"\x1b[0m:\n > fake output\n\x1b[36m\"fake command with more output\"\x1b[0m:\n > fake out\n > fake put\n > fake\n\x1b[36m\"fake failed command\"\x1b[0m, failed: \"fake error\":\n > fake output\n > \\ No newline at end of file\n",
979 []safcm.CommandChange{
981 Command: "fake command",
982 Output: "fake output",
985 `executed 1 command(s): (dry-run)
988 > \ No newline at end of file
997 []safcm.CommandChange{
999 Command: "fake command",
1000 Output: "fake output",
1003 "executed 1 command(s): (dry-run)\n\x1b[36m\"fake command\"\x1b[0m:\n > fake output\n > \\ No newline at end of file\n",
1011 []safcm.CommandChange{
1013 Command: "fake command",
1014 Output: "fake output",
1017 Command: "fake command with no output",
1020 Command: "fake command with newline",
1021 Output: "fake output\n",
1024 Command: "fake command with more output",
1025 Output: "fake out\nfake put\nfake\n",
1028 Command: "fake failed command",
1029 Output: "fake output",
1030 Error: "fake error",
1033 `executed 5 command(s), 1 with no output:
1036 > \ No newline at end of file
1037 "fake command with newline":
1039 "fake command with more output":
1043 "fake failed command", failed: "fake error":
1045 > \ No newline at end of file
1054 []safcm.CommandChange{
1056 Command: "fake command",
1057 Output: "fake output",
1060 Command: "fake command with no output",
1063 Command: "fake command with newline",
1064 Output: "fake output\n",
1067 Command: "fake command with more output",
1068 Output: "fake out\nfake put\nfake\n",
1071 Command: "fake failed command",
1072 Output: "fake output",
1073 Error: "fake error",
1076 "executed 5 command(s), 1 with no output:\n\x1b[36m\"fake command\"\x1b[0m:\n > fake output\n > \\ No newline at end of file\n\x1b[36m\"fake command with newline\"\x1b[0m:\n > fake output\n\x1b[36m\"fake command with more output\"\x1b[0m:\n > fake out\n > fake put\n > fake\n\x1b[36m\"fake failed command\"\x1b[0m, failed: \"fake error\":\n > fake output\n > \\ No newline at end of file\n",
1080 "quiet (only quiet commands)",
1084 []safcm.CommandChange{
1086 Command: "fake command with no output",
1089 Command: "fake command with no output",
1092 `executed 2 command(s), 2 with no output
1097 "quiet (quiet with errors)",
1101 []safcm.CommandChange{
1103 Command: "fake command with no output but error",
1104 Error: "fake error",
1107 Command: "fake command with no output",
1110 `executed 2 command(s), 1 with no output:
1111 "fake command with no output but error", failed: "fake error"
1120 []safcm.CommandChange{
1122 Command: "fake command",
1125 Command: "fake command with no output",
1128 Command: "fake command with newline",
1131 Command: "fake command with more output",
1134 Command: "fake failed command",
1137 `executed 5 command(s): (dry-run)
1139 "fake command with no output"
1140 "fake command with newline"
1141 "fake command with more output"
1142 "fake failed command"
1151 []safcm.CommandChange{
1159 `executed 1 command(s):
1160 "\x00", trigger for "\x01", failed: "\x03":
1162 > \ No newline at end of file
1171 []safcm.CommandChange{
1179 "executed 1 command(s):\n\x1b[36m\"\\x00\"\x1b[0m, trigger for \"\\x01\", failed: \"\\x03\":\n > \x1b[35m\\x02\x1b[0m\n > \\ No newline at end of file\n",
1183 for _, tc := range tests {
1184 t.Run(tc.name, func(t *testing.T) {
1186 config: &config.Config{
1193 res := s.formatCommandChanges(tc.changes)
1194 testutil.AssertEqual(t, "res", res, tc.exp)