blob: 15a06b149acb23527e7bdb8deb87bf098f451832 [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 main
import (
"context"
"fmt"
"strings"
"sync"
"testing"
"cloud.google.com/go/storage"
_struct "github.com/golang/protobuf/ptypes/struct"
buildbucketpb "go.chromium.org/luci/buildbucket/proto"
"go.fuchsia.dev/infra/artifacts"
)
type mockDirectory struct {
files []string
copiedFiles []string
lock sync.Mutex
}
func (d *mockDirectory) Object(path string) *storage.ObjectHandle {
return nil
}
func (d *mockDirectory) CopyFile(ctx context.Context, src, dest string) error {
for _, file := range d.files {
if file == src {
d.lock.Lock()
d.copiedFiles = append(d.copiedFiles, dest)
d.lock.Unlock()
return nil
}
}
return fmt.Errorf("source doesn't exist")
}
func (d *mockDirectory) List(ctx context.Context, prefix string) ([]string, error) {
var result []string
for _, file := range d.files {
if strings.HasPrefix(file, prefix) {
result = append(result, file)
}
}
return result, nil
}
type mockArtifactsClient struct {
files map[string][]string
dir *mockDirectory
}
func (a *mockArtifactsClient) GetBuildDir(bucket, buildID string) artifacts.Directory {
a.dir = &mockDirectory{
files: a.files[bucket],
}
return a.dir
}
func TestExecute(t *testing.T) {
archiveBucket := []string{
"build-archive.tgz",
"packages.tar.gz",
}
artifactsBucket := []string{
"images/a",
"images/b/c",
"packages/a",
"packages/b/c",
}
storageContents := map[string][]string{
"gcs_bucket": archiveBucket,
"artifacts_bucket": artifactsBucket,
}
buildID := "123"
buildsCli := &mockBuildsClient{
response: &buildbucketpb.Build{
Id: 123,
Output: &buildbucketpb.Build_Output{
Properties: &_struct.Struct{
Fields: map[string]*_struct.Value{
"gcs_bucket": {
Kind: &_struct.Value_StringValue{
StringValue: "gcs_bucket",
},
},
"artifact_gcs_bucket": {
Kind: &_struct.Value_StringValue{
StringValue: "artifacts_bucket",
},
},
},
},
},
},
}
tests := []struct {
name string
source string
dest string
expectedFiles []string
}{
{
name: "copy directory from the artifacts bucket",
source: "packages",
dest: "output/packages",
expectedFiles: []string{"output/packages/a", "output/packages/b/c"},
}, {
name: "copy archive",
source: "build-archive.tgz",
dest: "output/build-archive.tgz",
expectedFiles: []string{"output/build-archive.tgz"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
artifactsCli := &mockArtifactsClient{
files: storageContents,
}
cmd := &CopyCommand{
build: buildID,
source: tt.source,
dest: tt.dest,
}
err := cmd.execute(context.Background(), buildsCli, artifactsCli)
if err != nil {
t.Errorf("unxpected error: %v", err)
}
compare := func(expected []string, actual []string) {
if len(expected) != len(actual) {
t.Errorf("expected:\n%+v\nbut got:\n%+v", expected, actual)
}
fileMap := map[string]bool{}
for _, file := range expected {
fileMap[file] = true
}
for _, file := range actual {
if _, ok := fileMap[file]; !ok {
t.Errorf("expected:\n%+v\nbut got:\n%+v", expected, actual)
}
}
}
compare(tt.expectedFiles, artifactsCli.dir.copiedFiles)
})
}
}