blob: 55754b0fd7b3b86dc5e0f24943a7246c8ca72273 [file] [log] [blame]
package dkms
import (
"context"
"os"
"path"
"sort"
"strings"
"testing"
"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 TestBuild(t *testing.T) {
options := &Options{
Force: false,
MakeVariables: "",
InstallBuildDependencies: false,
}
trees := &Trees{
Dkms: t.TempDir(),
Source: "testdata/source-tree",
Kernel: "testdata/kernel-source/lib/modules/6.1.100/build",
}
pkg := &Package{
Name: "mymodule",
Version: "1.0",
KernelVersion: "6.1.100",
Arch: "x86_64",
BuildId: "18244.151.14",
Trees: trees,
}
err := Build(pkg, options)
if err != nil {
t.Fatalf("%v", err)
}
makefilePath := path.Join(trees.Dkms, "mymodule", "1.0", "6.1.100", "x86_64", "18244.151.14", "source", "Makefile")
if !fs.IsFile(makefilePath) {
t.Fatalf("expected to find file %s after adding sources", makefilePath)
}
buildMakefilePath := path.Join(trees.Dkms, "mymodule", "1.0", "6.1.100", "x86_64", "18244.151.14", "build", "Makefile")
if !fs.IsFile(buildMakefilePath) {
t.Fatalf("expected to find file %s after building", makefilePath)
}
builtModulePath := path.Join(trees.Dkms, "mymodule", "1.0", "6.1.100", "x86_64", "18244.151.14", "build", "mymodule.ko")
if !fs.IsFile(builtModulePath) {
t.Fatalf("expected to find file %s after building", makefilePath)
}
}
func TestCachedBuild(t *testing.T) {
options := &Options{
Force: false,
MakeVariables: "",
InstallBuildDependencies: false,
Upload: true,
}
trees := &Trees{
Dkms: t.TempDir(),
Source: "testdata/source-tree",
Kernel: "testdata/kernel-source/lib/modules/6.1.100/build",
}
pkg := &Package{
Name: "mymodule",
Version: "1.0",
KernelVersion: "6.1.100",
Arch: "x86_64",
BuildId: "18244.151.14",
Trees: trees,
}
ctx := context.Background()
fakeGCS := fakes.GCSForTest(t)
bucket := gcs.NewGCSBucket(fakeGCS.Client, "test", "dkms")
err := CachedBuild(ctx, pkg, bucket, options)
if err != nil {
t.Fatalf("%v", err)
}
makefilePath := path.Join(trees.Dkms, "mymodule", "1.0", "6.1.100", "x86_64", "18244.151.14", "source", "Makefile")
if !fs.IsFile(makefilePath) {
t.Fatalf("expected to find file %s after adding sources", makefilePath)
}
buildMakefilePath := path.Join(trees.Dkms, "mymodule", "1.0", "6.1.100", "x86_64", "18244.151.14", "build", "Makefile")
if !fs.IsFile(buildMakefilePath) {
t.Fatalf("expected to find file %s after building", makefilePath)
}
builtModulePath := path.Join(trees.Dkms, "mymodule", "1.0", "6.1.100", "x86_64", "18244.151.14", "build", "mymodule.ko")
if !fs.IsFile(builtModulePath) {
t.Fatalf("expected to find file %s after building", makefilePath)
}
cachedMakefileExists, err := bucket.Exists(ctx, makefilePath)
if err != nil {
t.Fatalf("failed to check if %s exists", makefilePath)
}
if !cachedMakefileExists {
t.Fatalf("expected to find file %s in cache after adding sources", makefilePath)
}
cachedModuleExists, err := bucket.Exists(ctx, builtModulePath)
if err != nil {
t.Fatalf("failed to check if %s exists", builtModulePath)
}
if !cachedModuleExists {
t.Fatalf("expected to find file %s in cache after building modules", builtModulePath)
}
}
func TestDefaultMakeVariables(t *testing.T) {
trees := &Trees{
Kernel: "testdata/kernel-sources",
}
pkg := &Package{
Arch: "abc",
Trees: trees,
}
variables, err := DefaultMakeVariables(pkg)
if err != nil {
t.Fatalf("%v", err)
}
expectedList := []string{
"ARCH=abc",
// because CC and CXX are loaded from toolchain_env, the arch will be
// arch from the file and not the argument to DefaultMakeVariables
"CC=toolchain/bin/x86_64-cros-linux-gnu-clang",
"CXX=toolchain/bin/x86_64-cros-linux-gnu-clang++",
"LD=toolchain/bin/abc-cros-linux-gnu-ld.lld",
"STRIP=toolchain/bin/llvm-strip",
"OBJCOPY=toolchain/bin/llvm-objcopy",
"HOSTCC=abc-pc-linux-gnu-clang",
"HOSTCXX=abc-pc-linux-gnu-clang++",
"HOSTLD=abc-pc-linux-gnu-clang",
}
sort.Strings(expectedList)
expected := strings.Join(expectedList, " ")
diff := cmp.Diff(expected, variables)
if diff != "" {
t.Fatalf("default variables did not match expected\ndiff: %s", diff)
}
}
func TestApplyPatch(t *testing.T) {
buildDir := t.TempDir()
if err := fs.CopyDir("testdata/source-tree/mymodule-1.0", buildDir, 0777); err != nil {
t.Fatalf("%v", err)
}
patchPath := path.Join(buildDir, "patches", "a.patch")
if err := ApplyPatch(buildDir, patchPath); err != nil {
t.Fatalf("%v", err)
}
contents, err := os.ReadFile(path.Join(buildDir, "mymodule.c"))
if err != nil {
t.Fatalf("%v", err)
}
text := string(contents)
if !strings.Contains(text, "patched") {
t.Fatalf("expected mymodule.c to have comment `//patched` after patch is applied")
}
}
func TestInstallBuildDependencies(t *testing.T) {
downloader := fakeDownloader{}
ctx := context.Background()
targetDir := t.TempDir()
defer os.RemoveAll(targetDir)
err := installBuildDependencies(ctx, &downloader, targetDir)
if err != nil {
t.Errorf("failed to install build dependencies headers: %v", err)
}
if !KernelHeadersInstalled(targetDir) {
t.Errorf("expected headers to be installed")
}
if !CompilerToolchainInstalled(targetDir) {
t.Errorf("expected compiler toolchain to be installed")
}
}