//go:build linux package provisioner import ( "bytes" "os" "os/exec" "path/filepath" "testing" ) func persistentDirectory(t *testing.T) string { t.Helper() // The native backend deliberately rejects /tmp when it is tmpfs. Exercise // durable operations on this checkout's persistent filesystem instead. path, err := os.MkdirTemp(".", ".provisioner-test-") if err != nil { t.Fatal(err) } path, err = filepath.Abs(path) if err != nil { t.Fatal(err) } t.Cleanup(func() { os.RemoveAll(path) }) if err = os.Chmod(path, 0700); err != nil { t.Fatal(err) } return path } func TestNativeStorageExclusiveDurableRecords(t *testing.T) { path := persistentDirectory(t) d, err := openPrivateDirectory(path) if err != nil { t.Fatal("native filesystem required", err) } body := []byte("synthetic signed record") if err = d.create("00000001", body); err != nil { t.Fatal(err) } if err = d.create("00000001", []byte("replacement")); err != ErrRefused { t.Fatal("immutable record replaced", err) } d.close() d, err = openPrivateDirectory(path) if err != nil { t.Fatal(err) } defer d.close() got, err := d.read("00000001", 128) if err != nil || !bytes.Equal(got, body) { t.Fatal("durable reopen", err) } if _, err = d.read("00000001", 2); err != ErrRefused { t.Fatal("unbounded read", err) } if err = os.Link(filepath.Join(path, "00000001"), filepath.Join(path, "alias")); err != nil { t.Fatal(err) } if _, err = d.read("00000001", 128); err != ErrRefused { t.Fatal("hardlink accepted", err) } } func TestNativeStorageRefusesSymlinksAndPermissions(t *testing.T) { path := persistentDirectory(t) real := filepath.Join(path, "real") if err := os.Mkdir(real, 0700); err != nil { t.Fatal(err) } alias := filepath.Join(path, "alias") if err := os.Symlink(real, alias); err != nil { t.Fatal(err) } if _, err := openPrivateDirectory(alias); err != ErrRefused { t.Fatal("symlink directory", err) } if err := os.Mkdir(filepath.Join(real, "nested"), 0700); err != nil { t.Fatal(err) } if _, err := openPrivateDirectory(filepath.Join(alias, "nested")); err != ErrRefused { t.Fatal("symlink ancestor", err) } d, err := openPrivateDirectory(real) if err != nil { t.Fatal(err) } defer d.close() if err = os.Symlink("target", filepath.Join(real, "record")); err != nil { t.Fatal(err) } if err = d.create("record", []byte("x")); err != ErrRefused { t.Fatal("followed record symlink", err) } if _, err = d.read("record", 128); err != ErrRefused { t.Fatal("read record symlink", err) } if err = os.Chmod(real, 0755); err != nil { t.Fatal(err) } if _, err = openPrivateDirectory(real); err != ErrRefused { t.Fatal("public directory", err) } } func TestNativeStorageProcessLock(t *testing.T) { if path := os.Getenv("OFICINA_TEST_LOCK_PATH"); path != "" { d, err := openPrivateDirectory(path) if err != nil { t.Fatal(err) } defer d.close() lock, err := d.lock() if lock != nil { lock.Close() } if err != ErrRefused { t.Fatal("second process acquired lock", err) } return } path := persistentDirectory(t) d, err := openPrivateDirectory(path) if err != nil { t.Fatal(err) } defer d.close() lock, err := d.lock() if err != nil { t.Fatal(err) } cmd := exec.Command(os.Args[0], "-test.run=^TestNativeStorageProcessLock$") cmd.Env = append(os.Environ(), "OFICINA_TEST_LOCK_PATH="+path) if output, err := cmd.CombinedOutput(); err != nil { t.Fatalf("child: %s: %v", output, err) } lock.Close() lock, err = d.lock() if err != nil { t.Fatal("lock did not release", err) } lock.Close() }