354 lines
8.2 KiB
Go
354 lines
8.2 KiB
Go
package fileio
|
|
|
|
import (
|
|
"io/fs"
|
|
"os"
|
|
"path/filepath"
|
|
"reflect"
|
|
"testing"
|
|
)
|
|
|
|
func TestExists(t *testing.T) {
|
|
t.Run("exists", func(t *testing.T) {
|
|
path := filepath.Join(t.TempDir(), "file.txt")
|
|
err := os.WriteFile(path, []byte{1, 2, 3}, 0444)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !Exists(path) {
|
|
t.Fatalf("Exists: %s does not exist", filepath.Base(path))
|
|
}
|
|
})
|
|
t.Run("does not exist", func(t *testing.T) {
|
|
path := filepath.Join(t.TempDir(), "file.txt")
|
|
if Exists(path) {
|
|
t.Fatalf("Exists: %s should not exist", filepath.Base(path))
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestCopyFiles(t *testing.T) {
|
|
// create a temporary directory for testing
|
|
srcDir, err := os.MkdirTemp("", "src")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer os.RemoveAll(srcDir)
|
|
|
|
// create a source file
|
|
srcFile := filepath.Join(srcDir, "source.txt")
|
|
err = os.WriteFile(srcFile, []byte("test data"), 0644)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// specify the destination directory
|
|
dstDir, err := os.MkdirTemp("", "dst")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer os.RemoveAll(dstDir)
|
|
|
|
t.Run("copy", func(t *testing.T) {
|
|
// call the CopyFiles function
|
|
const perm = fs.FileMode(0444)
|
|
pattern := filepath.Join(srcDir, "*.txt")
|
|
err = CopyFiles(pattern, dstDir, perm)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// verify that the file was copied correctly
|
|
dstFile := filepath.Join(dstDir, "source.txt")
|
|
fileInfo, err := os.Stat(dstFile)
|
|
if err != nil {
|
|
t.Fatalf("file not copied: %s", err)
|
|
}
|
|
if fileInfo.Mode() != perm {
|
|
t.Errorf("unexpected file permissions: got %v, want %v", fileInfo.Mode(), perm)
|
|
}
|
|
|
|
// read the contents of the copied file
|
|
data, err := os.ReadFile(dstFile)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// verify the contents of the copied file
|
|
expected := []byte("test data")
|
|
if string(data) != string(expected) {
|
|
t.Errorf("unexpected file content: got %q, want %q", data, expected)
|
|
}
|
|
})
|
|
|
|
t.Run("skip existing", func(t *testing.T) {
|
|
// existing file in the destination dir
|
|
path := filepath.Join(dstDir, "existing.txt")
|
|
err := os.WriteFile(path, []byte("v1"), 0444)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// same file in the source dir
|
|
path = filepath.Join(srcDir, "existing.txt")
|
|
err = os.WriteFile(path, []byte("v2"), 0444)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// copy files
|
|
pattern := filepath.Join(srcDir, "*.txt")
|
|
err = CopyFiles(pattern, dstDir, 0444)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// verify that the new file was copied correctly
|
|
newFile := filepath.Join(dstDir, "source.txt")
|
|
_, err = os.Stat(newFile)
|
|
if err != nil {
|
|
t.Fatalf("new file not copied: %s", err)
|
|
}
|
|
|
|
// verify that the existing file remained unchanged
|
|
existFile := filepath.Join(dstDir, "existing.txt")
|
|
data, err := os.ReadFile(existFile)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
expected := []byte("v1")
|
|
if string(data) != string(expected) {
|
|
t.Error("existing file got overwritten")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestReadJson(t *testing.T) {
|
|
type Person struct{ Name string }
|
|
|
|
t.Run("valid", func(t *testing.T) {
|
|
got, err := ReadJson[Person](filepath.Join("testdata", "valid.json"))
|
|
if err != nil {
|
|
t.Fatalf("unexpected error %v", err)
|
|
}
|
|
want := Person{"alice"}
|
|
if !reflect.DeepEqual(got, want) {
|
|
t.Errorf("expected %v, got %v", want, got)
|
|
}
|
|
})
|
|
t.Run("invalid", func(t *testing.T) {
|
|
_, err := ReadJson[Person](filepath.Join("testdata", "invalid.json"))
|
|
if err == nil {
|
|
t.Fatal("expected error, got nil")
|
|
}
|
|
})
|
|
t.Run("does not exist", func(t *testing.T) {
|
|
_, err := ReadJson[Person](filepath.Join("testdata", "missing.json"))
|
|
if err == nil {
|
|
t.Fatal("expected error, got nil")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestWriteFile(t *testing.T) {
|
|
dir, err := os.MkdirTemp("", "files")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer os.RemoveAll(dir)
|
|
|
|
t.Run("text", func(t *testing.T) {
|
|
path := filepath.Join(dir, "data.txt")
|
|
err = WriteFile(path, "hello", 0444)
|
|
if err != nil {
|
|
t.Fatalf("expected nil err, got %v", err)
|
|
}
|
|
got, err := os.ReadFile(path)
|
|
if err != nil {
|
|
t.Fatalf("read file: expected nil err, got %v", err)
|
|
}
|
|
want := []byte("hello")
|
|
if !reflect.DeepEqual(got, want) {
|
|
t.Errorf("read file: expected %v, got %v", want, got)
|
|
}
|
|
})
|
|
|
|
t.Run("binary", func(t *testing.T) {
|
|
path := filepath.Join(dir, "data.bin")
|
|
err = WriteFile(path, "data:application/octet-stream;base64,MTIz", 0444)
|
|
if err != nil {
|
|
t.Fatalf("expected nil err, got %v", err)
|
|
}
|
|
got, err := os.ReadFile(path)
|
|
if err != nil {
|
|
t.Fatalf("read file: expected nil err, got %v", err)
|
|
}
|
|
want := []byte("123")
|
|
if !reflect.DeepEqual(got, want) {
|
|
t.Errorf("read file: expected %v, got %v", want, got)
|
|
}
|
|
})
|
|
|
|
t.Run("perm", func(t *testing.T) {
|
|
const perm = 0444
|
|
path := filepath.Join(dir, "perm.txt")
|
|
err = WriteFile(path, "hello", perm)
|
|
if err != nil {
|
|
t.Fatalf("expected nil err, got %v", err)
|
|
}
|
|
fileInfo, err := os.Stat(path)
|
|
if err != nil {
|
|
t.Fatalf("file not created: %s", err)
|
|
}
|
|
if fileInfo.Mode().Perm() != perm {
|
|
t.Errorf("unexpected file permissions: expected %o, got %o", perm, fileInfo.Mode().Perm())
|
|
}
|
|
})
|
|
|
|
t.Run("missing data-url separator", func(t *testing.T) {
|
|
path := filepath.Join(dir, "data.bin")
|
|
err = WriteFile(path, "data:application/octet-stream:MTIz", 0444)
|
|
if err == nil {
|
|
t.Fatal("expected error, got nil")
|
|
}
|
|
})
|
|
|
|
t.Run("invalid binary value", func(t *testing.T) {
|
|
path := filepath.Join(dir, "data.bin")
|
|
err = WriteFile(path, "data:application/octet-stream;base64,12345", 0444)
|
|
if err == nil {
|
|
t.Fatal("expected error, got nil")
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestJoinDir(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
dir string
|
|
filename string
|
|
want string
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "regular join",
|
|
dir: "/home/user",
|
|
filename: "docs/report.txt",
|
|
want: "/home/user/docs/report.txt",
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "join with dot",
|
|
dir: "/home/user",
|
|
filename: ".",
|
|
want: "",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "join with absolute path",
|
|
dir: "/home/user",
|
|
filename: "/etc/passwd",
|
|
want: "",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "join with parent directory",
|
|
dir: "/home/user",
|
|
filename: "../user2/docs/report.txt",
|
|
want: "",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "empty directory",
|
|
dir: "",
|
|
filename: "report.txt",
|
|
want: "",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "empty filename",
|
|
dir: "/home/user",
|
|
filename: "",
|
|
want: "",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "directory with trailing slash",
|
|
dir: "/home/user/",
|
|
filename: "docs/report.txt",
|
|
want: "/home/user/docs/report.txt",
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "filename with leading slash",
|
|
dir: "/home/user",
|
|
filename: "/docs/report.txt",
|
|
want: "",
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "root directory",
|
|
dir: "/",
|
|
filename: "report.txt",
|
|
want: "/report.txt",
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "dot dot slash filename",
|
|
dir: "/home/user",
|
|
filename: "..",
|
|
want: "",
|
|
wantErr: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := JoinDir(tt.dir, tt.filename)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("JoinDir() error = %v, wantErr %v", err, tt.wantErr)
|
|
return
|
|
}
|
|
if got != tt.want {
|
|
t.Errorf("JoinDir() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestMkdirTemp(t *testing.T) {
|
|
t.Run("default permissions", func(t *testing.T) {
|
|
const perm = 0755
|
|
dir, err := MkdirTemp(perm)
|
|
if err != nil {
|
|
t.Fatalf("failed to create temp directory: %v", err)
|
|
}
|
|
defer os.Remove(dir)
|
|
|
|
info, err := os.Stat(dir)
|
|
if err != nil {
|
|
t.Fatalf("failed to stat temp directory: %v", err)
|
|
}
|
|
if info.Mode().Perm() != perm {
|
|
t.Errorf("unexpected permissions: expected %o, got %o", perm, info.Mode().Perm())
|
|
}
|
|
})
|
|
|
|
t.Run("non-default permissions", func(t *testing.T) {
|
|
const perm = 0777
|
|
dir, err := MkdirTemp(perm)
|
|
if err != nil {
|
|
t.Fatalf("failed to create temp directory: %v", err)
|
|
}
|
|
defer os.Remove(dir)
|
|
|
|
info, err := os.Stat(dir)
|
|
if err != nil {
|
|
t.Fatalf("failed to stat temp directory: %v", err)
|
|
}
|
|
if info.Mode().Perm() != perm {
|
|
t.Errorf("unexpected permissions: expected %o, got %o", perm, info.Mode().Perm())
|
|
}
|
|
})
|
|
}
|