]> ruderich.org/simon Gitweb - safcm/safcm.git/blobdiff - remote/ainsl/ainsl_test.go
Move implementation of cmd/safcm-remote/ to remote/
[safcm/safcm.git] / remote / ainsl / ainsl_test.go
diff --git a/remote/ainsl/ainsl_test.go b/remote/ainsl/ainsl_test.go
new file mode 100644 (file)
index 0000000..3d391f0
--- /dev/null
@@ -0,0 +1,336 @@
+// 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 ainsl
+
+import (
+       "fmt"
+       "io/fs"
+       "os"
+       "path/filepath"
+       "runtime"
+       "syscall"
+       "testing"
+
+       ft "ruderich.org/simon/safcm/remote/sync/filetest"
+       "ruderich.org/simon/safcm/testutil"
+)
+
+func TestHandle(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)
+       }
+
+       // Set umask to test mode for new files
+       umask := syscall.Umask(027)
+       defer syscall.Umask(umask)
+
+       root := ft.File{
+               Path: ".",
+               Mode: fs.ModeDir | 0700,
+       }
+       _, uid, _, gid := ft.CurrentUserAndGroup()
+
+       symlinkExists := "open file: too many levels of symbolic links"
+       if runtime.GOOS == "freebsd" {
+               // EMLINK instead of ELOOP
+               symlinkExists = "open file: too many links"
+       }
+
+       tests := []struct {
+               name       string
+               path       string
+               line       string
+               create     bool
+               prepare    func()
+               expFiles   []ft.File
+               expChanges []string
+               expErr     error
+       }{
+
+               // TODO: Add tests for chown and run them only as root
+
+               {
+                       "missing",
+                       "file",
+                       "line",
+                       false,
+                       nil,
+                       []ft.File{
+                               root,
+                       },
+                       nil,
+                       fmt.Errorf("\"file\": file does not exist, use -create"),
+               },
+
+               {
+                       "missing: create",
+                       "file",
+                       "line",
+                       true,
+                       nil,
+                       []ft.File{
+                               root,
+                               ft.File{
+                                       Path: "file",
+                                       Mode: 0640,
+                                       Data: []byte("line\n"),
+                               },
+                       },
+                       []string{
+                               fmt.Sprintf(`"file": created file (%d/%d -rw-r-----)`, uid, gid),
+                               `"file": added line "line"`,
+                       },
+                       nil,
+               },
+               {
+                       "missing: create (empty line)",
+                       "file",
+                       "",
+                       true,
+                       nil,
+                       []ft.File{
+                               root,
+                       },
+                       nil,
+                       fmt.Errorf("empty line"),
+               },
+               {
+                       "missing: create (newline)",
+                       "file",
+                       "line\n",
+                       true,
+                       nil,
+                       []ft.File{
+                               root,
+                       },
+                       nil,
+                       fmt.Errorf("line must not contain newlines: \"line\\n\""),
+               },
+
+               {
+                       "exists: unchanged",
+                       "file",
+                       "line",
+                       true,
+                       func() {
+                               ft.CreateFile("file", "line\n", 0641)
+                       },
+                       []ft.File{
+                               root,
+                               ft.File{
+                                       Path: "file",
+                                       Mode: 0641,
+                                       Data: []byte("line\n"),
+                               },
+                       },
+                       nil,
+                       nil,
+               },
+
+               {
+                       "exists: append",
+                       "file",
+                       "line",
+                       true,
+                       func() {
+                               ft.CreateFile("file", "existing\n", 0641)
+                       },
+                       []ft.File{
+                               root,
+                               ft.File{
+                                       Path: "file",
+                                       Mode: 0641,
+                                       Data: []byte("existing\nline\n"),
+                               },
+                       },
+                       []string{
+                               `"file": added line "line"`,
+                       },
+                       nil,
+               },
+               {
+                       "exists: append (no newline in file)",
+                       "file",
+                       "line",
+                       true,
+                       func() {
+                               ft.CreateFile("file", "existing", 0641)
+                       },
+                       []ft.File{
+                               root,
+                               ft.File{
+                                       Path: "file",
+                                       Mode: 0641,
+                                       Data: []byte("existing\nline\n"),
+                               },
+                       },
+                       []string{
+                               `"file": added missing trailing newline`,
+                               `"file": added line "line"`,
+                       },
+                       nil,
+               },
+               {
+                       "exists: append (only trailing newline I)",
+                       "file",
+                       "line",
+                       true,
+                       func() {
+                               ft.CreateFile("file", "first\nline", 0641)
+                       },
+                       []ft.File{
+                               root,
+                               ft.File{
+                                       Path: "file",
+                                       Mode: 0641,
+                                       Data: []byte("first\nline\n"),
+                               },
+                       },
+                       []string{
+                               `"file": added missing trailing newline`,
+                       },
+                       nil,
+               },
+               {
+                       "exists: append (only trailing newline II)",
+                       "file",
+                       "first",
+                       true,
+                       func() {
+                               ft.CreateFile("file", "first\nline", 0641)
+                       },
+                       []ft.File{
+                               root,
+                               ft.File{
+                                       Path: "file",
+                                       Mode: 0641,
+                                       Data: []byte("first\nline\n"),
+                               },
+                       },
+                       []string{
+                               `"file": added missing trailing newline`,
+                       },
+                       nil,
+               },
+               {
+                       "exists: append (partial line)",
+                       "file",
+                       "line with spaces",
+                       true,
+                       func() {
+                               ft.CreateFile("file", "# line with spaces\n", 0641)
+                       },
+                       []ft.File{
+                               root,
+                               ft.File{
+                                       Path: "file",
+                                       Mode: 0641,
+                                       Data: []byte("# line with spaces\nline with spaces\n"),
+                               },
+                       },
+                       []string{
+                               `"file": added line "line with spaces"`,
+                       },
+                       nil,
+               },
+
+               {
+                       "exists: symlink",
+                       "file",
+                       "line",
+                       true,
+                       func() {
+                               ft.CreateSymlink("file", "target")
+                       },
+                       []ft.File{
+                               root,
+                               ft.File{
+                                       Path: "file",
+                                       Mode: fs.ModeSymlink | 0777,
+                                       Data: []byte("target"),
+                               },
+                       },
+                       nil,
+                       fmt.Errorf(symlinkExists),
+               },
+               {
+                       "exists: fifo",
+                       "file",
+                       "line",
+                       true,
+                       func() {
+                               ft.CreateFifo("file", 0640)
+                       },
+                       []ft.File{
+                               root,
+                               ft.File{
+                                       Path: "file",
+                                       Mode: fs.ModeNamedPipe | 0640,
+                               },
+                       },
+                       nil,
+                       fmt.Errorf("\"file\" is not a regular file but p---------"),
+               },
+       }
+
+       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", 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()
+                       }
+
+                       changes, err := handle(tc.path, tc.line, tc.create)
+                       testutil.AssertEqual(t, "changes",
+                               changes, tc.expChanges)
+                       testutil.AssertErrorEqual(t, "err", err, tc.expErr)
+
+                       files, err := ft.WalkDir(path)
+                       if err != nil {
+                               t.Fatal(err)
+                       }
+                       testutil.AssertEqual(t, "files", files, tc.expFiles)
+               })
+       }
+
+       if !t.Failed() {
+               err = os.RemoveAll(filepath.Join(cwd, "testdata"))
+               if err != nil {
+                       t.Fatal(err)
+               }
+       }
+}