github.com/SAP/cloud-mta-build-tool@v1.2.27/internal/commands/commands_test.go (about) 1 package commands 2 3 import ( 4 "fmt" 5 "os" 6 "path/filepath" 7 8 "gopkg.in/yaml.v2" 9 10 . "github.com/onsi/ginkgo" 11 . "github.com/onsi/ginkgo/extensions/table" 12 . "github.com/onsi/gomega" 13 14 "github.com/SAP/cloud-mta-build-tool/internal/archive" 15 "github.com/SAP/cloud-mta/mta" 16 ) 17 18 var _ = Describe("Commands tests", func() { 19 It("Mesh", func() { 20 var moduleTypesCfg = []byte(` 21 version: 1 22 module-types: 23 - name: html5 24 info: "build UI application" 25 commands: 26 - command: npm install 27 - command: grunt 28 - command: npm prune --production 29 - name: java 30 info: "build java application" 31 commands: 32 - command: mvn clean install 33 - name: nodejs 34 info: "build nodejs application" 35 commands: 36 - command: npm install 37 - name: golang 38 info: "build golang application" 39 commands: 40 - command: go build *.go 41 `) 42 var modules = mta.Module{ 43 Name: "uiapp", 44 Type: "html5", 45 Path: "./", 46 } 47 var expected = CommandList{ 48 Info: "build UI application", 49 Command: []string{"npm install", "grunt", "npm prune --production"}, 50 } 51 commands := ModuleTypes{} 52 customCommands := Builders{} 53 Ω(yaml.Unmarshal(moduleTypesCfg, &commands)).Should(Succeed()) 54 Ω(mesh(&modules, &commands, &customCommands)).Should(Equal(expected)) 55 modules = mta.Module{ 56 Name: "uiapp1", 57 Type: "html5", 58 Path: "./", 59 } 60 _, _, err := mesh(&modules, &commands, &customCommands) 61 Ω(err).Should(Succeed()) 62 modules = mta.Module{ 63 Name: "uiapp1", 64 Type: "html5", 65 Path: "./", 66 BuildParams: map[string]interface{}{ 67 "builder": "html5x", 68 }, 69 } 70 _, _, err = mesh(&modules, &commands, &customCommands) 71 Ω(err).Should(HaveOccurred()) 72 }) 73 74 It("Mesh - fails on wrong type of property commands", func() { 75 module := mta.Module{ 76 Name: "uiapp1", 77 Type: "html5", 78 Path: "./", 79 BuildParams: map[string]interface{}{ 80 "builder": "custom", 81 "commands": "cmd", 82 }, 83 } 84 commands := ModuleTypes{} 85 customCommands := Builders{} 86 _, _, err := mesh(&module, &commands, &customCommands) 87 Ω(err).Should(HaveOccurred()) 88 }) 89 90 It("Mesh - fails on usage both builder and commands in one module type", func() { 91 var moduleTypesCfg = []byte(` 92 version: 1 93 module-types: 94 - name: html5 95 info: "build UI application" 96 builder: npm 97 commands: 98 - command: npm install 99 - command: grunt 100 - command: npm prune --production 101 `) 102 var modules = mta.Module{ 103 Name: "uiapp", 104 Type: "html5", 105 Path: "./", 106 } 107 commands := ModuleTypes{} 108 customCommands := Builders{} 109 Ω(yaml.Unmarshal(moduleTypesCfg, &commands)).Should(Succeed()) 110 _, _, err := mesh(&modules, &commands, &customCommands) 111 Ω(err).Should(HaveOccurred()) 112 }) 113 114 It("Mesh - custom builder", func() { 115 var modules = mta.Module{ 116 Name: "uiapp", 117 Type: "html5", 118 Path: "./", 119 BuildParams: map[string]interface{}{ 120 builderParam: "custom", 121 commandsParam: []string{"command1"}, 122 }, 123 } 124 commands := ModuleTypes{} 125 customCommands := Builders{} 126 cmds, _, err := mesh(&modules, &commands, &customCommands) 127 Ω(err).Should(Succeed()) 128 Ω(len(cmds.Command)).Should(Equal(1)) 129 Ω(cmds.Command[0]).Should(Equal("command1")) 130 }) 131 132 It("CommandProvider", func() { 133 expected := CommandList{ 134 Info: "installing module dependencies & remove dev dependencies", 135 Command: []string{"npm install --production"}, 136 } 137 Ω(CommandProvider(mta.Module{Type: "html5"})).Should(Equal(expected)) 138 }) 139 140 var _ = Describe("CommandProvider - Invalid module types cfg", func() { 141 var config []byte 142 143 BeforeEach(func() { 144 config = make([]byte, len(ModuleTypeConfig)) 145 copy(config, ModuleTypeConfig) 146 // Simplified commands configuration (performance purposes). removed "npm prune --production" 147 ModuleTypeConfig = []byte(` 148 module-types: 149 - name: html5 150 info: "installing module dependencies & execute grunt & remove dev dependencies" 151 path: "path to config file which override the following default commands" 152 commands: [xxx] 153 - name: nodejs 154 info: "build nodejs application" 155 path: "path to config file which override the following default commands" 156 commands: 157 `) 158 }) 159 160 AfterEach(func() { 161 ModuleTypeConfig = make([]byte, len(config)) 162 copy(ModuleTypeConfig, config) 163 }) 164 165 It("test", func() { 166 _, _, err := CommandProvider(mta.Module{Type: "html5"}) 167 Ω(err).Should(HaveOccurred()) 168 }) 169 }) 170 171 var _ = Describe("CommandProvider - Invalid builders cfg", func() { 172 var moduleTypesConfig []byte 173 var buildersConfig []byte 174 175 BeforeEach(func() { 176 moduleTypesConfig = make([]byte, len(ModuleTypeConfig)) 177 copy(moduleTypesConfig, ModuleTypeConfig) 178 // Simplified commands configuration (performance purposes). removed "npm prune --production" 179 ModuleTypeConfig = []byte(` 180 module-types: 181 - name: html5 182 info: "installing module dependencies & execute grunt & remove dev dependencies" 183 path: "path to config file which override the following default commands" 184 commands: 185 `) 186 187 buildersConfig = make([]byte, len(BuilderTypeConfig)) 188 copy(buildersConfig, BuilderTypeConfig) 189 BuilderTypeConfig = []byte(` 190 builders: 191 - name: html5 192 info: "installing module dependencies & execute grunt & remove dev dependencies" 193 path: "path to config file which override the following default commands" 194 commands: [xxx] 195 `) 196 }) 197 198 AfterEach(func() { 199 ModuleTypeConfig = make([]byte, len(moduleTypesConfig)) 200 copy(ModuleTypeConfig, moduleTypesConfig) 201 BuilderTypeConfig = make([]byte, len(buildersConfig)) 202 copy(BuilderTypeConfig, buildersConfig) 203 }) 204 205 It("test", func() { 206 _, _, err := CommandProvider(mta.Module{Type: "html5"}) 207 Ω(err).Should(HaveOccurred()) 208 }) 209 }) 210 211 var _ = Describe("Command converter", func() { 212 213 It("Sanity", func() { 214 cmdInput := []string{"npm install {{config}}", "grunt", "npm prune --production"} 215 cmdExpected := [][]string{ 216 {"path", "npm", "install", "{{config}}"}, 217 {"path", "grunt"}, 218 {"path", "npm", "prune", "--production"}} 219 result, e := CmdConverter("path", cmdInput) 220 Ω(e).Should(Succeed()) 221 Ω(result).Should(Equal(cmdExpected)) 222 }) 223 }) 224 225 DescribeTable("convert command with special characters", func(commandLine string, expected []string) { 226 result, e := CmdConverter("path", []string{commandLine}) 227 Ω(e).Should(Succeed()) 228 Ω(result, e).Should(Equal([][]string{append([]string{"path"}, expected...)})) 229 }, 230 Entry("string in double quotes should not be split", `sh -c "a && b"`, []string{"sh", "-c", "a && b"}), 231 Entry("string in single quotes should not be split", `do 'some thing' new`, []string{"do", "some thing", "new"}), 232 Entry("escaped space should not be split", `do some\ thing new`, []string{"do", "some thing", "new"}), 233 ) 234 235 DescribeTable("convert invalid command", func(commandLine string) { 236 _, e := CmdConverter("path", []string{commandLine}) 237 Ω(e).Should(HaveOccurred()) 238 Ω(e.Error()).Should(ContainSubstring(fmt.Sprintf(BadCommandMsg, commandLine))) 239 }, 240 Entry("double quotes should match", `sh -c "a && b`), 241 Entry("single quotes should match", `do 'some thing new`), 242 Entry("mixed quotes should match", `sh -c "a && b'`), 243 ) 244 245 var _ = Describe("moduleCmd", func() { 246 It("Sanity", func() { 247 var mtaCF = []byte(` 248 _schema-version: "2.0.0" 249 ID: mta_proj 250 version: 1.0.0 251 252 modules: 253 - name: htmlapp 254 type: html5 255 path: app 256 257 - name: htmlapp2 258 type: html5 259 path: app 260 261 - name: java 262 type: java 263 path: app 264 `) 265 266 m, err := mta.Unmarshal(mtaCF) 267 // parse mta yaml 268 Ω(err).Should(Succeed()) 269 module, commands, _, err := moduleCmd(m, "htmlapp") 270 Ω(err).Should(Succeed()) 271 Ω(module.Path).Should(Equal("app")) 272 Ω(commands).Should(Equal([]string{"npm install --production"})) 273 }) 274 275 It("Builder specified in build params", func() { 276 var mtaCF = []byte(` 277 _schema-version: "2.0.0" 278 ID: mta_proj 279 version: 1.0.0 280 281 modules: 282 - name: htmlapp 283 type: html5 284 path: app 285 build-parameters: 286 builder: npm 287 `) 288 289 m, err := mta.Unmarshal(mtaCF) 290 // parse mta yaml 291 Ω(err).Should(Succeed()) 292 module, commands, _, err := moduleCmd(m, "htmlapp") 293 Ω(err).Should(BeNil()) 294 Ω(module.Path).Should(Equal("app")) 295 Ω(commands).Should(Equal([]string{"npm install --production"})) 296 }) 297 298 It("Fetcher builder specified in build params", func() { 299 var mtaCF = []byte(` 300 _schema-version: "2.0.0" 301 ID: mta_proj 302 version: 1.0.0 303 304 modules: 305 - name: htmlapp 306 type: html5 307 path: app 308 build-parameters: 309 builder: fetcher 310 fetcher-opts: 311 repo-type: maven 312 repo-coordinates: com.sap.xs.java:xs-audit-log-api:1.2.3 313 314 `) 315 m, err := mta.Unmarshal(mtaCF) 316 // parse mta yaml 317 Ω(err).Should(Succeed()) 318 module, commands, _, err := moduleCmd(m, "htmlapp") 319 Ω(err).Should(BeNil()) 320 Ω(module.Path).Should(Equal("app")) 321 Ω(commands).Should(Equal([]string{"mvn -B dependency:copy -Dartifact=com.sap.xs.java:xs-audit-log-api:1.2.3 -DoutputDirectory=./target"})) 322 }) 323 324 It("Invalid case - wrong mta", func() { 325 wd, _ := os.Getwd() 326 ep := dir.Loc{SourcePath: filepath.Join(wd, "testdata"), MtaFilename: "mtaUnknown.yaml"} 327 _, _, _, err := GetModuleAndCommands(&ep, "node-js") 328 Ω(err).Should(HaveOccurred()) 329 330 }) 331 332 var _ = Describe("GetModuleAndCommands", func() { 333 It("Sanity", func() { 334 wd, _ := os.Getwd() 335 ep := dir.Loc{SourcePath: filepath.Join(wd, "testdata")} 336 module, cmd, _, err := GetModuleAndCommands(&ep, "node-js") 337 Ω(err).Should(Succeed()) 338 Ω(module.Name).Should(Equal("node-js")) 339 Ω(len(cmd)).Should(Equal(1)) 340 Ω(cmd[0]).Should(Equal("npm install --production")) 341 342 }) 343 It("Invalid case - wrong module name", func() { 344 wd, _ := os.Getwd() 345 ep := dir.Loc{SourcePath: filepath.Join(wd, "testdata")} 346 _, _, _, err := GetModuleAndCommands(&ep, "node-js1") 347 Ω(err).Should(HaveOccurred()) 348 349 }) 350 It("Invalid case - wrong mta", func() { 351 wd, _ := os.Getwd() 352 ep := dir.Loc{SourcePath: filepath.Join(wd, "testdata"), MtaFilename: "mtaUnknown.yaml"} 353 _, _, _, err := GetModuleAndCommands(&ep, "node-js") 354 Ω(err).Should(HaveOccurred()) 355 356 }) 357 It("Invalid case - wrong type", func() { 358 wd, _ := os.Getwd() 359 ep := dir.Loc{SourcePath: filepath.Join(wd, "testdata"), MtaFilename: "mtaUnknownBuilder.yaml"} 360 _, cmd, _, _ := GetModuleAndCommands(&ep, "node-js") 361 Ω(len(cmd)).Should(Equal(0)) 362 363 }) 364 It("Invalid case - broken commands config", func() { 365 conf := ModuleTypeConfig 366 ModuleTypeConfig = []byte("wrong config") 367 wd, _ := os.Getwd() 368 ep := dir.Loc{SourcePath: filepath.Join(wd, "testdata")} 369 _, _, _, err := GetModuleAndCommands(&ep, "node-js") 370 ModuleTypeConfig = conf 371 Ω(err).Should(HaveOccurred()) 372 }) 373 }) 374 }) 375 376 var _ = Describe("GetBuilder", func() { 377 It("Builder defined by type", func() { 378 m := mta.Module{ 379 Name: "x", 380 Type: "node-js", 381 } 382 Ω(GetBuilder(&m)).Should(Equal("node-js")) 383 }) 384 It("Builder defined by build params", func() { 385 m := mta.Module{ 386 Name: "x", 387 Type: "node-js", 388 BuildParams: map[string]interface{}{ 389 builderParam: "npm", 390 }, 391 } 392 builder, custom, cmds, _, err := GetBuilder(&m) 393 Ω(builder).Should(Equal("npm")) 394 Ω(custom).Should(Equal(true)) 395 Ω(len(cmds)).Should(Equal(0)) 396 Ω(err).Should(Succeed()) 397 }) 398 It("Custom builder with no commands", func() { 399 m := mta.Module{ 400 Name: "x", 401 Type: "node-js", 402 BuildParams: map[string]interface{}{ 403 builderParam: customBuilder, 404 }, 405 } 406 builder, custom, _, _, err := GetBuilder(&m) 407 Ω(builder).Should(Equal(customBuilder)) 408 Ω(custom).Should(Equal(true)) 409 Ω(err).Should(Succeed()) 410 }) 411 It("Custom builder with wrong commands definition", func() { 412 m := mta.Module{ 413 Name: "x", 414 Type: "node-js", 415 BuildParams: map[string]interface{}{ 416 builderParam: customBuilder, 417 commandsParam: "command1", 418 }, 419 } 420 builder, custom, _, _, err := GetBuilder(&m) 421 Ω(builder).Should(Equal(customBuilder)) 422 Ω(custom).Should(Equal(true)) 423 Ω(err.Error()).Should(Equal(`the "commands" property is defined incorrectly; the property must contain a sequence of strings`)) 424 }) 425 }) 426 })