blob: 9559c66c1aa6d50a0fb31ed073a72019e915bf6f [file] [edit]
// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package fsutil_test
import (
"io/ioutil"
"os"
"path/filepath"
"testing"
"golang.org/x/sys/unix"
"chromiumos/tast/fsutil"
"chromiumos/tast/testutil"
)
// setUpFile creates a temporary directory containing a file with the supplied data and mode.
// The temporary directory's and file's paths are returned.
// A fatal test error is reported if any operations fail.
func setUpFile(t *testing.T, data string, mode os.FileMode) (td, fn string) {
td = testutil.TempDir(t)
fn = filepath.Join(td, "src.txt")
if err := ioutil.WriteFile(fn, []byte(data), mode); err != nil {
t.Fatal(err)
}
if err := os.Chmod(fn, mode); err != nil {
t.Fatal(err)
}
return td, fn
}
// checkFile checks that the file at path has the supplied data and mode.
// Test errors are reported for any discrepancies.
func checkFile(t *testing.T, path, data string, mode os.FileMode) {
if fi, err := os.Stat(path); err != nil {
t.Errorf("Failed to stat %v: %v", path, err)
} else if newMode := fi.Mode() & os.ModePerm; newMode != mode {
t.Errorf("%v has mode 0%o; want 0%o", path, newMode, mode)
}
if b, err := ioutil.ReadFile(path); err != nil {
t.Errorf("Failed to read %v: %v", path, err)
} else if string(b) != data {
t.Errorf("%v contains %q; want %q", path, string(b), data)
}
}
func TestCopyFile(t *testing.T) {
const (
data = "this is not the most interesting text ever written"
mode = 0461
)
td, src := setUpFile(t, data, mode)
defer os.RemoveAll(td)
dst := filepath.Join(td, "dst.txt")
if err := fsutil.CopyFile(src, dst); err != nil {
t.Fatalf("CopyFile(%q, %q) failed: %v", src, dst, err)
}
checkFile(t, dst, data, mode)
}
func TestMoveFile(t *testing.T) {
const (
data = "another boring file"
mode = 0401
)
td, src := setUpFile(t, data, mode)
defer os.RemoveAll(td)
dst := filepath.Join(td, "dst.txt")
if err := fsutil.MoveFile(src, dst); err != nil {
t.Fatalf("MoveFile(%q, %q) failed: %v", src, dst, err)
}
checkFile(t, dst, data, mode)
if _, err := os.Stat(src); err == nil {
t.Errorf("%s still exists", src)
} else if !os.IsNotExist(err) {
t.Errorf("Failed to stat %s: %v", src, err)
}
}
func TestMoveFileAcrossFilesystems(t *testing.T) {
const (
data = "another boring file"
mode = 0401
)
td, src := setUpFile(t, data, mode)
defer os.RemoveAll(td)
var srcStat unix.Statfs_t
if err := unix.Statfs(src, &srcStat); err != nil {
t.Fatal(err)
}
// Check that we're actually crossing filesystems.
const dstFS = "/dev/shm"
var dstStat unix.Statfs_t
if err := unix.Statfs(dstFS, &dstStat); err != nil {
t.Logf("Failed to stat %v; skipping test: %v", dstFS, err)
return
} else if srcStat.Fsid == dstStat.Fsid {
t.Logf("FS for %v and %v both have ID %v; skipping test", src, srcStat.Fsid, dstStat.Fsid)
return
}
df, err := ioutil.TempFile(dstFS, "dst.txt.")
if err != nil {
t.Fatal(err)
}
df.Close()
dst := df.Name()
defer os.Remove(dst)
if err := fsutil.MoveFile(src, dst); err != nil {
t.Fatalf("MoveFile(%q, %q) failed: %v", src, dst, err)
}
checkFile(t, dst, data, mode)
if _, err := os.Stat(src); err == nil {
t.Errorf("%s still exists", src)
} else if !os.IsNotExist(err) {
t.Errorf("Failed to stat %s: %v", src, err)
}
}
func TestCopyFileOrMoveFileWithDir(t *testing.T) {
td := testutil.TempDir(t)
defer os.RemoveAll(td)
src := filepath.Join(td, "dir")
if err := os.Mkdir(src, 0755); err != nil {
t.Fatal(err)
}
// Both functions should reject directories.
if err := fsutil.CopyFile(src, filepath.Join(td, "copyDst")); err == nil {
t.Error("CopyFile unexpectedly succeeded for directory ", src)
}
if err := fsutil.MoveFile(src, filepath.Join(td, "moveDst")); err == nil {
t.Error("MoveFile unexpectedly succeeded for directory ", src)
}
}