blob: 4fb34441d0f62e69c8d3dbb1b83649a40c540151 [file] [log] [blame]
// Copyright 2015 The Vanadium 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 main_test
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"reflect"
"strings"
"testing"
"v.io/v23"
"v.io/v23/naming"
"v.io/v23/security"
"v.io/v23/services/application"
"v.io/v23/services/device"
"v.io/x/lib/cmdline"
"v.io/x/ref/lib/v23cmd"
"v.io/x/ref/test"
cmd_device "v.io/x/ref/services/device/device"
"v.io/x/ref/services/internal/servicetest"
)
func createFile(t *testing.T, path string, contents string) {
if err := ioutil.WriteFile(path, []byte(contents), 0700); err != nil {
t.Fatalf("Failed to create %v: %v", path, err)
}
}
func TestInstallLocalCommand(t *testing.T) {
ctx, shutdown := test.V23Init()
defer shutdown()
tapes := servicetest.NewTapeMap()
ctx, server, err := v23.WithNewDispatchingServer(ctx, "", newDispatcher(t, tapes))
if err != nil {
t.Fatalf("NewServer failed: %v", err)
}
// Setup the command-line.
cmd := cmd_device.CmdRoot
var stdout, stderr bytes.Buffer
env := &cmdline.Env{Stdout: &stdout, Stderr: &stderr}
deviceName := server.Status().Endpoints[0].Name()
const appTitle = "Appo di tutti Appi"
binary := os.Args[0]
fi, err := os.Stat(binary)
if err != nil {
t.Fatalf("Failed to stat %v: %v", binary, err)
}
binarySize := fi.Size()
rootTape := tapes.ForSuffix("")
for i, c := range []struct {
args []string
stderrSubstr string
}{
{
[]string{deviceName}, "incorrect number of arguments",
},
{
[]string{deviceName, appTitle}, "missing binary",
},
{
[]string{deviceName, appTitle, "a=b"}, "missing binary",
},
{
[]string{deviceName, appTitle, "foo"}, "binary foo not found",
},
{
[]string{deviceName, appTitle, binary, "PACKAGES", "foo"}, "foo not found",
},
} {
c.args = append([]string{"install-local"}, c.args...)
if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, c.args); err == nil {
t.Fatalf("test case %d: wrongly failed to receive a non-nil error.", i)
} else {
fmt.Fprintln(&stderr, "ERROR:", err)
if want, got := c.stderrSubstr, stderr.String(); !strings.Contains(got, want) {
t.Errorf("test case %d: %q not found in stderr: %q", i, want, got)
}
}
if got, expected := len(rootTape.Play()), 0; got != expected {
t.Errorf("test case %d: invalid call sequence. Got %v, want %v", i, got, expected)
}
rootTape.Rewind()
stdout.Reset()
stderr.Reset()
}
emptySig := security.Signature{}
emptyBlessings := security.Blessings{}
cfg := device.Config{"someflag": "somevalue"}
testPackagesDir, err := ioutil.TempDir("", "testdir")
if err != nil {
t.Fatalf("Failed to create temp dir: %v", err)
}
defer os.RemoveAll(testPackagesDir)
pkgFile1 := filepath.Join(testPackagesDir, "file1.txt")
createFile(t, pkgFile1, "1234567")
pkgFile2 := filepath.Join(testPackagesDir, "file2")
createFile(t, pkgFile2, string([]byte{0x01, 0x02, 0x03, 0x04}))
pkgDir1 := filepath.Join(testPackagesDir, "dir1")
if err := os.Mkdir(pkgDir1, 0700); err != nil {
t.Fatalf("Failed to create dir1: %v", err)
}
createFile(t, filepath.Join(pkgDir1, "f1"), "123")
createFile(t, filepath.Join(pkgDir1, "f2"), "456")
createFile(t, filepath.Join(pkgDir1, "f3"), "7890")
pkgFile3 := filepath.Join(testPackagesDir, "file3")
createFile(t, pkgFile3, "12345")
pkgFile4 := filepath.Join(testPackagesDir, "file4")
createFile(t, pkgFile4, "123")
pkgDir2 := filepath.Join(testPackagesDir, "dir2")
if err := os.Mkdir(pkgDir2, 0700); err != nil {
t.Fatalf("Failed to create dir2: %v", err)
}
createFile(t, filepath.Join(pkgDir2, "f1"), "123456")
createFile(t, filepath.Join(pkgDir2, "f2"), "78")
pkg := application.Packages{
"overridepkg1": application.SignedFile{File: pkgFile3},
"overridepkg2": application.SignedFile{File: pkgFile4},
"overridepkg3": application.SignedFile{File: pkgDir2},
}
for i, c := range []struct {
args []string
config device.Config
packages application.Packages
expectedTape interface{}
}{
{
[]string{deviceName, appTitle, binary},
nil,
nil,
InstallStimulus{
"Install",
appNameAfterFetch,
nil,
nil,
application.Envelope{
Title: appTitle,
Binary: application.SignedFile{
File: binaryNameAfterFetch,
Signature: emptySig,
},
Publisher: emptyBlessings,
},
map[string]int64{"binary": binarySize}},
},
{
[]string{deviceName, appTitle, binary},
cfg,
nil,
InstallStimulus{
"Install",
appNameAfterFetch,
cfg,
nil,
application.Envelope{
Title: appTitle,
Binary: application.SignedFile{
File: binaryNameAfterFetch,
Signature: emptySig,
},
Publisher: emptyBlessings,
},
map[string]int64{"binary": binarySize}},
},
{
[]string{deviceName, appTitle, "ENV1=V1", "ENV2=V2", binary, "FLAG1=V1", "FLAG2=V2"},
nil,
nil,
InstallStimulus{
"Install",
appNameAfterFetch,
nil,
nil,
application.Envelope{
Title: appTitle,
Binary: application.SignedFile{
File: binaryNameAfterFetch,
Signature: emptySig,
},
Publisher: emptyBlessings,
Env: []string{"ENV1=V1", "ENV2=V2"},
Args: []string{"FLAG1=V1", "FLAG2=V2"},
},
map[string]int64{"binary": binarySize}},
},
{
[]string{deviceName, appTitle, "ENV=V", binary, "FLAG=V", "PACKAGES", pkgFile1, pkgFile2, pkgDir1},
nil,
pkg,
InstallStimulus{"Install",
appNameAfterFetch,
nil,
nil,
application.Envelope{
Title: appTitle,
Binary: application.SignedFile{
File: binaryNameAfterFetch,
Signature: emptySig,
},
Publisher: emptyBlessings,
Env: []string{"ENV=V"},
Args: []string{"FLAG=V"},
},
map[string]int64{
"binary": binarySize,
"packages/file1.txt": 7,
"packages/file2": 4,
"packages/dir1": 10,
"overridepackages/overridepkg1": 5,
"overridepackages/overridepkg2": 3,
"overridepackages/overridepkg3": 8,
},
},
},
} {
const appId = "myBestAppID"
rootTape.SetResponses(InstallResponse{appId, nil})
if c.config != nil {
jsonConfig, err := json.Marshal(c.config)
if err != nil {
t.Fatalf("test case %d: Marshal(%v) failed: %v", i, c.config, err)
}
c.args = append([]string{fmt.Sprintf("--config=%s", string(jsonConfig))}, c.args...)
}
if c.packages != nil {
jsonPackages, err := json.Marshal(c.packages)
if err != nil {
t.Fatalf("test case %d: Marshal(%v) failed: %v", i, c.packages, err)
}
c.args = append([]string{fmt.Sprintf("--packages=%s", string(jsonPackages))}, c.args...)
}
c.args = append([]string{"install-local"}, c.args...)
if err := v23cmd.ParseAndRunForTest(cmd, ctx, env, c.args); err != nil {
t.Fatalf("test case %d: %v", i, err)
}
if expected, got := naming.Join(deviceName, appId), strings.TrimSpace(stdout.String()); got != expected {
t.Fatalf("test case %d: Unexpected output from Install. Got %q, expected %q", i, got, expected)
}
if got, expected := rootTape.Play(), []interface{}{c.expectedTape}; !reflect.DeepEqual(expected, got) {
t.Errorf("test case %d: Invalid call sequence. Got %#v, want %#v", i, got, expected)
}
rootTape.Rewind()
stdout.Reset()
stderr.Reset()
}
}