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/>.
29 "ruderich.org/simon/safcm/testutil"
32 func TestSyncSshEndToEnd(t *testing.T) {
33 cwd, err := os.Getwd()
40 // Needs different options in sshd_config
41 if runtime.GOOS == "openbsd" {
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",
53 sshCmd.Stderr = os.Stderr
58 defer sshCmd.Process.Kill()
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")
67 time.Sleep(time.Second)
70 err = os.Chdir(sshDir + "/project")
86 []string{"no-settings.example.org"},
87 `<LOG>[info] [no-settings.example.org] remote helper upload in progress
88 <LOG>[info] [no-settings.example.org] no changes
93 "no settings (no helper upload)",
95 []string{"no-settings.example.org"},
96 `<LOG>[info] [no-settings.example.org] no changes
101 "no settings (error)",
103 []string{"-log", "error", "no-settings.example.org"},
108 "no settings (verbose)",
110 []string{"-log", "verbose", "no-settings.example.org"},
111 `<LOG>[info] [no-settings.example.org] remote helper upload in progress
112 <LOG>[verbose] [no-settings.example.org] host groups: all <DET> <DET> no-settings.example.org
113 <LOG>[verbose] [no-settings.example.org] host group priorities (descending): no-settings.example.org
114 <LOG>[info] [no-settings.example.org] no changes
119 "no settings (debug2)",
121 []string{"-log", "debug2", "no-settings.example.org"},
122 `<LOG>[info] [no-settings.example.org] remote helper upload in progress
123 <LOG>[verbose] [no-settings.example.org] host groups: all <DET> <DET> no-settings.example.org
124 <LOG>[verbose] [no-settings.example.org] host group priorities (descending): no-settings.example.org
125 <LOG>[info] [no-settings.example.org] no changes
131 remotePath := fmt.Sprintf("/tmp/safcm-remote-%d", os.Getuid())
133 logRegexp := regexp.MustCompile(`^\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} `)
134 detectedRegexp := regexp.MustCompile(`detected_\S+`)
136 for _, tc := range tests {
137 t.Run(tc.name, func(t *testing.T) {
139 os.Remove(remotePath)
142 args := append([]string{"sync",
143 "-sshconfig", sshDir + "/ssh/ssh_config",
145 cmd := exec.Command("../../../../../safcm", args...)
146 out, err := cmd.CombinedOutput()
149 for _, x := range strings.Split(string(out), "\n") {
150 // Strip parts which change on each run (LOG)
151 // or depending on the system (DET)
152 x = logRegexp.ReplaceAllString(x, "<LOG>")
153 x = detectedRegexp.ReplaceAllString(x, "<DET>")
156 res := strings.Join(tmp, "\n")
158 testutil.AssertEqual(t, "res", res, tc.exp)
159 testutil.AssertErrorEqual(t, "err", err, tc.expErr)
163 os.Remove(remotePath)