From 0bd12e447450470bff7df9486297827371109bb3 Mon Sep 17 00:00:00 2001 From: Matej Vasek Date: Thu, 13 Jul 2023 21:03:41 +0200 Subject: [PATCH] test: OCI content created by "host" builder Signed-off-by: Matej Vasek --- pkg/oci/builder_test.go | 93 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 89 insertions(+), 4 deletions(-) diff --git a/pkg/oci/builder_test.go b/pkg/oci/builder_test.go index 0def0164a1..a8cfc2c9a3 100644 --- a/pkg/oci/builder_test.go +++ b/pkg/oci/builder_test.go @@ -1,15 +1,22 @@ package oci import ( + "archive/tar" + "compress/gzip" "context" "encoding/json" "errors" "fmt" + "io" + "io/fs" "os" "path/filepath" "runtime" + "sort" + "strings" "testing" + "github.com/google/go-cmp/cmp" v1 "github.com/google/go-containerregistry/pkg/v1" fn "knative.dev/func/pkg/functions" . "knative.dev/func/pkg/testing" @@ -172,8 +179,86 @@ func validateOCI(path string, t *testing.T) { t.Fatalf("invalid schema version, expected 2, got %d", imageIndex.SchemaVersion) } - // Additional validation of the Image Index structure can be added here - // extract. for example checking that the path includes the README.md - // and one of the binaries in the exact location expected (the data layer - // blob and exec layer blob, respectively) + if len(imageIndex.Manifests) < 1 { + t.Fatal("fewer manifests") + } + + digestParts := strings.SplitN(imageIndex.Manifests[0].Digest, ":", 2) + if len(digestParts) < 2 { + t.Fatal("invalid digest format") + } + manifestFile := filepath.Join(path, "blobs", "sha256", digestParts[1]) + manifestFileData, err := os.ReadFile(manifestFile) + if err != nil { + t.Fatal(err) + } + mf := struct { + Layers []struct { + Digest string `json:"digest"` + } `json:"layers"` + }{} + err = json.Unmarshal(manifestFileData, &mf) + if err != nil { + t.Fatal(err) + } + + type fileInfo struct { + Path string + Mod fs.FileMode + } + var files []fileInfo + + for _, layer := range mf.Layers { + func() { + digestParts = strings.SplitN(layer.Digest, ":", 2) + if len(digestParts) < 2 { + t.Fatal("invalid digest format") + } + f, err := os.Open(filepath.Join(path, "blobs", "sha256", digestParts[1])) + if err != nil { + t.Fatal(err) + } + defer f.Close() + + gr, err := gzip.NewReader(f) + if err != nil { + t.Fatal(err) + } + defer gr.Close() + + tr := tar.NewReader(gr) + for { + hdr, err := tr.Next() + if err != nil { + if errors.Is(err, io.EOF) { + break + } + t.Fatal(err) + } + files = append(files, fileInfo{ + Path: hdr.Name, + Mod: hdr.FileInfo().Mode() & (fs.ModeType | fs.ModePerm), + }) + } + }() + } + sort.Slice(files, func(i, j int) bool { + return files[i].Path < files[j].Path + }) + + expectedFiles := []fileInfo{ + {Path: "/etc/pki/tls/certs/ca-certificates.crt", Mod: 0644}, + {Path: "/etc/ssl/certs/ca-certificates.crt", Mod: 0644}, + {Path: "/func", Mod: 0755 | fs.ModeDir}, + {Path: "/func/README.md", Mod: 0644}, + {Path: "/func/f", Mod: 0755}, + {Path: "/func/func.yaml", Mod: 0644}, + {Path: "/func/go.mod", Mod: 0644}, + {Path: "/func/handle.go", Mod: 0644}, + {Path: "/func/handle_test.go", Mod: 0644}, + } + + if diff := cmp.Diff(expectedFiles, files); diff != "" { + t.Error("files in oci differ from expectation (-want, +got):", diff) + } }