Add test suite for filesystem tests
Updates tar tests to use test suite Add hardlink tests Signed-off-by: Derek McGowan <derek@mcgstyle.net>
This commit is contained in:
parent
92af03f193
commit
c2c490c66c
@ -1,6 +1,7 @@
|
|||||||
package archive
|
package archive
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
@ -46,64 +47,7 @@ func TestBaseDiff(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDiffApply(t *testing.T) {
|
func TestDiffApply(t *testing.T) {
|
||||||
as := []fstest.Applier{
|
fstest.FSSuite(t, diffApplier{})
|
||||||
baseApplier,
|
|
||||||
fstest.Apply(
|
|
||||||
fstest.CreateFile("/etc/hosts", []byte("127.0.0.1 localhost.localdomain"), 0644),
|
|
||||||
fstest.CreateFile("/etc/fstab", []byte("/dev/sda1\t/\text4\tdefaults 1 1\n"), 0600),
|
|
||||||
fstest.CreateFile("/etc/badfile", []byte(""), 0666),
|
|
||||||
fstest.CreateFile("/home/derek/.zshrc", []byte("#ZSH is just better\n"), 0640),
|
|
||||||
),
|
|
||||||
fstest.Apply(
|
|
||||||
fstest.Remove("/etc/badfile"),
|
|
||||||
fstest.Rename("/home/derek", "/home/notderek"),
|
|
||||||
),
|
|
||||||
fstest.Apply(
|
|
||||||
fstest.RemoveAll("/usr"),
|
|
||||||
fstest.Remove("/etc/hosts.allow"),
|
|
||||||
),
|
|
||||||
fstest.Apply(
|
|
||||||
fstest.RemoveAll("/home"),
|
|
||||||
fstest.CreateDir("/home/derek", 0700),
|
|
||||||
fstest.CreateFile("/home/derek/.bashrc", []byte("#not going away\n"), 0640),
|
|
||||||
fstest.Link("/etc/hosts", "/etc/hosts.allow"),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := testDiffApply(as...); err != nil {
|
|
||||||
t.Fatalf("Test diff apply failed: %+v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestDiffApplyDeletion checks various deletion scenarios to ensure
|
|
||||||
// deletions are properly picked up and applied
|
|
||||||
func TestDiffApplyDeletion(t *testing.T) {
|
|
||||||
as := []fstest.Applier{
|
|
||||||
fstest.Apply(
|
|
||||||
fstest.CreateDir("/test/somedir", 0755),
|
|
||||||
fstest.CreateDir("/lib", 0700),
|
|
||||||
fstest.CreateFile("/lib/hidden", []byte{}, 0644),
|
|
||||||
),
|
|
||||||
fstest.Apply(
|
|
||||||
fstest.CreateFile("/test/a", []byte{}, 0644),
|
|
||||||
fstest.CreateFile("/test/b", []byte{}, 0644),
|
|
||||||
fstest.CreateDir("/test/otherdir", 0755),
|
|
||||||
fstest.CreateFile("/test/otherdir/.empty", []byte{}, 0644),
|
|
||||||
fstest.RemoveAll("/lib"),
|
|
||||||
fstest.CreateDir("/lib", 0700),
|
|
||||||
fstest.CreateFile("/lib/not-hidden", []byte{}, 0644),
|
|
||||||
),
|
|
||||||
fstest.Apply(
|
|
||||||
fstest.Remove("/test/a"),
|
|
||||||
fstest.Remove("/test/b"),
|
|
||||||
fstest.RemoveAll("/test/otherdir"),
|
|
||||||
fstest.CreateFile("/lib/newfile", []byte{}, 0644),
|
|
||||||
),
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := testDiffApply(as...); err != nil {
|
|
||||||
t.Fatalf("Test diff apply failed: %+v", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func testApply(a fstest.Applier) error {
|
func testApply(a fstest.Applier) error {
|
||||||
@ -174,48 +118,43 @@ func testBaseDiff(a fstest.Applier) error {
|
|||||||
return fstest.CheckDirectoryEqual(td, dest)
|
return fstest.CheckDirectoryEqual(td, dest)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testDiffApply(as ...fstest.Applier) error {
|
type diffApplier struct{}
|
||||||
base, err := ioutil.TempDir("", "test-diff-apply-base-")
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "failed to create temp dir")
|
|
||||||
}
|
|
||||||
defer os.RemoveAll(base)
|
|
||||||
dest, err := ioutil.TempDir("", "test-diff-apply-dest-")
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "failed to create temp dir")
|
|
||||||
}
|
|
||||||
defer os.RemoveAll(dest)
|
|
||||||
|
|
||||||
ctx := context.Background()
|
func (d diffApplier) TestContext(ctx context.Context) (context.Context, func(), error) {
|
||||||
for i, a := range as {
|
base, err := ioutil.TempDir("", "test-diff-apply-")
|
||||||
if err := diffApply(ctx, a, base, dest); err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "diff apply failed at layer %d", i)
|
return ctx, nil, errors.Wrap(err, "failed to create temp dir")
|
||||||
}
|
}
|
||||||
}
|
return context.WithValue(ctx, d, base), func() {
|
||||||
return nil
|
os.RemoveAll(base)
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// diffApply applies the given changes on the base and
|
func (d diffApplier) Apply(ctx context.Context, a fstest.Applier) (string, func(), error) {
|
||||||
// computes the diff and applies to the dest.
|
base := ctx.Value(d).(string)
|
||||||
func diffApply(ctx context.Context, a fstest.Applier, base, dest string) error {
|
|
||||||
baseCopy, err := ioutil.TempDir("", "test-diff-apply-copy-")
|
applyCopy, err := ioutil.TempDir("", "test-diffapply-apply-copy-")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "failed to create temp dir")
|
return "", nil, errors.Wrap(err, "failed to create temp dir")
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(baseCopy)
|
defer os.RemoveAll(applyCopy)
|
||||||
if err := fs.CopyDir(baseCopy, base); err != nil {
|
if err = fs.CopyDir(applyCopy, base); err != nil {
|
||||||
return errors.Wrap(err, "failed to copy base")
|
return "", nil, errors.Wrap(err, "failed to copy base")
|
||||||
|
}
|
||||||
|
if err := a.Apply(applyCopy); err != nil {
|
||||||
|
return "", nil, errors.Wrap(err, "failed to apply changes to copy of base")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := a.Apply(base); err != nil {
|
diffBytes, err := ioutil.ReadAll(Diff(ctx, base, applyCopy))
|
||||||
return errors.Wrap(err, "failed to apply changes to base")
|
if err != nil {
|
||||||
|
return "", nil, errors.Wrap(err, "failed to create diff")
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := Apply(ctx, dest, Diff(ctx, baseCopy, base)); err != nil {
|
if _, err = Apply(ctx, base, bytes.NewReader(diffBytes)); err != nil {
|
||||||
return errors.Wrap(err, "failed to apply tar stream")
|
return "", nil, errors.Wrap(err, "failed to apply tar stream")
|
||||||
}
|
}
|
||||||
|
|
||||||
return fstest.CheckDirectoryEqual(base, dest)
|
return base, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func readDirNames(p string) ([]string, error) {
|
func readDirNames(p string) ([]string, error) {
|
||||||
|
161
fs/fstest/testsuite.go
Normal file
161
fs/fstest/testsuite.go
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
package fstest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TestApplier interface {
|
||||||
|
TestContext(context.Context) (context.Context, func(), error)
|
||||||
|
Apply(context.Context, Applier) (string, func(), error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func FSSuite(t *testing.T, a TestApplier) {
|
||||||
|
t.Run("Basic", makeTest(t, a, basicTest))
|
||||||
|
t.Run("Deletion", makeTest(t, a, deletionTest))
|
||||||
|
// TODO: Add hard section, run if command line arg or function arg set to true
|
||||||
|
// Hard tests
|
||||||
|
t.Run("HardlinkUnmodified", makeTest(t, a, hardlinkUnmodified))
|
||||||
|
t.Run("HardlinkBeforeUnmodified", makeTest(t, a, hardlinkBeforeUnmodified))
|
||||||
|
t.Run("HardlinkBeforeModified", makeTest(t, a, hardlinkBeforeModified))
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeTest(t *testing.T, ta TestApplier, as []Applier) func(t *testing.T) {
|
||||||
|
return func(t *testing.T) {
|
||||||
|
ctx, cleanup, err := ta.TestContext(context.Background())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Unable to get test context: %+v", err)
|
||||||
|
}
|
||||||
|
defer cleanup()
|
||||||
|
|
||||||
|
applyDir, err := ioutil.TempDir("", "test-expected-")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Unable to make temp directory: %+v", err)
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(applyDir)
|
||||||
|
|
||||||
|
for i, a := range as {
|
||||||
|
testDir, c, err := ta.Apply(ctx, a)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Apply failed at %d: %+v", i, err)
|
||||||
|
}
|
||||||
|
if err := a.Apply(applyDir); err != nil {
|
||||||
|
if c != nil {
|
||||||
|
c()
|
||||||
|
}
|
||||||
|
t.Fatalf("Error applying change to apply directory: %+v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = CheckDirectoryEqual(applyDir, testDir)
|
||||||
|
if c != nil {
|
||||||
|
c()
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Directories not equal at %d (expected <> tested): %+v", i, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
// baseApplier creates a basic filesystem layout
|
||||||
|
// with multiple types of files for basic tests.
|
||||||
|
baseApplier = Apply(
|
||||||
|
CreateDir("/etc/", 0755),
|
||||||
|
CreateFile("/etc/hosts", []byte("127.0.0.1 localhost"), 0644),
|
||||||
|
Link("/etc/hosts", "/etc/hosts.allow"),
|
||||||
|
CreateDir("/usr/local/lib", 0755),
|
||||||
|
CreateFile("/usr/local/lib/libnothing.so", []byte{0x00, 0x00}, 0755),
|
||||||
|
Symlink("libnothing.so", "/usr/local/lib/libnothing.so.2"),
|
||||||
|
CreateDir("/home", 0755),
|
||||||
|
CreateDir("/home/derek", 0700),
|
||||||
|
)
|
||||||
|
|
||||||
|
// basicTest covers basic operations
|
||||||
|
basicTest = []Applier{
|
||||||
|
baseApplier,
|
||||||
|
Apply(
|
||||||
|
CreateFile("/etc/hosts", []byte("127.0.0.1 localhost.localdomain"), 0644),
|
||||||
|
CreateFile("/etc/fstab", []byte("/dev/sda1\t/\text4\tdefaults 1 1\n"), 0600),
|
||||||
|
CreateFile("/etc/badfile", []byte(""), 0666),
|
||||||
|
CreateFile("/home/derek/.zshrc", []byte("#ZSH is just better\n"), 0640),
|
||||||
|
),
|
||||||
|
Apply(
|
||||||
|
Remove("/etc/badfile"),
|
||||||
|
Rename("/home/derek", "/home/notderek"),
|
||||||
|
),
|
||||||
|
Apply(
|
||||||
|
RemoveAll("/usr"),
|
||||||
|
Remove("/etc/hosts.allow"),
|
||||||
|
),
|
||||||
|
Apply(
|
||||||
|
RemoveAll("/home"),
|
||||||
|
CreateDir("/home/derek", 0700),
|
||||||
|
CreateFile("/home/derek/.bashrc", []byte("#not going away\n"), 0640),
|
||||||
|
Link("/etc/hosts", "/etc/hosts.allow"),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
// deletionTest covers various deletion scenarios to ensure
|
||||||
|
// deletions are properly picked up and applied
|
||||||
|
deletionTest = []Applier{
|
||||||
|
Apply(
|
||||||
|
CreateDir("/test/somedir", 0755),
|
||||||
|
CreateDir("/lib", 0700),
|
||||||
|
CreateFile("/lib/hidden", []byte{}, 0644),
|
||||||
|
),
|
||||||
|
Apply(
|
||||||
|
CreateFile("/test/a", []byte{}, 0644),
|
||||||
|
CreateFile("/test/b", []byte{}, 0644),
|
||||||
|
CreateDir("/test/otherdir", 0755),
|
||||||
|
CreateFile("/test/otherdir/.empty", []byte{}, 0644),
|
||||||
|
RemoveAll("/lib"),
|
||||||
|
CreateDir("/lib", 0700),
|
||||||
|
CreateFile("/lib/not-hidden", []byte{}, 0644),
|
||||||
|
),
|
||||||
|
Apply(
|
||||||
|
Remove("/test/a"),
|
||||||
|
Remove("/test/b"),
|
||||||
|
RemoveAll("/test/otherdir"),
|
||||||
|
CreateFile("/lib/newfile", []byte{}, 0644),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
hardlinkUnmodified = []Applier{
|
||||||
|
baseApplier,
|
||||||
|
Apply(
|
||||||
|
CreateFile("/etc/hosts", []byte("127.0.0.1 localhost.localdomain"), 0644),
|
||||||
|
),
|
||||||
|
Apply(
|
||||||
|
Link("/etc/hosts", "/etc/hosts.deny"),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hardlink name before with modification
|
||||||
|
// Tests link is created for unmodified files when new hardlinked file is seen first
|
||||||
|
hardlinkBeforeUnmodified = []Applier{
|
||||||
|
baseApplier,
|
||||||
|
Apply(
|
||||||
|
CreateFile("/etc/hosts", []byte("127.0.0.1 localhost.localdomain"), 0644),
|
||||||
|
),
|
||||||
|
Apply(
|
||||||
|
Link("/etc/hosts", "/etc/before-hosts"),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hardlink name after without modification
|
||||||
|
// tests link is created for modified file with new hardlink
|
||||||
|
hardlinkBeforeModified = []Applier{
|
||||||
|
baseApplier,
|
||||||
|
Apply(
|
||||||
|
CreateFile("/etc/hosts", []byte("127.0.0.1 localhost.localdomain"), 0644),
|
||||||
|
),
|
||||||
|
Apply(
|
||||||
|
Remove("/etc/hosts"),
|
||||||
|
CreateFile("/etc/hosts", []byte("127.0.0.1 localhost"), 0644),
|
||||||
|
Link("/etc/hosts", "/etc/before-hosts"),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)
|
Loading…
Reference in New Issue
Block a user