blob: 323eac1386f4523a1b3fc4c7fa39c4742157ce46 [file] [log] [blame]
package actions
import (
"context"
"fmt"
"os"
"path"
"testing"
"cos.googlesource.com/cos/tools.git/src/pkg/dkms"
"cos.googlesource.com/cos/tools.git/src/pkg/fakes"
"cos.googlesource.com/cos/tools.git/src/pkg/fs"
"cos.googlesource.com/cos/tools.git/src/pkg/gcs"
"github.com/google/go-cmp/cmp"
)
func TestFetchKernelVersion(t *testing.T) {
kernelVersion, err := FetchKernelVersion()
if err != nil {
t.Fatalf("error fetching kernel version: %v", err)
}
if kernelVersion == "" {
t.Fatal("expected to find kernel version, found none")
}
t.Setenv("KERNEL_VERSION", "abc")
kernelVersion, err = FetchKernelVersion()
if err != nil {
t.Fatalf("error fetching kernel version: %v", err)
}
if kernelVersion != "abc" {
t.Fatalf("expected kernel version to be abc, found %s", kernelVersion)
}
}
func TestFetchKernelVersionFromHeaders(t *testing.T) {
kernelVersion, err := FetchKernelVersionFromHeaders("19126.0.0", "lakitu")
if err != nil {
t.Fatalf("error fetching kernel version: %v", err)
}
if kernelVersion != "6.6.94+" {
t.Fatalf("expected to find kernel version 6.6.94+, found %s", kernelVersion)
}
}
func TestFetchArch(t *testing.T) {
arch, err := FetchArch()
if err != nil {
t.Fatalf("error fetching arch: %v", err)
}
if arch == "" {
t.Fatal("expected to find arch, found none")
}
t.Setenv("ARCH", "abc")
arch, err = FetchArch()
if err != nil {
t.Fatalf("error fetching arch: %v", err)
}
if arch != "abc" {
t.Fatalf("expected arch to be abc, found %s", arch)
}
}
func TestParsePackageNameAndVersion(t *testing.T) {
testCases := []struct {
name string
version string
expectedName string
expectedVersion string
okay bool
}{
{"mymodule", "123", "mymodule", "123", true},
{"mymodule/123", "", "mymodule", "123", true},
{"", "", "", "", false},
{"mymodule", "", "", "", false},
{"", "123", "", "", false},
{"mymodule/1", "3", "", "", false},
{"mymodule/1/2", "", "", "", false},
{"mymodule/1/2", "3", "", "", false},
}
for _, testCase := range testCases {
name, version, err := ParsePackageNameAndVersion(testCase.name, testCase.version)
if testCase.okay {
if err != nil {
t.Fatalf("unexpected error for test case %v: %v", testCase, err)
}
if name != testCase.expectedName || version != testCase.expectedVersion {
t.Fatalf("expected name to be %s and version to be %s, found %s and %s",
testCase.expectedName, testCase.expectedVersion, name, version)
}
}
if !testCase.okay && err == nil {
t.Fatalf("expected error for test case %v, but error was nil", testCase)
}
}
}
func TestFetchLatestCompatiblePackageVersion(t *testing.T) {
ctx := context.Background()
fakeGCS := fakes.GCSForTest(t)
fakeGCS.LogMissing = false
cache := gcs.NewGCSBucket(fakeGCS.Client, "test", "dkms")
pkg := &dkms.Package{
Name: "mymodule",
Trees: &dkms.Trees{
Source: t.TempDir(),
Dkms: t.TempDir(),
},
}
// Make sure we get errors when there are no compatible versions yet
version, err := FetchLatestCompatiblePackageVersion(pkg, nil)
if err == nil {
t.Fatal("expected an error when no compatible versoins are present locally")
}
version, err = FetchLatestCompatiblePackageVersion(pkg, cache)
if err == nil {
t.Fatal("expected an error when no compatible versions are present locally or in cache")
}
// We need to add some package before we can use --latest
for _, version := range []string{"0.3", "1.0", "1.5"} {
fs.CopyDir(
"testdata/source-tree/mymodule-1.0",
path.Join(pkg.Trees.Source, fmt.Sprintf("mymodule-%s", version)),
0777,
)
versionPackage := pkg
versionPackage.Version = version
InitPackage(versionPackage, nil, false)
options := &dkms.Options{Upload: true}
if err := dkms.CachedAdd(ctx, pkg, cache, options); err != nil {
t.Fatal(err)
}
}
// Check only the local versions first
version, err = FetchLatestCompatiblePackageVersion(pkg, nil)
if err != nil {
t.Fatal(err)
}
if version != "1.5" {
t.Fatalf("expected latest version to be 1.5, found %s", version)
}
// Remove the local sources so we're forced to check the cache
for _, version := range []string{"0.3", "1.0", "1.5"} {
os.RemoveAll(path.Join(pkg.Trees.Source, fmt.Sprintf("mymodule-%s", version)))
}
version, err = FetchLatestCompatiblePackageVersion(pkg, nil)
if err == nil {
t.Fatal("did not expect to find sources locally; check that remove is working")
}
// Check the cached versions
version, err = FetchLatestCompatiblePackageVersion(pkg, cache)
if err != nil {
t.Fatal(err)
}
if version != "1.5" {
t.Fatalf("expected latest version to be 1.5, found %s", version)
}
}
func TestInitPackage(t *testing.T) {
// Make sure unset keys get loaded from environment
t.Setenv("BUILD_ID", "test-build-id")
t.Setenv("BOARD", "test-board")
t.Setenv("KERNEL_VERSION", "test-kernel-version")
t.Setenv("ARCH", "test-arch")
pkg := &dkms.Package{Name: "mymodule/1.0", Trees: &dkms.Trees{}}
expectedTrees := &dkms.Trees{
Source: "/usr/src",
Dkms: "",
Install: "/lib/modules/test-kernel-version",
Kernel: "/lib/modules/test-kernel-version/build",
KernelModules: "/lib/modules/test-kernel-version",
}
expectedPackage := &dkms.Package{
Name: "mymodule",
Version: "1.0",
BuildId: "test-build-id",
Board: "test-board",
KernelVersion: "test-kernel-version",
Arch: "test-arch",
Trees: expectedTrees,
}
InitCOSValues(pkg, "testdata/lsb-release")
if err := InitPackage(pkg, nil, false); err != nil {
t.Fatal(err)
}
if diff := cmp.Diff(expectedPackage, pkg); diff != "" {
t.Fatalf("package differed from expected: %s", diff)
}
// Make sure that initPackage is a no-op for a package which is already
// initialized
expectedPackageCopy := expectedPackage
expectedTreesCopy := expectedTrees
expectedPackageCopy.Trees = expectedTreesCopy
if err := InitPackage(expectedPackageCopy, nil, false); err != nil {
t.Fatal(err)
}
if diff := cmp.Diff(expectedPackage, expectedPackageCopy); diff != "" {
t.Fatalf("package differed from expected: %s", diff)
}
}
func TestInitCOSValues(t *testing.T) {
// Make sure BuildId and Board get loaded from lsb-release
pkg := &dkms.Package{}
expectedPackage := &dkms.Package{
BuildId: "18808.0.0",
Board: "lakitu",
}
InitCOSValues(pkg, "testdata/lsb-release")
if diff := cmp.Diff(expectedPackage, pkg); diff != "" {
t.Fatalf("package differed from expected: %s", diff)
}
// Make sure that env variables can override the lsb-release values
t.Setenv("BUILD_ID", "test-env-build-id")
t.Setenv("BOARD", "test-env-board")
pkg = &dkms.Package{}
expectedPackage = &dkms.Package{
BuildId: "test-env-build-id",
Board: "test-env-board",
}
InitCOSValues(pkg, "")
if diff := cmp.Diff(expectedPackage, pkg); diff != "" {
t.Fatalf("package differed from expected: %s", diff)
}
}
func TestInitPackageLatest(t *testing.T) {
pkg := &dkms.Package{
Name: "mymodule",
Version: "1.0",
Trees: &dkms.Trees{
Source: "testdata/source-tree",
Dkms: t.TempDir(),
},
}
// We need to add a package before we can use --latest
InitPackage(pkg, nil, false)
if err := dkms.Add(pkg, &dkms.Options{}); err != nil {
t.Fatal(err)
}
latestPackage := pkg
latestPackage.Version = ""
if err := InitPackage(latestPackage, nil, true); err != nil {
t.Fatal(err)
}
if diff := cmp.Diff(pkg, latestPackage); diff != "" {
t.Fatalf("package differed from expected: %s", diff)
}
// Make sure that latest and an explicit version are mutually exclusive
if err := InitPackage(pkg, nil, true); err == nil {
t.Fatal("expected error when using --latest and explicit version")
}
pkg.Version = "123"
if err := InitPackage(pkg, nil, true); err == nil {
t.Fatal("expected error when using --latest and explicit version")
}
pkg.Version = ""
pkg.Name = "mymodule/1.0"
if err := InitPackage(pkg, nil, true); err == nil {
t.Fatal("expected error when using --latest and explicit version")
}
}
func TestInitPackageLatestCache(t *testing.T) {
ctx := context.Background()
fakeGCS := fakes.GCSForTest(t)
fakeGCS.LogMissing = false
cache := gcs.NewGCSBucket(fakeGCS.Client, "test", "dkms")
pkg := &dkms.Package{
Name: "mymodule",
Version: "1.0",
Trees: &dkms.Trees{
Source: "testdata/source-tree",
Dkms: t.TempDir(),
},
}
// We need to add a package before we can use --latest
InitPackage(pkg, nil, false)
options := &dkms.Options{Upload: true}
if err := dkms.CachedAdd(ctx, pkg, cache, options); err != nil {
t.Fatal(err)
}
// Remove the local sources so we're forced to check the cache
if err := dkms.Remove(pkg); err != nil {
t.Fatal(err)
}
latestPackage := pkg
latestPackage.Version = ""
if err := InitPackage(latestPackage, cache, true); err != nil {
t.Fatal(err)
}
if diff := cmp.Diff(pkg, latestPackage); diff != "" {
t.Fatalf("package differed from expected: %s", diff)
}
}
func TestInitCache(t *testing.T) {
testCases := []struct {
gcsPath string
buildId string
board string
expectedUri string
}{
{"gs://mybucket", "", "", "gs://mybucket/obj"},
{"gs://mybucket/abc", "", "", "gs://mybucket/abc/obj"},
{"gs://mybucket/abc/def", "", "", "gs://mybucket/abc/def/obj"},
{"cos-default", "18808.0.0", "lakitu", "gs://cos-tools/18808.0.0/lakitu/obj"},
}
for _, testCase := range testCases {
cache, err := InitCache(testCase.gcsPath, testCase.buildId, testCase.board)
if err != nil {
t.Fatalf("unexpected error for test case %v: %v", testCase, err)
}
if cache.URI("obj") != testCase.expectedUri {
t.Fatalf("expected obj URI to be %s, found %s", testCase.expectedUri, cache.URI("obj"))
}
}
}
func TestParsePositionalArgs(t *testing.T) {
testCases := []struct {
args []string
pkg *dkms.Package
expectedPackage *dkms.Package
okay bool
}{
{
[]string{"mymodule"},
&dkms.Package{Trees: &dkms.Trees{}},
&dkms.Package{Name: "mymodule", Trees: &dkms.Trees{}},
true,
},
{
[]string{"mymodule"},
&dkms.Package{Trees: &dkms.Trees{}},
&dkms.Package{Name: "mymodule", Trees: &dkms.Trees{}},
true,
},
{
[]string{"mymodule/1.0"},
&dkms.Package{Trees: &dkms.Trees{}},
&dkms.Package{Name: "mymodule/1.0", Trees: &dkms.Trees{}},
true,
},
{
[]string{"mymodule/1.0", "source-tree"},
&dkms.Package{Trees: &dkms.Trees{}},
&dkms.Package{Name: "mymodule/1.0", Trees: &dkms.Trees{Source: "source-tree"}},
true,
},
{
[]string{"mymodule"},
&dkms.Package{Name: "mymodule", Trees: &dkms.Trees{}},
nil,
false,
},
{
[]string{"mymodule", "1.0.1"},
&dkms.Package{Name: "mymodule", Trees: &dkms.Trees{}},
nil,
false,
},
{
[]string{"mymodule/1.0", "source-tree"},
&dkms.Package{Trees: &dkms.Trees{Source: "source-tree"}},
nil,
false,
},
{
[]string{"mymodule/1.0", "source-tree", "arg3"},
&dkms.Package{Trees: &dkms.Trees{}},
nil,
false,
},
}
for i, testCase := range testCases {
err := parsePositionalArgs(testCase.args, testCase.pkg)
t.Log(err)
if testCase.okay {
if err != nil {
t.Fatalf("unexpected error for test case %v: %v", testCase, err)
}
if diff := cmp.Diff(testCase.expectedPackage, testCase.pkg); diff != "" {
t.Fatalf("test case %d package differed from expected: %v", i, diff)
}
}
if !testCase.okay && err == nil {
t.Fatalf("expected error for test case %v, but error was nil", testCase)
}
}
}