blob: 99c587f1b8169dc86ecbe944f9837ef4b48d42b8 [file] [edit]
// Copyright 2026 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package androidtools
import (
"context"
"testing"
"time"
"github.com/golang/mock/gomock"
"google.golang.org/grpc"
"go.chromium.org/chromiumos/config/go/test/api"
"go.chromium.org/luci/common/errors"
"go.chromium.org/infra/cros/lib/provisions/common"
"go.chromium.org/infra/cros/lib/provisions/common/mocks"
)
func TestDownloadFileLocally(t *testing.T) {
t.Parallel()
ctx := context.Background()
ctrl := gomock.NewController(t)
defer ctrl.Finish()
timeout := 1 * time.Minute
sourcePath := "http://example.com/file.zip"
distPath := "/tmp/file.zip"
mockRun := func(ctx context.Context, timeout time.Duration, cmd string, args ...string) (common.Response, error) {
if cmd != "curl" {
t.Errorf("Expected 'curl', got %q", cmd)
}
foundOutput := false
for i, arg := range args {
if arg == "--output" && i+1 < len(args) && args[i+1] == distPath {
foundOutput = true
break
}
}
if !foundOutput {
t.Errorf("Expected --output %s in args: %v", distPath, args)
}
mockResp := mocks.NewMockResponse(ctrl)
mockResp.EXPECT().GetStdout().Return([]byte("success"))
mockResp.EXPECT().GetStderr().Return([]byte(""))
return mockResp, nil
}
err := downloadFileLocally(ctx, mockRun, timeout, sourcePath, distPath)
if err != nil {
t.Errorf("downloadFileLocally() returned an unexpected error: %v", err)
}
}
func TestDownloadFileLocally_Errors(t *testing.T) {
t.Parallel()
ctx := context.Background()
ctrl := gomock.NewController(t)
defer ctrl.Finish()
timeout := 1 * time.Minute
sourcePath := "http://example.com/file.zip"
distPath := "/tmp/file.zip"
tests := []struct {
name string
runner common.RunnerFunc
wantErr bool
}{
{
name: "nil runner",
runner: nil,
wantErr: true,
},
{
name: "runner error",
runner: func(context.Context, time.Duration, string, ...string) (common.Response, error) {
return nil, errors.New("runner failed")
},
wantErr: true,
},
{
name: "curl non-zero exit",
runner: func(ctx context.Context, timeout time.Duration, cmd string, args ...string) (common.Response, error) {
return nil, errors.New("exit code 1") // common.Run delegates error for non-zero exit
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := downloadFileLocally(ctx, tt.runner, timeout, sourcePath, distPath)
if tt.wantErr != (err != nil) {
t.Errorf("downloadFileLocally() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
type mockToolsServiceClient struct {
api.ToolsServiceClient
downloadFileFunc func(ctx context.Context, in *api.DownloadFileRequest, opts ...grpc.CallOption) (*api.DownloadFileResponse, error)
}
func (m *mockToolsServiceClient) DownloadFile(ctx context.Context, in *api.DownloadFileRequest, opts ...grpc.CallOption) (*api.DownloadFileResponse, error) {
if m.downloadFileFunc != nil {
return m.downloadFileFunc(ctx, in, opts...)
}
return nil, nil
}
func TestDownloadFileGRPC(t *testing.T) {
t.Parallel()
ctx := context.Background()
timeout := 1 * time.Minute
sourcePath := "http://example.com/file.zip"
distPath := "/tmp/file.zip"
client := &mockToolsServiceClient{
downloadFileFunc: func(ctx context.Context, in *api.DownloadFileRequest, opts ...grpc.CallOption) (*api.DownloadFileResponse, error) {
if in.GetUrl() != sourcePath {
t.Errorf("Expected URL %q, got %q", sourcePath, in.GetUrl())
}
if in.GetDestinationPath() != distPath {
t.Errorf("Expected destination path %q, got %q", distPath, in.GetDestinationPath())
}
return &api.DownloadFileResponse{
DestinationPath: distPath,
}, nil
},
}
err := downloadFileGRPC(ctx, client, timeout, sourcePath, distPath)
if err != nil {
t.Errorf("downloadFileGRPC() returned unexpected error: %v", err)
}
}
func TestDownloadFileGRPC_Errors(t *testing.T) {
t.Parallel()
ctx := context.Background()
timeout := 1 * time.Minute
sourcePath := "http://example.com/file.zip"
distPath := "/tmp/file.zip"
tests := []struct {
name string
client api.ToolsServiceClient
wantErr bool
}{
{
name: "nil client",
client: nil,
wantErr: true,
},
{
name: "client error",
client: &mockToolsServiceClient{
downloadFileFunc: func(ctx context.Context, in *api.DownloadFileRequest, opts ...grpc.CallOption) (*api.DownloadFileResponse, error) {
return nil, errors.New("gRPC error")
},
},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := downloadFileGRPC(ctx, tt.client, timeout, sourcePath, distPath)
if tt.wantErr != (err != nil) {
t.Errorf("downloadFileGRPC() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}