blob: 6a4159f862119ac7180e7108614244c34face188 [file] [log] [blame]
package main
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"reflect"
"syscall"
"testing"
)
const attr = "user.gitsha1"
const checksum = "3f75526aa8f01eea5d76cee10722195dc73676de"
func createFSTree(names []string) (string, error) {
dir, err := ioutil.TempDir("", "")
if err != nil {
return dir, err
}
for _, f := range names {
p := filepath.Join(dir, f)
if err := os.MkdirAll(filepath.Dir(p), 0755); err != nil {
return dir, err
}
if err := ioutil.WriteFile(p, []byte{42}, 0644); err != nil {
return dir, err
}
if err := syscall.Setxattr(p, attr, []byte(checksum), 0); err != nil {
return dir, fmt.Errorf("Setxattr: %v", err)
}
}
return dir, nil
}
func TestConstruct(t *testing.T) {
dir, err := createFSTree([]string{
"toplevel",
"build/core/.git/HEAD",
"build/core/subdir/core.h",
"build/core/song/.git/HEAD",
"build/core/song/song.mp3",
"build/core/top",
"build/subfile",
})
if err != nil {
t.Fatal(err)
}
parent := newRepoTree(dir)
construct(dir, "", parent)
songT := &repoTree{
children: map[string]*repoTree{},
entries: []string{"song.mp3"},
}
coreT := &repoTree{
children: map[string]*repoTree{"song": songT},
entries: []string{"subdir/core.h",
"top",
},
}
topT := &repoTree{
children: map[string]*repoTree{
"build/core": coreT,
},
entries: []string{
"build/subfile",
"toplevel",
},
}
if !reflect.DeepEqual(topT, parent) {
t.Errorf("got %#v want %#v", parent, topT)
}
all := topT.allChildren()
want := map[string]*repoTree{
"": topT,
"build/core": coreT,
"build/core/song": songT,
}
if !reflect.DeepEqual(all, want) {
t.Errorf("got %#v want %#v", all, want)
}
}
func TestPopulate(t *testing.T) {
dir, err := createFSTree([]string{
"ro/toplevel",
"ro/build/core/.gitid",
"ro/build/core/subdir/core.h",
"ro/build/core/song/.gitid",
"ro/build/core/song/song.mp3",
"ro/build/core/top",
"ro/build/subfile",
"ro/platform/art/.gitid",
"ro/platform/art/art.c",
"ro/platform/art/art.h",
"ro/platform/art/painting/.gitid",
"ro/platform/art/painting/picasso.c",
"rw/build/core/.git/head",
"rw/build/core/newdir/bla",
})
if err != nil {
t.Fatal("createFSTree:", err)
}
if err := os.Symlink(filepath.Join(dir, "ro/obsolete"), filepath.Join(dir, "rw/obsolete")); err != nil {
t.Errorf("Symlink: %v", err)
}
if err := populateCheckout(filepath.Join(dir, "ro"), filepath.Join(dir, "rw")); err != nil {
t.Errorf("populateCheckout: %v", err)
}
for _, f := range []string{
"build/core/newdir/bla",
"build/core/song/song.mp3",
"platform/art/art.c",
"platform/art/art.h",
"platform/art/painting/picasso.c",
} {
fn := filepath.Join(dir, "rw", f)
fi, err := os.Stat(fn)
if err != nil || fi.Size() != 1 {
t.Errorf("Stat(%s): %v, %v", fn, fi, err)
}
}
// The following files are in repo that has a r/w checkout, so
// they should not appear in the populated tree.
for _, f := range []string{
"ro/build/core/subdir/core.h",
"ro/build/core/top",
} {
fn := filepath.Join(dir, "rw", f)
_, err := os.Stat(fn)
if err == nil {
t.Errorf("file %s exists", fn)
}
}
if fi, err := os.Lstat(filepath.Join(dir, "rw/obsolete")); err == nil {
t.Fatalf("obsolete symlink still there: %v", fi)
}
}
func TestChangedFiles(t *testing.T) {
dir, err := createFSTree([]string{
"r1/manifest.xml",
"r1/a",
"r1/b",
"r2/manifest.xml",
"r2/a",
"r2/b",
"r2/c",
})
if err != nil {
t.Fatalf("createFSTree: %v", err)
}
ck2 := "3f75526aa8f01eea5d76cee10722195dc73676df"
for _, changed := range []string{"r2/b", "r2/manifest.xml"} {
if err := syscall.Setxattr(filepath.Join(dir, changed), attr, []byte(ck2), 0); err != nil {
t.Fatalf("Setxattr: %v", err)
}
}
got, err := changedFiles(filepath.Join(dir, "r1"), filepath.Join(dir, "r2"))
if err != nil {
t.Fatalf("changedFiles: %v", err)
}
if want := []string{"b", "c"}; !reflect.DeepEqual(want, got) {
t.Errorf("got %v, want %v", got, want)
}
}