2019-11-13 15:43:53 +02:00
package helper
import (
"fmt"
"io"
"io/ioutil"
"os"
"strings"
"testing"
"github.com/SAP/jenkins-library/pkg/config"
"github.com/stretchr/testify/assert"
)
2020-04-29 14:40:11 +02:00
var expectedResultDocument string = "# testStep\n\n\t## Description\n\nLong Test description\n\n\t\n\t" +
"## Prerequisites\n\t\n\tnone\n\n\t\n\t\n\t" +
"## Parameters\n\n| name | mandatory | default | possible values |\n" +
"| ---- | --------- | ------- | --------------- |\n" +
"| `param0` | No | `val0` | |\n" +
"| `param1` | No | | |\n" +
"| `param2` | Yes | | |\n" +
"| `script` | Yes | | |\n" +
2020-04-30 06:39:48 +02:00
"| `verbose` | No | `false` | `true`, `false` |\n\n" +
2020-04-29 14:40:11 +02:00
" * `param0`: param0 description\n" +
" * `param1`: param1 description\n" +
" * `param2`: param1 description\n" +
" * `script`: The common script environment of the Jenkinsfile running. Typically the reference to the script calling the pipeline step is provided with the `this` parameter, as in `script: this`. This allows the function to access the `commonPipelineEnvironment` for retrieving, e.g. configuration parameters.\n" +
" * `verbose`: verbose output\n\n\t\n\t" +
"## Step Configuration\n\nWe recommend to define values of step parameters via [config.yml file](../configuration.md).\n\n" +
"In following sections of the config.yml the configuration is possible:\n\n" +
"| parameter | general | step/stage |\n" +
"| --------- | ------- | ---------- |\n" +
"| `param0` | X | |\n" +
"| `param1` | | |\n" +
"| `param2` | | |\n" +
"| `verbose` | X | |\n\n\t\n\t" +
"## Side effects\n\t\n\tnone\n\t\n\t" +
"## Exceptions\n\t\n\tnone\n\t\n\t" +
"## Example\n\n\tnone\n"
2019-11-13 15:43:53 +02:00
func configMetaDataMock ( name string ) ( io . ReadCloser , error ) {
meta1 := ` metadata :
name : testStep
description : Test description
longDescription : |
Long Test description
spec :
inputs :
params :
- name : param0
type : string
description : param0 description
default : val0
scope :
- GENERAL
- PARAMETERS
mandatory : true
- name : param1
type : string
description : param1 description
scope :
- PARAMETERS
- name : param2
type : string
description : param1 description
scope :
- PARAMETERS
mandatory : true
`
var r string
switch name {
case "test.yaml" :
r = meta1
default :
r = ""
}
return ioutil . NopCloser ( strings . NewReader ( r ) ) , nil
}
func configOpenDocTemplateFileMock ( docTemplateFilePath string ) ( io . ReadCloser , error ) {
meta1 := ` # $ { docGenStepName }
# # $ { docGenDescription }
# # Prerequisites
none
# # $ { docJenkinsPluginDependencies }
# # $ { docGenParameters }
# # $ { docGenConfiguration }
# # Side effects
none
# # Exceptions
none
# # Example
none
`
switch docTemplateFilePath {
case "testStep.md" :
return ioutil . NopCloser ( strings . NewReader ( meta1 ) ) , nil
default :
return ioutil . NopCloser ( strings . NewReader ( "" ) ) , fmt . Errorf ( "Wrong Path: %v" , docTemplateFilePath )
}
}
2019-11-14 14:59:31 +02:00
var stepData config . StepData = config . StepData {
Spec : config . StepSpec {
Inputs : config . StepInputs {
Parameters : [ ] config . StepParameters {
2019-11-14 16:09:12 +02:00
{ Name : "param0" , Scope : [ ] string { "GENERAL" } , Type : "string" , Default : "default0" ,
Conditions : [ ] config . Condition {
{ Params : [ ] config . Param {
{ "name0a" , "val0a" } ,
{ "name0b" , "val0b" } ,
} ,
} } ,
} ,
{ Name : "param1" , Scope : [ ] string { "GENERAL" } , Type : "string" , Default : "default1" ,
Conditions : [ ] config . Condition {
{ Params : [ ] config . Param {
{ "name1a" , "val1a" } ,
} ,
} } ,
} ,
{ Name : "param1" , Scope : [ ] string { "GENERAL" } , Type : "string" , Default : "default1" ,
Conditions : [ ] config . Condition {
{ Params : [ ] config . Param {
{ "name1b" , "val1b" } ,
} ,
} } ,
} ,
2019-11-14 14:59:31 +02:00
} ,
Resources : [ ] config . StepResources {
{ Name : "resource0" , Type : "stash" , Description : "val0" } ,
{ Name : "resource1" , Type : "stash" , Description : "val1" } ,
{ Name : "resource2" , Type : "stash" , Description : "val2" } ,
} ,
} ,
Containers : [ ] config . Container {
{ Name : "container0" , Image : "image" , WorkingDir : "workingdir" , Shell : "shell" ,
EnvVars : [ ] config . EnvVar {
{ "envar.name0" , "envar.value0" } ,
} ,
} ,
{ Name : "container1" , Image : "image" , WorkingDir : "workingdir" ,
EnvVars : [ ] config . EnvVar {
{ "envar.name1" , "envar.value1" } ,
} ,
} ,
{ Name : "container2a" , Command : [ ] string { "command" } , ImagePullPolicy : "pullpolicy" , Image : "image" , WorkingDir : "workingdir" ,
EnvVars : [ ] config . EnvVar {
{ "envar.name2a" , "envar.value2a" } } ,
Conditions : [ ] config . Condition {
{ Params : [ ] config . Param {
2019-11-20 15:36:07 +02:00
{ "param_name2a" , "param_value2a" } ,
2019-11-14 14:59:31 +02:00
} } ,
} ,
} ,
{ Name : "container2b" , Image : "image" , WorkingDir : "workingdir" ,
EnvVars : [ ] config . EnvVar {
{ "envar.name2b" , "envar.value2b" } ,
} ,
Conditions : [ ] config . Condition {
{ Params : [ ] config . Param {
{ "param.name2b" , "param.value2b" } ,
} } ,
} ,
2019-11-20 10:05:10 +02:00
//VolumeMounts: []config.VolumeMount{
// {"mp.2b", "mn.2b"},
//},
Options : [ ] config . Option {
{ "option.name2b" , "option.value2b" } ,
2019-11-18 12:14:45 +02:00
} ,
2019-11-14 14:59:31 +02:00
} ,
} ,
Sidecars : [ ] config . Container {
{ Name : "sidecar0" , Command : [ ] string { "command" } , ImagePullPolicy : "pullpolicy" , Image : "image" , WorkingDir : "workingdir" , ReadyCommand : "readycommand" ,
EnvVars : [ ] config . EnvVar {
{ "envar.name3" , "envar.value3" } } ,
Conditions : [ ] config . Condition {
{ Params : [ ] config . Param {
{ "param.name0" , "param.value0" } ,
} } ,
} ,
2019-11-20 10:05:10 +02:00
//VolumeMounts: []config.VolumeMount{
// {"mp.3b", "mn.3b"},
//},
Options : [ ] config . Option {
{ "option.name3b" , "option.value3b" } ,
2019-11-18 12:14:45 +02:00
} ,
2019-11-14 14:59:31 +02:00
} ,
} ,
} ,
}
2019-11-13 15:43:53 +02:00
var resultDocumentContent string
func docFileWriterMock ( docTemplateFilePath string , data [ ] byte , perm os . FileMode ) error {
resultDocumentContent = string ( data )
switch docTemplateFilePath {
case "testStep.md" :
return nil
default :
return fmt . Errorf ( "Wrong Path: %v" , docTemplateFilePath )
}
}
func TestGenerateStepDocumentationSuccess ( t * testing . T ) {
var stepData config . StepData
contentMetaData , _ := configMetaDataMock ( "test.yaml" )
stepData . ReadPipelineStepData ( contentMetaData )
generateStepDocumentation ( stepData , DocuHelperData { true , "" , configOpenDocTemplateFileMock , docFileWriterMock } )
t . Run ( "Docu Generation Success" , func ( t * testing . T ) {
assert . Equal ( t , expectedResultDocument , resultDocumentContent )
} )
}
func TestGenerateStepDocumentationError ( t * testing . T ) {
var stepData config . StepData
contentMetaData , _ := configMetaDataMock ( "test.yaml" )
stepData . ReadPipelineStepData ( contentMetaData )
err := generateStepDocumentation ( stepData , DocuHelperData { true , "Dummy" , configOpenDocTemplateFileMock , docFileWriterMock } )
t . Run ( "Docu Generation Success" , func ( t * testing . T ) {
assert . Error ( t , err , fmt . Sprintf ( "Error occured: %v\n" , err ) )
} )
}
2019-11-14 14:59:31 +02:00
func TestReadAndAdjustTemplate ( t * testing . T ) {
t . Run ( "Success Case" , func ( t * testing . T ) {
tmpl , _ := configOpenDocTemplateFileMock ( "testStep.md" )
content := readAndAdjustTemplate ( tmpl )
cases := [ ] struct {
x , y string
} {
{ "{{docGenStepName .}}" , "${docGenStepName}" } ,
{ "{{docGenConfiguration .}}" , "${docGenConfiguration}" } ,
{ "{{docGenParameters .}}" , "${docGenParameters}" } ,
{ "{{docGenDescription .}}" , "${docGenDescription}" } ,
{ "" , "${docJenkinsPluginDependencies}" } ,
}
for _ , c := range cases {
if len ( c . x ) > 0 {
assert . Contains ( t , content , c . x )
}
if len ( c . y ) > 0 {
assert . NotContains ( t , content , c . y )
}
}
} )
}
2019-11-20 12:29:13 +02:00
func TestAddDefaultContainerContent ( t * testing . T ) {
2019-11-14 14:59:31 +02:00
t . Run ( "Success Case" , func ( t * testing . T ) {
var m map [ string ] string = make ( map [ string ] string )
2019-11-20 12:29:13 +02:00
addDefaultContainerContent ( & stepData , m )
2019-11-14 14:59:31 +02:00
cases := [ ] struct {
x , want string
} {
2020-04-27 12:16:41 +02:00
{ "containerCommand" , "`command`" } ,
{ "containerName" , "`container0`, `container1``container2a`<br>`container2b`<br>" } ,
{ "containerShell" , "`shell`" } ,
{ "dockerEnvVars" , "`[envar.name0=envar.value0]`, `[envar.name1=envar.value1]`param_name2a=`param_value2a`: `[envar.name2a=envar.value2a]`<br>param.name2b=`param.value2b`: `[envar.name2b=envar.value2b]`<br>" } ,
{ "dockerImage" , "`image`, `image`param_name2a=`param_value2a`: `image`<br>param.name2b=`param.value2b`: `image`<br>" } ,
{ "dockerName" , "`container0`, `container1``container2a`<br>`container2b`<br>" } ,
2019-11-14 14:59:31 +02:00
{ "dockerPullImage" , "true" } ,
2019-11-20 11:50:23 +02:00
{ "dockerOptions" , "option.name2b option.value2b" } ,
2020-04-27 12:16:41 +02:00
{ "dockerWorkspace" , "`workingdir`, `workingdir`param_name2a=`param_value2a`: `workingdir`<br>param.name2b=`param.value2b`: `workingdir`<br>" } ,
2019-11-14 14:59:31 +02:00
}
2020-04-27 12:16:41 +02:00
//assert.Equal(t, len(cases), len(m))
2019-11-14 14:59:31 +02:00
for _ , c := range cases {
assert . Contains ( t , m , c . x )
assert . True ( t , len ( m [ c . x ] ) > 0 )
2020-04-27 12:16:41 +02:00
assert . True ( t , strings . Contains ( m [ c . x ] , c . want ) , fmt . Sprintf ( "%v: %v != %v" , c . x , m [ c . x ] , c . want ) )
2019-11-14 14:59:31 +02:00
}
} )
}
2019-11-20 12:29:13 +02:00
func TestAddDefaultSidecarContent ( t * testing . T ) {
2019-11-14 14:59:31 +02:00
t . Run ( "Success Case" , func ( t * testing . T ) {
var m map [ string ] string = make ( map [ string ] string )
2019-11-20 12:29:13 +02:00
addDefaultSidecarContent ( & stepData , m )
2019-11-14 14:59:31 +02:00
cases := [ ] struct {
x , want string
} {
{ "sidecarCommand" , "command" } ,
{ "sidecarEnvVars" , "envar.name3=envar.value3" } ,
2020-04-27 12:16:41 +02:00
{ "sidecarImage" , "`image`" } ,
{ "sidecarName" , "`sidecar0`" } ,
2019-11-14 14:59:31 +02:00
{ "sidecarPullImage" , "true" } ,
{ "sidecarReadyCommand" , "readycommand" } ,
2019-11-20 11:50:23 +02:00
{ "sidecarOptions" , "option.name3b option.value3b" } ,
2019-11-14 14:59:31 +02:00
{ "sidecarWorkspace" , "workingdir" } ,
}
2019-11-20 11:50:23 +02:00
assert . Equal ( t , len ( cases ) , len ( m ) )
2019-11-14 14:59:31 +02:00
for _ , c := range cases {
assert . Contains ( t , m , c . x )
assert . True ( t , len ( m [ c . x ] ) > 0 )
assert . Equal ( t , c . want , m [ c . x ] , fmt . Sprintf ( "%v:%v" , c . x , m [ c . x ] ) )
}
} )
}
func TestAddStashContent ( t * testing . T ) {
t . Run ( "Success Case" , func ( t * testing . T ) {
var m map [ string ] string = make ( map [ string ] string )
addStashContent ( & stepData , m )
cases := [ ] struct {
x , want string
} {
{ "stashContent" , "resource0, resource1, resource2" } ,
}
2019-11-20 11:50:23 +02:00
assert . Equal ( t , len ( cases ) , len ( m ) )
2019-11-14 14:59:31 +02:00
for _ , c := range cases {
assert . Contains ( t , m , c . x )
assert . True ( t , len ( m [ c . x ] ) > 0 )
assert . True ( t , strings . Contains ( m [ c . x ] , c . want ) , fmt . Sprintf ( "%v:%v" , c . x , m [ c . x ] ) )
}
} )
}
func TestGetDocuContextDefaults ( t * testing . T ) {
t . Run ( "Success Case" , func ( t * testing . T ) {
m := getDocuContextDefaults ( & stepData )
cases := [ ] struct {
x , want string
} {
{ "stashContent" , "resource0, resource1, resource2" } ,
{ "sidecarCommand" , "command" } ,
{ "sidecarEnvVars" , "envar.name3=envar.value3" } ,
{ "sidecarImage" , "image" } ,
{ "sidecarName" , "sidecar0" } ,
{ "sidecarPullImage" , "true" } ,
{ "sidecarReadyCommand" , "readycommand" } ,
2019-11-20 11:50:23 +02:00
{ "sidecarOptions" , "option.name3b option.value3b" } ,
2019-11-14 14:59:31 +02:00
{ "sidecarWorkspace" , "workingdir" } ,
{ "containerCommand" , "command" } ,
2020-04-27 12:16:41 +02:00
{ "containerName" , "`container0`, `container1``container2a`<br>`container2b`<br>" } ,
2019-11-14 14:59:31 +02:00
{ "containerShell" , "shell" } ,
2020-04-27 12:16:41 +02:00
{ "dockerEnvVars" , "`[envar.name0=envar.value0]`, `[envar.name1=envar.value1]`param_name2a=`param_value2a`: `[envar.name2a=envar.value2a]`<br>param.name2b=`param.value2b`: `[envar.name2b=envar.value2b]`<br>" } ,
{ "dockerImage" , "`image`, `image`param_name2a=`param_value2a`: `image`<br>param.name2b=`param.value2b`: `image`" } ,
{ "dockerName" , "`container0`, `container1``container2a`<br>`container2b`<br>" } ,
2019-11-14 14:59:31 +02:00
{ "dockerPullImage" , "true" } ,
2019-11-20 11:50:23 +02:00
{ "dockerOptions" , "option.name2b option.value2b" } ,
2020-04-27 12:16:41 +02:00
{ "dockerWorkspace" , "`workingdir`, `workingdir`param_name2a=`param_value2a`: `workingdir`<br>param.name2b=`param.value2b`: `workingdir`<br>" } ,
2019-11-14 14:59:31 +02:00
}
2019-11-20 11:50:23 +02:00
assert . Equal ( t , len ( cases ) , len ( m ) )
2019-11-14 14:59:31 +02:00
for _ , c := range cases {
assert . Contains ( t , m , c . x )
assert . True ( t , len ( m [ c . x ] ) > 0 )
2020-04-27 12:16:41 +02:00
assert . True ( t , strings . Contains ( m [ c . x ] , c . want ) , fmt . Sprintf ( "%v: %v != %v" , c . x , m [ c . x ] , c . want ) )
2019-11-14 14:59:31 +02:00
}
} )
}
2019-11-14 16:09:12 +02:00
func TestAddNewParameterWithCondition ( t * testing . T ) {
t . Run ( "Success Case" , func ( t * testing . T ) {
var m map [ string ] string = make ( map [ string ] string )
cases := [ ] struct {
x , want string
i int
} {
2020-04-27 12:16:41 +02:00
{ "param0" , "name0a=`val0a`: `default0` name0b=`val0b`: `default0`" , 0 } ,
{ "param1" , "name1a=`val1a`: `default1`" , 1 } ,
2019-11-14 16:09:12 +02:00
}
for _ , c := range cases {
addNewParameterWithCondition ( stepData . Spec . Inputs . Parameters [ c . i ] , m )
assert . Contains ( t , m , c . x )
assert . True ( t , len ( m [ c . x ] ) > 0 )
assert . True ( t , strings . Contains ( m [ c . x ] , c . want ) , fmt . Sprintf ( "%v" , m [ c . x ] ) )
}
} )
}
func TestAddExistingParameterWithCondition ( t * testing . T ) {
t . Run ( "Success Case" , func ( t * testing . T ) {
var m map [ string ] string = make ( map [ string ] string )
addNewParameterWithCondition ( stepData . Spec . Inputs . Parameters [ 1 ] , m )
cases := [ ] struct {
x , want string
} {
2020-04-27 12:16:41 +02:00
{ "param1" , "name1a=`val1a`: `default1` <br>name1b=`val1b`: `default1` " } ,
2019-11-14 16:09:12 +02:00
}
for _ , c := range cases {
addExistingParameterWithCondition ( stepData . Spec . Inputs . Parameters [ 2 ] , m )
assert . Contains ( t , m , c . x )
assert . True ( t , len ( m [ c . x ] ) > 0 )
assert . True ( t , strings . Contains ( m [ c . x ] , c . want ) , fmt . Sprintf ( "%v" , m [ c . x ] ) )
}
} )
}
2020-04-24 14:13:02 +02:00
func TestRenderPossibleValues ( t * testing . T ) {
t . Run ( "none" , func ( t * testing . T ) {
// init
var in [ ] interface { }
// test
out := possibleValuesToString ( in )
// assert
assert . Empty ( t , out )
} )
t . Run ( "one" , func ( t * testing . T ) {
// init
var in [ ] interface { }
in = append ( in , "fu" )
// test
out := possibleValuesToString ( in )
// assert
assert . Equal ( t , "`fu`" , out )
} )
t . Run ( "many" , func ( t * testing . T ) {
// init
var in [ ] interface { }
in = append ( in , "fu" , "fara" )
// test
out := possibleValuesToString ( in )
// assert
assert . Equal ( t , "`fu`, `fara`" , out )
} )
t . Run ( "boolean" , func ( t * testing . T ) {
// init
var in [ ] interface { }
in = append ( in , false , true )
// test
out := possibleValuesToString ( in )
// assert
assert . Equal ( t , "`false`, `true`" , out )
} )
}