2016-03-23 20:58:16 +00:00
|
|
|
package mtree
|
|
|
|
|
2016-04-12 20:49:52 +00:00
|
|
|
import (
|
2016-06-27 17:17:03 +00:00
|
|
|
"bytes"
|
2016-04-12 20:49:52 +00:00
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
)
|
2016-03-23 20:58:16 +00:00
|
|
|
|
2016-04-12 20:49:52 +00:00
|
|
|
// simple walk of current directory, and imediately check it.
|
|
|
|
// may not be parallelizable.
|
2016-03-23 20:58:16 +00:00
|
|
|
func TestCheck(t *testing.T) {
|
|
|
|
dh, err := Walk(".", nil, append(DefaultKeywords, "sha1"))
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2016-04-12 20:49:52 +00:00
|
|
|
res, err := Check(".", dh, nil)
|
2016-03-23 20:58:16 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2016-04-05 22:13:27 +00:00
|
|
|
|
2016-10-31 10:42:53 +00:00
|
|
|
if len(res) > 0 {
|
2016-04-05 22:13:27 +00:00
|
|
|
t.Errorf("%#v", res)
|
|
|
|
}
|
2016-03-23 20:58:16 +00:00
|
|
|
}
|
2016-04-05 22:13:27 +00:00
|
|
|
|
2016-04-12 20:49:52 +00:00
|
|
|
// 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, err := ioutil.TempDir("", "test-check-keywords")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2016-08-17 14:25:15 +00:00
|
|
|
defer os.RemoveAll(dir) // clean up
|
2016-04-12 20:49:52 +00:00
|
|
|
|
|
|
|
tmpfn := filepath.Join(dir, "tmpfile")
|
|
|
|
if err := ioutil.WriteFile(tmpfn, content, 0666); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Walk this tempdir
|
|
|
|
dh, err := Walk(dir, nil, append(DefaultKeywords, "sha1"))
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check for sanity. This ought to pass.
|
|
|
|
res, err := Check(dir, dh, nil)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2016-10-31 10:42:53 +00:00
|
|
|
if len(res) > 0 {
|
2016-04-12 20:49:52 +00:00
|
|
|
t.Errorf("%#v", res)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Touch a file, so the mtime changes.
|
|
|
|
now := time.Now()
|
|
|
|
if err := os.Chtimes(tmpfn, now, now); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check again. This ought to fail.
|
|
|
|
res, err = Check(dir, dh, nil)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2016-10-31 10:42:53 +00:00
|
|
|
if len(res) != 1 {
|
|
|
|
t.Errorf("expected to get 1 delta on changed mtimes, but did not")
|
|
|
|
}
|
|
|
|
if res[0].Type() != Modified {
|
|
|
|
t.Errorf("expected to get modified delta on changed mtimes, but did not")
|
2016-04-12 20:49:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Check again, but only sha1 and mode. This ought to pass.
|
|
|
|
res, err = Check(dir, dh, []string{"sha1", "mode"})
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2016-10-31 10:42:53 +00:00
|
|
|
if len(res) > 0 {
|
2016-04-12 20:49:52 +00:00
|
|
|
t.Errorf("%#v", res)
|
|
|
|
}
|
|
|
|
}
|
2016-04-13 20:04:48 +00:00
|
|
|
|
|
|
|
func ExampleCheck() {
|
|
|
|
dh, err := Walk(".", nil, append(DefaultKeywords, "sha1"))
|
|
|
|
if err != nil {
|
|
|
|
// handle error ...
|
|
|
|
}
|
|
|
|
|
|
|
|
res, err := Check(".", dh, nil)
|
|
|
|
if err != nil {
|
|
|
|
// handle error ...
|
|
|
|
}
|
2016-10-31 10:42:53 +00:00
|
|
|
if len(res) > 0 {
|
2016-04-13 20:04:48 +00:00
|
|
|
// handle failed validity ...
|
|
|
|
}
|
|
|
|
}
|
2016-06-27 17:17:03 +00:00
|
|
|
|
2016-07-26 13:02:30 +00:00
|
|
|
// Tests default action for evaluating a symlink, which is just to compare the
|
|
|
|
// link itself, not to follow it
|
|
|
|
func TestDefaultBrokenLink(t *testing.T) {
|
|
|
|
dh, err := Walk("./testdata/dirwithbrokenlink", nil, append(DefaultKeywords, "sha1"))
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
res, err := Check("./testdata/dirwithbrokenlink", dh, nil)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2016-10-31 10:42:53 +00:00
|
|
|
if len(res) > 0 {
|
|
|
|
for _, delta := range res {
|
|
|
|
t.Error(delta)
|
2016-07-26 13:02:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-27 17:17:03 +00:00
|
|
|
// https://github.com/vbatts/go-mtree/issues/8
|
|
|
|
func TestTimeComparison(t *testing.T) {
|
|
|
|
dir, err := ioutil.TempDir("", "test-time.")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
defer os.RemoveAll(dir)
|
|
|
|
|
|
|
|
// This is the format of time from FreeBSD
|
|
|
|
spec := `
|
2016-06-27 17:24:03 +00:00
|
|
|
/set type=file time=5.000000000
|
2016-07-15 15:48:40 +00:00
|
|
|
. type=dir
|
2016-06-27 17:24:03 +00:00
|
|
|
file time=5.000000000
|
2016-06-27 17:17:03 +00:00
|
|
|
..
|
|
|
|
`
|
|
|
|
|
|
|
|
fh, err := os.Create(filepath.Join(dir, "file"))
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
// This is what mode we're checking for. Round integer of epoch seconds
|
2016-06-27 17:24:03 +00:00
|
|
|
epoch := time.Unix(5, 0)
|
2016-06-27 17:17:03 +00:00
|
|
|
if err := os.Chtimes(fh.Name(), epoch, epoch); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2016-07-15 12:58:26 +00:00
|
|
|
if err := os.Chtimes(dir, epoch, epoch); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2016-06-27 17:17:03 +00:00
|
|
|
if err := fh.Close(); err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
dh, err := ParseSpec(bytes.NewBufferString(spec))
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
res, err := Check(dir, dh, nil)
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
2016-10-31 10:42:53 +00:00
|
|
|
if len(res) > 0 {
|
|
|
|
t.Fatal(res)
|
2016-06-27 17:17:03 +00:00
|
|
|
}
|
|
|
|
}
|
2016-07-15 15:48:40 +00:00
|
|
|
|
2016-07-22 22:01:54 +00:00
|
|
|
func TestTarTime(t *testing.T) {
|
|
|
|
dir, err := ioutil.TempDir("", "test-tar-time.")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
defer os.RemoveAll(dir)
|
|
|
|
|
|
|
|
// 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"))
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
// This is what mode we're checking for. Round integer of epoch seconds
|
|
|
|
epoch := time.Unix(5, 0)
|
|
|
|
if err := os.Chtimes(fh.Name(), epoch, epoch); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if err := os.Chtimes(dir, epoch, epoch); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if err := fh.Close(); err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
dh, err := ParseSpec(bytes.NewBufferString(spec))
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2016-11-16 19:43:05 +00:00
|
|
|
keywords := dh.UsedKeywords()
|
2016-10-31 10:42:53 +00:00
|
|
|
|
2016-07-22 22:01:54 +00:00
|
|
|
// make sure "time" keyword works
|
2016-10-31 10:42:53 +00:00
|
|
|
_, err = Check(dir, dh, keywords)
|
2016-07-22 22:01:54 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// make sure tar_time wins
|
2016-10-31 10:42:53 +00:00
|
|
|
res, err := Check(dir, dh, append(keywords, "tar_time"))
|
2016-07-22 22:01:54 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
2016-10-31 10:42:53 +00:00
|
|
|
if len(res) > 0 {
|
|
|
|
t.Fatal(res)
|
2016-07-22 22:01:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-15 15:48:40 +00:00
|
|
|
func TestIgnoreComments(t *testing.T) {
|
|
|
|
dir, err := ioutil.TempDir("", "test-comments.")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
defer os.RemoveAll(dir)
|
|
|
|
|
|
|
|
// 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"))
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
// This is what mode we're checking for. Round integer of epoch seconds
|
|
|
|
epoch := time.Unix(5, 0)
|
|
|
|
if err := os.Chtimes(fh.Name(), epoch, epoch); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if err := os.Chtimes(dir, epoch, epoch); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if err := fh.Close(); err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
dh, err := ParseSpec(bytes.NewBufferString(spec))
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
res, err := Check(dir, dh, nil)
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
2016-10-31 10:42:53 +00:00
|
|
|
if len(res) > 0 {
|
|
|
|
t.Fatal(res)
|
2016-07-15 15:48:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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))
|
|
|
|
|
|
|
|
res, err = Check(dir, dh, nil)
|
|
|
|
if err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
2016-10-31 10:42:53 +00:00
|
|
|
if len(res) > 0 {
|
|
|
|
t.Fatal(res)
|
2016-07-15 15:48:40 +00:00
|
|
|
}
|
|
|
|
}
|
2016-07-21 01:18:27 +00:00
|
|
|
|
|
|
|
func TestCheckNeedsEncoding(t *testing.T) {
|
|
|
|
dir, err := ioutil.TempDir("", "test-needs-encoding")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
defer os.RemoveAll(dir)
|
|
|
|
|
|
|
|
fh, err := os.Create(filepath.Join(dir, "file[ "))
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if err := fh.Close(); err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
fh, err = os.Create(filepath.Join(dir, " , should work"))
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if err := fh.Close(); err != nil {
|
|
|
|
t.Error(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
dh, err := Walk(dir, nil, DefaultKeywords)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
res, err := Check(dir, dh, nil)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2016-10-31 10:42:53 +00:00
|
|
|
if len(res) > 0 {
|
|
|
|
t.Fatal(res)
|
2016-07-21 01:18:27 +00:00
|
|
|
}
|
|
|
|
}
|