| 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 TestParseKeyCertPaths(t *testing.T) { | |
| t.Setenv("MODULES_SIGN_KEY", "/var/modules/key") | |
| t.Setenv("MODULES_SIGN_CERT", "/var/modules/cert") | |
| opts := &dkms.Options{} | |
| parseKeyCertPaths(opts) | |
| if opts.PrivateKeyPath != "/var/modules/key" { | |
| t.Fatalf("expected private key path '/var/modules/key', got: %s", opts.PrivateKeyPath) | |
| } | |
| if opts.CertificatePath != "/var/modules/cert" { | |
| t.Fatalf("expected private key path '/var/modules/cert', got: %s", opts.CertificatePath) | |
| } | |
| } | |
| func TestFetchKernelVersionFromHeaders(t *testing.T) { | |
| kernelVersion, err := FetchKernelVersionFromHeaders("19126.0.0", "lakitu", false) | |
| 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, "", "", 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) | |
| } | |
| // Check for versions in the given range | |
| version, err = FetchLatestCompatiblePackageVersion(pkg, cache, "1.0", "1.2") | |
| if err != nil { | |
| t.Fatal(err) | |
| } | |
| if version != "1.0" { | |
| t.Fatalf("expected latest version to be 1.0, 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, "", "", 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, "", "", 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, "", "", false) | |
| if err := dkms.Add(pkg, &dkms.Options{}); err != nil { | |
| t.Fatal(err) | |
| } | |
| latestPackage := pkg | |
| latestPackage.Version = "" | |
| if err := InitPackage(latestPackage, nil, true, "", "", false); 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, "", "", false); err == nil { | |
| t.Fatal("expected error when using --latest and explicit version") | |
| } | |
| pkg.Version = "123" | |
| if err := InitPackage(pkg, nil, true, "", "", false); 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, "", "", false); err == nil { | |
| t.Fatal("expected error when using --latest and explicit version") | |
| } | |
| pkg.Name = "mymodule" | |
| // minVersion/maxVersion should not be used at the same time as an | |
| // explicit version. | |
| pkg.Version = "123" | |
| if err := InitPackage(pkg, nil, false, "234", "", false); err == nil { | |
| t.Fatal("expected error when using --min-version and explicit version") | |
| } | |
| pkg.Version = "123" | |
| if err := InitPackage(pkg, nil, false, "", "234", false); err == nil { | |
| t.Fatal("expected error when using --max-version and explicit version") | |
| } | |
| // minVersion or maxVersion should work with --latest. | |
| pkg.Version = "" | |
| if err := InitPackage(pkg, nil, true, "0.9", "", false); err != nil { | |
| t.Fatal(err) | |
| } | |
| if pkg.Version != "1.0" { | |
| t.Fatalf("expected package version to be 1.0, got %s", pkg.Version) | |
| } | |
| pkg.Version = "" | |
| if err := InitPackage(pkg, nil, true, "", "1.1", false); err != nil { | |
| t.Fatal(err) | |
| } | |
| if pkg.Version != "1.0" { | |
| t.Fatalf("expected package version to be 1.0, got %s", pkg.Version) | |
| } | |
| // minVersion or maxVersion should imply --latest. | |
| pkg.Version = "" | |
| if err := InitPackage(pkg, nil, false, "0.9", "", false); err != nil { | |
| t.Fatal(err) | |
| } | |
| if pkg.Version != "1.0" { | |
| t.Fatalf("expected package version to be 1.0, got %s", pkg.Version) | |
| } | |
| pkg.Version = "" | |
| if err := InitPackage(pkg, nil, false, "", "1.1", false); err != nil { | |
| t.Fatal(err) | |
| } | |
| if pkg.Version != "1.0" { | |
| t.Fatalf("expected package version to be 1.0, got %s", pkg.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, "", "", 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, "", "", false); 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 | |
| useRegional bool | |
| expectedUri string | |
| }{ | |
| {"gs://mybucket", "", "", false, "gs://mybucket/obj"}, | |
| {"gs://mybucket/abc", "", "", false, "gs://mybucket/abc/obj"}, | |
| {"gs://mybucket/abc/def", "", "", false, "gs://mybucket/abc/def/obj"}, | |
| {"cos-default", "18808.0.0", "lakitu", false, "gs://cos-tools/18808.0.0/lakitu/obj"}, | |
| } | |
| for _, testCase := range testCases { | |
| cache, err := InitCache(testCase.gcsPath, testCase.buildId, testCase.board, testCase.useRegional) | |
| 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) | |
| } | |
| } | |
| } |