Files
clr-installer/args/args_test.go
T
Mark D Horn ef45a32849 args: model: New options for partition checks
Add command line arguments and YAML file configurations for settings
skipping partition size checks during validation.

Skip Validation All implies Skip Size.

Never write skip validation options to YAML

Signed-off-by: Mark D Horn <mark.d.horn@intel.com>
2020-03-27 15:07:10 -07:00

623 lines
18 KiB
Go

// Copyright © 2020 Intel Corporation
//
// SPDX-License-Identifier: GPL-3.0-only
package args
import (
"fmt"
"io/ioutil"
"net/http"
"os"
"strconv"
"testing"
"github.com/clearlinux/clr-installer/log"
)
var (
testHTTPPort string
)
func init() {
testHTTPPort = os.Getenv("TEST_HTTP_PORT")
_ = os.Setenv(logFileEnvironVar, "")
}
func makeTestKernelCmd(cmd string) (string, error) {
kernelCmd := []byte(cmd)
tmpfile, err := ioutil.TempFile("/tmp", "kargTestCmd")
if err != nil {
return "", err
}
if _, err := tmpfile.Write(kernelCmd); err != nil {
return tmpfile.Name(), err
}
if err := tmpfile.Close(); err != nil {
return tmpfile.Name(), err
}
return tmpfile.Name(), nil
}
func serveHTTPDescFile(t *testing.T) (*http.Server, error) {
srv := &http.Server{Addr: ":" + testHTTPPort}
http.HandleFunc("/clr-installer.yaml", func(w http.ResponseWriter, r *http.Request) {
if _, err := fmt.Fprintf(w, "{}"); err != nil {
t.Error(err)
}
})
go func() {
_ = srv.ListenAndServe()
}()
return srv, nil
}
func TestKernelCmdInvalidFile(t *testing.T) {
var testArgs Args
var err error
// Check for read error
kernelCmdlineFile = "/proc/not-a-real-filename"
err = testArgs.setKernelArgs()
if testArgs.CfDownloaded && testArgs.ConfigFile != "" {
defer func() { _ = os.Remove(testArgs.ConfigFile) }()
}
if err == nil {
t.Errorf("Failed to detect a valid error reading kernel command")
return
}
}
func TestParseArgsKernelCmdInvalidFile(t *testing.T) {
var testArgs Args
var err error
// Check for read error
kernelCmdlineFile = "/proc/not-a-real-filename"
err = testArgs.ParseArgs()
if testArgs.CfDownloaded && testArgs.ConfigFile != "" {
defer func() { _ = os.Remove(testArgs.ConfigFile) }()
}
if err == nil {
t.Fatal("Failed to detect a valid error reading kernel command")
}
}
func TestTelemetry(t *testing.T) {
var testArgs Args
var err error
currArgs := make([]string, len(os.Args))
copy(currArgs, os.Args)
os.Args = append(os.Args, "--telemetry-url=http://telemetry")
err = testArgs.ParseArgs()
if testArgs.CfDownloaded && testArgs.ConfigFile != "" {
defer func() { _ = os.Remove(testArgs.ConfigFile) }()
}
if err == nil {
t.Fatal("Telemetry should require both --telemetry-url and --telemetry-tid")
}
os.Args = currArgs
}
func TestKernelCmdDemoTrue(t *testing.T) {
var testArgs Args
var kernelCmd string
var err error
// Check for Demo mode set true
kernelCmd = "root=PARTUUID=694da991-29f6-4cbd-ab72-6da064a799c0 quiet modprobe.blacklist=ccipciedrv,aalbus,aalrms,aalrmc console=tty0 console=ttyS0,115200n8 init=/usr/lib/systemd/systemd-bootchart initcall_debug tsc=reliable no_timer_check noreplace-smp kvm-intel.nested=1 rootfstype=ext4,btrfs,xfs,f2fs intel_iommu=igfx_off cryptomgr.notests rcupdate.rcu_expedited=1 i915.fastboot=1 rcu_nocbs=0-64 rw" + " " + kernelCmdlineDemo
kernelCmdlineFile, err = makeTestKernelCmd(kernelCmd)
defer func() {
_ = os.Remove(kernelCmdlineFile)
}()
if err != nil {
t.Errorf("Failed to makeTestKernelCmd with error %q", err)
return
}
err = testArgs.setKernelArgs()
if testArgs.CfDownloaded && testArgs.ConfigFile != "" {
defer func() { _ = os.Remove(testArgs.ConfigFile) }()
}
if err != nil {
t.Errorf("Failed to setKernelArgs with error %q", err)
return
}
if testArgs.DemoMode == false {
t.Errorf("Failed to detect Demo Mode TRUE with error kernel command %q", kernelCmd)
}
}
func TestKernelCmdDemoFalse(t *testing.T) {
var testArgs Args
var kernelCmd string
var err error
// Check for Demo mode set false
kernelCmd = "root=PARTUUID=694da991-29f6-4cbd-ab72-6da064a799c0 quiet modprobe.blacklist=ccipciedrv,aalbus,aalrms,aalrmc console=tty0 console=ttyS0,115200n8 init=/usr/lib/systemd/systemd-bootchart initcall_debug tsc=reliable no_timer_check noreplace-smp kvm-intel.nested=1 rootfstype=ext4,btrfs,xfs,f2fs intel_iommu=igfx_off cryptomgr.notests rcupdate.rcu_expedited=1 i915.fastboot=1 rcu_nocbs=0-64 rw .demo"
kernelCmdlineFile, err = makeTestKernelCmd(kernelCmd)
defer func() {
_ = os.Remove(kernelCmdlineFile)
}()
if err != nil {
t.Errorf("Failed to makeTestKernelCmd with error %q", err)
return
}
err = testArgs.setKernelArgs()
if testArgs.CfDownloaded && testArgs.ConfigFile != "" {
defer func() { _ = os.Remove(testArgs.ConfigFile) }()
}
if err != nil {
t.Errorf("Failed to setKernelArgs with error %q", err)
return
}
if testArgs.DemoMode == true {
t.Errorf("Failed to detect Demo Mode FALSE with error kernel command %q", kernelCmd)
}
}
func TestKernelCmdConfPresent(t *testing.T) {
var testArgs Args
var kernelCmd string
var err error
// Check for configuration file present
kernelCmd = "root=PARTUUID=694da991-29f6-4cbd-ab72-6da064a799c0 quiet modprobe.blacklist=ccipciedrv,aalbus,aalrms,aalrmc console=tty0 console=ttyS0,115200n8 init=/usr/lib/systemd/systemd-bootchart initcall_debug tsc=reliable no_timer_check noreplace-smp kvm-intel.nested=1 rootfstype=ext4,btrfs,xfs,f2fs intel_iommu=igfx_off cryptomgr.notests rcupdate.rcu_expedited=1 i915.fastboot=1 rcu_nocbs=0-64 rw" +
" " + kernelCmdlineConf + "=http://google.com"
kernelCmdlineFile, err = makeTestKernelCmd(kernelCmd)
defer func() {
_ = os.Remove(kernelCmdlineFile)
}()
if err != nil {
t.Errorf("Failed to makeTestKernelCmd with error %q", err)
return
}
err = testArgs.setKernelArgs()
if testArgs.CfDownloaded && testArgs.ConfigFile != "" {
defer func() { _ = os.Remove(testArgs.ConfigFile) }()
}
if err != nil {
t.Errorf("Failed to setKernelArgs with error %q", err)
return
}
if testArgs.ConfigFile == "" {
t.Errorf("Failed to detect Configuration File with kernel command %q", kernelCmd)
}
}
func TestKernelCmdLogPresent(t *testing.T) {
var testArgs Args
var kernelCmd string
var err error
forcedLogLevel := "1"
// Check for configuration file present
kernelCmd = "root=PARTUUID=694da991-29f6-4cbd-ab72-6da064a799c0 quiet modprobe.blacklist=ccipciedrv,aalbus,aalrms,aalrmc console=tty0 console=ttyS0,115200n8 init=/usr/lib/systemd/systemd-bootchart initcall_debug tsc=reliable no_timer_check noreplace-smp kvm-intel.nested=1 rootfstype=ext4,btrfs,xfs,f2fs intel_iommu=igfx_off cryptomgr.notests rcupdate.rcu_expedited=1 i915.fastboot=1 rcu_nocbs=0-64 rw" +
" " + kernelCmdlineLog + "=" + forcedLogLevel
kernelCmdlineFile, err = makeTestKernelCmd(kernelCmd)
defer func() {
_ = os.Remove(kernelCmdlineFile)
}()
if err != nil {
t.Errorf("Failed to makeTestKernelCmd with error %q", err)
return
}
err = testArgs.setKernelArgs()
if testArgs.CfDownloaded && testArgs.ConfigFile != "" {
defer func() { _ = os.Remove(testArgs.ConfigFile) }()
}
if err != nil {
t.Errorf("Failed to setKernelArgs with error %q", err)
return
}
var logLevel int
if logLevel, _ = strconv.Atoi(forcedLogLevel); err != nil {
t.Errorf("Invalid logLevel value '%s'", forcedLogLevel)
}
if testArgs.LogLevel != logLevel {
t.Errorf("Failed to detect Log Level with kernel command %q", kernelCmd)
}
}
func TestKernelCmdLogError(t *testing.T) {
var testArgs Args
var kernelCmd string
var err error
forcedLogLevel := "a"
// Check for configuration file present
kernelCmd = "root=PARTUUID=694da991-29f6-4cbd-ab72-6da064a799c0 quiet modprobe.blacklist=ccipciedrv,aalbus,aalrms,aalrmc console=tty0 console=ttyS0,115200n8 init=/usr/lib/systemd/systemd-bootchart initcall_debug tsc=reliable no_timer_check noreplace-smp kvm-intel.nested=1 rootfstype=ext4,btrfs,xfs,f2fs intel_iommu=igfx_off cryptomgr.notests rcupdate.rcu_expedited=1 i915.fastboot=1 rcu_nocbs=0-64 rw" +
" " + kernelCmdlineLog + "=" + forcedLogLevel
kernelCmdlineFile, err = makeTestKernelCmd(kernelCmd)
defer func() {
_ = os.Remove(kernelCmdlineFile)
}()
if err != nil {
t.Errorf("Failed to makeTestKernelCmd with error %q", err)
return
}
err = testArgs.setKernelArgs()
if testArgs.CfDownloaded && testArgs.ConfigFile != "" {
defer func() { _ = os.Remove(testArgs.ConfigFile) }()
}
if err != nil {
t.Errorf("Failed to setKernelArgs with error %q", err)
return
}
if testArgs.LogLevel != 0 {
t.Errorf("Failed to detect Log Level with bad kernel command %q", kernelCmd)
}
}
func TestKernelCmdFileProtocol(t *testing.T) {
var testArgs Args
var kernelCmd string
var err error
// the remote fetch supports only http protocol for now
kernelCmd = kernelCmdlineConf + "=file:///proc/cmdline"
kernelCmdlineFile, err = makeTestKernelCmd(kernelCmd)
defer func() {
_ = os.Remove(kernelCmdlineFile)
}()
if err != nil {
t.Errorf("Failed to makeTestKernelCmd with error %q", err)
return
}
err = testArgs.setKernelArgs()
if testArgs.CfDownloaded && testArgs.ConfigFile != "" {
defer func() { _ = os.Remove(testArgs.ConfigFile) }()
}
if err != nil {
t.Errorf("setKernelArgs() should not fail with FILE protocol")
return
}
}
func TestKernelCmdValidFetch(t *testing.T) {
var testArgs Args
var kernelCmd string
var err error
// Check for configuration file present
kernelCmd = kernelCmdlineConf + "=http://localhost:" + testHTTPPort + "/clr-installer.yaml"
kernelCmdlineFile, err = makeTestKernelCmd(kernelCmd)
defer func() {
_ = os.Remove(kernelCmdlineFile)
}()
if err != nil {
t.Errorf("Failed to makeTestKernelCmd with error %q", err)
return
}
srv, err := serveHTTPDescFile(t)
if err != nil {
t.Fatalf("Failed to serve http desc file with error %q", err)
}
defer func() {
if err = srv.Shutdown(nil); err != nil {
t.Fatal(err)
}
}()
err = testArgs.setKernelArgs()
if testArgs.CfDownloaded && testArgs.ConfigFile != "" {
defer func() { _ = os.Remove(testArgs.ConfigFile) }()
}
if err != nil {
t.Errorf("Failed to setKernelArgs with error %q", err)
return
}
if testArgs.ConfigFile == "" {
t.Errorf("Failed to detect Configuration File with kernel command %q", kernelCmd)
}
}
func TestKernelCmdConfEmpty(t *testing.T) {
var testArgs Args
var kernelCmd string
var err error
// Check for configuration file missing
kernelCmd = "root=PARTUUID=694da991-29f6-4cbd-ab72-6da064a799c0 quiet modprobe.blacklist=ccipciedrv,aalbus,aalrms,aalrmc console=tty0 console=ttyS0,115200n8 init=/usr/lib/systemd/systemd-bootchart initcall_debug tsc=reliable no_timer_check noreplace-smp kvm-intel.nested=1 rootfstype=ext4,btrfs,xfs,f2fs intel_iommu=igfx_off cryptomgr.notests rcupdate.rcu_expedited=1 i915.fastboot=1 rcu_nocbs=0-64 rw" +
" " + "nothere"
kernelCmdlineFile, err = makeTestKernelCmd(kernelCmd)
defer func() {
_ = os.Remove(kernelCmdlineFile)
}()
if err != nil {
t.Errorf("Failed to makeTestKernelCmd with error %q", err)
return
}
err = testArgs.setKernelArgs()
if testArgs.CfDownloaded && testArgs.ConfigFile != "" {
defer func() { _ = os.Remove(testArgs.ConfigFile) }()
}
if err != nil {
t.Errorf("Failed to setKernelArgs with error %q", err)
return
}
if testArgs.ConfigFile != "" {
t.Errorf("Found Configuration File value when should be empty with kernel command %q", kernelCmd)
}
}
func TestConvertArg(t *testing.T) {
var testArgs Args
currArgs := make([]string, len(os.Args))
copy(currArgs, os.Args)
os.Args = []string{currArgs[0], currArgs[1], currArgs[2], "--json-yaml", "fubar.json"}
t.Logf("Current os.Args: %v", os.Args)
err := testArgs.setCommandLineArgs()
os.Args = currArgs
if err != nil {
t.Fatal("Failed to parse arguments")
}
t.Logf("testArgs.ConvertConfigFile: %s", testArgs.ConvertConfigFile)
if testArgs.ConvertConfigFile != "fubar.json" {
t.Fatal("Failed to parse config file for --json-yaml")
}
}
func TestBundleArg(t *testing.T) {
var testArgs Args
currArgs := make([]string, len(os.Args))
copy(currArgs, os.Args)
os.Args = []string{currArgs[0], currArgs[1], currArgs[2], "--bundles", "os-core,os-core-update"}
t.Logf("Current os.Args: %v", os.Args)
err := testArgs.setCommandLineArgs()
os.Args = currArgs
if err != nil {
t.Fatal("Failed to parse arguments")
}
t.Logf("testArgs.Bundles: %v", testArgs.Bundles)
if len(testArgs.Bundles) != 2 {
t.Fatal("Failed to parse bundles")
}
}
func TestTemplateArg(t *testing.T) {
var testArgs Args
currArgs := make([]string, len(os.Args))
copy(currArgs, os.Args)
_ = os.Setenv(logFileEnvironVar, "/tmp/fubar.log")
os.Args = []string{currArgs[0], currArgs[1], currArgs[2], "--template", "fubar.yaml"}
t.Logf("Current os.Args: %v", os.Args)
err := testArgs.setCommandLineArgs()
os.Args = currArgs
if err != nil {
t.Fatal("Failed to parse arguments")
}
t.Logf("testArgs.TemplateConfigFile: %s", testArgs.TemplateConfigFile)
if testArgs.TemplateConfigFile != "fubar.yaml" {
t.Fatal("Failed to parse config file for --template")
}
}
func TestSwupdUrlMirrorFailArg(t *testing.T) {
var testArgs Args
currArgs := make([]string, len(os.Args))
copy(currArgs, os.Args)
os.Args = []string{currArgs[0], currArgs[1], currArgs[2],
"--swupd-url", "https://cdn.download.clearlinux.org/update/",
"--swupd-mirror", "https://cdn.download.clearlinux.org/update/",
}
t.Logf("Current os.Args: %v", os.Args)
err := testArgs.setCommandLineArgs()
os.Args = currArgs
if err == nil {
t.Fatal("Should have failed to parse arguments")
}
}
func TestSwupdUrlContentArg(t *testing.T) {
var testArgs Args
currArgs := make([]string, len(os.Args))
copy(currArgs, os.Args)
os.Args = []string{currArgs[0], currArgs[1], currArgs[2],
"--swupd-url", "https://cdn.download.clearlinux.org/update/",
"--swupd-contenturl", "https://cdn.download.clearlinux.org/update/",
}
t.Logf("Current os.Args: %v", os.Args)
err := testArgs.setCommandLineArgs()
os.Args = currArgs
if err != nil {
t.Fatalf("Failed to parse arguments: %v", err)
}
}
func TestSwupdUrlVersionArg(t *testing.T) {
var testArgs Args
currArgs := make([]string, len(os.Args))
copy(currArgs, os.Args)
os.Args = []string{currArgs[0], currArgs[1], currArgs[2],
"--swupd-url", "https://cdn.download.clearlinux.org/update/",
"--swupd-versionurl", "https://cdn.download.clearlinux.org/update/",
}
t.Logf("Current os.Args: %v", os.Args)
err := testArgs.setCommandLineArgs()
os.Args = currArgs
if err != nil {
t.Fatalf("Failed to parse arguments: %v", err)
}
}
func TestCheckAllBooleans(t *testing.T) {
var testArgs Args
currArgs := make([]string, len(os.Args))
copy(currArgs, os.Args)
os.Args = []string{currArgs[0], currArgs[1], currArgs[2],
"--demo", "--telemetry", "--reboot",
"--iso", "--keep-image", "--allow-insecure-http", "--offline",
"--cfPurge", "--swupd-skip-optional", "--archive", "--copy-swupd", "--high-contrast",
"--skip-validation-size", "--skip-validation-all",
}
t.Logf("Current os.Args: %v", os.Args)
err := testArgs.setCommandLineArgs()
os.Args = currArgs
if err != nil {
t.Fatalf("Failed to parse arguments: %v", err)
}
}
func TestCheckAllBooleansFalse(t *testing.T) {
var testArgs Args
currArgs := make([]string, len(os.Args))
copy(currArgs, os.Args)
os.Args = []string{currArgs[0], currArgs[1], currArgs[2],
"--demo=0", "--telemetry=0", "--reboot=0",
"--iso=0", "--keep-image=0", "--allow-insecure-http=0", "--offline=0",
"--cfPurge=0", "--swupd-skip-optional=0", "--archive=0", "--copy-swupd=0", "--high-contrast=0",
"--skip-validation-size=0", "--skip-validation-all=0",
}
t.Logf("Current os.Args: %v", os.Args)
err := testArgs.setCommandLineArgs()
os.Args = currArgs
if err != nil {
t.Fatalf("Failed to parse arguments: %v", err)
}
}
func TestKernelAndCommandlineAllArgs(t *testing.T) {
var testArgs Args
var kernelCmd string
var err error
const confName = "command.conf"
t.Logf("%v", os.Args)
os.Args = append(os.Args, "--config="+confName, "--demo", "--telemetry", "--reboot",
"--iso", "--keep-image", "--allow-insecure-http", "--offline",
"--swupd-url", "https://cdn.download.clearlinux.org/update/")
fmt.Println(os.Args)
// Check for configuration file missing
kernelCmd = "root=PARTUUID=694da991-29f6-4cbd-ab72-6da064a799c0 quiet modprobe.blacklist=ccipciedrv,aalbus,aalrms,aalrmc console=tty0 console=ttyS0,115200n8 init=/usr/lib/systemd/systemd-bootchart initcall_debug tsc=reliable no_timer_check noreplace-smp kvm-intel.nested=1 rootfstype=ext4,btrfs,xfs,f2fs intel_iommu=igfx_off cryptomgr.notests rcupdate.rcu_expedited=1 i915.fastboot=1 rcu_nocbs=0-64 rw" +
" " + kernelCmdlineConf + "=http://google.com"
kernelCmdlineFile, err = makeTestKernelCmd(kernelCmd)
defer func() {
_ = os.Remove(kernelCmdlineFile)
}()
if err != nil {
t.Errorf("Failed to makeTestKernelCmd with error %q", err)
return
}
err = testArgs.ParseArgs()
if testArgs.CfDownloaded && testArgs.ConfigFile != "" {
defer func() { _ = os.Remove(testArgs.ConfigFile) }()
}
if err != nil {
t.Errorf("Failed to ParseArgs with error %q", err)
return
}
if testArgs.Version != false {
t.Errorf("Command Line 'version' is not defaulted to 'false'")
}
if testArgs.Reboot != true {
t.Errorf("Command Line 'reboot' is not defaulted to 'true'")
}
if testArgs.Offline != true {
t.Errorf("Command Line 'offline' is not defaulted to 'true'")
}
if testArgs.MakeISO != true {
t.Errorf("Command Line 'iso' is not defaulted to 'true'")
}
if testArgs.AllowInsecureHTTP != true {
t.Errorf("Command Line 'allow-insecure-http' is not defaulted to 'true'")
}
if testArgs.KeepImage != true {
t.Errorf("Command Line 'keep-image' is not defaulted to 'true'")
}
if testArgs.ConfigFile != confName {
t.Errorf("Command Line 'config' is %q, NOT overridden to %q", testArgs.ConfigFile, confName)
}
if testArgs.SwupdMirror != "" {
t.Errorf("Command Line 'mirror' is not defaulted to ''")
}
if testArgs.SwupdSkipOptional != false {
t.Errorf("Command Line '--swupd-skip-optional' is not defaulted to 'false'")
}
if testArgs.SwupdVersion != "" {
t.Errorf("Command Line 'swupd-version' is not defaulted to ''")
}
if testArgs.PamSalt != "" {
t.Errorf("Command Line 'genpwd' is not defaulted to ''")
}
if testArgs.LogLevel != log.LogLevelDebug {
t.Errorf("Command Line 'log-level' is not defaulted to '%d'", log.LogLevelDebug)
}
if testArgs.LogFile == "" {
t.Errorf("Command Line 'log-file' is NOT set to value")
}
if testArgs.SwupdURL == "" {
t.Errorf("Command Line 'swupd-url' is NOT set to value")
}
if testArgs.SkipValidationSize != false {
t.Errorf("Command Line '--skip-validation-size' is not defaulted to 'false'")
}
if testArgs.SkipValidationAll != false {
t.Errorf("Command Line '--skip-validation-all' is not defaulted to 'false'")
}
}