Add some more tests for notary CLI

Signed-off-by: Ying Li <ying.li@docker.com>
This commit is contained in:
Ying Li 2016-02-03 11:09:38 -08:00
parent d67a7e128c
commit 718002acea
2 changed files with 172 additions and 7 deletions

View File

@ -72,17 +72,13 @@ func (n *notaryCommander) parseConfig() (*viper.Viper, error) {
// If there was a commandline configFile set, we parse that. // If there was a commandline configFile set, we parse that.
// If there wasn't we attempt to find it on the default location ~/.notary/config.json // If there wasn't we attempt to find it on the default location ~/.notary/config.json
configFileName, configFileExt, configPath := "config", "json", defaultTrustDir
if n.configFile != "" { if n.configFile != "" {
configFileExt = strings.TrimPrefix(filepath.Ext(n.configFile), ".") config.SetConfigFile(n.configFile)
configFileName = strings.TrimSuffix(filepath.Base(n.configFile), filepath.Ext(n.configFile)) } else {
configPath = filepath.Dir(n.configFile) config.SetConfigFile(filepath.Join(defaultTrustDir, "config.json"))
} }
// Setup the configuration details into viper // Setup the configuration details into viper
config.SetConfigName(configFileName)
config.SetConfigType(configFileExt)
config.AddConfigPath(configPath)
config.SetDefault("trust_dir", defaultTrustDir) config.SetDefault("trust_dir", defaultTrustDir)
config.SetDefault("remote_server", map[string]string{"url": defaultServerURL}) config.SetDefault("remote_server", map[string]string{"url": defaultServerURL})

169
cmd/notary/main_test.go Normal file
View File

@ -0,0 +1,169 @@
package main
import (
"bytes"
"io/ioutil"
"os"
"path/filepath"
"strings"
"testing"
"github.com/docker/notary/passphrase"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// the default location for the config file is in ~/.notary/config.json - even if it doesn't exist.
func TestNotaryConfigFileDefault(t *testing.T) {
commander := &notaryCommander{
getRetriever: func() passphrase.Retriever { return passphrase.ConstantRetriever("pass") },
}
config, err := commander.parseConfig()
assert.NoError(t, err)
configFileUsed := config.ConfigFileUsed()
assert.True(t, strings.HasSuffix(configFileUsed,
filepath.Join(".notary", "config.json")), "Unknown config file: %s", configFileUsed)
}
// the default server address is notary-server
func TestRemoteServerDefault(t *testing.T) {
tempDir := tempDirWithConfig(t, "{}")
defer os.RemoveAll(tempDir)
configFile := filepath.Join(tempDir, "config.json")
commander := &notaryCommander{
getRetriever: func() passphrase.Retriever { return passphrase.ConstantRetriever("pass") },
}
// set a blank config file, so it doesn't check ~/.notary/config.json by default
// and execute a random command so that the flags are parsed
cmd := commander.GetCommand()
cmd.SetArgs([]string{"-c", configFile, "list"})
cmd.SetOutput(new(bytes.Buffer)) // eat the output
cmd.Execute()
config, err := commander.parseConfig()
assert.NoError(t, err)
assert.Equal(t, "https://notary-server:4443", getRemoteTrustServer(config))
}
// providing a config file uses the config file's server url instead
func TestRemoteServerUsesConfigFile(t *testing.T) {
tempDir := tempDirWithConfig(t, `{"remote_server": {"url": "https://myserver"}}`)
defer os.RemoveAll(tempDir)
configFile := filepath.Join(tempDir, "config.json")
commander := &notaryCommander{
getRetriever: func() passphrase.Retriever { return passphrase.ConstantRetriever("pass") },
}
// set a config file, so it doesn't check ~/.notary/config.json by default,
// and execute a random command so that the flags are parsed
cmd := commander.GetCommand()
cmd.SetArgs([]string{"-c", configFile, "list"})
cmd.SetOutput(new(bytes.Buffer)) // eat the output
cmd.Execute()
config, err := commander.parseConfig()
assert.NoError(t, err)
assert.Equal(t, "https://myserver", getRemoteTrustServer(config))
}
// a command line flag overrides the config file's server url
func TestRemoteServerCommandLineFlagOverridesConfig(t *testing.T) {
tempDir := tempDirWithConfig(t, `{"remote_server": {"url": "https://myserver"}}`)
defer os.RemoveAll(tempDir)
configFile := filepath.Join(tempDir, "config.json")
commander := &notaryCommander{
getRetriever: func() passphrase.Retriever { return passphrase.ConstantRetriever("pass") },
}
// set a config file, so it doesn't check ~/.notary/config.json by default,
// and execute a random command so that the flags are parsed
cmd := commander.GetCommand()
cmd.SetArgs([]string{"-c", configFile, "-s", "http://overridden", "list"})
cmd.SetOutput(new(bytes.Buffer)) // eat the output
cmd.Execute()
config, err := commander.parseConfig()
assert.NoError(t, err)
assert.Equal(t, "http://overridden", getRemoteTrustServer(config))
}
var exampleValidCommands = []string{
"init repo",
"list repo",
"status repo",
"publish repo",
"add repo v1 somefile",
"verify repo v1",
"key list",
"key rotate repo",
"key generate rsa",
"key backup tempfile.zip",
"key export e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 backup.pem",
"key restore tempfile.zip",
"key import backup.pem",
"key remove e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"key passwd e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"cert list",
"cert remove e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"delegation list repo",
"delegation add repo targets/releases path/to/pem/file.pem",
"delegation remove repo targets/releases",
}
// config parsing bugs are propagated in all commands
func TestConfigParsingErrorsPropagatedByCommands(t *testing.T) {
tempdir, err := ioutil.TempDir("", "empty-dir")
require.NoError(t, err)
defer os.RemoveAll(tempdir)
for _, args := range exampleValidCommands {
b := new(bytes.Buffer)
cmd := NewNotaryCommand()
cmd.SetOutput(b)
cmd.SetArgs(append(
[]string{"-c", filepath.Join(tempdir, "idonotexist.json"), "-d", tempdir},
strings.Fields(args)...))
err = cmd.Execute()
require.Error(t, err, "expected error when running %s", args)
require.Contains(t, err.Error(), "error opening config file", "running %s", args)
require.NotContains(t, b.String(), "Usage:")
}
}
// insufficient arguments produce an error before any parsing of configs happens
func TestInsufficientArgumentsReturnsErrorAndPrintsUsage(t *testing.T) {
tempdir, err := ioutil.TempDir("", "empty-dir")
require.NoError(t, err)
defer os.RemoveAll(tempdir)
for _, args := range exampleValidCommands {
b := new(bytes.Buffer)
cmd := NewNotaryCommand()
cmd.SetOutput(b)
arglist := strings.Fields(args)
if args == "key list" || args == "cert list" || args == "key generate rsa" {
// in these case, "key" or "cert" or "key generate" are valid commands, so add an arg to them instead
arglist = append(arglist, "extraArg")
} else {
arglist = arglist[:len(arglist)-1]
}
invalid := strings.Join(arglist, " ")
cmd.SetArgs(append(
[]string{"-c", filepath.Join(tempdir, "idonotexist.json"), "-d", tempdir}, arglist...))
err = cmd.Execute()
require.NotContains(t, err.Error(), "error opening config file", "running %s", invalid)
// it's a usage error, so the usage is printed
require.Contains(t, b.String(), "Usage:", "expected usage when running %s", invalid)
}
}