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  })