X-Git-Url: https://ruderich.org/simon/gitweb/?a=blobdiff_plain;f=cmd%2Fsafcm-remote%2Fsync%2Ffiles_test.go;fp=cmd%2Fsafcm-remote%2Fsync%2Ffiles_test.go;h=0000000000000000000000000000000000000000;hb=9269fa3c94e700afc0be823f58ea473a2db8f3dc;hp=88a5b51f85cd3fa4a4d36f1422ecbe37424565de;hpb=fd97e8019e2ab166d9475ed59782c86247d8430b;p=safcm%2Fsafcm.git diff --git a/cmd/safcm-remote/sync/files_test.go b/cmd/safcm-remote/sync/files_test.go deleted file mode 100644 index 88a5b51..0000000 --- a/cmd/safcm-remote/sync/files_test.go +++ /dev/null @@ -1,2428 +0,0 @@ -// Copyright (C) 2021 Simon Ruderich -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -package sync - -import ( - "fmt" - "io/fs" - "math/rand" - "os" - "path/filepath" - "regexp" - "testing" - - "ruderich.org/simon/safcm" - ft "ruderich.org/simon/safcm/cmd/safcm-remote/sync/filetest" - "ruderich.org/simon/safcm/testutil" -) - -var randFilesRegexp = regexp.MustCompile(`\d+"$`) - -func TestSyncFiles(t *testing.T) { - cwd, err := os.Getwd() - if err != nil { - t.Fatal(err) - } - defer os.Chdir(cwd) - - err = os.RemoveAll("testdata") - if err != nil { - t.Fatal(err) - } - err = os.Mkdir("testdata", 0700) - if err != nil { - t.Fatal(err) - } - - root := ft.File{ - Path: ".", - Mode: fs.ModeDir | 0700, - } - 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() - expTriggers []string - expFiles []ft.File - expResp safcm.MsgSyncResp - expDbg []string - expErr error - }{ - - // NOTE: Also update MsgSyncResp in safcm test cases when - // changing the MsgSyncResp struct! - - // See TestSyncFile() for most file related tests. This - // function only tests the overall results and triggers. - - { - "basic: create", - false, - safcm.MsgSyncReq{ - Files: map[string]*safcm.File{ - ".": { - Path: ".", - Mode: fs.ModeDir | 0700, - Uid: -1, - Gid: -1, - OrigGroup: "group", - }, - "dir": { - Path: "dir", - Mode: fs.ModeDir | 0755, - Uid: -1, - Gid: -1, - OrigGroup: "group", - }, - "dir/file": { - Path: "dir/file", - Mode: 0644, - Uid: -1, - Gid: -1, - Data: []byte("content\n"), - OrigGroup: "group", - }, - }, - }, - nil, - nil, - []ft.File{ - root, - { - Path: "dir", - Mode: fs.ModeDir | 0755, - }, - { - Path: "dir/file", - Mode: 0644, - Data: []byte("content\n"), - }, - }, - safcm.MsgSyncResp{ - FileChanges: []safcm.FileChange{ - { - Path: "dir", - Created: true, - New: safcm.FileChangeInfo{ - Mode: fs.ModeDir | 0755, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - }, - { - Path: "dir/file", - Created: true, - New: safcm.FileChangeInfo{ - Mode: 0644, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - }, - }, - }, - []string{ - `4: files: "." (group): unchanged`, - `4: files: "dir" (group): will create`, - `3: files: "dir" (group): creating`, - `4: files: "dir" (group): creating directory`, - `4: files: "dir" (group): chmodding drwxr-xr-x`, - fmt.Sprintf(`4: files: "dir" (group): chowning %d/%d`, uid, gid), - `4: files: "dir/file" (group): will create`, - `3: files: "dir/file" (group): creating`, - `4: files: "dir/file" (group): creating temporary file "dir/.file*"`, - `4: files: "dir/file" (group): renaming "dir/.fileRND"`, - }, - nil, - }, - - { - "basic: no change", - false, - safcm.MsgSyncReq{ - Files: map[string]*safcm.File{ - ".": { - Path: ".", - Mode: fs.ModeDir | 0700, - Uid: -1, - Gid: -1, - OrigGroup: "group", - }, - "dir": { - Path: "dir", - Mode: fs.ModeDir | 0755, - Uid: -1, - Gid: -1, - OrigGroup: "group", - }, - "dir/file": { - Path: "dir/file", - Mode: 0644, - Uid: -1, - Gid: -1, - Data: []byte("content\n"), - OrigGroup: "group", - }, - }, - }, - func() { - ft.CreateDirectory("dir", 0755) - ft.CreateFile("dir/file", "content\n", 0644) - }, - nil, - []ft.File{ - root, - { - Path: "dir", - Mode: fs.ModeDir | 0755, - }, - { - Path: "dir/file", - Mode: 0644, - Data: []byte("content\n"), - }, - }, - safcm.MsgSyncResp{}, - []string{ - `4: files: "." (group): unchanged`, - `4: files: "dir" (group): unchanged`, - `4: files: "dir/file" (group): unchanged`, - }, - nil, - }, - - { - "invalid File: user", - false, - safcm.MsgSyncReq{ - Files: map[string]*safcm.File{ - ".": { - Path: ".", - Mode: fs.ModeDir | 0700, - User: "user", - Uid: 1, - Gid: -1, - OrigGroup: "group", - }, - }, - }, - nil, - nil, - []ft.File{ - root, - }, - safcm.MsgSyncResp{}, - nil, - fmt.Errorf("\".\": cannot set both User (\"user\") and Uid (1)"), - }, - { - "invalid File: group", - false, - safcm.MsgSyncReq{ - Files: map[string]*safcm.File{ - ".": { - Path: ".", - Mode: fs.ModeDir | 0700, - Uid: -1, - Group: "group", - Gid: 1, - OrigGroup: "group", - }, - }, - }, - nil, - nil, - []ft.File{ - root, - }, - safcm.MsgSyncResp{}, - nil, - fmt.Errorf("\".\": cannot set both Group (\"group\") and Gid (1)"), - }, - - { - // We use relative paths for most tests because we - // 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, - Uid: 0, - Gid: 0, - OrigGroup: "group", - }, - "/etc": { - Path: "/etc", - Mode: fs.ModeDir | 0755, - Uid: 0, - Gid: 0, - OrigGroup: "group", - }, - "/tmp": { - Path: "/tmp", - Mode: fs.ModeDir | 0777 | fs.ModeSticky, - Uid: 0, - Gid: 0, - OrigGroup: "group", - }, - }, - }, - nil, - nil, - []ft.File{ - root, - }, - safcm.MsgSyncResp{}, - []string{ - `4: files: "/" (group): unchanged`, - `4: files: "/etc" (group): unchanged`, - `4: files: "/tmp" (group): unchanged`, - }, - nil, - }, - - { - "triggers: no change", - false, - safcm.MsgSyncReq{ - Files: map[string]*safcm.File{ - ".": { - Path: ".", - Mode: fs.ModeDir | 0700, - Uid: -1, - Gid: -1, - OrigGroup: "group", - TriggerCommands: []string{ - "echo trigger .", - }, - }, - "dir": { - Path: "dir", - Mode: fs.ModeDir | 0755, - Uid: -1, - Gid: -1, - OrigGroup: "group", - TriggerCommands: []string{ - "echo trigger dir", - }, - }, - "dir/file": { - Path: "dir/file", - Mode: 0644, - Uid: -1, - Gid: -1, - Data: []byte("content\n"), - OrigGroup: "group", - TriggerCommands: []string{ - "echo trigger dir/file", - }, - }, - }, - }, - func() { - ft.CreateDirectory("dir", 0755) - ft.CreateFile("dir/file", "content\n", 0644) - }, - nil, - []ft.File{ - root, - { - Path: "dir", - Mode: fs.ModeDir | 0755, - }, - { - Path: "dir/file", - Mode: 0644, - Data: []byte("content\n"), - }, - }, - safcm.MsgSyncResp{}, - []string{ - `4: files: "." (group): unchanged`, - `4: files: "dir" (group): unchanged`, - `4: files: "dir/file" (group): unchanged`, - }, - nil, - }, - - { - "triggers: change root", - false, - safcm.MsgSyncReq{ - Files: map[string]*safcm.File{ - ".": { - Path: ".", - Mode: fs.ModeDir | 0700, - Uid: -1, - Gid: -1, - OrigGroup: "group", - TriggerCommands: []string{ - "echo trigger .", - }, - }, - "dir": { - Path: "dir", - Mode: fs.ModeDir | 0755, - Uid: -1, - Gid: -1, - OrigGroup: "group", - TriggerCommands: []string{ - "echo trigger dir", - }, - }, - "dir/file": { - Path: "dir/file", - Mode: 0644, - Uid: -1, - Gid: -1, - Data: []byte("content\n"), - OrigGroup: "group", - TriggerCommands: []string{ - "echo trigger dir/file", - }, - }, - }, - }, - func() { - ft.CreateDirectoryExists(".", 0750) - ft.CreateDirectory("dir", 0755) - ft.CreateFile("dir/file", "content\n", 0644) - }, - []string{ - ".", - }, - []ft.File{ - root, - { - Path: "dir", - Mode: fs.ModeDir | 0755, - }, - { - Path: "dir/file", - Mode: 0644, - Data: []byte("content\n"), - }, - }, - safcm.MsgSyncResp{ - FileChanges: []safcm.FileChange{ - { - Path: ".", - Old: safcm.FileChangeInfo{ - Mode: fs.ModeDir | 0750, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - New: safcm.FileChangeInfo{ - Mode: fs.ModeDir | 0700, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - }, - }, - }, - []string{ - `4: files: "." (group): permission differs drwxr-x--- -> drwx------`, - `3: files: "." (group): updating`, - `4: files: "." (group): chmodding drwx------`, - `3: files: ".": queuing trigger on "."`, - `4: files: "dir" (group): unchanged`, - `4: files: "dir/file" (group): unchanged`, - }, - nil, - }, - - { - "triggers: change middle", - false, - safcm.MsgSyncReq{ - Files: map[string]*safcm.File{ - ".": { - Path: ".", - Mode: fs.ModeDir | 0700, - Uid: -1, - Gid: -1, - OrigGroup: "group", - TriggerCommands: []string{ - "echo trigger .", - }, - }, - "dir": { - Path: "dir", - Mode: fs.ModeDir | 0755, - Uid: -1, - Gid: -1, - OrigGroup: "group", - TriggerCommands: []string{ - "echo trigger dir", - }, - }, - "dir/file": { - Path: "dir/file", - Mode: 0644, - Uid: -1, - Gid: -1, - Data: []byte("content\n"), - OrigGroup: "group", - TriggerCommands: []string{ - "echo trigger dir/file", - }, - }, - }, - }, - func() { - ft.CreateDirectory("dir", 0750) - ft.CreateFile("dir/file", "content\n", 0644) - }, - []string{ - ".", - "dir", - }, - []ft.File{ - root, - { - Path: "dir", - Mode: fs.ModeDir | 0755, - }, - { - Path: "dir/file", - Mode: 0644, - Data: []byte("content\n"), - }, - }, - safcm.MsgSyncResp{ - FileChanges: []safcm.FileChange{ - { - Path: "dir", - Old: safcm.FileChangeInfo{ - Mode: fs.ModeDir | 0750, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - New: safcm.FileChangeInfo{ - Mode: fs.ModeDir | 0755, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - }, - }, - }, - []string{ - `4: files: "." (group): unchanged`, - `4: files: "dir" (group): permission differs drwxr-x--- -> drwxr-xr-x`, - `3: files: "dir" (group): updating`, - `4: files: "dir" (group): chmodding drwxr-xr-x`, - `3: files: "dir": queuing trigger on "."`, - `3: files: "dir": queuing trigger on "dir"`, - `4: files: "dir/file" (group): unchanged`, - }, - nil, - }, - - { - "triggers: change leaf", - false, - safcm.MsgSyncReq{ - Files: map[string]*safcm.File{ - ".": { - Path: ".", - Mode: fs.ModeDir | 0700, - Uid: -1, - Gid: -1, - OrigGroup: "group", - TriggerCommands: []string{ - "echo trigger .", - }, - }, - "dir": { - Path: "dir", - Mode: fs.ModeDir | 0755, - Uid: -1, - Gid: -1, - OrigGroup: "group", - TriggerCommands: []string{ - "echo trigger dir", - }, - }, - "dir/file": { - Path: "dir/file", - Mode: 0644, - Uid: -1, - Gid: -1, - Data: []byte("content\n"), - OrigGroup: "group", - TriggerCommands: []string{ - "echo trigger dir/file", - }, - }, - }, - }, - func() { - ft.CreateDirectory("dir", 0755) - }, - []string{ - ".", - "dir", - "dir/file", - }, - []ft.File{ - root, - { - Path: "dir", - Mode: fs.ModeDir | 0755, - }, - { - Path: "dir/file", - Mode: 0644, - Data: []byte("content\n"), - }, - }, - safcm.MsgSyncResp{ - FileChanges: []safcm.FileChange{ - { - Path: "dir/file", - Created: true, - New: safcm.FileChangeInfo{ - Mode: 0644, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - }, - }, - }, - []string{ - `4: files: "." (group): unchanged`, - `4: files: "dir" (group): unchanged`, - `4: files: "dir/file" (group): will create`, - `3: files: "dir/file" (group): creating`, - `4: files: "dir/file" (group): creating temporary file "dir/.file*"`, - `4: files: "dir/file" (group): renaming "dir/.fileRND"`, - `3: files: "dir/file": queuing trigger on "."`, - `3: files: "dir/file": queuing trigger on "dir"`, - `3: files: "dir/file": queuing trigger on "dir/file"`, - }, - nil, - }, - - { - "triggers: multiple changes", - false, - safcm.MsgSyncReq{ - Files: map[string]*safcm.File{ - ".": { - Path: ".", - Mode: fs.ModeDir | 0700, - Uid: -1, - Gid: -1, - OrigGroup: "group", - TriggerCommands: []string{ - "echo trigger .", - }, - }, - "dir": { - Path: "dir", - Mode: fs.ModeDir | 0755, - Uid: -1, - Gid: -1, - OrigGroup: "group", - TriggerCommands: []string{ - "echo trigger dir", - }, - }, - "dir/file": { - Path: "dir/file", - Mode: 0644, - Uid: -1, - Gid: -1, - Data: []byte("content\n"), - OrigGroup: "group", - TriggerCommands: []string{ - "echo trigger dir/file", - }, - }, - }, - }, - nil, - []string{ - ".", - "dir", - "dir/file", - }, - []ft.File{ - root, - { - Path: "dir", - Mode: fs.ModeDir | 0755, - }, - { - Path: "dir/file", - Mode: 0644, - Data: []byte("content\n"), - }, - }, - safcm.MsgSyncResp{ - FileChanges: []safcm.FileChange{ - { - Path: "dir", - Created: true, - New: safcm.FileChangeInfo{ - Mode: fs.ModeDir | 0755, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - }, - { - Path: "dir/file", - Created: true, - New: safcm.FileChangeInfo{ - Mode: 0644, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - }, - }, - }, - []string{ - `4: files: "." (group): unchanged`, - `4: files: "dir" (group): will create`, - `3: files: "dir" (group): creating`, - `4: files: "dir" (group): creating directory`, - `4: files: "dir" (group): chmodding drwxr-xr-x`, - fmt.Sprintf(`4: files: "dir" (group): chowning %d/%d`, uid, gid), - `3: files: "dir": queuing trigger on "."`, - `3: files: "dir": queuing trigger on "dir"`, - `4: files: "dir/file" (group): will create`, - `3: files: "dir/file" (group): creating`, - `4: files: "dir/file" (group): creating temporary file "dir/.file*"`, - `4: files: "dir/file" (group): renaming "dir/.fileRND"`, - `4: files: "dir/file": skipping trigger on ".", already active`, - `4: files: "dir/file": skipping trigger on "dir", already active`, - `3: files: "dir/file": queuing trigger on "dir/file"`, - }, - nil, - }, - - { - "triggers: absolute paths", - skipUnlessCiRun, - safcm.MsgSyncReq{ - Files: map[string]*safcm.File{ - "/": { - Path: "/", - Mode: fs.ModeDir | 0755, - Uid: 0, - Gid: 0, - OrigGroup: "group", - TriggerCommands: []string{ - "echo trigger /", - }, - }, - "/tmp": { - Path: "/tmp", - Mode: fs.ModeDir | 0777 | fs.ModeSticky, - Uid: 0, - Gid: 0, - OrigGroup: "group", - TriggerCommands: []string{ - "echo trigger /tmp", - }, - }, - tmpTestFilePath: { - Path: tmpTestFilePath, - Mode: 0600, - Uid: -1, - Gid: -1, - OrigGroup: "group", - TriggerCommands: []string{ - "echo trigger /tmp/file", - }, - }, - }, - }, - nil, - []string{ - "/", - "/tmp", - // Don't use variable for more robust test - "/tmp/safcm-sync-files-test-file", - }, - []ft.File{ - root, - }, - safcm.MsgSyncResp{ - FileChanges: []safcm.FileChange{ - { - Path: "/tmp/safcm-sync-files-test-file", - Created: true, - New: safcm.FileChangeInfo{ - Mode: 0600, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - }, - }, - }, - []string{ - `4: files: "/" (group): unchanged`, - `4: files: "/tmp" (group): unchanged`, - `4: files: "/tmp/safcm-sync-files-test-file" (group): will create`, - `3: files: "/tmp/safcm-sync-files-test-file" (group): creating`, - `4: files: "/tmp/safcm-sync-files-test-file" (group): creating temporary file "/tmp/.safcm-sync-files-test-file*"`, - `4: files: "/tmp/safcm-sync-files-test-file" (group): renaming "/tmp/.safcm-sync-files-test-fileRND"`, - `3: files: "/tmp/safcm-sync-files-test-file": queuing trigger on "/"`, - `3: files: "/tmp/safcm-sync-files-test-file": queuing trigger on "/tmp"`, - `3: files: "/tmp/safcm-sync-files-test-file": queuing trigger on "/tmp/safcm-sync-files-test-file"`, - }, - nil, - }, - } - - 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) - if err != nil { - t.Fatal(err) - } - err = os.Chdir(path) - if err != nil { - t.Fatal(err) - } - - if tc.prepare != nil { - tc.prepare() - } - - s, res := prepareSync(tc.req, &testRunner{ - t: t, - }) - err = s.setDefaults() - if err != nil { - t.Fatal(err) - } - - err = s.syncFiles() - 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"`) - } - testutil.AssertEqual(t, "dbg", dbg, tc.expDbg) - - files, err := ft.WalkDir(path) - if err != nil { - t.Fatal(err) - } - testutil.AssertEqual(t, "files", files, tc.expFiles) - - testutil.AssertEqual(t, "resp", s.resp, tc.expResp) - testutil.AssertEqual(t, "triggers", - s.triggers, tc.expTriggers) - }) - } - - os.Remove(tmpTestFilePath) - if !t.Failed() { - err = os.RemoveAll(filepath.Join(cwd, "testdata")) - if err != nil { - t.Fatal(err) - } - } -} - -func TestSyncFile(t *testing.T) { - cwd, err := os.Getwd() - if err != nil { - t.Fatal(err) - } - defer os.Chdir(cwd) - - err = os.RemoveAll("testdata") - if err != nil { - t.Fatal(err) - } - err = os.Mkdir("testdata", 0700) - if err != nil { - t.Fatal(err) - } - - root := ft.File{ - Path: ".", - Mode: fs.ModeDir | 0700, - } - user, uid, group, gid := ft.CurrentUserAndGroup() - - tests := []struct { - name string - req safcm.MsgSyncReq - file *safcm.File - prepare func() - expChanged bool - expFiles []ft.File - expResp safcm.MsgSyncResp - expDbg []string - expErr error - }{ - - // NOTE: Also update MsgSyncResp in safcm test cases when - // changing the MsgSyncResp struct! - - // TODO: Add tests for chown and run them only as root - - // Regular file - - { - "file: create", - safcm.MsgSyncReq{}, - &safcm.File{ - Path: "file", - Mode: 0644, - Uid: -1, - Gid: -1, - Data: []byte("content\n"), - OrigGroup: "group", - }, - nil, - true, - []ft.File{ - root, - { - Path: "file", - Mode: 0644, - Data: []byte("content\n"), - }, - }, - safcm.MsgSyncResp{ - FileChanges: []safcm.FileChange{ - { - Path: "file", - Created: true, - New: safcm.FileChangeInfo{ - Mode: 0644, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - }, - }, - }, - []string{ - `4: files: "file" (group): will create`, - `3: files: "file" (group): creating`, - `4: files: "file" (group): creating temporary file ".file*"`, - `4: files: "file" (group): renaming "./.fileRND"`, - }, - nil, - }, - { - "file: create (dry-run)", - safcm.MsgSyncReq{ - DryRun: true, - }, - &safcm.File{ - Path: "file", - Mode: 0644, - Uid: -1, - Gid: -1, - Data: []byte("content\n"), - OrigGroup: "group", - }, - nil, - true, - []ft.File{root}, - safcm.MsgSyncResp{ - FileChanges: []safcm.FileChange{ - { - Path: "file", - Created: true, - New: safcm.FileChangeInfo{ - Mode: 0644, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - }, - }, - }, - []string{ - `4: files: "file" (group): will create`, - `3: files: "file" (group): creating`, - `4: files: "file" (group): dry-run, skipping changes`, - }, - nil, - }, - - { - "file: unchanged", - safcm.MsgSyncReq{}, - &safcm.File{ - Path: "file", - Mode: 0644, - Uid: -1, - Gid: -1, - Data: []byte("content\n"), - OrigGroup: "group", - }, - func() { - ft.CreateFile("file", "content\n", 0644) - }, - false, - []ft.File{ - root, - { - Path: "file", - Mode: 0644, - Data: []byte("content\n"), - }, - }, - safcm.MsgSyncResp{}, - []string{ - `4: files: "file" (group): unchanged`, - }, - nil, - }, - - { - "file: unchanged (non-default user-group)", - safcm.MsgSyncReq{}, - &safcm.File{ - Path: "file", - Mode: 0644, - User: user, - Uid: -1, - Group: group, - Gid: -1, - Data: []byte("content\n"), - OrigGroup: "group", - }, - func() { - ft.CreateFile("file", "content\n", 0644) - }, - false, - []ft.File{ - root, - { - Path: "file", - Mode: 0644, - Data: []byte("content\n"), - }, - }, - safcm.MsgSyncResp{}, - []string{ - `4: files: "file" (group): unchanged`, - }, - nil, - }, - - { - "file: permission", - safcm.MsgSyncReq{}, - &safcm.File{ - Path: "file", - Mode: 0755 | fs.ModeSetuid, - Uid: -1, - Gid: -1, - Data: []byte("content\n"), - OrigGroup: "group", - }, - func() { - ft.CreateFile("file", "content\n", 0755) - }, - true, - []ft.File{ - root, - { - Path: "file", - Mode: 0755 | fs.ModeSetuid, - Data: []byte("content\n"), - }, - }, - safcm.MsgSyncResp{ - FileChanges: []safcm.FileChange{ - { - Path: "file", - Old: safcm.FileChangeInfo{ - Mode: 0755, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - New: safcm.FileChangeInfo{ - Mode: 0755 | fs.ModeSetuid, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - }, - }, - }, - []string{ - `4: files: "file" (group): permission differs -rwxr-xr-x -> urwxr-xr-x`, - `3: files: "file" (group): updating`, - `4: files: "file" (group): creating temporary file ".file*"`, - `4: files: "file" (group): renaming "./.fileRND"`, - }, - nil, - }, - - { - "file: content", - safcm.MsgSyncReq{}, - &safcm.File{ - Path: "file", - Mode: 0644, - Uid: -1, - Gid: -1, - Data: []byte("content\n"), - OrigGroup: "group", - }, - func() { - ft.CreateFile("file", "old content\n", 0644) - }, - true, - []ft.File{ - root, - { - Path: "file", - Mode: 0644, - Data: []byte("content\n"), - }, - }, - safcm.MsgSyncResp{ - FileChanges: []safcm.FileChange{ - { - Path: "file", - Old: safcm.FileChangeInfo{ - Mode: 0644, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - New: safcm.FileChangeInfo{ - Mode: 0644, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - DataDiff: `@@ -1,2 +1,2 @@ --old content -+content - -`, - }, - }, - }, - []string{ - `4: files: "file" (group): content differs`, - `3: files: "file" (group): updating`, - `4: files: "file" (group): creating temporary file ".file*"`, - `4: files: "file" (group): renaming "./.fileRND"`, - }, - nil, - }, - - // Symbolic link - - { - "symlink: create", - safcm.MsgSyncReq{}, - &safcm.File{ - Path: "link", - Mode: fs.ModeSymlink | 0777, - Uid: -1, - Gid: -1, - Data: []byte("target"), - OrigGroup: "group", - }, - nil, - true, - []ft.File{ - root, - { - Path: "link", - Mode: fs.ModeSymlink | 0777, - Data: []byte("target"), - }, - }, - safcm.MsgSyncResp{ - FileChanges: []safcm.FileChange{ - { - Path: "link", - Created: true, - New: safcm.FileChangeInfo{ - Mode: fs.ModeSymlink | 0777, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - }, - }, - }, - []string{ - `4: files: "link" (group): will create`, - `3: files: "link" (group): creating`, - `4: files: "link" (group): creating temporary symlink ".linkRND"`, - `4: files: "link" (group): renaming ".linkRND"`, - }, - nil, - }, - { - "symlink: create (conflict)", - safcm.MsgSyncReq{}, - &safcm.File{ - Path: "link", - Mode: fs.ModeSymlink | 0777, - Uid: -1, - Gid: -1, - Data: []byte("target"), - OrigGroup: "group", - }, - func() { - ft.CreateFile(".link8717895732742165505", "", 0600) - }, - true, - []ft.File{ - root, - { - Path: ".link8717895732742165505", - Mode: 0600, - Data: []byte(""), - }, - { - Path: "link", - Mode: fs.ModeSymlink | 0777, - Data: []byte("target"), - }, - }, - safcm.MsgSyncResp{ - FileChanges: []safcm.FileChange{ - { - Path: "link", - Created: true, - New: safcm.FileChangeInfo{ - Mode: fs.ModeSymlink | 0777, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - }, - }, - }, - []string{ - `4: files: "link" (group): will create`, - `3: files: "link" (group): creating`, - `4: files: "link" (group): creating temporary symlink ".linkRND"`, - `4: files: "link" (group): creating temporary symlink ".linkRND"`, - `4: files: "link" (group): renaming ".linkRND"`, - }, - nil, - }, - { - "symlink: create (dry-run)", - safcm.MsgSyncReq{ - DryRun: true, - }, - &safcm.File{ - Path: "link", - Mode: fs.ModeSymlink | 0777, - Uid: -1, - Gid: -1, - Data: []byte("target"), - OrigGroup: "group", - }, - nil, - true, - []ft.File{root}, - safcm.MsgSyncResp{ - FileChanges: []safcm.FileChange{ - { - Path: "link", - Created: true, - New: safcm.FileChangeInfo{ - Mode: fs.ModeSymlink | 0777, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - }, - }, - }, - []string{ - `4: files: "link" (group): will create`, - `3: files: "link" (group): creating`, - `4: files: "link" (group): dry-run, skipping changes`, - }, - nil, - }, - - { - "symlink: unchanged", - safcm.MsgSyncReq{}, - &safcm.File{ - Path: "link", - Mode: fs.ModeSymlink | 0777, - Uid: -1, - Gid: -1, - Data: []byte("target"), - OrigGroup: "group", - }, - func() { - ft.CreateSymlink("link", "target") - }, - false, - []ft.File{ - root, - { - Path: "link", - Mode: fs.ModeSymlink | 0777, - Data: []byte("target"), - }, - }, - safcm.MsgSyncResp{}, - []string{ - `4: files: "link" (group): unchanged`, - }, - nil, - }, - - { - "symlink: content", - safcm.MsgSyncReq{}, - &safcm.File{ - Path: "link", - Mode: fs.ModeSymlink | 0777, - Uid: -1, - Gid: -1, - Data: []byte("target"), - OrigGroup: "group", - }, - func() { - ft.CreateSymlink("link", "old-target") - }, - true, - []ft.File{ - root, - { - Path: "link", - Mode: fs.ModeSymlink | 0777, - Data: []byte("target"), - }, - }, - safcm.MsgSyncResp{ - FileChanges: []safcm.FileChange{ - { - Path: "link", - Old: safcm.FileChangeInfo{ - Mode: fs.ModeSymlink | 0777, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - New: safcm.FileChangeInfo{ - Mode: fs.ModeSymlink | 0777, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - DataDiff: `@@ -1 +1 @@ --old-target -+target -`, - }, - }, - }, - []string{ - `4: files: "link" (group): content differs`, - `3: files: "link" (group): updating`, - `4: files: "link" (group): creating temporary symlink ".linkRND"`, - `4: files: "link" (group): renaming ".linkRND"`, - }, - nil, - }, - - // Directory - - { - "directory: create", - safcm.MsgSyncReq{}, - &safcm.File{ - Path: "dir", - Mode: fs.ModeDir | 0705, - Uid: -1, - Gid: -1, - OrigGroup: "group", - }, - nil, - true, - []ft.File{ - root, - { - Path: "dir", - Mode: fs.ModeDir | 0705, - }, - }, - safcm.MsgSyncResp{ - FileChanges: []safcm.FileChange{ - { - Path: "dir", - Created: true, - New: safcm.FileChangeInfo{ - Mode: fs.ModeDir | 0705, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - }, - }, - }, - []string{ - `4: files: "dir" (group): will create`, - `3: files: "dir" (group): creating`, - `4: files: "dir" (group): creating directory`, - `4: files: "dir" (group): chmodding drwx---r-x`, - fmt.Sprintf(`4: files: "dir" (group): chowning %d/%d`, uid, gid), - }, - nil, - }, - { - "directory: create (dry-run)", - safcm.MsgSyncReq{ - DryRun: true, - }, - &safcm.File{ - Path: "dir", - Mode: fs.ModeDir | 0644, - Uid: -1, - Gid: -1, - OrigGroup: "group", - }, - nil, - true, - []ft.File{root}, - safcm.MsgSyncResp{ - FileChanges: []safcm.FileChange{ - { - Path: "dir", - Created: true, - New: safcm.FileChangeInfo{ - Mode: fs.ModeDir | 0644, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - }, - }, - }, - []string{ - `4: files: "dir" (group): will create`, - `3: files: "dir" (group): creating`, - `4: files: "dir" (group): dry-run, skipping changes`, - }, - nil, - }, - - { - "directory: unchanged", - safcm.MsgSyncReq{}, - &safcm.File{ - Path: "dir", - Mode: fs.ModeDir | 0755, - Uid: -1, - Gid: -1, - OrigGroup: "group", - }, - func() { - ft.CreateDirectory("dir", 0755) - }, - false, - []ft.File{ - root, - { - Path: "dir", - Mode: fs.ModeDir | 0755, - }, - }, - safcm.MsgSyncResp{}, - []string{ - `4: files: "dir" (group): unchanged`, - }, - nil, - }, - - { - "directory: permission", - safcm.MsgSyncReq{}, - &safcm.File{ - Path: "dir", - Mode: fs.ModeDir | 0755 | fs.ModeSetgid, - Uid: -1, - Gid: -1, - OrigGroup: "group", - }, - func() { - ft.CreateDirectory("dir", 0500|fs.ModeSticky) - }, - true, - []ft.File{ - root, - { - Path: "dir", - Mode: fs.ModeDir | 0755 | fs.ModeSetgid, - }, - }, - safcm.MsgSyncResp{ - FileChanges: []safcm.FileChange{ - { - Path: "dir", - Old: safcm.FileChangeInfo{ - Mode: fs.ModeDir | 0500 | fs.ModeSticky, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - New: safcm.FileChangeInfo{ - Mode: fs.ModeDir | 0755 | fs.ModeSetgid, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - }, - }, - }, - []string{ - `4: files: "dir" (group): permission differs dtr-x------ -> dgrwxr-xr-x`, - `3: files: "dir" (group): updating`, - `4: files: "dir" (group): chmodding dgrwxr-xr-x`, - }, - nil, - }, - - // Type changes - - { - "change: file to directory", - safcm.MsgSyncReq{}, - &safcm.File{ - Path: "path", - Mode: fs.ModeDir | 0751, - Uid: -1, - Gid: -1, - OrigGroup: "group", - }, - func() { - ft.CreateFile("path", "content\n", 0644) - }, - true, - []ft.File{ - root, - { - Path: "path", - Mode: fs.ModeDir | 0751, - }, - }, - safcm.MsgSyncResp{ - FileChanges: []safcm.FileChange{ - { - Path: "path", - Old: safcm.FileChangeInfo{ - Mode: 0644, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - New: safcm.FileChangeInfo{ - Mode: fs.ModeDir | 0751, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - DataDiff: `@@ -1,2 +1 @@ --content - -`, - }, - }, - }, - []string{ - `4: files: "path" (group): type differs ---------- -> d---------`, - `3: files: "path" (group): updating`, - `4: files: "path" (group): removing (due to type change)`, - `4: files: "path" (group): creating directory`, - `4: files: "path" (group): chmodding drwxr-x--x`, - fmt.Sprintf(`4: files: "path" (group): chowning %d/%d`, uid, gid), - }, - nil, - }, - - { - "change: file to symlink", - safcm.MsgSyncReq{}, - &safcm.File{ - Path: "path", - Mode: fs.ModeSymlink | 0777, - Uid: -1, - Gid: -1, - OrigGroup: "group", - Data: []byte("target"), - }, - func() { - ft.CreateFile("path", "content\n", 0644) - }, - true, - []ft.File{ - root, - { - Path: "path", - Mode: fs.ModeSymlink | 0777, - Data: []byte("target"), - }, - }, - safcm.MsgSyncResp{ - FileChanges: []safcm.FileChange{ - { - Path: "path", - Old: safcm.FileChangeInfo{ - Mode: 0644, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - New: safcm.FileChangeInfo{ - Mode: fs.ModeSymlink | 0777, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - DataDiff: `@@ -1,2 +1 @@ --content -- -+target -`, - }, - }, - }, - []string{ - `4: files: "path" (group): type differs ---------- -> L---------`, - `3: files: "path" (group): updating`, - `4: files: "path" (group): creating temporary symlink ".pathRND"`, - `4: files: "path" (group): renaming ".pathRND"`, - }, - nil, - }, - - { - "change: symlink to file", - safcm.MsgSyncReq{}, - &safcm.File{ - Path: "path", - Mode: 0640, - Uid: -1, - Gid: -1, - OrigGroup: "group", - Data: []byte("content\n"), - }, - func() { - ft.CreateSymlink("path", "target") - }, - true, - []ft.File{ - root, - { - Path: "path", - Mode: 0640, - Data: []byte("content\n"), - }, - }, - safcm.MsgSyncResp{ - FileChanges: []safcm.FileChange{ - { - Path: "path", - Old: safcm.FileChangeInfo{ - Mode: fs.ModeSymlink | 0777, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - New: safcm.FileChangeInfo{ - Mode: 0640, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - DataDiff: `@@ -1 +1,2 @@ --target -+content -+ -`, - }, - }, - }, - []string{ - `4: files: "path" (group): type differs L--------- -> ----------`, - `3: files: "path" (group): updating`, - `4: files: "path" (group): creating temporary file ".path*"`, - `4: files: "path" (group): renaming "./.pathRND"`, - }, - nil, - }, - - { - "change: symlink to directory", - safcm.MsgSyncReq{}, - &safcm.File{ - Path: "path", - Mode: fs.ModeDir | 0751, - Uid: -1, - Gid: -1, - OrigGroup: "group", - }, - func() { - ft.CreateSymlink("path", "target") - }, - true, - []ft.File{ - root, - { - Path: "path", - Mode: fs.ModeDir | 0751, - }, - }, - safcm.MsgSyncResp{ - FileChanges: []safcm.FileChange{ - { - Path: "path", - Old: safcm.FileChangeInfo{ - Mode: fs.ModeSymlink | 0777, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - New: safcm.FileChangeInfo{ - Mode: fs.ModeDir | 0751, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - DataDiff: `@@ -1 +1 @@ --target -+ -`, - }, - }, - }, - []string{ - `4: files: "path" (group): type differs L--------- -> d---------`, - `3: files: "path" (group): updating`, - `4: files: "path" (group): removing (due to type change)`, - `4: files: "path" (group): creating directory`, - `4: files: "path" (group): chmodding drwxr-x--x`, - fmt.Sprintf(`4: files: "path" (group): chowning %d/%d`, uid, gid), - }, - nil, - }, - - { - "change: directory to file", - safcm.MsgSyncReq{}, - &safcm.File{ - Path: "path", - Mode: 0666, - Uid: -1, - Gid: -1, - OrigGroup: "group", - Data: []byte("content\n"), - }, - func() { - ft.CreateDirectory("path", 0777) - }, - true, - []ft.File{ - root, - { - Path: "path", - Mode: 0666, - Data: []byte("content\n"), - }, - }, - safcm.MsgSyncResp{ - FileChanges: []safcm.FileChange{ - { - Path: "path", - Old: safcm.FileChangeInfo{ - Mode: fs.ModeDir | 0777, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - New: safcm.FileChangeInfo{ - Mode: 0666, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - }, - }, - }, - []string{ - `4: files: "path" (group): type differs d--------- -> ----------`, - `3: files: "path" (group): updating`, - `4: files: "path" (group): removing (due to type change)`, - `4: files: "path" (group): creating temporary file ".path*"`, - `4: files: "path" (group): renaming "./.pathRND"`, - }, - nil, - }, - - { - "change: directory to symlink", - safcm.MsgSyncReq{}, - &safcm.File{ - Path: "path", - Mode: fs.ModeSymlink | 0777, - Uid: -1, - Gid: -1, - OrigGroup: "group", - Data: []byte("target"), - }, - func() { - ft.CreateDirectory("path", 0777) - }, - true, - []ft.File{ - root, - { - Path: "path", - Mode: fs.ModeSymlink | 0777, - Data: []byte("target"), - }, - }, - safcm.MsgSyncResp{ - FileChanges: []safcm.FileChange{ - { - Path: "path", - Old: safcm.FileChangeInfo{ - Mode: fs.ModeDir | 0777, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - New: safcm.FileChangeInfo{ - Mode: fs.ModeSymlink | 0777, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - }, - }, - }, - []string{ - `4: files: "path" (group): type differs d--------- -> L---------`, - `3: files: "path" (group): updating`, - `4: files: "path" (group): removing (due to type change)`, - `4: files: "path" (group): creating temporary symlink ".pathRND"`, - `4: files: "path" (group): renaming ".pathRND"`, - }, - nil, - }, - - { - "change: other to file", - safcm.MsgSyncReq{}, - &safcm.File{ - Path: "path", - Mode: 0640, - Uid: -1, - Gid: -1, - OrigGroup: "group", - Data: []byte("content\n"), - }, - func() { - ft.CreateFifo("path", 0666) - }, - true, - []ft.File{ - root, - { - Path: "path", - Mode: 0640, - Data: []byte("content\n"), - }, - }, - safcm.MsgSyncResp{ - FileChanges: []safcm.FileChange{ - { - Path: "path", - Old: safcm.FileChangeInfo{ - Mode: fs.ModeNamedPipe | 0666, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - New: safcm.FileChangeInfo{ - Mode: 0640, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - }, - }, - }, - []string{ - `4: files: "path" (group): type differs p--------- -> ----------`, - `3: files: "path" (group): updating`, - `4: files: "path" (group): creating temporary file ".path*"`, - `4: files: "path" (group): renaming "./.pathRND"`, - }, - nil, - }, - - { - "change: other to symlink", - safcm.MsgSyncReq{}, - &safcm.File{ - Path: "path", - Mode: fs.ModeSymlink | 0777, - Uid: -1, - Gid: -1, - OrigGroup: "group", - Data: []byte("target"), - }, - func() { - ft.CreateFifo("path", 0666) - }, - true, - []ft.File{ - root, - { - Path: "path", - Mode: fs.ModeSymlink | 0777, - Data: []byte("target"), - }, - }, - safcm.MsgSyncResp{ - FileChanges: []safcm.FileChange{ - { - Path: "path", - Old: safcm.FileChangeInfo{ - Mode: fs.ModeNamedPipe | 0666, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - New: safcm.FileChangeInfo{ - Mode: fs.ModeSymlink | 0777, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - }, - }, - }, - []string{ - `4: files: "path" (group): type differs p--------- -> L---------`, - `3: files: "path" (group): updating`, - `4: files: "path" (group): creating temporary symlink ".pathRND"`, - `4: files: "path" (group): renaming ".pathRND"`, - }, - nil, - }, - - { - "change: other to directory", - safcm.MsgSyncReq{}, - &safcm.File{ - Path: "path", - Mode: fs.ModeDir | 0751, - Uid: -1, - Gid: -1, - OrigGroup: "group", - }, - func() { - ft.CreateFifo("path", 0666) - }, - true, - []ft.File{ - root, - { - Path: "path", - Mode: fs.ModeDir | 0751, - }, - }, - safcm.MsgSyncResp{ - FileChanges: []safcm.FileChange{ - { - Path: "path", - Old: safcm.FileChangeInfo{ - Mode: fs.ModeNamedPipe | 0666, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - New: safcm.FileChangeInfo{ - Mode: fs.ModeDir | 0751, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - }, - }, - }, - []string{ - `4: files: "path" (group): type differs p--------- -> d---------`, - `3: files: "path" (group): updating`, - `4: files: "path" (group): removing (due to type change)`, - `4: files: "path" (group): creating directory`, - `4: files: "path" (group): chmodding drwxr-x--x`, - fmt.Sprintf(`4: files: "path" (group): chowning %d/%d`, uid, gid), - }, - nil, - }, - - { - "change: file to symlink (same content)", - safcm.MsgSyncReq{}, - &safcm.File{ - Path: "path", - Mode: fs.ModeSymlink | 0777, - Uid: -1, - Gid: -1, - OrigGroup: "group", - Data: []byte("target"), - }, - func() { - ft.CreateFile("path", "target", 0644) - }, - true, - []ft.File{ - root, - { - Path: "path", - Mode: fs.ModeSymlink | 0777, - Data: []byte("target"), - }, - }, - safcm.MsgSyncResp{ - FileChanges: []safcm.FileChange{ - { - Path: "path", - Old: safcm.FileChangeInfo{ - Mode: 0644, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - New: safcm.FileChangeInfo{ - Mode: fs.ModeSymlink | 0777, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - }, - }, - }, - []string{ - `4: files: "path" (group): type differs ---------- -> L---------`, - `3: files: "path" (group): updating`, - `4: files: "path" (group): creating temporary symlink ".pathRND"`, - `4: files: "path" (group): renaming ".pathRND"`, - }, - nil, - }, - - // Diffs - - { - "diff: textual", - safcm.MsgSyncReq{ - DryRun: true, - }, - &safcm.File{ - Path: "file", - Mode: 0644, - Uid: -1, - Gid: -1, - Data: []byte(` -this -is -a -simple -file -`), - OrigGroup: "group", - }, - func() { - ft.CreateFile("file", `this -is -file -! -`, 0644) - }, - true, - []ft.File{ - root, - { - Path: "file", - Mode: 0644, - Data: []byte(`this -is -file -! -`), - }, - }, - safcm.MsgSyncResp{ - FileChanges: []safcm.FileChange{ - { - Path: "file", - Old: safcm.FileChangeInfo{ - Mode: 0644, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - New: safcm.FileChangeInfo{ - Mode: 0644, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - DataDiff: `@@ -1,5 +1,7 @@ -+ - this - is -+a -+simple - file --! - -`, - }, - }, - }, - []string{ - `4: files: "file" (group): content differs`, - `3: files: "file" (group): updating`, - `4: files: "file" (group): dry-run, skipping changes`, - }, - nil, - }, - - { - "diff: binary both", - safcm.MsgSyncReq{ - DryRun: true, - }, - &safcm.File{ - Path: "file", - Mode: 0644, - Uid: -1, - Gid: -1, - Data: []byte("\x00\x01\x02\x03"), - OrigGroup: "group", - }, - func() { - ft.CreateFile("file", "\x00\x01\x02", 0644) - }, - true, - []ft.File{ - root, - { - Path: "file", - Mode: 0644, - Data: []byte("\x00\x01\x02"), - }, - }, - safcm.MsgSyncResp{ - FileChanges: []safcm.FileChange{ - { - Path: "file", - Old: safcm.FileChangeInfo{ - Mode: 0644, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - New: safcm.FileChangeInfo{ - Mode: 0644, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - DataDiff: "Binary files differ (3 -> 4 bytes), cannot show diff", - }, - }, - }, - []string{ - `4: files: "file" (group): content differs`, - `3: files: "file" (group): updating`, - `4: files: "file" (group): dry-run, skipping changes`, - }, - nil, - }, - - { - "diff: binary old", - safcm.MsgSyncReq{ - DryRun: true, - }, - &safcm.File{ - Path: "file", - Mode: 0644, - Uid: -1, - Gid: -1, - Data: []byte("content\n"), - OrigGroup: "group", - }, - func() { - ft.CreateFile("file", "\x00\x01\x02", 0644) - }, - true, - []ft.File{ - root, - { - Path: "file", - Mode: 0644, - Data: []byte("\x00\x01\x02"), - }, - }, - safcm.MsgSyncResp{ - FileChanges: []safcm.FileChange{ - { - Path: "file", - Old: safcm.FileChangeInfo{ - Mode: 0644, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - New: safcm.FileChangeInfo{ - Mode: 0644, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - DataDiff: `@@ -1,2 +1,2 @@ -- -+content - -`, - }, - }, - }, - []string{ - `4: files: "file" (group): content differs`, - `3: files: "file" (group): updating`, - `4: files: "file" (group): dry-run, skipping changes`, - }, - nil, - }, - - { - "diff: binary new", - safcm.MsgSyncReq{ - DryRun: true, - }, - &safcm.File{ - Path: "file", - Mode: 0644, - Uid: -1, - Gid: -1, - Data: []byte("\x00\x01\x02\x03"), - OrigGroup: "group", - }, - func() { - ft.CreateFile("file", "content\n", 0644) - }, - true, - []ft.File{ - root, - { - Path: "file", - Mode: 0644, - Data: []byte("content\n"), - }, - }, - safcm.MsgSyncResp{ - FileChanges: []safcm.FileChange{ - { - Path: "file", - Old: safcm.FileChangeInfo{ - Mode: 0644, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - New: safcm.FileChangeInfo{ - Mode: 0644, - User: user, - Uid: uid, - Group: group, - Gid: gid, - }, - DataDiff: `@@ -1,2 +1,2 @@ --content -+ - -`, - }, - }, - }, - []string{ - `4: files: "file" (group): content differs`, - `3: files: "file" (group): updating`, - `4: files: "file" (group): dry-run, skipping changes`, - }, - nil, - }, - } - - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - // Create separate test directory for each test case - path := filepath.Join(cwd, "testdata", "file-"+tc.name) - err := os.Mkdir(path, 0700) - if err != nil { - t.Fatal(err) - } - err = os.Chdir(path) - if err != nil { - t.Fatal(err) - } - - if tc.prepare != nil { - tc.prepare() - } - - s, res := prepareSync(tc.req, &testRunner{ - t: t, - }) - err = s.setDefaults() - if err != nil { - t.Fatal(err) - } - - // Deterministic temporary symlink names - rand.Seed(0) - - var changed bool - err = s.syncFile(tc.file, &changed) - 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"`) - } - testutil.AssertEqual(t, "dbg", dbg, tc.expDbg) - - files, err := ft.WalkDir(path) - if err != nil { - t.Fatal(err) - } - testutil.AssertEqual(t, "files", files, tc.expFiles) - - testutil.AssertEqual(t, "changed", changed, tc.expChanged) - testutil.AssertEqual(t, "resp", s.resp, tc.expResp) - }) - } - - if !t.Failed() { - err = os.RemoveAll(filepath.Join(cwd, "testdata")) - if err != nil { - t.Fatal(err) - } - } -}