diff --git a/command/agent_info_test.go b/command/agent_info_test.go index 4552b5cac..5ee879bd0 100644 --- a/command/agent_info_test.go +++ b/command/agent_info_test.go @@ -1,6 +1,7 @@ package command import ( + "strings" "testing" "github.com/mitchellh/cli" @@ -11,7 +12,36 @@ func TestAgentInfoCommand_Implements(t *testing.T) { } func TestAgentInfoCommand_Run(t *testing.T) { - agent := testAgent(t) + agent, http, _, url := testAgent(t) defer agent.Shutdown() - println("yay") + defer http.Shutdown() + + ui := new(cli.MockUi) + cmd := &AgentInfoCommand{Ui: ui} + + code := cmd.Run([]string{"-http-addr=" + url}) + if code != 0 { + t.Fatalf("expected exit 0, got: %d %s", code) + } +} + +func TestAgentInfoCommand_Fails(t *testing.T) { + ui := new(cli.MockUi) + cmd := &AgentInfoCommand{Ui: ui} + + // Fails on misuse + if code := cmd.Run([]string{"some", "bad", "args"}); code != 1 { + t.Fatalf("expected exit code 1, got: %d", code) + } + if out := ui.ErrorWriter.String(); !strings.Contains(out, cmd.Help()) { + t.Fatalf("expected help output, got: %s", out) + } + + // Fails on connection failure + if code := cmd.Run([]string{"-http-addr=nope"}); code != 1 { + t.Fatalf("expected exit code 1, got: %d", code) + } + if out := ui.ErrorWriter.String(); !strings.Contains(out, "Failed querying agent info") { + t.Fatalf("expected failed query error, got: %s", out) + } } diff --git a/command/agent_members_test.go b/command/agent_members_test.go index 7ad16cb7d..c348bba7a 100644 --- a/command/agent_members_test.go +++ b/command/agent_members_test.go @@ -1,6 +1,7 @@ package command import ( + "strings" "testing" "github.com/mitchellh/cli" @@ -9,3 +10,56 @@ import ( func TestAgentMembersCommand_Implements(t *testing.T) { var _ cli.Command = &AgentMembersCommand{} } + +func TestAgentMembersCommand_Run(t *testing.T) { + agent, http, client, url := testAgent(t) + defer agent.Shutdown() + defer http.Shutdown() + + ui := new(cli.MockUi) + cmd := &AgentMembersCommand{Ui: ui} + + // Get our own node name + name, err := client.Agent().NodeName() + if err != nil { + t.Fatalf("err: %s", err) + } + + // Query the members + if code := cmd.Run([]string{"-http-addr=" + url}); code != 0 { + t.Fatalf("expected exit 0, got: %d", code) + } + if out := ui.OutputWriter.String(); !strings.Contains(out, name) { + t.Fatalf("expected %q in output, got: %s", name, out) + } + ui.OutputWriter.Reset() + + // Query members with detailed output + if code := cmd.Run([]string{"-http-addr=" + url, "-detailed"}); code != 0 { + t.Fatalf("expected exit 0, got: %d", code) + } + if out := ui.OutputWriter.String(); !strings.Contains(out, "Tags") { + t.Fatalf("expected tags in output, got: %s", out) + } +} + +func TestMembersCommand_Fails(t *testing.T) { + ui := new(cli.MockUi) + cmd := &AgentMembersCommand{Ui: ui} + + // Fails on misuse + if code := cmd.Run([]string{"some", "bad", "args"}); code != 1 { + t.Fatalf("expected exit code 1, got: %d", code) + } + if out := ui.ErrorWriter.String(); !strings.Contains(out, cmd.Help()) { + t.Fatalf("expected help output, got: %s", out) + } + + // Fails on connection failure + if code := cmd.Run([]string{"-http-addr=nope"}); code != 1 { + t.Fatalf("expected exit code 1, got: %d", code) + } + if out := ui.ErrorWriter.String(); !strings.Contains(out, "Failed querying members") { + t.Fatalf("expected failed query error, got: %s", out) + } +} diff --git a/command/status_test.go b/command/status_test.go index 37164016a..2ed1dbaf0 100644 --- a/command/status_test.go +++ b/command/status_test.go @@ -1,11 +1,84 @@ package command import ( + "strings" "testing" + "github.com/hashicorp/nomad/api" "github.com/mitchellh/cli" ) func TestStatusCommand_Implements(t *testing.T) { var _ cli.Command = &StatusCommand{} } + +func TestStatusCommand_Run(t *testing.T) { + agent, http, client, url := testAgent(t) + defer agent.Shutdown() + defer http.Shutdown() + + ui := new(cli.MockUi) + cmd := &StatusCommand{Ui: ui} + + // Should return blank for no jobs + if code := cmd.Run([]string{"-http-addr=" + url}); code != 0 { + t.Fatalf("expected exit 0, got: %d %s", code) + } + + // Check for this awkward nil string, since a nil bytes.Buffer + // returns this purposely, and mitchellh/cli has a nil pointer + // if nothing was ever output. + if out := ui.OutputWriter.String(); out != "" { + t.Fatalf("expected empty output, got: %s", out) + } + + // Register two jobs + job1 := api.NewBatchJob("job1", "myjob", 1) + if _, _, err := client.Jobs().Register(job1, nil); err != nil { + t.Fatalf("err: %s", err) + } + job2 := api.NewBatchJob("job2", "myjob", 1) + if _, _, err := client.Jobs().Register(job2, nil); err != nil { + t.Fatalf("err: %s", err) + } + + // Query again and check the result + if code := cmd.Run([]string{"-http-addr=" + url}); code != 0 { + t.Fatalf("expected exit 0, got: %d", code) + } + out := ui.OutputWriter.String() + if !strings.Contains(out, "job1") || !strings.Contains(out, "job2") { + t.Fatalf("expected job1 and job2, got: %s", out) + } + ui.OutputWriter.Reset() + + // Query a single job + if code := cmd.Run([]string{"-http-addr=" + url, "job2"}); code != 0 { + t.Fatalf("expected exit 0, got: %d", code) + } + out = ui.OutputWriter.String() + if strings.Contains(out, "job1") || !strings.Contains(out, "job2") { + t.Fatalf("expected only job2, got: %s", out) + } +} + +func TestStatusCommand_Fails(t *testing.T) { + ui := new(cli.MockUi) + cmd := &StatusCommand{Ui: ui} + + // Fails on misuse + if code := cmd.Run([]string{"some", "bad", "args"}); code != 1 { + t.Fatalf("expected exit code 1, got: %d", code) + } + if out := ui.ErrorWriter.String(); !strings.Contains(out, cmd.Help()) { + t.Fatalf("expected help output, got: %s", out) + } + + // Fails on connection failure + if code := cmd.Run([]string{"-http-addr=nope"}); code != 1 { + t.Fatalf("expected exit code 1, got: %d", code) + } + if out := ui.ErrorWriter.String(); !strings.Contains(out, "Failed querying jobs") { + t.Fatalf("expected failed query error, got: %s", out) + } +} diff --git a/command/util_test.go b/command/util_test.go index a30651da3..1738921d2 100644 --- a/command/util_test.go +++ b/command/util_test.go @@ -6,7 +6,9 @@ import ( "sync/atomic" "testing" + "github.com/hashicorp/nomad/api" "github.com/hashicorp/nomad/command/agent" + "github.com/hashicorp/nomad/testutil" ) var offset uint64 @@ -29,8 +31,10 @@ func nextConfig() *agent.Config { return conf } -func testAgent(t *testing.T) (*agent.Agent, *agent.HTTPServer) { +func testAgent(t *testing.T) (*agent.Agent, *agent.HTTPServer, *api.Client, string) { + // Make the agent conf := nextConfig() + conf.DevMode = true a, err := agent.NewAgent(conf, os.Stderr) if err != nil { t.Fatalf("err: %s", err) @@ -40,5 +44,27 @@ func testAgent(t *testing.T) (*agent.Agent, *agent.HTTPServer) { a.Shutdown() t.Fatalf("err: %s", err) } - return a, http + url := fmt.Sprintf("http://127.0.0.1:%d", conf.Ports.HTTP) + + // Make a client + clientConf := api.DefaultConfig() + clientConf.URL = url + client, err := api.NewClient(clientConf) + if err != nil { + t.Fatalf("err: %s", err) + } + + waitForLeader(t, client) + return a, http, client, url +} + +func waitForLeader(t *testing.T, client *api.Client) { + testutil.WaitForResult(func() (bool, error) { + if _, err := client.Status().Leader(); err != nil { + return false, err + } + return true, nil + }, func(err error) { + t.Fatalf("timeout waiting for leader: %s", err) + }) }