blob: 94b85666c574d3ceda262b4f2f62f83c95cbe25f [file] [edit]
package kernelmods
import (
"context"
"fmt"
"os"
"path/filepath"
"reflect"
"strings"
"testing"
"github.com/fsouza/fake-gcs-server/fakestorage"
"cos-extensions/tools/gcs"
)
func TestListInstalledModulesDirNonExistent(t *testing.T) {
dirName := "nonexistent/"
_, err := ListInstalledModules(dirName, false)
wantErrMessage := "failed to retrieve module files from directory nonexistent/: failed to validate local directory"
if err == nil || !strings.HasPrefix(err.Error(), wantErrMessage) {
t.Errorf(" TestListNewModulesDirNonExistent: expected error: %s \t got error: %v", wantErrMessage, err)
}
}
func TestListInstalledModulesSuccessful(t *testing.T) {
retrieveInstalledModules = func(moduleFiles []string) (map[string]string, error) {
modMap := make(map[string]string)
for _, modFile := range moduleFiles {
mod := strings.Split(modFile, "/")
modName, _ := strings.CutSuffix(mod[len(mod)-1], ".ko")
modMap[modFile] = modName
}
return modMap, nil
}
tmpDir, err := os.MkdirTemp("", "test-module")
if err != nil {
t.Fatalf("Failed to create temp dir: %v", err)
}
defer os.RemoveAll(tmpDir)
filePath := filepath.Join(tmpDir, "unknown.txt")
_, err = os.Create(filePath)
if err != nil {
t.Fatalf("Failed to create temp file: %v", err)
}
filePath = filepath.Join(tmpDir, "module.ko")
_, err = os.Create(filePath)
if err != nil {
t.Fatalf("Failed to create temp file: %v", err)
}
got, err := ListInstalledModules(tmpDir, false)
if err != nil {
t.Errorf("TestListModulesSuccessful: error: %v", err)
}
want := map[string]string{filePath: "module"}
if !reflect.DeepEqual(got, want) {
t.Errorf("TestListModulesSuccessful: expected module paths: %v\t got module paths: %v", want, got)
}
}
func TestListDownloadedModulesSuccessful(t *testing.T) {
tmpDir, err := os.MkdirTemp("", "test-module")
if err != nil {
t.Fatalf("Failed to create temp dir: %v", err)
}
defer os.RemoveAll(tmpDir)
filePath := filepath.Join(tmpDir, "unknown.txt")
_, err = os.Create(filePath)
if err != nil {
t.Fatalf("Failed to create temp file: %v", err)
}
filePath = filepath.Join(tmpDir, "module.ko")
_, err = os.Create(filePath)
if err != nil {
t.Fatalf("Failed to create temp file: %v", err)
}
retrieveLocalModulesInfo = func(moduleFiles []string) map[string]string {
modMap := make(map[string]string)
for _, modFile := range moduleFiles {
mod := strings.Split(modFile, "/")
modName, _ := strings.CutSuffix(mod[len(mod)-1], ".ko")
modMap[modFile] = modName
}
return modMap
}
got, err := ListDownloadedModules(tmpDir, false)
if err != nil {
t.Errorf("TestListModulesSuccessful: error: %v", err)
}
want := map[string]string{
filePath: "module",
}
if !reflect.DeepEqual(got, want) {
t.Errorf("TestListDownloadedModulesSuccessful: expected module paths: %v\t got module paths: %v", want, got)
}
}
func TestInstallModules(t *testing.T) {
retrieveInstalledModules = func(_ []string) (map[string]string, error) {
return map[string]string{"/var/lib/module/skip1.ko": "skip1", "/var/lib/module/skip2.ko": "skip2"}, nil
}
installModule = func(modPath string, _ []string) error {
if modPath == "/var/lib/module/error.ko" {
return fmt.Errorf("An error occured")
}
return nil
}
tests := []struct {
desc string
modulePaths []string
want []string
}{
{
desc: "Successfully installs modules",
modulePaths: []string{"/var/lib/module/module1.ko", "/var/lib/module/module2.ko"},
want: []string{"/var/lib/module/module1.ko", "/var/lib/module/module2.ko"},
}, {
desc: "Skips module already installed.",
modulePaths: []string{"/var/lib/module/skip1.ko", "/var/lib/module/module2.ko"},
want: []string{"/var/lib/module/module2.ko"},
}, {
desc: "Skips module that fails to install",
modulePaths: []string{"/var/lib/module/error.ko", "/var/lib/module/module2.ko"},
want: []string{"/var/lib/module/module2.ko"},
},
}
for _, test := range tests {
t.Run(test.desc, func(t *testing.T) {
got, err := InstallModules(test.modulePaths, []string{})
if err != nil {
t.Errorf("TestInstallModules(%s): error: %v", test.desc, err)
}
if !reflect.DeepEqual(got, test.want) {
t.Errorf("TestInstallModules(%s): expected module paths: %s\t got module paths: %s", test.desc, test.want, got)
}
})
}
}
func TestDownloadModulesSuccessful(t *testing.T) {
ctx := context.Background()
tmpDir, err := os.MkdirTemp("", "test-gcs")
if err != nil {
t.Fatalf("Failed to create temp dir: %v", err)
}
defer os.RemoveAll(tmpDir)
server := fakestorage.NewServer(
[]fakestorage.Object{
{ObjectAttrs: fakestorage.ObjectAttrs{
BucketName: "my-bucket", Name: "path/to/module/module1.ko",
},
Content: []byte("content"),
},
})
var cfg gcs.GCSConfig
err = cfg.Init(ctx, "gs://my-bucket/path/to/module", server.Client())
if err != nil {
t.Fatalf("Failed to initialize gcs config: %v", err)
}
moduleFiles := []string{"module1.ko", "skip.ko"}
want := []string{fmt.Sprintf("%s/module1.ko", tmpDir)}
got, err := DownloadModules(ctx, &cfg, moduleFiles, tmpDir, false)
if err != nil {
t.Errorf("TestDownloadModulesSuccessful: error: %v", err)
}
if !reflect.DeepEqual(want, got) {
t.Errorf("TestDownloadKernelModuleSuccessful: expected module paths: %s\t got module paths: %s", want, got)
}
}
func TestDownloadModulesRecursivelySuccessful(t *testing.T) {
ctx := context.Background()
tmpDir, err := os.MkdirTemp("", "test-gcs")
if err != nil {
t.Fatalf("Failed to create temp dir: %v", err)
}
defer os.RemoveAll(tmpDir)
server := fakestorage.NewServer(
[]fakestorage.Object{
{ObjectAttrs: fakestorage.ObjectAttrs{
BucketName: "my-bucket", Name: "path/to/module/a.ko",
},
Content: []byte("content"),
},
{ObjectAttrs: fakestorage.ObjectAttrs{
BucketName: "my-bucket", Name: "path/to/module/b/b.ko",
},
Content: []byte("content"),
},
{ObjectAttrs: fakestorage.ObjectAttrs{
BucketName: "my-bucket", Name: "path/to/module/c.ko",
},
Content: []byte("content"),
},
{ObjectAttrs: fakestorage.ObjectAttrs{
BucketName: "my-bucket", Name: "path/to/module/d",
},
Content: []byte("not module"),
},
})
defer server.Stop()
var cfg gcs.GCSConfig
err = cfg.Init(ctx, "gs://my-bucket/path/to/module", server.Client())
if err != nil {
t.Fatalf("Failed to initialize gcs config: %v", err)
}
got, err := DownloadModules(ctx, &cfg, []string{}, tmpDir, true)
if err != nil {
t.Errorf("TestDownloadAllKernelModulesSuccessful: failed to download module: %v", err)
}
want := []string{filepath.Join(tmpDir, "a.ko"), filepath.Join(tmpDir, "b/b.ko"), filepath.Join(tmpDir, "c.ko")}
if !reflect.DeepEqual(got, want) {
t.Errorf("TestDownloadModulesRecursivelySuccessful: expected path: %s\t got path: %s", want, got)
}
}
func TestRetrieveModulePaths(t *testing.T) {
tmpDir, err := os.MkdirTemp("", "test-gcs")
if err != nil {
t.Fatalf("Failed to create temp dir (%s): %v", tmpDir, err)
}
defer os.RemoveAll(tmpDir)
subdir, err := os.MkdirTemp(tmpDir, "sub-test-gcs")
if err != nil {
t.Fatalf("Failed to create temp dir (%s): %v", subdir, err)
}
dsts := []string{filepath.Join(tmpDir, "module1.ko"), filepath.Join(subdir, "module2.ko")}
for _, dst := range dsts {
f, err := os.Create(dst)
f.Close()
if err != nil {
t.Fatalf("Failed to file (%s): %v", dst, err)
}
}
tests := []struct {
desc string
recursive bool
want []string
}{
{
desc: "Returns all module files in immediate directory.",
want: []string{dsts[0]},
},
{
desc: "Returns all module files in directory and subdirectory recursively.",
recursive: true,
want: dsts,
},
}
for _, test := range tests {
t.Run(test.desc, func(t *testing.T) {
var modPaths []string
got, err := retrieveModulePaths(tmpDir, modPaths, test.recursive)
if err != nil {
t.Errorf("TestRetrieveModulePaths(%s): error: %v", test.desc, err)
}
if !reflect.DeepEqual(got, test.want) {
t.Errorf("TestRetrieveModulePaths(%s): expected module paths: %s\t got module paths: %s", test.desc, test.want, got)
}
})
}
}