Files
atlantis/server/events/comment_parser_test.go
2018-02-28 11:04:28 -08:00

365 lines
8.7 KiB
Go

package events_test
import (
"fmt"
"strings"
"testing"
"github.com/runatlantis/atlantis/server/events"
"github.com/runatlantis/atlantis/server/events/vcs"
. "github.com/runatlantis/atlantis/testing"
)
var commentParser = events.CommentParser{
GithubUser: "github-user",
GithubToken: "github-token",
GitlabUser: "gitlab-user",
GitlabToken: "gitlab-token",
}
func TestParse_Ignored(t *testing.T) {
t.Log("given a comment that should be ignored we should set " +
"CommentParseResult.Ignore to true")
ignoreComments := []string{
"",
"a",
"abc",
"atlantis plan\nbut with newlines",
"terraform plan\nbut with newlines",
}
for _, c := range ignoreComments {
r := commentParser.Parse(c, vcs.Github)
Assert(t, r.Ignore, "expected Ignore to be true for comment %q", c)
}
}
func TestParse_HelpResponse(t *testing.T) {
t.Log("given a comment that should result in help output we " +
"should set CommentParseResult.CommentResult")
helpComments := []string{
"run",
"atlantis",
"@github-user",
"atlantis help",
"atlantis --help",
"atlantis -h",
"atlantis help something else",
"atlantis help plan",
}
for _, c := range helpComments {
r := commentParser.Parse(c, vcs.Github)
Equals(t, events.HelpComment, r.CommentResponse)
}
}
func TestParse_DidYouMeanAtlantis(t *testing.T) {
t.Log("given a comment that should result in a 'did you mean atlantis'" +
"response, should set CommentParseResult.CommentResult")
comments := []string{
"terraform",
"terraform help",
"terraform --help",
"terraform -h",
"terraform plan",
"terraform apply",
"terraform plan -w workspace -d . -- test",
}
for _, c := range comments {
r := commentParser.Parse(c, vcs.Github)
Assert(t, r.CommentResponse == events.DidYouMeanAtlantisComment,
"For comment %q expected CommentResponse==%q but got %q", c, events.DidYouMeanAtlantisComment, r.CommentResponse)
}
}
func TestParse_InvalidCommand(t *testing.T) {
t.Log("given a comment with an invalid atlantis command, should return " +
"a warning.")
comments := []string{
"atlantis paln",
"atlantis Plan",
"atlantis appely apply",
}
for _, c := range comments {
r := commentParser.Parse(c, vcs.Github)
exp := fmt.Sprintf("```\nError: unknown command %q.\nRun 'atlantis --help' for usage.\n```", strings.Fields(c)[1])
Assert(t, r.CommentResponse == exp,
"For comment %q expected CommentResponse==%q but got %q", c, exp, r.CommentResponse)
}
}
func TestParse_SubcommandUsage(t *testing.T) {
t.Log("given a comment asking for the usage of a subcommand should " +
"return help")
comments := []string{
"atlantis plan -h",
"atlantis plan --help",
"atlantis apply -h",
"atlantis apply --help",
}
for _, c := range comments {
r := commentParser.Parse(c, vcs.Github)
exp := "Usage of " + strings.Fields(c)[1]
Assert(t, strings.Contains(r.CommentResponse, exp),
"For comment %q expected CommentResponse %q to contain %q", c, r.CommentResponse, exp)
Assert(t, !strings.Contains(r.CommentResponse, "Error:"),
"For comment %q expected CommentResponse %q to not contain %q", c, r.CommentResponse, "Error: ")
}
}
func TestParse_InvalidFlags(t *testing.T) {
t.Log("given a comment with a valid atlantis command but invalid" +
" flags, should return a warning and the proper usage")
cases := []struct {
comment string
exp string
}{
{
"atlantis plan -e",
"Error: unknown shorthand flag: 'e' in -e",
},
{
"atlantis plan --abc",
"Error: unknown flag: --abc",
},
{
"atlantis apply -e",
"Error: unknown shorthand flag: 'e' in -e",
},
{
"atlantis apply --abc",
"Error: unknown flag: --abc",
},
}
for _, c := range cases {
r := commentParser.Parse(c.comment, vcs.Github)
Assert(t, strings.Contains(r.CommentResponse, c.exp),
"For comment %q expected CommentResponse %q to contain %q", c.comment, r.CommentResponse, c.exp)
Assert(t, strings.Contains(r.CommentResponse, "Usage of "),
"For comment %q expected CommentResponse %q to contain %q", c.comment, r.CommentResponse, "Usage of ")
}
}
func TestParse_RelativeDirPath(t *testing.T) {
t.Log("if -d is used with a relative path, should return an error")
comments := []string{
"atlantis plan -d ..",
"atlantis apply -d ..",
// These won't return an error because we prepend with . when parsing.
//"atlantis plan -d /..",
//"atlantis apply -d /..",
"atlantis plan -d ./..",
"atlantis apply -d ./..",
"atlantis plan -d a/b/../../..",
"atlantis apply -d a/../..",
}
for _, c := range comments {
r := commentParser.Parse(c, vcs.Github)
exp := "Error: Using a relative path"
Assert(t, strings.Contains(r.CommentResponse, exp),
"For comment %q expected CommentResponse %q to contain %q", c, r.CommentResponse, exp)
}
}
func TestParse_InvalidWorkspace(t *testing.T) {
t.Log("if -w is used with '..', should return an error")
comments := []string{
"atlantis plan -w ..",
"atlantis apply -w ..",
"atlantis plan -w ..abc",
"atlantis apply -w abc..",
"atlantis plan -w abc..abc",
"atlantis apply -w ../../../etc/passwd",
}
for _, c := range comments {
r := commentParser.Parse(c, vcs.Github)
exp := "Error: Value for -w/--workspace can't contain '..'"
Assert(t, r.CommentResponse == exp,
"For comment %q expected CommentResponse %q to be %q", c, r.CommentResponse, exp)
}
}
func TestParse_Parsing(t *testing.T) {
cases := []struct {
flags string
expWorkspace string
expDir string
expVerbose bool
expExtraArgs string
}{
// Test defaults.
{
"",
"default",
"",
false,
"",
},
// Test each flag individually.
{
"-w workspace",
"workspace",
"",
false,
"",
},
{
"-d dir",
"default",
"dir",
false,
"",
},
{
"--verbose",
"default",
"",
true,
"",
},
// Test all of them with different permutations.
{
"-w workspace -d dir --verbose",
"workspace",
"dir",
true,
"",
},
{
"-d dir -w workspace --verbose",
"workspace",
"dir",
true,
"",
},
{
"--verbose -w workspace -d dir",
"workspace",
"dir",
true,
"",
},
// Test that flags after -- are ignored
{
"-w workspace -d dir -- --verbose",
"workspace",
"dir",
false,
"\"--verbose\"",
},
{
"-w workspace -- -d dir --verbose",
"workspace",
"",
false,
"\"-d\" \"dir\" \"--verbose\"",
},
// Test missing arguments.
{
"-w -d dir --verbose",
"-d",
"",
true,
"",
},
// Test the extra args parsing.
{
"--",
"default",
"",
false,
"",
},
{
"abc --",
"default",
"",
false,
"",
},
// Test trying to escape quoting
{
"abc -- \";echo \"hi",
"default",
"",
false,
`"\";echo" "\"hi"`,
},
{
"-w workspace -d dir --verbose -- arg one -two --three &&",
"workspace",
"dir",
true,
"\"arg\" \"one\" \"-two\" \"--three\" \"&&\"",
},
// Test whitespace.
{
"\t-w\tworkspace\t-d\tdir\t--verbose\t--\targ\tone\t-two\t--three\t&&",
"workspace",
"dir",
true,
"\"arg\" \"one\" \"-two\" \"--three\" \"&&\"",
},
{
" -w workspace -d dir --verbose -- arg one -two --three &&",
"workspace",
"dir",
true,
"\"arg\" \"one\" \"-two\" \"--three\" \"&&\"",
},
// Test that the dir string is normalized.
{
"-d /",
"default",
".",
false,
"",
},
{
"-d /adir",
"default",
"adir",
false,
"",
},
{
"-d .",
"default",
".",
false,
"",
},
{
"-d ./",
"default",
".",
false,
"",
},
{
"-d ./adir",
"default",
"adir",
false,
"",
},
}
for _, test := range cases {
for _, cmdName := range []string{"plan", "apply"} {
comment := fmt.Sprintf("atlantis %s %s", cmdName, test.flags)
r := commentParser.Parse(comment, vcs.Github)
Assert(t, r.CommentResponse == "", "CommentResponse should have been empty but was %q for comment %q", r.CommentResponse, comment)
Assert(t, test.expDir == r.Command.Dir, "exp dir to equal %q but was %q for comment %q", test.expDir, r.Command.Dir, comment)
Assert(t, test.expWorkspace == r.Command.Workspace, "exp workspace to equal %q but was %q for comment %q", test.expWorkspace, r.Command.Workspace, comment)
Assert(t, test.expVerbose == r.Command.Verbose, "exp verbose to equal %v but was %v for comment %q", test.expVerbose, r.Command.Verbose, comment)
actExtraArgs := strings.Join(r.Command.Flags, " ")
Assert(t, test.expExtraArgs == actExtraArgs, "exp extra args to equal %v but got %v for comment %q", test.expExtraArgs, actExtraArgs, comment)
if cmdName == "plan" {
Assert(t, r.Command.Name == events.Plan, "did not parse comment %q as plan command", comment)
}
if cmdName == "apply" {
Assert(t, r.Command.Name == events.Apply, "did not parse comment %q as apply command", comment)
}
}
}
}