blob: 4837826ca1deab05000c6d121dc248aae45b703e [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package artifactory
import (
"os"
"path/filepath"
"strings"
"testing"
"github.com/google/go-cmp/cmp"
"go.fuchsia.dev/fuchsia/src/sys/pkg/bin/pm/build"
)
// createBuildDir generates a mock build directory for the tests to use.
//
// The tree will be cleaned up automatically.
func createBuildDir(t *testing.T, files map[string]string, manifests []string) (string, string) {
dir := t.TempDir()
for filename, data := range files {
if err := os.MkdirAll(filepath.Join(dir, filepath.Dir(filename)), 0o700); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(dir, filename), []byte(data), 0o600); err != nil {
t.Fatal(err)
}
}
// write the newline-delimited file that is produced by a ninja target
newlineLocation := "manifests.list"
manifestPaths := strings.Join(manifests[:], "\n")
if err := os.WriteFile(filepath.Join(dir, newlineLocation), []byte(manifestPaths), 0o600); err != nil {
t.Fatal(err)
}
return dir, newlineLocation
}
// Implements pkgManifestModules
type mockPkgManifestModules struct {
pkgManifestsLocation []string
buildDir string
}
func (m mockPkgManifestModules) BuildDir() string {
return m.buildDir
}
func (m mockPkgManifestModules) PackageManifestsLocation() []string {
return m.pkgManifestsLocation
}
// Verifies we can parse the build dir to produce a blobs Upload.
func TestBlobsUpload(t *testing.T) {
testCases := []struct {
name string
buildDirContents map[string]string
packageManifests []string
uploadDestination string
expectedUpload Upload
wantError bool
}{
{
name: "success",
buildDirContents: map[string]string{
"a": `{
"version": "1",
"blobs": [
{
"merkle": "0000000000000000000000000000000000000000000000000000000000000000"
},
{
"merkle": "1111111111111111111111111111111111111111111111111111111111111111"
}
]
}`,
"b": `{
"version": "1",
"blobs": [
{
"merkle": "1111111111111111111111111111111111111111111111111111111111111111"
}
]
}`,
},
packageManifests: []string{"a", "b"},
uploadDestination: "namespace/all_blobs.json",
expectedUpload: Upload{
Compress: true,
Destination: "namespace/all_blobs.json",
Contents: []byte("[" +
"{" +
"\"source_path\":\"\"," +
"\"path\":\"\"," +
"\"merkle\":\"0000000000000000000000000000000000000000000000000000000000000000\"," +
"\"size\":0" +
"}," +
"{" +
"\"source_path\":\"\"," +
"\"path\":\"\"," +
"\"merkle\":\"1111111111111111111111111111111111111111111111111111111111111111\"," +
"\"size\":0" +
"}" +
"]"),
},
},
{
name: "failure package manifest improper json formatting",
buildDirContents: map[string]string{
"a": `{
Oops. This is not valid json.
}`,
},
packageManifests: []string{"a"},
wantError: true,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
// Generate test env based on input.
tempDirPath, manifestLocation := createBuildDir(t, tc.buildDirContents, tc.packageManifests)
// Now that we're set up, we can actually determine the blobs Upload.
mockModules := mockPkgManifestModules{
pkgManifestsLocation: []string{manifestLocation},
buildDir: tempDirPath,
}
actualUpload, err := blobsUpload(mockModules, tc.uploadDestination)
// Ensure the results match the expectations.
if (err == nil) == tc.wantError {
t.Fatalf("got error [%v], want error? %t", err, tc.wantError)
}
if diff := cmp.Diff(actualUpload, tc.expectedUpload); diff != "" {
t.Fatalf("got upload %#v, expected %#v", actualUpload, tc.expectedUpload)
}
})
}
}
// Verifies blobs can be properly loaded via the package manifests.
func TestLoadBlobsFromPackageManifests(t *testing.T) {
testCases := []struct {
name string
buildDirContents map[string]string
packageManifests []string
expectedBlobs []build.PackageBlobInfo
wantError bool
}{
{
name: "success one package manifest",
buildDirContents: map[string]string{
"a": `{
"version": "1",
"blobs": [
{
"merkle": "1111111111111111111111111111111111111111111111111111111111111111"
}
]
}`,
},
packageManifests: []string{"a"},
expectedBlobs: []build.PackageBlobInfo{
{Merkle: build.MustDecodeMerkleRoot("1111111111111111111111111111111111111111111111111111111111111111")},
},
},
{
name: "success multiple nested package manifests",
buildDirContents: map[string]string{
"a/b": `{
"version": "1",
"blobs": [
{ "merkle": "0000000000000000000000000000000000000000000000000000000000000000" },
{ "merkle": "1111111111111111111111111111111111111111111111111111111111111111" }
]
}`,
"a/a/b": `{
"version": "1",
"blobs": [
{ "merkle": "2222222222222222222222222222222222222222222222222222222222222222" }
]
}`,
"c/d": `{
"version": "1",
"blobs": [
{ "merkle": "3333333333333333333333333333333333333333333333333333333333333333" }
]
}`,
},
packageManifests: []string{"a/b", "a/a/b", "c/d"},
expectedBlobs: []build.PackageBlobInfo{
{Merkle: build.MustDecodeMerkleRoot("0000000000000000000000000000000000000000000000000000000000000000")},
{Merkle: build.MustDecodeMerkleRoot("1111111111111111111111111111111111111111111111111111111111111111")},
{Merkle: build.MustDecodeMerkleRoot("2222222222222222222222222222222222222222222222222222222222222222")},
{Merkle: build.MustDecodeMerkleRoot("3333333333333333333333333333333333333333333333333333333333333333")},
},
},
{
name: "success multiple package manifests, duplicate blobs",
buildDirContents: map[string]string{
"a": `{
"version": "1",
"blobs": [
{ "merkle": "0000000000000000000000000000000000000000000000000000000000000000" },
{ "merkle": "1111111111111111111111111111111111111111111111111111111111111111" },
{ "merkle": "1111111111111111111111111111111111111111111111111111111111111111" }
]
}`,
"b": `{
"version": "1",
"blobs": [
{ "merkle": "0000000000000000000000000000000000000000000000000000000000000000" }
]
}`,
},
packageManifests: []string{"a", "b"},
expectedBlobs: []build.PackageBlobInfo{
{Merkle: build.MustDecodeMerkleRoot("0000000000000000000000000000000000000000000000000000000000000000")},
{Merkle: build.MustDecodeMerkleRoot("1111111111111111111111111111111111111111111111111111111111111111")},
},
},
{
name: "succeess package manifest does not exist",
packageManifests: []string{"non-existent-manifest"},
},
{
name: "failure package manifest improper json formatting",
buildDirContents: map[string]string{
"a": `{
"version": "1",
"blobs": [
Oops. This is not valid json.
]
}`,
},
packageManifests: []string{"a"},
wantError: true,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
// Generate test env based on input.
tempDirPath, _ := createBuildDir(t, tc.buildDirContents, tc.packageManifests)
paths := make([]string, len(tc.packageManifests))
for _, path := range tc.packageManifests {
paths = append(paths, filepath.Join(tempDirPath, path))
}
// Now that we're set up, we can actually load the blobs.
actualBlobs, err := loadBlobsFromPackageManifests(paths)
// Ensure the results match the expectations.
if (err == nil) == tc.wantError {
t.Fatalf("got error [%v], want error? %t", err, tc.wantError)
}
if diff := cmp.Diff(actualBlobs, tc.expectedBlobs); diff != "" {
t.Fatalf("got blobs %#v, expected %#v", actualBlobs, tc.expectedBlobs)
}
})
}
}