145 lines
5.2 KiB
Go
145 lines
5.2 KiB
Go
package index
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"strings"
|
|
"testing"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/delivery"
|
|
)
|
|
|
|
func twoModules(t *testing.T) (*Indexer, *memStore) {
|
|
t.Helper()
|
|
ix, mods := modulesIndexer(t)
|
|
if err := ix.Apply(context.Background(), mergedMsg(catalogueRepo, map[string]string{"modules/a": "t", "modules/b": "t"})); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, k := range []string{"a", "b"} {
|
|
if _, ok := mods.vals[k]; !ok {
|
|
t.Fatalf("setup: modules.%s not written", k)
|
|
}
|
|
}
|
|
return ix, mods
|
|
}
|
|
|
|
func TestAMergeThatRemovesAModuleDeletesItsKey(t *testing.T) { // 1900/AC1
|
|
ix, mods := twoModules(t)
|
|
if err := ix.Apply(context.Background(), mergedMsg(catalogueRepo, map[string]string{"modules/a": "t2"})); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, ok := mods.vals["b"]; ok {
|
|
t.Error("modules.b is still held after a merge whose trunk has no module b")
|
|
}
|
|
if _, ok := mods.vals["a"]; !ok {
|
|
t.Error("modules.a, which the trunk still holds, was deleted")
|
|
}
|
|
}
|
|
|
|
func TestAMergeLeavesTheModulesOfAnotherRepository(t *testing.T) { // 1900/AC1 (scope)
|
|
ix, mods := twoModules(t)
|
|
if err := ix.Apply(context.Background(), mergedMsg("novox/mesh-delivery", map[string]string{"modules/c": "t"})); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, ok := mods.vals["a"]; !ok {
|
|
t.Error("a merge of another repository deleted modules.a")
|
|
}
|
|
if _, ok := mods.vals["b"]; !ok {
|
|
t.Error("a merge of another repository deleted modules.b")
|
|
}
|
|
}
|
|
|
|
func TestAMergeWithoutManifestsDeletesNothing(t *testing.T) { // 1900/AC1: older writers send none, which does not say the trunk is empty
|
|
ix, mods := twoModules(t)
|
|
f := mergedMsg(catalogueRepo, map[string]string{"modules/a": "t2"})
|
|
f.Manifests = nil
|
|
if err := ix.Apply(context.Background(), f); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, ok := mods.vals["b"]; !ok {
|
|
t.Error("a merge message with no manifests deleted modules.b")
|
|
}
|
|
}
|
|
|
|
func TestAPathWithoutAModuleJSONIsNeverAModule(t *testing.T) { // 1900/AC2: testdata such as fixture-build
|
|
ix, mods := twoModules(t)
|
|
f := mergedMsg(catalogueRepo, map[string]string{"modules/a": "t2"})
|
|
f.Trees["testdata/fixture-build"] = "t" // a directory in the tree whose module.json the message does not carry
|
|
if err := ix.Apply(context.Background(), f); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, ok := mods.vals["fixture-build"]; ok {
|
|
t.Error("modules.fixture-build written for a path without a module.json")
|
|
}
|
|
}
|
|
|
|
func TestStartingDeletesTheKeysTheTrunkDoesNotHold(t *testing.T) { // 1900/AC3
|
|
ix, mods := twoModules(t)
|
|
ctx := context.Background()
|
|
if err := ix.ApplySource(ctx, 3, sourceOf(catalogueRepo, merge)); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var asked string
|
|
ix.Trunk = func(_ context.Context, repository, sha string) ([]string, error) {
|
|
asked = repository + "@" + sha
|
|
return []string{"modules/a"}, nil
|
|
}
|
|
ix.Contains = func(context.Context, string, string, string) (bool, error) { return true, nil }
|
|
if err := ix.Reconcile(ctx); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if asked != catalogueRepo+"@"+merge {
|
|
t.Errorf("the trunk was asked as %q, want the source's head of the repository", asked)
|
|
}
|
|
if _, ok := mods.vals["b"]; ok {
|
|
t.Error("modules.b is still held though the trunk holds no module at modules/b")
|
|
}
|
|
if _, ok := mods.vals["a"]; !ok {
|
|
t.Error("modules.a was deleted")
|
|
}
|
|
}
|
|
|
|
func TestStartingDeletesNothingWhenTheTrunkCannotBeRead(t *testing.T) { // 1900/AC3: failure is loud, never a mass delete
|
|
ix, mods := twoModules(t)
|
|
ctx := context.Background()
|
|
if err := ix.ApplySource(ctx, 3, sourceOf(catalogueRepo, merge)); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for name, trunk := range map[string]func(context.Context, string, string) ([]string, error){
|
|
"an error": func(context.Context, string, string) ([]string, error) { return nil, errors.New("forge down") },
|
|
"no module at all": func(context.Context, string, string) ([]string, error) { return nil, nil },
|
|
} {
|
|
ix.Trunk = trunk
|
|
_ = ix.Reconcile(ctx)
|
|
if len(mods.vals) != 2 {
|
|
t.Errorf("%s: %d keys held, want 2 untouched", name, len(mods.vals))
|
|
}
|
|
}
|
|
_ = delivery.RootPath
|
|
}
|
|
|
|
func TestAKeyWrittenAheadOfTheSourceHeadStaysAndOneWithoutAPathIsSkipped(t *testing.T) { // 1900/AC3 (review): the source lags a merge already applied
|
|
ix, mods := twoModules(t) // written at the merge commit C
|
|
ctx := context.Background()
|
|
const older = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
|
|
if err := ix.ApplySource(ctx, 3, sourceOf(catalogueRepo, older)); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
mods.put("nopath", mustEncode(t, delivery.Module{Repository: catalogueRepo, Commit: older, None2: "x", Manifest: strings.Repeat("a", 64)}))
|
|
ix.Trunk = func(context.Context, string, string) ([]string, error) { return []string{"modules/a"}, nil }
|
|
ix.Contains = func(_ context.Context, _, commit, in string) (bool, error) { return commit == in, nil } // C is not in B
|
|
if err := ix.Reconcile(ctx); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, k := range []string{"a", "b", "nopath"} {
|
|
if _, ok := mods.vals[k]; !ok {
|
|
t.Errorf("modules.%s was deleted", k)
|
|
}
|
|
}
|
|
ix.Contains = func(context.Context, string, string, string) (bool, error) { return false, errors.New("forge down") }
|
|
_ = ix.Reconcile(ctx)
|
|
if _, ok := mods.vals["b"]; !ok {
|
|
t.Error("modules.b deleted though whether its commit is in the head cannot be read")
|
|
}
|
|
}
|