blob: f24febcbbe7eb85ae009a377bfcb7b1ffc112d47 [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package paver
import (
"bytes"
"context"
"crypto/rand"
"crypto/rsa"
"fmt"
"golang.org/x/crypto/ssh"
"io/ioutil"
"os"
"strings"
"testing"
)
// The easiest way to make a fake key is to just generate a real one.
func GeneratePublicKey() (ssh.PublicKey, error) {
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return nil, err
}
return ssh.NewPublicKey(&privateKey.PublicKey)
}
func CreateScript(fileName string) (script string, err error) {
file, err := ioutil.TempFile("", fileName)
if err != nil {
return "", err
}
defer file.Close()
// Script outputs its name and all its arguments.
contents := `#!/bin/sh
echo "$0 $@"
`
if _, err := file.Write([]byte(contents)); err != nil {
os.Remove(file.Name())
return "", err
}
if err := file.Chmod(0744); err != nil {
os.Remove(file.Name())
return "", err
}
return file.Name(), nil
}
func CreateAndRunPaver(options ...BuildPaverOption) (zedbootPaverArgs []string, paverArgs []string, err error) {
zedbootPaverScript, err := CreateScript("zedbootpave.*.sh")
if err != nil {
return nil, nil, err
}
defer os.Remove(zedbootPaverScript)
paverScript, err := CreateScript("pave.*.sh")
if err != nil {
return nil, nil, err
}
defer os.Remove(paverScript)
var output bytes.Buffer
options = append(options, Stdout(&output))
paver, err := NewBuildPaver(zedbootPaverScript, paverScript, options...)
if err != nil {
return nil, nil, err
}
if err := paver.Pave(context.Background(), "a-fake-device-name"); err != nil {
return nil, nil, err
}
outputs := strings.Split(output.String(), "\n")
zedbootPaverArgs = strings.Split(outputs[0], " ")
paverArgs = strings.Split(outputs[1], " ")
if zedbootPaverArgs[0] != zedbootPaverScript {
err := fmt.Errorf("Paver called the wrong zedboot paver script. Expected %s, actual %s",
zedbootPaverScript, zedbootPaverArgs[0])
return nil, nil, err
}
if paverArgs[0] != paverScript {
err := fmt.Errorf("Paver called the wrong paver script. Expected %s, actual %s",
paverScript, paverArgs[0])
return nil, nil, err
}
return
}
func TestDefault(t *testing.T) {
zedbootPaverArgs, paverArgs, err := CreateAndRunPaver()
if err != nil {
t.Fatal(err)
}
{
var deviceName string
hasAllowVersionMismatch := false
for i, arg := range zedbootPaverArgs {
if arg == "-n" {
if i+1 < len(zedbootPaverArgs) {
deviceName = zedbootPaverArgs[i+1]
}
} else if arg == "--allow-zedboot-version-mismatch" {
hasAllowVersionMismatch = true
}
}
if deviceName != "a-fake-device-name" {
t.Fatalf("Missing device name in zedboot paver arguments.")
}
if !hasAllowVersionMismatch {
t.Fatalf("Missing allow version mismatch flag in zedboot paver arguments.")
}
}
{
var deviceName string
hasFailFastIfVersionMismatch := false
for i, arg := range paverArgs {
if arg == "-n" {
if i+1 < len(paverArgs) {
deviceName = paverArgs[i+1]
}
} else if arg == "--fail-fast-if-version-mismatch" {
hasFailFastIfVersionMismatch = true
}
}
if deviceName != "a-fake-device-name" {
t.Fatalf("Missing device name in paver arguments.")
}
if !hasFailFastIfVersionMismatch {
t.Fatalf("Missing allow version mismatch flag in paver arguments.")
}
}
}
func TestSSHKeys(t *testing.T) {
sshKey, err := GeneratePublicKey()
if err != nil {
t.Fatal(err)
}
_, paverArgs, err := CreateAndRunPaver(SSHPublicKey(sshKey))
if err != nil {
t.Fatal(err)
}
hasAuthorizedKeys := false
for i, arg := range paverArgs {
if arg == "--authorized-keys" {
// Check that there's at least one more argument.
if i+1 < len(paverArgs) {
hasAuthorizedKeys = true
}
}
}
if !hasAuthorizedKeys {
t.Fatalf("Missing authorized keys file in paver arguments.")
}
}
func TestOverrideSlotA(t *testing.T) {
zirconAFile, err := ioutil.TempFile("", "zircona.*")
if err != nil {
t.Fatal(err)
}
defer func() {
zirconAFile.Close()
os.Remove(zirconAFile.Name())
}()
_, paverArgs, err := CreateAndRunPaver(OverrideSlotA(zirconAFile.Name()))
if err != nil {
t.Fatal(err)
}
var zirconAPath string
for i, arg := range paverArgs {
if arg == "--zircona" {
if i+1 < len(paverArgs) {
zirconAPath = paverArgs[i+1]
}
}
}
if zirconAPath != zirconAFile.Name() {
t.Fatalf("Missing zircon A image in paver arguments.")
}
}
func TestOverrideVBMetaA(t *testing.T) {
vbMetaAFile, err := ioutil.TempFile("", "vbmetaa.*")
if err != nil {
t.Fatal(err)
}
defer func() {
vbMetaAFile.Close()
os.Remove(vbMetaAFile.Name())
}()
_, paverArgs, err := CreateAndRunPaver(
OverrideVBMetaA(vbMetaAFile.Name()))
if err != nil {
t.Fatal(err)
}
var vbmetaAPath string
for i, arg := range paverArgs {
if arg == "--vbmetaa" {
if i+1 < len(paverArgs) {
vbmetaAPath = paverArgs[i+1]
}
}
}
if vbmetaAPath != vbMetaAFile.Name() {
t.Fatalf("Missing vbmeta A image in paver arguments.")
}
}