package apply import ( "context" "os" "testing" "github.com/novox/mesh-host/internal/store" ) // novox/hq issue 220: the tree on disk is exactly the archive. A file the previous archive had and // this one does not is gone, and nothing is left beside the directory. func TestAnArchiveReplacesTheTreeItWasUnpackedOver(t *testing.T) { dir := t.TempDir() first, firstDigest := anArchive(t, map[string]string{"index.js": "old", "node_modules/dep/index.js": "dep"}) d := declare(t, `{"id":"bundle-tools","type":"archive","source":"`+serving(t, first)+ `","digest":"`+firstDigest+`","path":"`+dir+`/tools"}`) _, state, err := Apply(context.Background(), archHost(t), d, store.State{}, store.OriginCarried, noServices, nil, nil) if err != nil { t.Fatal(err) } second, secondDigest := anArchive(t, map[string]string{"index.js": "one file"}) d = declare(t, `{"id":"bundle-tools","type":"archive","source":"`+serving(t, second)+ `","digest":"`+secondDigest+`","path":"`+dir+`/tools"}`) if _, _, err := Apply(context.Background(), archHost(t), d, state, store.OriginCarried, noServices, nil, nil); err != nil { t.Fatal(err) } if got, _ := os.ReadFile(dir + "/tools/index.js"); string(got) != "one file" { t.Fatalf("index.js is %q", got) } if _, err := os.Stat(dir + "/tools/node_modules"); err == nil { t.Fatal("the previous archive's directory is still there") } entries, _ := os.ReadDir(dir) if len(entries) != 1 { names := []string{} for _, e := range entries { names = append(names, e.Name()) } t.Fatalf("beside the tree: %v", names) } } // A tree is replaced only by one that unpacked whole: an archive refused halfway leaves the old // tree as it was. func TestARefusedArchiveLeavesTheTreeItWouldHaveReplaced(t *testing.T) { dir := t.TempDir() first, firstDigest := anArchive(t, map[string]string{"index.js": "old"}) d := declare(t, `{"id":"bundle-tools","type":"archive","source":"`+serving(t, first)+ `","digest":"`+firstDigest+`","path":"`+dir+`/tools"}`) _, state, err := Apply(context.Background(), archHost(t), d, store.State{}, store.OriginCarried, noServices, nil, nil) if err != nil { t.Fatal(err) } bad, badDigest := anArchive(t, map[string]string{"index.js": "new", "../../escaped": "no"}) d = declare(t, `{"id":"bundle-tools","type":"archive","source":"`+serving(t, bad)+ `","digest":"`+badDigest+`","path":"`+dir+`/tools"}`) if _, _, err := Apply(context.Background(), archHost(t), d, state, store.OriginCarried, noServices, nil, nil); err == nil { t.Fatal("an escaping archive was accepted") } if got, _ := os.ReadFile(dir + "/tools/index.js"); string(got) != "old" { t.Fatalf("index.js is %q after a refused archive", got) } if entries, _ := os.ReadDir(dir); len(entries) != 1 { t.Fatalf("%d entries beside the tree after a refused archive", len(entries)) } }