+++ /dev/null
-// 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 <http://www.gnu.org/licenses/>.
-
-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 @@
--<binary content, 3 bytes>
-+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
-+<binary content, 4 bytes>
-
-`,
- },
- },
- },
- []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)
- }
- }
-}