]> ruderich.org/simon Gitweb - safcm/safcm.git/blob - cmd/safcm/main_sync_test.go
tests: add very basic end-to-end test with real ssh server
[safcm/safcm.git] / cmd / safcm / main_sync_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_test
17
18 import (
19         "fmt"
20         "net"
21         "os"
22         "os/exec"
23         "regexp"
24         "runtime"
25         "strings"
26         "testing"
27         "time"
28
29         "ruderich.org/simon/safcm/testutil"
30 )
31
32 func TestSyncSshEndToEnd(t *testing.T) {
33         cwd, err := os.Getwd()
34         if err != nil {
35                 t.Fatal(err)
36         }
37         defer os.Chdir(cwd)
38
39         var suffix string
40         // Needs different options in sshd_config
41         if runtime.GOOS == "openbsd" {
42                 suffix = ".openbsd"
43         }
44
45         sshDir := cwd + "/testdata/ssh"
46         sshCmd := exec.Command("/usr/sbin/sshd",
47                 "-D", // stay in foreground
48                 "-e", // write messages to stderr instead of syslog
49                 "-f", sshDir+"/sshd/sshd_config"+suffix,
50                 "-h", sshDir+"/sshd/ssh_host_key",
51                 "-o", "AuthorizedKeysFile="+sshDir+"/ssh/authorized_keys",
52         )
53         sshCmd.Stderr = os.Stderr
54         err = sshCmd.Start()
55         if err != nil {
56                 t.Fatal(err)
57         }
58         defer sshCmd.Process.Kill()
59
60         // Wait until SSH server is ready (up to 30 seconds)
61         for i := 0; i < 30; i++ {
62                 conn, err := net.Dial("tcp", "127.0.0.1:29327")
63                 if err == nil {
64                         conn.Close()
65                         break
66                 }
67                 time.Sleep(time.Second)
68         }
69
70         err = os.Chdir(sshDir + "/project")
71         if err != nil {
72                 t.Fatal(err)
73         }
74
75         tests := []struct {
76                 name   string
77                 remove bool
78                 args   []string
79                 exp    string
80                 expErr error
81         }{
82
83                 {
84                         "no settings",
85                         true,
86                         []string{"no-settings.example.org"},
87                         `<LOG>[info]    [no-settings.example.org] remote helper upload in progress
88 `,
89                         nil,
90                 },
91                 {
92                         "no settings (no helper upload)",
93                         false,
94                         []string{"no-settings.example.org"},
95                         ``,
96                         nil,
97                 },
98                 {
99                         "no settings (verbose)",
100                         true,
101                         []string{"-log", "verbose", "no-settings.example.org"},
102                         `<LOG>[info]    [no-settings.example.org] remote helper upload in progress
103 <LOG>[verbose] [no-settings.example.org] host groups: all <DET> <DET> no-settings.example.org
104 <LOG>[verbose] [no-settings.example.org] host group priorities (desc. order): no-settings.example.org
105 `,
106                         nil,
107                 },
108                 {
109                         "no settings (debug2)",
110                         true,
111                         []string{"-log", "debug2", "no-settings.example.org"},
112                         `<LOG>[info]    [no-settings.example.org] remote helper upload in progress
113 <LOG>[verbose] [no-settings.example.org] host groups: all <DET> <DET> no-settings.example.org
114 <LOG>[verbose] [no-settings.example.org] host group priorities (desc. order): no-settings.example.org
115 `,
116                         nil,
117                 },
118         }
119
120         remotePath := fmt.Sprintf("/tmp/safcm-remote-%d", os.Getuid())
121
122         logRegexp := regexp.MustCompile(`^\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} `)
123         detectedRegexp := regexp.MustCompile(`detected_\S+`)
124
125         for _, tc := range tests {
126                 t.Run(tc.name, func(t *testing.T) {
127                         if tc.remove {
128                                 os.Remove(remotePath)
129                         }
130
131                         args := append([]string{"sync",
132                                 "-sshconfig", sshDir + "/ssh/ssh_config",
133                         }, tc.args...)
134                         cmd := exec.Command("../../../../../safcm", args...)
135                         out, err := cmd.CombinedOutput()
136
137                         var tmp []string
138                         for _, x := range strings.Split(string(out), "\n") {
139                                 // Strip parts which change on each run (LOG)
140                                 // or depending on the system (DET)
141                                 x = logRegexp.ReplaceAllString(x, "<LOG>")
142                                 x = detectedRegexp.ReplaceAllString(x, "<DET>")
143                                 tmp = append(tmp, x)
144                         }
145                         res := strings.Join(tmp, "\n")
146
147                         testutil.AssertEqual(t, "res", res, tc.exp)
148                         testutil.AssertErrorEqual(t, "err", err, tc.expErr)
149                 })
150         }
151
152         os.Remove(remotePath)
153 }