blob: aea92d910726abfed5fdad19a318d06ca2e4141b [file] [log] [blame]
package build
import (
"reflect"
"sort"
"testing"
)
// snapshotBuilder allows test cases to hand generate Snapshot structures
type snapshotBuilder struct {
snapshot Snapshot
currentBlobID MerkleRoot
}
type fileRef = PackageFileRef
func newSnapshotBuilder() *snapshotBuilder {
return &snapshotBuilder{
snapshot: Snapshot{
Packages: map[string]Package{},
Blobs: map[MerkleRoot]BlobInfo{},
},
}
}
func (b *snapshotBuilder) ensurePackage(name string) {
if _, ok := b.snapshot.Packages[name]; !ok {
b.snapshot.Packages[name] = Package{
Files: map[string]MerkleRoot{},
}
}
}
// IncrementMerkleRootEpoch moves to the start of the next block of merkle roots
func (b *snapshotBuilder) IncrementMerkleRootEpoch() *snapshotBuilder {
b.currentBlobID[0]++
b.currentBlobID[1] = 0
return b
}
// IncrementMerkleRoot moves to the next sequential merkle root
func (b *snapshotBuilder) IncrementMerkleRoot() *snapshotBuilder {
b.currentBlobID[1]++
return b
}
// Package declares a new package with the given tags
func (b *snapshotBuilder) Package(pkg string, tags ...string) *snapshotBuilder {
if _, ok := b.snapshot.Packages[pkg]; ok {
panic("Package already defined")
}
b.snapshot.Packages[pkg] = Package{
Files: map[string]MerkleRoot{},
Tags: tags,
}
return b
}
// File defines a new file with the given size, included at the given locations
func (b *snapshotBuilder) File(size uint64, refs ...fileRef) *snapshotBuilder {
if len(refs) == 0 {
panic("File called without any file refs")
}
b.IncrementMerkleRoot()
b.snapshot.Blobs[b.currentBlobID] = BlobInfo{Size: size}
for _, ref := range refs {
b.ensurePackage(ref.Name)
b.snapshot.Packages[ref.Name].Files[ref.Path] = b.currentBlobID
}
return b
}
// Build finalizes and returns the Snapshot
func (b *snapshotBuilder) Build() Snapshot {
if err := b.snapshot.Verify(); err != nil {
panic(err)
}
return b.snapshot
}
func makeTestSnapshot() Snapshot {
return newSnapshotBuilder().
Package("system/0", "monolith").
Package("foo/0", "monolith").
Package("bar/0", "monolith").
Package("foobar/0", "monolith").
Package("optional/0", "available").
File(1024, fileRef{"system/0", "a"}).
File(1024, fileRef{"system/0", "b"}).
File(1024, fileRef{"system/0", "c"}).
File(1024, fileRef{"system/0", "d"}).
File(1024, fileRef{"system/0", "e"}).
File(1024, fileRef{"system/0", "f"}).
File(1024, fileRef{"system/0", "meta/"}).
File(1024, fileRef{"foo/0", "bin/app"}).
File(1024, fileRef{"foo/0", "fileA"}).
File(1024, fileRef{"foo/0", "meta/"}).
File(1024, fileRef{"bar/0", "bin/app"}).
File(1024, fileRef{"bar/0", "fileB"}).
File(1024, fileRef{"bar/0", "meta/"}).
File(1024, fileRef{"foobar/0", "bin/app"}).
File(1024, fileRef{"foobar/0", "meta/"}).
File(1024, fileRef{"optional/0", "bin/app"}).
File(1024, fileRef{"optional/0", "meta/"}).
File(1024,
fileRef{"foo/0", "lib/ld.so.1"},
fileRef{"bar/0", "lib/ld.so.1"},
fileRef{"foobar/0", "lib/ld.so.1"},
fileRef{"optional/0", "lib/ld.so.1"},
).
File(1024,
fileRef{"foo/0", "lib/libfdio.so"},
fileRef{"bar/0", "lib/libfdio.so"},
fileRef{"foobar/0", "lib/libfdio.so"},
fileRef{"optional/0", "lib/libfdio.so"},
).
Build()
}
func verifyFilteredSnapshot(t *testing.T, original Snapshot, filtered Snapshot, expected []string) {
// Ensure the correct blobs are present
if err := filtered.Verify(); err != nil {
t.Errorf("filter produced inconsistent snapshot: %v", err)
}
// Package entries should not change
actual := []string{}
for name, pkg := range filtered.Packages {
actual = append(actual, name)
if !reflect.DeepEqual(pkg, original.Packages[name]) {
t.Errorf("filter modified a package entry")
}
}
// Only the expected packages should be there
sort.Strings(actual)
sort.Strings(expected)
if !reflect.DeepEqual(actual, expected) {
t.Errorf("expected %v, got %v", expected, actual)
}
}
func TestSnapshotFilter_includeAll(t *testing.T) {
original := makeTestSnapshot()
filtered := original.Filter([]string{"*"}, []string{})
if !reflect.DeepEqual(original, filtered) {
t.Errorf("identity filter did not produce an equivalent Snapshot")
}
}
func TestSnapshotFilter_includeNone(t *testing.T) {
original := makeTestSnapshot()
filtered := original.Filter([]string{}, []string{})
verifyFilteredSnapshot(t, original, filtered, []string{})
}
func TestSnapshotFilter_includeSingleTag(t *testing.T) {
original := makeTestSnapshot()
filtered := original.Filter([]string{"monolith"}, []string{})
verifyFilteredSnapshot(t, original, filtered, []string{"system/0", "foo/0", "bar/0", "foobar/0"})
filtered = original.Filter([]string{"available"}, []string{})
verifyFilteredSnapshot(t, original, filtered, []string{"optional/0"})
}
func TestSnapshotFilter_matchSingleTag(t *testing.T) {
original := makeTestSnapshot()
filtered := original.Filter([]string{"monolith"}, []string{})
verifyFilteredSnapshot(t, original, filtered, []string{"system/0", "foo/0", "bar/0", "foobar/0"})
}
func TestSnapshotFilter_excludeSingleTag(t *testing.T) {
original := makeTestSnapshot()
filtered := original.Filter([]string{"*"}, []string{"available"})
verifyFilteredSnapshot(t, original, filtered, []string{"system/0", "foo/0", "bar/0", "foobar/0"})
}
func TestSnapshotFilter_excludeSinglePackage(t *testing.T) {
original := makeTestSnapshot()
filtered := original.Filter([]string{"*"}, []string{"bar/0"})
verifyFilteredSnapshot(t, original, filtered, []string{"system/0", "foo/0", "optional/0", "foobar/0"})
filtered = original.Filter([]string{"*"}, []string{"bar/*"})
verifyFilteredSnapshot(t, original, filtered, []string{"system/0", "foo/0", "optional/0", "foobar/0"})
}
func TestSnapshotFilter_includeMultiplePackage(t *testing.T) {
original := makeTestSnapshot()
filtered := original.Filter([]string{"foo/0", "optional/0"}, []string{})
verifyFilteredSnapshot(t, original, filtered, []string{"foo/0", "optional/0"})
}
func TestSnapshotFilter_excludeMultiplePackage(t *testing.T) {
original := makeTestSnapshot()
filtered := original.Filter([]string{"*"}, []string{"foo/0", "optional/0"})
verifyFilteredSnapshot(t, original, filtered, []string{"system/0", "bar/0", "foobar/0"})
}
func TestSnapshotFilter_includeWildcardPackage(t *testing.T) {
original := makeTestSnapshot()
filtered := original.Filter([]string{"foo*"}, []string{})
verifyFilteredSnapshot(t, original, filtered, []string{"foo/0", "foobar/0"})
}
func TestSnapshotFilter_excludeWildcardPackage(t *testing.T) {
original := makeTestSnapshot()
filtered := original.Filter([]string{"*"}, []string{"foo*"})
verifyFilteredSnapshot(t, original, filtered, []string{"system/0", "bar/0", "optional/0"})
}