mirror of
https://github.com/vbatts/go-mtree.git
synced 2025-10-04 04:31:00 +00:00
testify makes most bog-standard test checks much easier to read and maintain, and is quite widely used. It wasn't really well known back when go-mtree was first written, but the migration is fairly straight-forward for most tests. Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
245 lines
7 KiB
Go
245 lines
7 KiB
Go
package mtree
|
|
|
|
import (
|
|
"bytes"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// simple walk of current directory, and immediately check it.
|
|
// may not be parallelizable.
|
|
func TestCheck(t *testing.T) {
|
|
dh, err := Walk(".", nil, append(DefaultKeywords, []Keyword{"sha1", "xattr"}...), nil)
|
|
require.NoError(t, err, "walk .")
|
|
|
|
res, err := Check(".", dh, nil, nil)
|
|
require.NoError(t, err, "check .")
|
|
|
|
if !assert.Empty(t, res, "check after no changes should have no diff") {
|
|
pprintInodeDeltas(t, res)
|
|
}
|
|
}
|
|
|
|
// make a directory, walk it, check it, modify the timestamp and ensure it fails.
|
|
// only check again for size and sha1, and ignore time, and ensure it passes
|
|
func TestCheckKeywords(t *testing.T) {
|
|
content := []byte("I know half of you half as well as I ought to")
|
|
dir := t.TempDir()
|
|
|
|
tmpfn := filepath.Join(dir, "tmpfile")
|
|
require.NoError(t, os.WriteFile(tmpfn, content, 0666))
|
|
|
|
// Walk this tempdir
|
|
dh, err := Walk(dir, nil, append(DefaultKeywords, "sha1"), nil)
|
|
require.NoErrorf(t, err, "walk %s", dir)
|
|
|
|
// Check for sanity. This ought to pass.
|
|
res, err := Check(dir, dh, nil, nil)
|
|
require.NoErrorf(t, err, "check %s", dir)
|
|
if !assert.Empty(t, res, "check after no changes should have no diff") {
|
|
pprintInodeDeltas(t, res)
|
|
}
|
|
|
|
// Touch a file, so the mtime changes.
|
|
newtime := time.Date(2006, time.February, 1, 3, 4, 5, 0, time.UTC)
|
|
require.NoError(t, os.Chtimes(tmpfn, newtime, newtime))
|
|
|
|
// Check again. This ought to fail.
|
|
res, err = Check(dir, dh, nil, nil)
|
|
require.NoErrorf(t, err, "check %s", dir)
|
|
|
|
if assert.NotEmpty(t, res, "should get a delta after mtime change") {
|
|
assert.Len(t, res, 1, "should only be one changed file entry")
|
|
diff := res[0]
|
|
assert.Equal(t, Modified, diff.Type(), "expected to get modified entry")
|
|
kds := diff.Diff()
|
|
if assert.Len(t, kds, 1, "should have one key different after mtime change") {
|
|
kd := kds[0]
|
|
assert.Equal(t, Modified, kd.Type(), "after mtime change key delta type should be modified")
|
|
assert.Equal(t, Keyword("time"), kd.Name(), "after mtime change key delta should be 'time'")
|
|
assert.NotNil(t, kd.Old(), "after mtime change key delta Old")
|
|
assert.NotNil(t, kd.New(), "after mtime change key delta New")
|
|
}
|
|
}
|
|
|
|
// Check again, but only sha1 and mode. This ought to pass.
|
|
res, err = Check(dir, dh, []Keyword{"sha1", "mode"}, nil)
|
|
require.NoErrorf(t, err, "check .", err)
|
|
if !assert.Empty(t, res, "check (~time) should have no diff") {
|
|
pprintInodeDeltas(t, res)
|
|
}
|
|
}
|
|
|
|
func ExampleCheck() {
|
|
dh, err := Walk(".", nil, append(DefaultKeywords, "sha1"), nil)
|
|
if err != nil {
|
|
// handle error ...
|
|
}
|
|
|
|
res, err := Check(".", dh, nil, nil)
|
|
if err != nil {
|
|
// handle error ...
|
|
}
|
|
if len(res) > 0 {
|
|
// handle failed validity ...
|
|
}
|
|
}
|
|
|
|
// Tests default action for evaluating a symlink, which is just to compare the
|
|
// link itself, not to follow it
|
|
func TestDefaultBrokenLink(t *testing.T) {
|
|
dir := "./testdata/dirwithbrokenlink"
|
|
|
|
dh, err := Walk(dir, nil, append(DefaultKeywords, "sha1"), nil)
|
|
require.NoErrorf(t, err, "walk %s", dir)
|
|
|
|
res, err := Check(dir, dh, nil, nil)
|
|
require.NoErrorf(t, err, "check %s", dir)
|
|
|
|
if !assert.Empty(t, res, "check after no changes should have no diff") {
|
|
pprintInodeDeltas(t, res)
|
|
}
|
|
}
|
|
|
|
// https://github.com/vbatts/go-mtree/issues/8
|
|
func TestTimeComparison(t *testing.T) {
|
|
dir := t.TempDir()
|
|
|
|
// This is the format of time from FreeBSD
|
|
spec := `
|
|
/set type=file time=5.000000000
|
|
. type=dir
|
|
file time=5.000000000
|
|
..
|
|
`
|
|
|
|
fh, err := os.Create(filepath.Join(dir, "file"))
|
|
require.NoError(t, err)
|
|
|
|
// This is what mode we're checking for. Round integer of epoch seconds
|
|
epoch := time.Unix(5, 0)
|
|
require.NoError(t, os.Chtimes(fh.Name(), epoch, epoch))
|
|
require.NoError(t, os.Chtimes(dir, epoch, epoch))
|
|
require.NoError(t, fh.Close())
|
|
|
|
dh, err := ParseSpec(bytes.NewBufferString(spec))
|
|
require.NoError(t, err, "parse specfile")
|
|
|
|
res, err := Check(dir, dh, nil, nil)
|
|
require.NoErrorf(t, err, "check %s against spec", dir)
|
|
if !assert.Empty(t, res) {
|
|
pprintInodeDeltas(t, res)
|
|
}
|
|
}
|
|
|
|
func TestTarTime(t *testing.T) {
|
|
dir := t.TempDir()
|
|
|
|
// This is the format of time from FreeBSD
|
|
spec := `
|
|
/set type=file time=5.454353132
|
|
. type=dir time=5.123456789
|
|
file time=5.911134111
|
|
..
|
|
`
|
|
|
|
fh, err := os.Create(filepath.Join(dir, "file"))
|
|
require.NoError(t, err)
|
|
|
|
// This is what mode we're checking for. Round integer of epoch seconds
|
|
epoch := time.Unix(5, 0)
|
|
require.NoError(t, os.Chtimes(fh.Name(), epoch, epoch))
|
|
require.NoError(t, os.Chtimes(dir, epoch, epoch))
|
|
require.NoError(t, fh.Close())
|
|
|
|
dh, err := ParseSpec(bytes.NewBufferString(spec))
|
|
require.NoError(t, err, "parse specfile")
|
|
|
|
keywords := dh.UsedKeywords()
|
|
assert.ElementsMatch(t, keywords, []Keyword{"type", "time"}, "UsedKeywords")
|
|
|
|
// make sure "time" keyword works
|
|
res1, err := Check(dir, dh, keywords, nil)
|
|
require.NoErrorf(t, err, "check %s (UsedKeywords)", dir)
|
|
assert.NotEmpty(t, res1, "check should have errors when time mismatched")
|
|
|
|
// make sure tar_time wins
|
|
res2, err := Check(dir, dh, append(keywords, "tar_time"), nil)
|
|
require.NoErrorf(t, err, "check %s (UsedKeywords + tar_time)", dir)
|
|
if !assert.Empty(t, res2, "tar_time should check against truncated timestamp") {
|
|
pprintInodeDeltas(t, res2)
|
|
}
|
|
}
|
|
|
|
func TestIgnoreComments(t *testing.T) {
|
|
dir := t.TempDir()
|
|
|
|
// This is the format of time from FreeBSD
|
|
spec := `
|
|
/set type=file time=5.000000000
|
|
. type=dir
|
|
file1 time=5.000000000
|
|
..
|
|
`
|
|
|
|
fh, err := os.Create(filepath.Join(dir, "file1"))
|
|
require.NoError(t, err)
|
|
// This is what mode we're checking for. Round integer of epoch seconds
|
|
epoch := time.Unix(5, 0)
|
|
require.NoError(t, os.Chtimes(fh.Name(), epoch, epoch))
|
|
require.NoError(t, os.Chtimes(dir, epoch, epoch))
|
|
require.NoError(t, fh.Close())
|
|
|
|
dh, err := ParseSpec(bytes.NewBufferString(spec))
|
|
require.NoError(t, err, "parse specfile")
|
|
|
|
res, err := Check(dir, dh, nil, nil)
|
|
require.NoErrorf(t, err, "check %s", dir)
|
|
if !assert.Empty(t, res) {
|
|
pprintInodeDeltas(t, res)
|
|
}
|
|
|
|
// now change the spec to a comment that looks like an actual Entry but has
|
|
// whitespace in front of it
|
|
spec = `
|
|
/set type=file time=5.000000000
|
|
. type=dir
|
|
file1 time=5.000000000
|
|
#file2 time=5.000000000
|
|
..
|
|
`
|
|
dh, err = ParseSpec(bytes.NewBufferString(spec))
|
|
require.NoError(t, err, "parse specfile")
|
|
|
|
res, err = Check(dir, dh, nil, nil)
|
|
require.NoErrorf(t, err, "check %s", dir)
|
|
if !assert.Empty(t, res) {
|
|
pprintInodeDeltas(t, res)
|
|
}
|
|
}
|
|
|
|
func TestCheckNeedsEncoding(t *testing.T) {
|
|
dir := t.TempDir()
|
|
|
|
fh, err := os.Create(filepath.Join(dir, "file[ "))
|
|
require.NoError(t, err)
|
|
require.NoError(t, fh.Close())
|
|
|
|
fh, err = os.Create(filepath.Join(dir, " , should work"))
|
|
require.NoError(t, err)
|
|
require.NoError(t, fh.Close())
|
|
|
|
dh, err := Walk(dir, nil, DefaultKeywords, nil)
|
|
require.NoErrorf(t, err, "walk %s", dir)
|
|
|
|
res, err := Check(dir, dh, nil, nil)
|
|
require.NoErrorf(t, err, "check %s", dir)
|
|
if !assert.Empty(t, res) {
|
|
pprintInodeDeltas(t, res)
|
|
}
|
|
}
|