blob: d7f63c3f866145880b82777ca8be79df0e3871bd [file] [log] [blame]
// Copyright 2021 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 fint
import (
"fmt"
"sort"
"testing"
"github.com/google/go-cmp/cmp"
"go.fuchsia.dev/fuchsia/tools/build"
fintpb "go.fuchsia.dev/fuchsia/tools/integration/fint/proto"
"google.golang.org/protobuf/testing/protocmp"
"google.golang.org/protobuf/types/known/structpb"
)
type fakeBuildModules struct {
archives []build.Archive
generatedSources []string
images []build.Image
pbinSets []build.PrebuiltBinarySet
testSpecs []build.TestSpec
tools build.Tools
zbiTests []build.ZBITest
}
func (m fakeBuildModules) Archives() []build.Archive { return m.archives }
func (m fakeBuildModules) GeneratedSources() []string { return m.generatedSources }
func (m fakeBuildModules) Images() []build.Image { return m.images }
func (m fakeBuildModules) PrebuiltBinarySets() []build.PrebuiltBinarySet { return m.pbinSets }
func (m fakeBuildModules) TestSpecs() []build.TestSpec { return m.testSpecs }
func (m fakeBuildModules) Tools() build.Tools { return m.tools }
func (m fakeBuildModules) ZBITests() []build.ZBITest { return m.zbiTests }
func TestConstructNinjaTargets(t *testing.T) {
testCases := []struct {
name string
staticSpec *fintpb.Static
modules fakeBuildModules
expectedTargets []string
expectedArtifacts *fintpb.BuildArtifacts
expectErr bool
}{
{
name: "empty spec produces no ninja targets",
staticSpec: &fintpb.Static{},
expectedTargets: nil,
},
{
name: "extra ad-hoc ninja targets",
staticSpec: &fintpb.Static{
NinjaTargets: []string{"foo", "bar"},
},
expectedTargets: []string{"foo", "bar"},
},
{
name: "duplicate targets",
staticSpec: &fintpb.Static{
NinjaTargets: []string{"foo", "foo"},
},
expectedTargets: []string{"foo"},
},
{
name: "images for testing included",
staticSpec: &fintpb.Static{
IncludeImages: true,
},
modules: fakeBuildModules{
images: []build.Image{
{Name: qemuImageNames[0], Path: "qemu_image_path"},
{Name: "should-be-ignored", Path: "different_path"},
},
},
expectedTargets: append(extraTargetsForImages, "qemu_image_path", "build/images:updates"),
expectedArtifacts: &fintpb.BuildArtifacts{
BuiltImages: []*structpb.Struct{
mustStructPB(t, build.Image{Name: qemuImageNames[0], Path: "qemu_image_path"}),
},
},
},
{
name: "images and archives included",
staticSpec: &fintpb.Static{
IncludeImages: true,
IncludeArchives: true,
},
modules: fakeBuildModules{
archives: []build.Archive{
{Name: "packages", Path: "p.tar.gz", Type: "tgz"},
{Name: "archive", Path: "b.tar", Type: "tar"},
{Name: "archive", Path: "b.tgz", Type: "tgz"},
{Name: "other", Path: "other.tgz", Type: "tgz"},
},
},
expectedTargets: append(extraTargetsForImages, "p.tar.gz", "b.tgz"),
expectedArtifacts: &fintpb.BuildArtifacts{
BuiltArchives: []*structpb.Struct{
mustStructPB(t, build.Archive{Name: "packages", Path: "p.tar.gz", Type: "tgz"}),
mustStructPB(t, build.Archive{Name: "archive", Path: "b.tgz", Type: "tgz"}),
},
},
},
{
name: "host tests included",
staticSpec: &fintpb.Static{
IncludeHostTests: true,
},
modules: fakeBuildModules{
testSpecs: []build.TestSpec{
{Test: build.Test{OS: "fuchsia", Path: "fuchsia_path"}},
{Test: build.Test{OS: "linux", Path: "linux_path"}},
{Test: build.Test{OS: "mac", Path: "mac_path"}},
},
},
expectedTargets: []string{"linux_path", "mac_path"},
},
{
name: "generated sources included",
staticSpec: &fintpb.Static{
IncludeGeneratedSources: true,
},
modules: fakeBuildModules{
generatedSources: []string{"foo.h", "bar.h"},
},
expectedTargets: []string{"foo.h", "bar.h"},
},
{
name: "prebuilt binary manifests included",
staticSpec: &fintpb.Static{
IncludePrebuiltBinaryManifests: true,
},
modules: fakeBuildModules{
pbinSets: []build.PrebuiltBinarySet{
{Manifest: "manifest1.json"},
{Manifest: "manifest2.json"},
},
},
expectedTargets: []string{"manifest1.json", "manifest2.json"},
},
{
name: "tools included",
staticSpec: &fintpb.Static{
Tools: []string{"tool1", "tool2"},
},
modules: fakeBuildModules{
tools: makeTools(map[string][]string{
"tool1": {"linux", "mac"},
"tool2": {"linux"},
"tool3": {"linux", "mac"},
}),
},
expectedTargets: []string{"linux_x64/tool1", "linux_x64/tool2"},
},
{
name: "nonexistent tool",
staticSpec: &fintpb.Static{
Tools: []string{"tool1"},
},
expectErr: true,
},
{
name: "tool not supported on current platform",
staticSpec: &fintpb.Static{
Tools: []string{"tool1"},
},
modules: fakeBuildModules{
tools: makeTools(map[string][]string{
"tool1": {"mac"},
}),
},
expectErr: true,
},
{
name: "zbi tests",
staticSpec: &fintpb.Static{
TargetArch: fintpb.Static_ARM64,
IncludeZbiTests: true,
},
modules: fakeBuildModules{
zbiTests: []build.ZBITest{
{
Name: "foo",
Label: "//src/foo",
DeviceTypes: []string{"AEMU"},
Path: "foo.zbi",
},
{
Name: "bar",
Label: "//src/bar",
DeviceTypes: []string{"Intel NUC Kit NUC7i5DNHE"},
Path: "bar.zbi",
},
},
images: []build.Image{
{
Name: qemuKernelImageName,
Label: "//src/foo",
Path: "foo-qemu-kernel",
},
{
Name: "fastboot",
Path: "fastboot",
},
{
Name: "zircon-a",
PaveZedbootArgs: []string{"--boot", "--zircona"},
Path: "zircona",
},
{
Name: "zircon-r",
PaveZedbootArgs: []string{"--zirconr"},
Path: "zirconr",
},
},
},
expectedTargets: []string{"foo.zbi", "bar.zbi", "foo-qemu-kernel", "zircona", "zirconr"},
expectedArtifacts: &fintpb.BuildArtifacts{
BuiltZedbootImages: []*structpb.Struct{
mustStructPB(t, build.Image{
Name: "zircon-a",
PaveZedbootArgs: []string{"--boot", "--zircona", "--zirconb"},
Path: "zircona",
}),
mustStructPB(t, build.Image{
Name: "zircon-r",
PaveZedbootArgs: []string{"--zirconr"},
Path: "zirconr",
}),
},
ZbiTestQemuKernelImages: map[string]*structpb.Struct{
"foo": mustStructPB(t, build.Image{
Name: qemuKernelImageName,
Label: "//src/foo",
Path: "foo-qemu-kernel",
Type: "kernel",
}),
},
},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
// Normalize expected data so tests are less painful to write.
sort.Strings(tc.expectedTargets)
if tc.expectedArtifacts == nil {
tc.expectedArtifacts = &fintpb.BuildArtifacts{}
}
targets, artifacts, err := constructNinjaTargets(tc.modules, tc.staticSpec, "linux-x64")
if err != nil {
if tc.expectErr {
return
}
t.Fatal(err)
} else if tc.expectErr {
t.Fatalf("Expected an error, but got nil")
}
if diff := cmp.Diff(tc.expectedTargets, targets); diff != "" {
t.Errorf("Got wrong targets (-want +got):\n%s", diff)
}
if diff := cmp.Diff(tc.expectedArtifacts, artifacts, protocmp.Transform()); diff != "" {
t.Errorf("Got wrong artifacts (-want +got):\n%s", diff)
}
})
}
}
func makeTools(supportedOSes map[string][]string) build.Tools {
var res build.Tools
for toolName, systems := range supportedOSes {
for _, os := range systems {
res = append(res, build.Tool{
Name: toolName,
OS: os,
CPU: "x64",
Path: fmt.Sprintf("%s_x64/%s", os, toolName),
})
}
}
return res
}
// mustStructPB converts a Go struct to a protobuf Struct, failing the test in
// case of failure.
func mustStructPB(t *testing.T, s interface{}) *structpb.Struct {
ret, err := toStructPB(s)
if err != nil {
t.Fatal(err)
}
return ret
}