1
16
17 package edit
18
19 import (
20 "reflect"
21 "strconv"
22 "strings"
23 "testing"
24 )
25
26 func TestEmptyCommandFileContainsNoCommands(t *testing.T) {
27 reader := strings.NewReader("")
28 commandsByBuildFile := make(map[string][]commandsForTarget)
29 appendCommandsFromReader(NewOpts(), reader, commandsByBuildFile, []string{})
30 t.Logf("Read commands:\n%s", prettyFormat(commandsByBuildFile))
31
32 if len(commandsByBuildFile) != 0 {
33 t.Error("No commands should be read")
34 }
35 }
36
37 func TestCommandFileWithOneSetAttributeLineContainsOneCommand(t *testing.T) {
38 commands := parseCommandFile("set srcs mytarget.go|//test-project:mytarget\n", t)
39 if len(commands) != 1 {
40 t.Error("Exactly one command should be read")
41 return
42 }
43 if commands[0].target != "//test-project:mytarget" {
44 t.Error("Read command should be for the correct target")
45 }
46 if !reflect.DeepEqual(commands[0].command, command{[]string{"set", "srcs", "mytarget.go"}}) {
47 t.Error("Read command should contain the correct command tokens")
48 }
49 }
50
51 func TestCommandFileWithTwoSetAttributesInOneLineContainsTwoCommands(t *testing.T) {
52 commands := parseCommandFile("set srcs mytarget.go|set deps //other-project:othertarget|//test-project:mytarget\n", t)
53 if len(commands) != 2 {
54 t.Error("Exactly two commands should be read")
55 return
56 }
57 if commands[0].target != "//test-project:mytarget" {
58 t.Error("First read command should be for the correct target")
59 }
60 if !reflect.DeepEqual(commands[0].command, command{[]string{"set", "srcs", "mytarget.go"}}) {
61 t.Error("First read command should contain the correct command tokens")
62 }
63 if commands[1].target != "//test-project:mytarget" {
64 t.Error("Second read command should be for the correct target")
65 }
66 if !reflect.DeepEqual(commands[1].command, command{[]string{"set", "deps", "//other-project:othertarget"}}) {
67 t.Error("Second read command should contain the correct command tokens")
68 }
69 }
70
71 func TestCommandFileWithTwoSetAttributesInSeparateLinesContainsTwoCommands(t *testing.T) {
72 commands := parseCommandFile("set srcs mytarget.go|//test-project:mytarget\nset deps //other-project:othertarget|//test-project:mytarget\n", t)
73 if len(commands) != 2 {
74 t.Error("Exactly two commands should be read")
75 return
76 }
77 if commands[0].target != "//test-project:mytarget" {
78 t.Error("First read command should be for the correct target")
79 }
80 if !reflect.DeepEqual(commands[0].command, command{[]string{"set", "srcs", "mytarget.go"}}) {
81 t.Error("First read command should contain the correct command tokens")
82 }
83 if commands[1].target != "//test-project:mytarget" {
84 t.Error("Second read command should be for the correct target")
85 }
86 if !reflect.DeepEqual(commands[1].command, command{[]string{"set", "deps", "//other-project:othertarget"}}) {
87 t.Error("Second read command should contain the correct command tokens")
88 }
89 }
90
91 func TestCommandFileWithoutTrailingNewlineContainsCommand(t *testing.T) {
92 commands := parseCommandFile("set srcs mytarget.go|//test-project:mytarget", t)
93 if len(commands) != 1 {
94 t.Error("Exactly one command should be read")
95 return
96 }
97 if commands[0].target != "//test-project:mytarget" {
98 t.Error("Read command should be for the correct target")
99 }
100 }
101
102 func TestBlankLinesInCommandFileAreIgnored(t *testing.T) {
103 commands := parseCommandFile("set srcs mytarget.go|//test-project:mytarget\n\n\n\n\nset srcs othertarget.go|//test-project:othertarget\n", t)
104 if len(commands) != 2 {
105 t.Error("Exactly two commands should be read")
106 }
107 }
108
109 func TestLongLineInCommandFileParsesAsOneCommand(t *testing.T) {
110 srcsLength := 10000
111
112 expectedCommandTokens := make([]string, srcsLength+2)
113 expectedCommandTokens[0] = "set"
114 expectedCommandTokens[1] = "srcs"
115 srcs := make([]string, srcsLength)
116 for i := 0; i < srcsLength; i++ {
117 src := "source_" + strconv.Itoa(i) + ".go"
118 srcs[i] = src
119 expectedCommandTokens[i+2] = src
120 }
121
122 commands := parseCommandFile("set srcs "+strings.Join(srcs, " ")+"|//test-project:mytarget\n", t)
123 if len(commands) != 1 {
124 t.Error("Exactly one command should be read")
125 return
126 }
127 if !reflect.DeepEqual(commands[0].command, command{expectedCommandTokens}) {
128 t.Errorf("First read command should contain the correct command tokens")
129 }
130 }
131
132 func TestEscapedPipesInCommandFileArentSplit(t *testing.T) {
133 commands := parseCommandFile("set srcs mytarget.go|//test-project:mytarget(\\|\\|)\n", t)
134 if len(commands) != 1 {
135 t.Error("Exactly one command should be read")
136 }
137 if commands[0].target != "//test-project:mytarget(||)" {
138 t.Error("Read command target should be for the correct target")
139 }
140 }
141
142 func parseCommandFile(fileContent string, t *testing.T) []parsedCommand {
143 reader := strings.NewReader(fileContent)
144 commandsByBuildFile := make(map[string][]commandsForTarget)
145 appendCommandsFromReader(NewOpts(), reader, commandsByBuildFile, []string{})
146 t.Logf("Read commands:\n%s", prettyFormat(commandsByBuildFile))
147 return extractCommands(commandsByBuildFile)
148 }
149
150 type parsedCommand struct {
151 command command
152 target string
153 buildFile string
154 }
155
156 func extractCommands(commandsByBuildFile map[string][]commandsForTarget) []parsedCommand {
157 out := make([]parsedCommand, 0)
158 for buildFile, targets := range commandsByBuildFile {
159 for _, target := range targets {
160 for _, command := range target.commands {
161 out = append(out, parsedCommand{command, target.target, buildFile})
162 }
163 }
164 }
165 return out
166 }
167
168 func prettyFormat(commandsByBuildFile map[string][]commandsForTarget) string {
169 out := ""
170 for buildFile, targets := range commandsByBuildFile {
171 out += buildFile + "\n"
172 for _, target := range targets {
173 out += " target: " + target.target + "\n"
174 for _, command := range target.commands {
175 out += " -"
176 for _, token := range command.tokens {
177 out += " " + token
178 }
179 out += "\n"
180 }
181 }
182 }
183 return out
184 }
185
View as plain text