"math/rand"
"os"
"path/filepath"
- "reflect"
"regexp"
"testing"
- "github.com/google/go-cmp/cmp"
-
"ruderich.org/simon/safcm"
ft "ruderich.org/simon/safcm/cmd/safcm-remote/sync/filetest"
+ "ruderich.org/simon/safcm/testutil"
)
var randFilesRegexp = regexp.MustCompile(`\d+"$`)
}
user, uid, group, gid := ft.CurrentUserAndGroup()
+ skipUnlessCiRun := len(os.Getenv("SAFCM_CI_RUN")) == 0
+
tmpTestFilePath := "/tmp/safcm-sync-files-test-file"
tests := []struct {
name string
+ skip bool
req safcm.MsgSyncReq
prepare func()
triggers []string
{
"basic: create",
+ false,
safcm.MsgSyncReq{
Files: map[string]*safcm.File{
".": {
{
"basic: no change",
+ false,
safcm.MsgSyncReq{
Files: map[string]*safcm.File{
".": {
{
"invalid File: user",
+ false,
safcm.MsgSyncReq{
Files: map[string]*safcm.File{
".": {
},
{
"invalid File: group",
+ false,
safcm.MsgSyncReq{
Files: map[string]*safcm.File{
".": {
// don't want to modify the running system. Use this
// test (and the one below for triggers) as a basic
// check that absolute paths work.
+ //
+ // Use numeric IDs as not all systems use root/root;
+ // for example BSDs use root/wheel.
"absolute paths: no change",
+ skipUnlessCiRun,
safcm.MsgSyncReq{
Files: map[string]*safcm.File{
"/": {
Path: "/",
Mode: fs.ModeDir | 0755,
- User: "root",
- Uid: -1,
- Group: "root",
- Gid: -1,
+ Uid: 0,
+ Gid: 0,
OrigGroup: "group",
},
"/etc": {
Path: "/etc",
Mode: fs.ModeDir | 0755,
- User: "root",
- Uid: -1,
- Group: "root",
- Gid: -1,
+ Uid: 0,
+ Gid: 0,
OrigGroup: "group",
},
"/tmp": {
Path: "/tmp",
Mode: fs.ModeDir | 0777 | fs.ModeSticky,
- User: "root",
- Uid: -1,
- Group: "root",
- Gid: -1,
- OrigGroup: "group",
- },
- "/var/tmp": {
- Path: "/var/tmp",
- Mode: fs.ModeDir | 0777 | fs.ModeSticky,
- User: "root",
- Uid: -1,
- Group: "root",
- Gid: -1,
+ Uid: 0,
+ Gid: 0,
OrigGroup: "group",
},
},
`4: sync remote: files: "/" (group): unchanged`,
`4: sync remote: files: "/etc" (group): unchanged`,
`4: sync remote: files: "/tmp" (group): unchanged`,
- `4: sync remote: files: "/var/tmp" (group): unchanged`,
},
nil,
},
{
"triggers: no change",
+ false,
safcm.MsgSyncReq{
Files: map[string]*safcm.File{
".": {
{
"triggers: change root",
+ false,
safcm.MsgSyncReq{
Files: map[string]*safcm.File{
".": {
{
"triggers: change middle",
+ false,
safcm.MsgSyncReq{
Files: map[string]*safcm.File{
".": {
{
"triggers: change leaf",
+ false,
safcm.MsgSyncReq{
Files: map[string]*safcm.File{
".": {
{
"triggers: multiple changes",
+ false,
safcm.MsgSyncReq{
Files: map[string]*safcm.File{
".": {
{
"triggers: absolute paths",
+ skipUnlessCiRun,
safcm.MsgSyncReq{
Files: map[string]*safcm.File{
"/": {
Path: "/",
Mode: fs.ModeDir | 0755,
- User: "root",
- Uid: -1,
- Group: "root",
- Gid: -1,
+ Uid: 0,
+ Gid: 0,
OrigGroup: "group",
TriggerCommands: []string{
"echo trigger /",
"/tmp": {
Path: "/tmp",
Mode: fs.ModeDir | 0777 | fs.ModeSticky,
- User: "root",
- Uid: -1,
- Group: "root",
- Gid: -1,
+ Uid: 0,
+ Gid: 0,
OrigGroup: "group",
TriggerCommands: []string{
"echo trigger /tmp",
},
},
},
- func() {
- // This is slightly racy but the file name
- // should be rare enough that this isn't an
- // issue
- _, err := os.Stat(tmpTestFilePath)
- if err == nil {
- t.Fatalf("%q exists, aborting",
- tmpTestFilePath)
- }
- },
+ nil,
[]string{
"/",
"/tmp",
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
+ if tc.skip {
+ t.SkipNow()
+ }
+
// Create separate test directory for each test case
path := filepath.Join(cwd, "testdata", "files-"+tc.name)
err = os.Mkdir(path, 0700)
s.setDefaults()
err := s.syncFiles()
- // Ugly but the simplest way to compare errors (including nil)
- if fmt.Sprintf("%s", err) != fmt.Sprintf("%s", tc.expErr) {
- t.Errorf("err = %#v, want %#v",
- err, tc.expErr)
- }
+ testutil.AssertErrorEqual(t, "err", err, tc.expErr)
dbg := res.Wait()
// Remove random file names from result
for i, x := range dbg {
dbg[i] = randFilesRegexp.ReplaceAllString(x, `RND"`)
}
- if !reflect.DeepEqual(tc.expDbg, dbg) {
- t.Errorf("dbg: %s",
- cmp.Diff(tc.expDbg, dbg))
- }
+ testutil.AssertEqual(t, "dbg", dbg, tc.expDbg)
files, err := ft.WalkDir(path)
if err != nil {
t.Fatal(err)
}
- if !reflect.DeepEqual(tc.expFiles, files) {
- t.Errorf("files: %s",
- cmp.Diff(tc.expFiles, files))
- }
+ testutil.AssertEqual(t, "files", files, tc.expFiles)
- if !reflect.DeepEqual(tc.expResp, s.resp) {
- t.Errorf("resp: %s",
- cmp.Diff(tc.expResp, s.resp))
- }
- if !reflect.DeepEqual(tc.triggers, s.triggers) {
- t.Errorf("triggers: %s",
- cmp.Diff(tc.triggers, s.triggers))
- }
+ testutil.AssertEqual(t, "resp", s.resp, tc.expResp)
+ testutil.AssertEqual(t, "triggers",
+ s.triggers, tc.triggers)
})
}
var changed bool
err := s.syncFile(tc.file, &changed)
- // Ugly but the simplest way to compare errors (including nil)
- if fmt.Sprintf("%s", err) != fmt.Sprintf("%s", tc.expErr) {
- t.Errorf("err = %#v, want %#v",
- err, tc.expErr)
- }
+ testutil.AssertErrorEqual(t, "err", err, tc.expErr)
dbg := res.Wait()
// Remove random file names from result
for i, x := range dbg {
dbg[i] = randFilesRegexp.ReplaceAllString(x, `RND"`)
}
- if !reflect.DeepEqual(tc.expDbg, dbg) {
- t.Errorf("dbg: %s",
- cmp.Diff(tc.expDbg, dbg))
- }
+ testutil.AssertEqual(t, "dbg", dbg, tc.expDbg)
files, err := ft.WalkDir(path)
if err != nil {
t.Fatal(err)
}
- if !reflect.DeepEqual(tc.expFiles, files) {
- t.Errorf("files: %s",
- cmp.Diff(tc.expFiles, files))
- }
+ testutil.AssertEqual(t, "files", files, tc.expFiles)
- if tc.expChanged != changed {
- t.Errorf("changed = %#v, want %#v",
- changed, tc.expChanged)
- }
- if !reflect.DeepEqual(tc.expResp, s.resp) {
- t.Errorf("resp: %s",
- cmp.Diff(tc.expResp, s.resp))
- }
+ testutil.AssertEqual(t, "changed", changed, tc.expChanged)
+ testutil.AssertEqual(t, "resp", s.resp, tc.expResp)
})
}