]> ruderich.org/simon Gitweb - safcm/safcm.git/blob - cmd/safcm-remote/sync/packages_debian_test.go
tests: use subtests
[safcm/safcm.git] / cmd / safcm-remote / sync / packages_debian_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 sync
17
18 import (
19         "bytes"
20         "fmt"
21         "os"
22         "os/exec"
23         "reflect"
24         "testing"
25
26         "github.com/google/go-cmp/cmp"
27
28         "ruderich.org/simon/safcm"
29 )
30
31 func TestSyncPackagesDebian(t *testing.T) {
32         tests := []struct {
33                 name    string
34                 req     safcm.MsgSyncReq
35                 stdout  [][]byte
36                 stderr  [][]byte
37                 errors  []error
38                 expCmds []*exec.Cmd
39                 expDbg  []string
40                 expResp safcm.MsgSyncResp
41                 expErr  error
42         }{
43
44                 // NOTE: Also update MsgSyncResp in safcm test cases when
45                 // changing anything here!
46
47                 {
48                         "packages already installed",
49                         safcm.MsgSyncReq{
50                                 Packages: []string{
51                                         "package-one",
52                                         "package-two",
53                                 },
54                         },
55                         [][]byte{
56                                 []byte(`install ok installed    golang
57 install ok installed    golang-1.16
58 install ok installed    golang-1.16-doc
59 install ok installed    golang-1.16-go
60 install ok installed    golang-1.16-src
61 hold ok installed       package-one
62 install ok installed    package-two
63 `),
64                         },
65                         [][]byte{nil},
66                         []error{nil},
67                         []*exec.Cmd{&exec.Cmd{
68                                 Path: "/usr/bin/dpkg-query",
69                                 Args: []string{
70                                         "/usr/bin/dpkg-query",
71                                         "--show",
72                                         `--showformat=${Status}\t${Package}\n`,
73                                 },
74                                 Stdout: &bytes.Buffer{},
75                                 Stderr: &bytes.Buffer{},
76                         }},
77                         []string{
78                                 "4: sync remote: packages: detected debian",
79                                 `4: sync remote: packages: running "/usr/bin/dpkg-query" "--show" "--showformat=${Status}\\t${Package}\\n"`,
80                                 `5: sync remote: packages: command stdout:
81 install ok installed    golang
82 install ok installed    golang-1.16
83 install ok installed    golang-1.16-doc
84 install ok installed    golang-1.16-go
85 install ok installed    golang-1.16-src
86 hold ok installed       package-one
87 install ok installed    package-two
88 `,
89                                 "4: sync remote: packages: checking package-one package-two",
90                         },
91                         safcm.MsgSyncResp{},
92                         nil,
93                 },
94
95                 {
96                         "packages not yet installed",
97                         safcm.MsgSyncReq{
98                                 Packages: []string{
99                                         "package-one",
100                                         "package-two",
101                                         "package-three",
102                                 },
103                         },
104                         [][]byte{
105                                 []byte(`install ok installed    golang
106 install ok installed    golang-1.16
107 install ok installed    golang-1.16-doc
108 install ok installed    golang-1.16-go
109 install ok installed    golang-1.16-src
110 install ok installed    package-two
111 `),
112                                 []byte("fake stdout/stderr"),
113                         },
114                         [][]byte{nil, nil},
115                         []error{nil, nil},
116                         []*exec.Cmd{&exec.Cmd{
117                                 Path: "/usr/bin/dpkg-query",
118                                 Args: []string{
119                                         "/usr/bin/dpkg-query",
120                                         "--show",
121                                         `--showformat=${Status}\t${Package}\n`,
122                                 },
123                                 Stdout: &bytes.Buffer{},
124                                 Stderr: &bytes.Buffer{},
125                         }, &exec.Cmd{
126                                 Path: "/usr/bin/apt-get",
127                                 Args: []string{
128                                         "/usr/bin/apt-get",
129                                         "install",
130                                         "--assume-yes",
131                                         "--no-upgrade",
132                                         "--no-install-recommends",
133                                         "-o", "Dpkg::Options::=--force-confdef",
134                                         "-o", "Dpkg::Options::=--force-confold",
135                                         "package-one",
136                                         "package-three",
137                                 },
138                                 Env: append(os.Environ(),
139                                         "DEBIAN_FRONTEND=noninteractive",
140                                 ),
141                         }},
142                         []string{
143                                 "4: sync remote: packages: detected debian",
144                                 `4: sync remote: packages: running "/usr/bin/dpkg-query" "--show" "--showformat=${Status}\\t${Package}\\n"`,
145                                 `5: sync remote: packages: command stdout:
146 install ok installed    golang
147 install ok installed    golang-1.16
148 install ok installed    golang-1.16-doc
149 install ok installed    golang-1.16-go
150 install ok installed    golang-1.16-src
151 install ok installed    package-two
152 `,
153                                 "4: sync remote: packages: checking package-one package-two package-three",
154                                 "3: sync remote: packages: installing package-one package-three",
155                                 `4: sync remote: packages: running "/usr/bin/apt-get" "install" "--assume-yes" "--no-upgrade" "--no-install-recommends" "-o" "Dpkg::Options::=--force-confdef" "-o" "Dpkg::Options::=--force-confold" "package-one" "package-three"`,
156                                 "5: sync remote: packages: command output:\nfake stdout/stderr",
157                         },
158                         safcm.MsgSyncResp{
159                                 PackageChanges: []safcm.PackageChange{
160                                         {
161                                                 Name: "package-one",
162                                         },
163                                         {
164                                                 Name: "package-three",
165                                         },
166                                 },
167                         },
168                         nil,
169                 },
170
171                 {
172                         "packages not yet installed (error)",
173                         safcm.MsgSyncReq{
174                                 Packages: []string{
175                                         "package-one",
176                                         "package-two",
177                                 },
178                         },
179                         [][]byte{
180                                 []byte(`install ok installed    golang
181 install ok installed    golang-1.16
182 install ok installed    golang-1.16-doc
183 install ok installed    golang-1.16-go
184 install ok installed    golang-1.16-src
185 `),
186                                 []byte("fake stdout/stderr"),
187                         },
188                         [][]byte{nil, nil},
189                         []error{
190                                 nil,
191                                 fmt.Errorf("fake error"),
192                         },
193                         []*exec.Cmd{&exec.Cmd{
194                                 Path: "/usr/bin/dpkg-query",
195                                 Args: []string{
196                                         "/usr/bin/dpkg-query",
197                                         "--show",
198                                         `--showformat=${Status}\t${Package}\n`,
199                                 },
200                                 Stdout: &bytes.Buffer{},
201                                 Stderr: &bytes.Buffer{},
202                         }, &exec.Cmd{
203                                 Path: "/usr/bin/apt-get",
204                                 Args: []string{
205                                         "/usr/bin/apt-get",
206                                         "install",
207                                         "--assume-yes",
208                                         "--no-upgrade",
209                                         "--no-install-recommends",
210                                         "-o", "Dpkg::Options::=--force-confdef",
211                                         "-o", "Dpkg::Options::=--force-confold",
212                                         "package-one",
213                                         "package-two",
214                                 },
215                                 Env: append(os.Environ(),
216                                         "DEBIAN_FRONTEND=noninteractive",
217                                 ),
218                         }},
219                         []string{
220                                 "4: sync remote: packages: detected debian",
221                                 `4: sync remote: packages: running "/usr/bin/dpkg-query" "--show" "--showformat=${Status}\\t${Package}\\n"`,
222                                 `5: sync remote: packages: command stdout:
223 install ok installed    golang
224 install ok installed    golang-1.16
225 install ok installed    golang-1.16-doc
226 install ok installed    golang-1.16-go
227 install ok installed    golang-1.16-src
228 `,
229                                 "4: sync remote: packages: checking package-one package-two",
230                                 "3: sync remote: packages: installing package-one package-two",
231                                 `4: sync remote: packages: running "/usr/bin/apt-get" "install" "--assume-yes" "--no-upgrade" "--no-install-recommends" "-o" "Dpkg::Options::=--force-confdef" "-o" "Dpkg::Options::=--force-confold" "package-one" "package-two"`,
232                                 "5: sync remote: packages: command output:\nfake stdout/stderr",
233                         },
234                         safcm.MsgSyncResp{
235                                 PackageChanges: []safcm.PackageChange{
236                                         {
237                                                 Name: "package-one",
238                                         },
239                                         {
240                                                 Name: "package-two",
241                                         },
242                                 },
243                         },
244                         fmt.Errorf(`"/usr/bin/apt-get" "install" "--assume-yes" "--no-upgrade" "--no-install-recommends" "-o" "Dpkg::Options::=--force-confdef" "-o" "Dpkg::Options::=--force-confold" "package-one" "package-two" failed: fake error; output: "fake stdout/stderr"`),
245                 },
246
247                 {
248                         "packages not yet installed (dry-run)",
249                         safcm.MsgSyncReq{
250                                 DryRun: true,
251                                 Packages: []string{
252                                         "package-one",
253                                         "package-two",
254                                 },
255                         },
256                         [][]byte{
257                                 []byte(`install ok installed    golang
258 install ok installed    golang-1.16
259 install ok installed    golang-1.16-doc
260 install ok installed    golang-1.16-go
261 install ok installed    golang-1.16-src
262 `),
263                         },
264                         [][]byte{nil},
265                         []error{nil},
266                         []*exec.Cmd{&exec.Cmd{
267                                 Path: "/usr/bin/dpkg-query",
268                                 Args: []string{
269                                         "/usr/bin/dpkg-query",
270                                         "--show",
271                                         `--showformat=${Status}\t${Package}\n`,
272                                 },
273                                 Stdout: &bytes.Buffer{},
274                                 Stderr: &bytes.Buffer{},
275                         }},
276                         []string{
277                                 "4: sync remote: packages: detected debian",
278                                 `4: sync remote: packages: running "/usr/bin/dpkg-query" "--show" "--showformat=${Status}\\t${Package}\\n"`,
279                                 `5: sync remote: packages: command stdout:
280 install ok installed    golang
281 install ok installed    golang-1.16
282 install ok installed    golang-1.16-doc
283 install ok installed    golang-1.16-go
284 install ok installed    golang-1.16-src
285 `,
286                                 "4: sync remote: packages: checking package-one package-two",
287                         },
288                         safcm.MsgSyncResp{
289                                 PackageChanges: []safcm.PackageChange{
290                                         {
291                                                 Name: "package-one",
292                                         },
293                                         {
294                                                 Name: "package-two",
295                                         },
296                                 },
297                         },
298                         nil,
299                 },
300         }
301
302         for _, tc := range tests {
303                 t.Run(tc.name, func(t *testing.T) {
304                 s, res := prepareSync(tc.req, &testRunner{
305                         t:         t,
306                         expCmds:   tc.expCmds,
307                         resStdout: tc.stdout,
308                         resStderr: tc.stderr,
309                         resError:  tc.errors,
310                 })
311
312                 err := s.syncPackagesDebian()
313                 // Ugly but the simplest way to compare errors (including nil)
314                 if fmt.Sprintf("%s", err) != fmt.Sprintf("%s", tc.expErr) {
315                         t.Errorf("err = %#v, want %#v",
316                                 err, tc.expErr)
317                 }
318                 dbg := res.Wait()
319
320                 if !reflect.DeepEqual(tc.expResp, s.resp) {
321                         t.Errorf("resp: %s",
322                                 cmp.Diff(tc.expResp, s.resp))
323                 }
324                 if !reflect.DeepEqual(tc.expDbg, dbg) {
325                         t.Errorf("dbg: %s",
326                                 cmp.Diff(tc.expDbg, dbg))
327                 }
328                 })
329         }
330 }