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