blob: c5df5a594c8ddd44c0105014107f0a9f6d9d4ecc [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 (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"reflect"
"testing"
"go.fuchsia.dev/fuchsia/tools/build/lib"
)
// Implements binModules
type mockBinModules struct {
buildDir string
bins []build.Binary
pbins []build.PrebuiltBinaries
}
func (m mockBinModules) BuildDir() string {
return m.buildDir
}
func (m mockBinModules) Args() build.Args {
val := true
trueMsg, err := json.Marshal(&val)
if err != nil {
panic("was not able to marshal `true`: " + err.Error())
}
return build.Args(map[string]json.RawMessage{
"output_breakpad_syms": trueMsg,
})
}
func (m mockBinModules) Binaries() []build.Binary {
return m.bins
}
func (m mockBinModules) PrebuiltBinaries() []build.PrebuiltBinaries {
return m.pbins
}
func TestDebugBinaryUploads(t *testing.T) {
checkout, err := ioutil.TempDir("", "")
if err != nil {
t.Fatalf("failed to create a temporary directory: %v", err)
}
defer os.RemoveAll(checkout)
buildDir, err := ioutil.TempDir(checkout, "out")
if err != nil {
t.Fatalf("failed to create a 'build directory'")
}
pbins := []build.Binary{
{
Debug: filepath.Join("..", ".build-id", "pr", "ebuiltA.debug"),
Breakpad: filepath.Join("..", ".build-id", "pr", "ebuiltA.sym"),
OS: "fuchsia",
Label: "//prebuilt",
},
{
Debug: filepath.Join("..", ".build-id", "pr", "ebuiltA.debug"),
Breakpad: filepath.Join("..", ".build-id", "pr", "ebuiltA.sym"),
OS: "fuchsia",
Label: "//prebuilt",
},
{
Debug: filepath.Join("..", ".build-id", "pr", "ebuiltB.debug"),
Breakpad: filepath.Join("..", ".build-id", "pr", "ebuiltB.sym"),
OS: "linux",
Label: "//prebuilt",
},
}
prebuiltBinManifest, err := binaryManifest(buildDir, pbins)
if err != nil {
t.Fatalf("failed to create binary manifest: %v", err)
}
m := &mockBinModules{
buildDir: buildDir,
bins: []build.Binary{
{
Debug: filepath.Join(".build-id", "fi", "rst.debug"),
Breakpad: filepath.Join("gen", "first.sym"),
OS: "fuchsia",
Label: "//first",
},
{
Debug: filepath.Join(".build-id", "fi", "rst.debug"),
Breakpad: filepath.Join("gen", "first.sym"),
OS: "fuchsia",
Label: "//first",
},
{
Debug: filepath.Join(".build-id", "se", "cond.debug"),
Breakpad: filepath.Join("host", "gen", "second.sym"),
OS: "linux",
Label: "//second",
},
{
Debug: filepath.Join(".build-id", "th", "ird.debug"),
OS: "linux",
Label: "//third",
},
},
pbins: []build.PrebuiltBinaries{
{
Name: "prebuilt",
Manifest: prebuiltBinManifest,
},
},
}
// The logic under test deals in file existence.
for _, bin := range pbins {
touch(t, filepath.Join(buildDir, bin.Debug))
touch(t, filepath.Join(buildDir, bin.Breakpad))
}
for _, bin := range m.bins {
touch(t, filepath.Join(buildDir, bin.Debug))
if bin.Breakpad != "" {
touch(t, filepath.Join(buildDir, bin.Breakpad))
}
}
expectedUploads := []Upload{
{
Source: filepath.Join(buildDir, ".build-id", "fi", "rst.debug"),
Destination: "NAMESPACE/first.debug",
Compress: true,
Deduplicate: true,
},
{
Source: filepath.Join(buildDir, "gen", "first.sym"),
Destination: "NAMESPACE/first.sym",
Compress: true,
Deduplicate: true,
},
{
Source: filepath.Join(buildDir, ".build-id", "se", "cond.debug"),
Destination: "NAMESPACE/second.debug",
Compress: true,
Deduplicate: true,
},
{
Source: filepath.Join(buildDir, "host", "gen", "second.sym"),
Destination: "NAMESPACE/second.sym",
Compress: true,
Deduplicate: true,
},
{
Source: filepath.Join(buildDir, ".build-id", "th", "ird.debug"),
Destination: "NAMESPACE/third.debug",
Compress: true,
Deduplicate: true,
},
{
Source: filepath.Join(checkout, ".build-id", "pr", "ebuiltA.debug"),
Destination: "NAMESPACE/prebuiltA.debug",
Compress: true,
Deduplicate: true,
},
{
Source: filepath.Join(checkout, ".build-id", "pr", "ebuiltA.sym"),
Destination: "NAMESPACE/prebuiltA.sym",
Compress: true,
Deduplicate: true,
},
{
Source: filepath.Join(checkout, ".build-id", "pr", "ebuiltB.debug"),
Destination: "NAMESPACE/prebuiltB.debug",
Compress: true,
Deduplicate: true,
},
{
Source: filepath.Join(checkout, ".build-id", "pr", "ebuiltB.sym"),
Destination: "NAMESPACE/prebuiltB.sym",
Compress: true,
Deduplicate: true,
},
}
expectedIDs := []string{"first", "prebuiltA"}
actualUploads, actualIDs, err := debugBinaryUploads(m, "NAMESPACE")
if err != nil {
t.Fatalf("failed to generate debug binary uploads: %v", err)
}
if !reflect.DeepEqual(actualUploads, expectedUploads) {
t.Fatalf("unexpected debug binary uploads:\nexpected:\n%#v\nactual:\n%#v\n", expectedUploads, actualUploads)
}
if !reflect.DeepEqual(actualIDs, expectedIDs) {
t.Fatalf("unexpected build IDs:\nexpected:\n%#v\nactual:\n%#v\n", expectedIDs, actualIDs)
}
}
func touch(t *testing.T, file string) {
t.Helper()
file, err := filepath.Abs(file)
if err != nil {
t.Fatalf("failed to absolutize: %v", err)
}
if err := os.MkdirAll(filepath.Dir(file), os.ModePerm); err != nil {
t.Fatalf("failed to create parent directories for %s: %v", file, err)
}
f, err := os.Create(file)
if err != nil {
t.Fatalf("failed to create %s: %v", file, err)
}
f.Close()
}
func binaryManifest(buildDir string, bins []build.Binary) (string, error) {
manifest, err := ioutil.TempFile(buildDir, "artifactory_tests")
if err != nil {
return "", err
}
defer manifest.Close()
if err := json.NewEncoder(manifest).Encode(&bins); err != nil {
return "", fmt.Errorf("failed to encode binary manifest: %v", err)
}
return filepath.Base(manifest.Name()), nil
}