Files
distributor/internal/bundle/validate_test.go

133 lines
4.2 KiB
Go

package bundle
import (
"context"
"encoding/json"
"strings"
"testing"
"gitea.maximumdirect.net/eric/distributor/internal/storage"
"gitea.maximumdirect.net/eric/distributor/internal/storage/fake"
)
func TestValidateValidBundle(t *testing.T) {
backend := validFakeBundle(t)
sourceBundle, err := Validate(context.Background(), backend, "")
if err != nil {
t.Fatalf("Validate() error = %v", err)
}
if sourceBundle.RootRelativePath != "" {
t.Fatalf("root = %q, want empty", sourceBundle.RootRelativePath)
}
if sourceBundle.Manifest.ID != "weather.daily.brentwood.2026-05-30" {
t.Fatalf("id = %q", sourceBundle.Manifest.ID)
}
}
func TestValidateRejectsMissingFile(t *testing.T) {
backend := validFakeBundle(t)
deleteFakeFile(t, backend, "summary.txt")
_, err := Validate(context.Background(), backend, "")
assertErrorContains(t, err, "stat")
}
func TestValidateRejectsSizeMismatch(t *testing.T) {
backend := validFakeBundle(t)
manifest := validFixtureManifest(t)
manifest.Files[1].Size = 9
manifest.Digest = BundleDigest(manifest.Files)
writeManifest(t, backend, manifest)
_, err := Validate(context.Background(), backend, "")
assertErrorContains(t, err, "size mismatch")
}
func TestValidateRejectsPerFileDigestMismatch(t *testing.T) {
backend := validFakeBundle(t)
writeFakeFile(t, backend, "report.md", "# Report\nCloud.\n")
_, err := Validate(context.Background(), backend, "")
assertErrorContains(t, err, "sha256 mismatch")
}
func TestValidateRejectsBundleDigestMismatch(t *testing.T) {
backend := validFakeBundle(t)
manifest := strings.Replace(string(readFixture(t, "testdata/valid_bundle/manifest.json")), `"digest": "sha256:099b205780d2b050024868399961b05731729a548d5d6329c7b06a6740dd75fe"`, `"digest": "sha256:0000000000000000000000000000000000000000000000000000000000000000"`, 1)
writeFakeFile(t, backend, "manifest.json", manifest)
_, err := Validate(context.Background(), backend, "")
assertErrorContains(t, err, "digest mismatch")
}
func TestValidateRejectsSymlinkFile(t *testing.T) {
backend := validFakeBundle(t)
if err := backend.AddSymlink("summary.txt"); err != nil {
t.Fatalf("AddSymlink() error = %v", err)
}
_, err := Validate(context.Background(), backend, "")
assertErrorContains(t, err, "regular file")
}
func TestValidateRejectsUnsafeManifestPaths(t *testing.T) {
tests := []string{
"",
".",
"./report.md",
"../report.md",
"/report.md",
"nested/../report.md",
"nested/./report.md",
"nested//report.md",
`nested\report.md`,
ManifestName,
storage.StateFileName,
"nested/" + ManifestName,
"nested/" + storage.StateFileName,
}
for _, path := range tests {
t.Run(path, func(t *testing.T) {
backend := validFakeBundle(t)
manifest := validFixtureManifest(t)
manifest.Files[0].Path = path
manifest.Digest = BundleDigest(manifest.Files)
writeManifest(t, backend, manifest)
_, err := Validate(context.Background(), backend, "")
if err == nil {
t.Fatal("Validate() error = nil, want unsafe path error")
}
})
}
}
func validFakeBundle(t *testing.T) *fake.Backend {
t.Helper()
backend := fake.New()
writeFakeFile(t, backend, "manifest.json", string(readFixture(t, "testdata/valid_bundle/manifest.json")))
writeFakeFile(t, backend, "report.md", string(readFixture(t, "testdata/valid_bundle/report.md")))
writeFakeFile(t, backend, "summary.txt", string(readFixture(t, "testdata/valid_bundle/summary.txt")))
return backend
}
func writeFakeFile(t *testing.T, backend *fake.Backend, path, data string) {
t.Helper()
_, err := backend.WriteFile(context.Background(), path, []byte(data), storage.WriteOptions{Overwrite: true})
if err != nil {
t.Fatalf("WriteFile(%q) error = %v", path, err)
}
}
func writeManifest(t *testing.T, backend *fake.Backend, manifest Manifest) {
t.Helper()
data, err := json.MarshalIndent(manifest, "", " ")
if err != nil {
t.Fatalf("MarshalIndent() error = %v", err)
}
writeFakeFile(t, backend, ManifestName, string(append(data, '\n')))
}
func deleteFakeFile(t *testing.T, backend *fake.Backend, path string) {
t.Helper()
err := backend.DeleteManagedBundle(context.Background(), "", []string{path}, storage.DeleteOptions{IgnoreMissing: true})
if err != nil {
t.Fatalf("DeleteManagedBundle(%q) error = %v", path, err)
}
}