This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

core / spindle / engines / microvm / image_test.go
3.4 kB 135 lines
1package microvm 2 3import ( 4 "encoding/json" 5 "os" 6 "path/filepath" 7 "strings" 8 "testing" 9) 10 11func writeSpecFile(t *testing.T, path string) { 12 t.Helper() 13 data, err := json.Marshal(validImageSpec()) 14 if err != nil { 15 t.Fatal(err) 16 } 17 if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { 18 t.Fatal(err) 19 } 20 if err := os.WriteFile(path, data, 0o644); err != nil { 21 t.Fatal(err) 22 } 23} 24 25func TestResolveImageConventionalLayouts(t *testing.T) { 26 cases := []struct { 27 name string 28 layout func(t *testing.T, dir string) 29 }{ 30 { 31 name: "directory with spec.json", 32 layout: func(t *testing.T, dir string) { 33 writeSpecFile(t, filepath.Join(dir, "nixos", "spec.json")) 34 }, 35 }, 36 { 37 name: "flat <name>.json", 38 layout: func(t *testing.T, dir string) { 39 writeSpecFile(t, filepath.Join(dir, "nixos.json")) 40 }, 41 }, 42 } 43 44 for _, tc := range cases { 45 t.Run(tc.name, func(t *testing.T) { 46 dir := t.TempDir() 47 tc.layout(t, dir) 48 49 e := testEngine(t, dir) 50 spec, path, name, err := e.resolveImage("nixos") 51 if err != nil { 52 t.Fatalf("resolveImage: %v", err) 53 } 54 if name != "nixos" { 55 t.Fatalf("name = %q, want nixos", name) 56 } 57 if !strings.HasPrefix(path, dir) { 58 t.Fatalf("resolved path %q not under image dir %q", path, dir) 59 } 60 if spec.Shell == "" { 61 t.Fatal("resolved spec not loaded") 62 } 63 }) 64 } 65} 66 67func TestResolveImageDirectoryMissingSpec(t *testing.T) { 68 dir := t.TempDir() 69 if err := os.MkdirAll(filepath.Join(dir, "nixos"), 0o755); err != nil { 70 t.Fatal(err) 71 } 72 73 e := testEngine(t, dir) 74 _, _, _, err := e.resolveImage("nixos") 75 if err == nil || !strings.Contains(err.Error(), imageSpecFileName) { 76 t.Fatalf("directory without %s should error, got: %v", imageSpecFileName, err) 77 } 78} 79 80func TestResolveImageRequiresImageDirOnlyWhenUsed(t *testing.T) { 81 e := testEngine(t, "") 82 _, _, _, err := e.resolveImage("nixos") 83 if err == nil || !strings.Contains(err.Error(), "SPINDLE_MICROVM_PIPELINES_IMAGE_DIR") { 84 t.Fatalf("missing image directory should error when resolving an image, got: %v", err) 85 } 86} 87 88func TestResolveImageRejectsPaths(t *testing.T) { 89 e := testEngine(t, t.TempDir()) 90 for _, name := range []string{"/etc/passwd", "../evil", "sub/evil", "..", "."} { 91 if _, _, _, err := e.resolveImage(name); err == nil || !strings.Contains(err.Error(), "must be a plain name") { 92 t.Fatalf("name %q should be rejected as a path, got: %v", name, err) 93 } 94 } 95} 96 97func validImageSpec() ImageSpec { 98 return ImageSpec{ 99 Arch: "x86_64", 100 BootArgs: "console=ttyS0", 101 Initrd: "initrd", 102 Kernel: "kernel", 103 RunnerConfig: RunnerConfig{ 104 Machine: "microvm", 105 }, 106 MemoryMiB: 2048, 107 Shell: "/bin/sh", 108 StoreDisk: "store-disk", 109 VCPUs: 2, 110 } 111} 112 113func TestImageSpecValidateWithoutBaseConfigHash(t *testing.T) { 114 spec := validImageSpec() 115 if err := spec.Validate(); err != nil { 116 t.Fatalf("non-NixOS image spec should validate: %v", err) 117 } 118 if spec.SupportsConfigActivation() { 119 t.Fatal("spec without baseConfigHash should not support config activation") 120 } 121 122 spec.BaseConfigHash = "abcdef" 123 if !spec.SupportsConfigActivation() { 124 t.Fatal("spec with baseConfigHash should support config activation") 125 } 126} 127 128func TestImageSpecRequiresShell(t *testing.T) { 129 spec := validImageSpec() 130 spec.Shell = "" 131 err := spec.Validate() 132 if err == nil || !strings.Contains(err.Error(), "shell") { 133 t.Fatalf("spec without shell should fail validation, got: %v", err) 134 } 135}