libgocryptfs/tests/defaults/main_test.go

296 lines
6.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Tests and benchmarks performed with default settings only.
package defaults
import (
"bytes"
"io"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"sync"
"testing"
"github.com/rfjakob/gocryptfs/tests/test_helpers"
)
func TestMain(m *testing.M) {
test_helpers.ResetTmpDir(true)
test_helpers.MountOrExit(test_helpers.DefaultCipherDir, test_helpers.DefaultPlainDir, "-zerokey")
r := m.Run()
test_helpers.UnmountPanic(test_helpers.DefaultPlainDir)
os.Exit(r)
}
// Test that we get the right timestamp when extracting a tarball.
func Test1980Tar(t *testing.T) {
c := exec.Command("tar", "xzf", "1980.tar.gz", "-C", test_helpers.DefaultPlainDir)
c.Stderr = os.Stderr
c.Stdout = os.Stdout
err := c.Run()
if err != nil {
t.Fatal(err)
}
fi, err := os.Stat(test_helpers.DefaultPlainDir + "/1980.txt")
if err != nil {
t.Fatal(err)
}
m := fi.ModTime().Unix()
if m != 315619323 {
t.Errorf("Wrong mtime: %d", m)
}
}
// In gocryptfs before v1.2, the file header was only read once for each
// open. But truncating a file to zero will generate a new random file ID.
// The sequence below caused an I/O error to be returned.
func TestOpenTruncateRead(t *testing.T) {
fn := test_helpers.DefaultPlainDir + "/TestTruncateWrite"
// First FD is used for write and truncate.
writeFd, err := os.Create(fn)
if err != nil {
t.Fatal(err)
}
defer writeFd.Close()
abc := []byte("abc")
_, err = writeFd.WriteAt(abc, 0)
if err != nil {
t.Fatal(err)
}
// Second FD is just for reading.
readFd, err := os.Open(fn)
if err != nil {
t.Fatal(err)
}
defer readFd.Close()
content := make([]byte, 3)
_, err = readFd.ReadAt(content, 0)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(content, abc) {
t.Fatalf("wrong content: %s", string(content))
}
// Truncate to zero to generate a new file ID and write new content.
err = writeFd.Truncate(0)
if err != nil {
t.Fatal(err)
}
xyz := []byte("xyz")
_, err = writeFd.WriteAt(xyz, 0)
if err != nil {
t.Fatal(err)
}
// Try to read from the other FD.
_, err = readFd.ReadAt(content, 0)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(content, xyz) {
t.Fatalf("wrong content: %s", string(content))
}
}
// TestWORead tries to read from a write-only FD.
func TestWORead(t *testing.T) {
fn := test_helpers.DefaultPlainDir + "/TestWORead"
fd, err := os.OpenFile(fn, os.O_CREATE|os.O_WRONLY, 0600)
if err != nil {
t.Fatal(err)
}
defer fd.Close()
buf := make([]byte, 10)
_, err = fd.Read(buf)
if err == nil {
t.Error("Reading from write-only file should fail, but did not")
}
}
// xfstests generic/124 triggers this warning:
// cipherSize 18 == header size: interrupted write?
// This test reproduces the problem.
func TestXfs124(t *testing.T) {
// GOMAXPROCS=8 and N=5000 seem to reliably trigger the problem. With N=1000,
// the test passes sometimes.
runtime.GOMAXPROCS(8)
N := 5000
fn := test_helpers.DefaultPlainDir + "/TestXfs124"
fd, err := os.Create(fn)
if err != nil {
t.Fatal(err)
}
defer fd.Close()
var wg sync.WaitGroup
wg.Add(2)
go func() {
buf := make([]byte, 10)
var err2 error
for i := 0; i < N; i++ {
err2 = fd.Truncate(0)
if err2 != nil {
panic(err2)
}
_, err2 = fd.WriteAt(buf, 0)
if err2 != nil {
panic(err2)
}
}
wg.Done()
}()
fd2, err := os.Open(fn)
if err != nil {
t.Fatal(err)
}
defer fd2.Close()
go func() {
buf := make([]byte, 10)
var err3 error
for i := 0; i < N; i++ {
_, err3 = fd2.ReadAt(buf, 0)
if err3 == io.EOF {
continue
}
if err3 != nil {
panic(err3)
}
}
wg.Done()
}()
wg.Wait()
}
func TestWrite0200File(t *testing.T) {
fn := test_helpers.DefaultPlainDir + "/TestWrite0200File"
err := ioutil.WriteFile(fn, nil, 0200)
if err != nil {
t.Fatalf("creating empty file failed: %v", err)
}
fd, err := os.OpenFile(fn, os.O_WRONLY, 0)
if err != nil {
t.Fatal(err)
}
fi, err := fd.Stat()
if err != nil {
t.Fatal(err)
}
perms := fi.Mode().Perm()
if perms != 0200 {
t.Fatal("wrong initial permissions")
}
defer fd.Close()
_, err = fd.Write(make([]byte, 10))
if err != nil {
t.Fatal(err)
}
perms = fi.Mode().Perm()
if perms != 0200 {
t.Fatal("wrong restored permissions")
}
}
// TestMvWarnings:
// When xattr support was introduced, mv threw warnings like these:
// mv: preserving permissions for b/x: Operation not permitted
// because we returned EPERM when it tried to set system.posix_acl_access.
// Now we return EOPNOTSUPP and mv is happy.
func TestMvWarnings(t *testing.T) {
fn := test_helpers.TmpDir + "/TestMvWarnings"
err := ioutil.WriteFile(fn, nil, 0600)
if err != nil {
t.Fatalf("creating file failed: %v", err)
}
cmd := exec.Command("mv", fn, test_helpers.DefaultPlainDir)
out, err := cmd.CombinedOutput()
if err != nil {
t.Log(string(out))
t.Fatal(err)
}
if len(out) != 0 {
t.Fatalf("Got warnings from mv:\n%s", string(out))
}
}
// Check for this bug in symlink handling:
// $ ln -s /asd/asdasd/asdasd b/foo
// $ mv b/foo .
// mv: listing attributes of 'b/foo': No such file or directory
// strace shows:
// llistxattr("b/foo", NULL, 0) = -1 ENOENT (No such file or directory)
func TestMvWarningSymlink(t *testing.T) {
fn := test_helpers.DefaultPlainDir + "/TestMvWarningSymlink"
err := os.Symlink("/foo/bar/baz", fn)
if err != nil {
t.Fatal(err)
}
cmd := exec.Command("mv", fn, test_helpers.TmpDir)
out, err := cmd.CombinedOutput()
if err != nil {
t.Log(string(out))
if runtime.GOOS == "darwin" {
t.Skip("mv on darwin chokes on broken symlinks, see https://github.com/rfjakob/gocryptfs/issues/349")
}
t.Fatal(err)
}
if len(out) != 0 {
t.Log(strings.TrimSpace(string(out)))
t.Fatal("Got warnings")
}
}
// See TestMvWarnings.
func TestCpWarnings(t *testing.T) {
fn := test_helpers.TmpDir + "/TestCpWarnings"
err := ioutil.WriteFile(fn, []byte("foo"), 0600)
if err != nil {
t.Fatalf("creating file failed: %v", err)
}
cmd := exec.Command("cp", "-a", fn, test_helpers.DefaultPlainDir)
out, err := cmd.CombinedOutput()
if err != nil {
t.Log(string(out))
t.Fatal(err)
}
if len(out) != 0 {
t.Fatalf("Got warnings from cp -a:\n%s", string(out))
}
}
func TestSeekData(t *testing.T) {
fn := filepath.Join(test_helpers.DefaultPlainDir, t.Name())
f, err := os.Create(fn)
if err != nil {
t.Fatal(err)
}
var oneTiB int64 = 1024 * 1024 * 1024 * 1024
if _, err = f.Seek(oneTiB, 0); err != nil {
t.Fatal(err)
}
if _, err = f.Write([]byte("foo")); err != nil {
t.Fatal(err)
}
f.Close()
const SEEK_DATA = 3
f, err = os.Open(fn)
if err != nil {
t.Fatal(err)
}
off, err := f.Seek(1024*1024, SEEK_DATA)
if err != nil {
t.Fatal(err)
}
if off < oneTiB-1024*1024 {
t.Errorf("off=%d, expected=%d\n", off, oneTiB)
}
f.Close()
}