blob: a489356b0c36f5e3bd43bb50303f02da6de7b56d [file] [log] [blame]
// Copyright 2022 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 synckeys
import (
"context"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path"
"path/filepath"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
)
func TestProcessLocalFuchsiaKeys(t *testing.T) {
emptyDir, err := ioutil.TempDir(t.TempDir(), "fssh-test-")
if err != nil {
t.Fatalf("could not create temporary folder: %s", err)
}
defer os.RemoveAll(emptyDir)
var tests = []struct {
homeDir string
expectedWorkstation *Workstation
}{
{
homeDir: emptyDir,
expectedWorkstation: &Workstation{
KeysExist: false,
HomeDir: emptyDir,
SSHDir: filepath.Join(emptyDir, sshDirName),
KeyPaths: []string{
filepath.Join(emptyDir, sshDirName, fuchsiaAuthorizedKeyFilename),
filepath.Join(emptyDir, sshDirName, fuchsiaPrivateSSHKeyFilename),
},
},
},
}
for _, test := range tests {
ctx := context.Background()
w, err := processLocalFuchsiaKeys(ctx, test.homeDir)
if err != nil {
t.Errorf("processLocalFuchsiaKeys(): got error %s, expected no error", err)
}
if diff := cmp.Diff(test.expectedWorkstation, w); diff != "" {
t.Errorf("processLocalFuchsiaKeys(): %s", diff)
}
}
}
func TestGenerateFuchsiaKeys(t *testing.T) {
tempDir := t.TempDir()
localDir, err := ioutil.TempDir(tempDir, "fssh-test-")
if err != nil {
t.Fatalf("could not create temporary folder %s: %s", localDir, err)
}
defer os.RemoveAll(localDir)
localSSHDir := filepath.Join(localDir, sshDirName)
if err = os.Mkdir(localSSHDir, 0755); err != nil {
t.Fatalf("could not create temporary folder %s: %s", localSSHDir, err)
}
remoteDir, err := ioutil.TempDir(tempDir, "fssh-test-")
if err != nil {
t.Fatalf("could not create temporary folder: %s", err)
}
defer os.RemoveAll(remoteDir)
remoteSSHDir := filepath.Join(remoteDir, sshDirName)
if err = os.Mkdir(remoteSSHDir, 0755); err != nil {
t.Fatalf("could not create temporary folder %s: %s", remoteSSHDir, err)
}
var tests = []struct {
local *Workstation
remote *Workstation
}{
{
local: &Workstation{
KeysExist: false,
HomeDir: localDir,
SSHDir: localSSHDir,
KeyPaths: []string{
filepath.Join(localSSHDir, fuchsiaAuthorizedKeyFilename),
filepath.Join(localSSHDir, fuchsiaPrivateSSHKeyFilename),
},
},
remote: &Workstation{
KeysExist: false,
Hostname: "",
HomeDir: remoteDir,
SSHDir: remoteSSHDir,
KeyPaths: []string{
filepath.Join(remoteSSHDir, fuchsiaAuthorizedKeyFilename),
filepath.Join(remoteSSHDir, fuchsiaPrivateSSHKeyFilename),
},
},
},
}
for _, test := range tests {
ctx := context.Background()
if err := generateFuchsiaKeys(ctx, testRunCommand, test.local, test.remote); err != nil {
t.Fatalf("error calling generateFuchsiaKeys: %s", err)
}
}
}
func TestProcessRemoteFuchsiaKeys(t *testing.T) {
emptyDir, err := ioutil.TempDir(t.TempDir(), "fssh-test-")
if err != nil {
t.Fatalf("could not create temporary folder: %s", err)
}
defer os.RemoveAll(emptyDir)
var tests = []struct {
hostname string
homeDir string
expectedWorkstation *Workstation
}{
{
hostname: "",
homeDir: emptyDir,
expectedWorkstation: &Workstation{
KeysExist: false,
HomeDir: emptyDir,
SSHDir: filepath.Join(emptyDir, sshDirName),
KeyPaths: []string{
filepath.Join(emptyDir, sshDirName, fuchsiaAuthorizedKeyFilename),
filepath.Join(emptyDir, sshDirName, fuchsiaPrivateSSHKeyFilename),
},
},
},
}
for _, test := range tests {
ctx := context.Background()
w, err := processRemoteFuchsiaKeys(ctx, testRunCommand, test.hostname, test.homeDir)
defer os.RemoveAll(w.TempKeyDir)
if err != nil {
t.Errorf("processRemoteFuchsiaKeys(): got error %s, expected no error", err)
}
if diff := cmp.Diff(test.expectedWorkstation, w, cmpopts.IgnoreFields(Workstation{}, "TempKeyDir")); diff != "" {
t.Errorf("processRemoteFuchsiaKeys(): %s", diff)
}
}
}
func TestCheckLocalFuchsiaKeys(t *testing.T) {
tempDir := t.TempDir()
failingKeyCheckTestDir, err := ioutil.TempDir(tempDir, "fssh-key-check-test-")
if err != nil {
t.Fatalf("could not create temporary folder: %s", err)
}
defer os.RemoveAll(failingKeyCheckTestDir)
passingKeyCheckTestDir, err := ioutil.TempDir(tempDir, "fssh-key-check-test-")
if err != nil {
t.Fatalf("could not create temporary folder: %s", err)
}
defer os.RemoveAll(passingKeyCheckTestDir)
authKeyPath := filepath.Join(passingKeyCheckTestDir, fuchsiaAuthorizedKeyFilename)
if _, err = os.Create(authKeyPath); err != nil {
t.Fatalf("could not create needed file %s: %s", authKeyPath, err)
}
privateKeyPath := filepath.Join(passingKeyCheckTestDir, fuchsiaPrivateSSHKeyFilename)
if _, err = os.Create(privateKeyPath); err != nil {
t.Fatalf("could not create needed file %s: %s", privateKeyPath, err)
}
var tests = []struct {
localPaths []string
expectedResult bool
}{
{
localPaths: []string{
path.Join(failingKeyCheckTestDir, fuchsiaAuthorizedKeyFilename),
path.Join(failingKeyCheckTestDir, fuchsiaPrivateSSHKeyFilename),
},
expectedResult: false,
},
{
localPaths: []string{
path.Join(passingKeyCheckTestDir, fuchsiaAuthorizedKeyFilename),
path.Join(passingKeyCheckTestDir, fuchsiaPrivateSSHKeyFilename),
},
expectedResult: true,
},
}
for _, test := range tests {
ctx := context.Background()
keysExist := checkLocalFuchsiaKeys(ctx, test.localPaths)
if keysExist != test.expectedResult {
t.Fatalf("checkLocalFuchsiaKeys() got %t, want %t", keysExist, test.expectedResult)
}
}
}
func TestGenerateLocalKeys(t *testing.T) {
// Test setup
tempDir, err := ioutil.TempDir(t.TempDir(), "fssh-gen-key-test-")
if err != nil {
t.Fatalf("could not create temporary folder: %s", err)
}
defer os.RemoveAll(tempDir)
ctx := context.Background()
err = generateLocalKeys(ctx, testRunCommand, tempDir)
if err != nil {
t.Fatalf("error calling generateLocalKeys: %s", err)
}
// Check for generated key file existence
privateKeyPath := filepath.Join(tempDir, fuchsiaPrivateSSHKeyFilename)
if !localFileExists(privateKeyPath) {
t.Fatalf("expected file %s to exist but does not", privateKeyPath)
}
authorizedKeyPath := filepath.Join(tempDir, fuchsiaAuthorizedKeyFilename)
if !localFileExists(authorizedKeyPath) {
t.Fatalf("expected file %s to exist but does not", authorizedKeyPath)
}
}
func TestFilesHaveSameContents(t *testing.T) {
tempDir := t.TempDir()
file1, err := writeTempFile(tempDir, []string{"This is file1\n"})
if err != nil {
t.Fatal(err)
}
defer os.Remove(file1)
file1NoNewline, err := writeTempFile(tempDir, []string{"This is file1"})
if err != nil {
t.Fatal(err)
}
defer os.Remove(file1NoNewline)
file1WithBlankLine, err := writeTempFile(tempDir, []string{"This is file1\n\n"})
if err != nil {
t.Fatal(err)
}
defer os.Remove(file1WithBlankLine)
multiline, err := writeTempFile(tempDir, []string{"This is line1", "line2", "line3"})
if err != nil {
t.Fatal(err)
}
defer os.Remove(multiline)
file2, err := writeTempFile(tempDir, []string{"This is file2", "\n"})
if err != nil {
t.Fatal(err)
}
defer os.Remove(file2)
empty, err := writeTempFile(tempDir, []string{"\n"})
if err != nil {
t.Fatal(err)
}
defer os.Remove(empty)
tests := []struct {
left string
right string
expected bool
}{
{
left: file1,
right: file1,
expected: true,
},
{
left: file1,
right: file1NoNewline,
expected: true,
},
{
left: file1,
right: file1WithBlankLine,
expected: true,
},
{
left: file1NoNewline,
right: file1WithBlankLine,
expected: true,
},
{
left: file1,
right: file2,
expected: false,
},
{
left: multiline,
right: empty,
expected: false,
},
{
left: empty,
right: multiline,
expected: false,
},
}
for i, test := range tests {
t.Run(fmt.Sprintf("TestFilesHaveSameContents %d", i), func(t *testing.T) {
ctx := context.Background()
same, err := filesHaveSameContents(ctx, test.left, test.right)
if err != nil {
t.Fatal(err)
}
if same != test.expected {
t.Fatalf("filesHaveSameContents() got %s, want %s", test.left, test.right)
}
})
}
}
func writeTempFile(dir string, contents []string) (path string, err error) {
f, err := ioutil.TempFile(dir, "fssh-test-")
if err != nil {
return "", fmt.Errorf("could not create temp testing file %s: %s", f.Name(), err)
}
defer f.Close()
for _, content := range contents {
written, err := f.WriteString(content)
if err != nil || written == 0 {
return "", fmt.Errorf("could not write %s to temp testing file %s: %s", content, f.Name(), err)
}
}
return f.Name(), nil
}
func testRunCommand(_ context.Context, execName string, args []string) (string, error) {
path, err := findOnPath(execName)
if err != nil {
return "", err
}
cmd := exec.Command(path, args...)
out, err := cmd.CombinedOutput()
if err != nil {
return "", fmt.Errorf(
"could not run %s: %s",
path,
string(out),
)
}
return string(out), nil
}