github.com/ouraigua/jenkins-library@v0.0.0-20231028010029-fbeaf2f3aa9b/test/groovy/com/sap/piper/ConfigurationHelperTest.groovy (about)

     1  package com.sap.piper
     2  
     3  import static org.hamcrest.Matchers.*
     4  import static org.junit.Assert.assertThat
     5  
     6  import org.junit.Assert
     7  import org.junit.Rule
     8  import org.junit.Test
     9  import org.junit.rules.ExpectedException
    10  import org.yaml.snakeyaml.Yaml
    11  
    12  class ConfigurationHelperTest {
    13  
    14      Script mockScript = new Script() {
    15  
    16          def run() {
    17              // it never runs
    18              throw new UnsupportedOperationException()
    19          }
    20  
    21          def STEP_NAME = 'mock'
    22  
    23          def echo(message) {
    24          }
    25  
    26          def libraryResource(String r) {
    27              'key: value' // just a stupid default
    28          }
    29  
    30          def readYaml(Map m) {
    31             new Yaml().load(m.text)
    32          }
    33  
    34          def env = [STAGE_NAME: 'test']
    35      }
    36  
    37      @Rule
    38      public ExpectedException thrown = ExpectedException.none()
    39  
    40      private static getConfiguration() {
    41          Map configuration = [dockerImage: 'maven:3.2-jdk-8-onbuild']
    42          return configuration
    43      }
    44  
    45      @Test
    46      void testGetPropertyNestedLeafNodeIsString() {
    47          assertThat(ConfigurationHelper.getConfigPropertyNested([a:[b: 'c']], 'a/b'), is('c'))
    48      }
    49  
    50      @Test
    51      void testGetPropertyNestedLeafNodeIsMap() {
    52          assertThat(ConfigurationHelper.getConfigPropertyNested([a:[b: [c: 'd']]], 'a/b'), is([c: 'd']))
    53      }
    54  
    55      @Test
    56      void testGetPropertyNestedPathNotFound() {
    57          assertThat(ConfigurationHelper.getConfigPropertyNested([a:[b: 'c']], 'a/c'), is((nullValue())))
    58      }
    59  
    60      @Test
    61      void testGetPropertyNestedPathStartsWithTokenizer() {
    62          assertThat(ConfigurationHelper.getConfigPropertyNested([k:'v'], '/k'), is(('v')))
    63      }
    64  
    65      @Test
    66      void testGetPropertyNestedPathEndsWithTokenizer() {
    67          assertThat(ConfigurationHelper.getConfigPropertyNested([k:'v'], 'k/'), is(('v')))
    68      }
    69  
    70      @Test
    71      void testGetPropertyNestedPathManyTokenizer() {
    72          assertThat(ConfigurationHelper.getConfigPropertyNested([k1:[k2 : 'v']], '///k1/////k2///'), is(('v')))
    73      }
    74  
    75      @Test
    76      void testConfigurationLoaderWithDefaults() {
    77          Map config = ConfigurationHelper.newInstance(mockScript, [property1: '27']).use()
    78          // asserts
    79          Assert.assertThat(config, hasEntry('property1', '27'))
    80      }
    81  
    82      @Test
    83      void testConfigurationLoaderWithCustomSettings() {
    84          Map config = ConfigurationHelper.newInstance(mockScript, [property1: '27'])
    85              .mixin([property1: '41'])
    86              .use()
    87          // asserts
    88          Assert.assertThat(config, hasEntry('property1', '41'))
    89      }
    90  
    91      @Test
    92      void testConfigurationLoaderWithFilteredCustomSettings() {
    93          Set filter = ['property2']
    94          Map config = ConfigurationHelper.newInstance(mockScript, [property1: '27'])
    95              .mixin([property1: '41', property2: '28', property3: '29'], filter)
    96              .use()
    97          // asserts
    98          Assert.assertThat(config, hasEntry('property1', '27'))
    99          Assert.assertThat(config, hasEntry('property2', '28'))
   100          Assert.assertThat(config, not(hasKey('property3')))
   101      }
   102  
   103      @Test
   104      void testConfigurationHelperLoadingStepDefaults() {
   105          Set filter = ['property2']
   106          Map config = ConfigurationHelper.newInstance(mockScript, [property1: '27'])
   107              .loadStepDefaults()
   108              .mixinGeneralConfig([configuration:[general: ['general': 'test', 'oldGeneral': 'test2']]], null, [general2: 'oldGeneral'])
   109              .mixinStageConfig([configuration:[stages:[testStage:['stage': 'test', 'oldStage': 'test2']]]], 'testStage', null, [stage2: 'oldStage'])
   110              .mixinStepConfig([configuration:[steps:[mock: [step: 'test', 'oldStep': 'test2']]]], null, [step2: 'oldStep'])
   111              .mixin([property1: '41', property2: '28', property3: '29'], filter)
   112              .use()
   113          // asserts
   114          Assert.assertThat(config, not(hasEntry('property1', '27')))
   115          Assert.assertThat(config, hasEntry('property2', '28'))
   116          Assert.assertThat(config, hasEntry('general', 'test'))
   117          Assert.assertThat(config, hasEntry('general2', 'test2'))
   118          Assert.assertThat(config, hasEntry('stage', 'test'))
   119          Assert.assertThat(config, hasEntry('stage2', 'test2'))
   120          Assert.assertThat(config, hasEntry('step', 'test'))
   121          Assert.assertThat(config, hasEntry('step2', 'test2'))
   122          Assert.assertThat(config, not(hasKey('property3')))
   123      }
   124  
   125      @Test
   126      void testConfigurationHelperAddIfEmpty() {
   127          Map config = ConfigurationHelper.newInstance(mockScript, [:])
   128              .mixin([property1: '41', property2: '28', property3: '29', property4: ''])
   129              .addIfEmpty('property3', '30')
   130              .addIfEmpty('property4', '40')
   131              .addIfEmpty('property5', '50')
   132              .use()
   133          // asserts
   134          Assert.assertThat(config, hasEntry('property1', '41'))
   135          Assert.assertThat(config, hasEntry('property2', '28'))
   136          Assert.assertThat(config, hasEntry('property3', '29'))
   137          Assert.assertThat(config, hasEntry('property4', '40'))
   138      }
   139  
   140      @Test
   141      void testConfigurationHelperAddIfNull() {
   142          Map config = ConfigurationHelper.newInstance(mockScript, [:])
   143              .mixin([property1: '29', property2: '', property3: null])
   144              .addIfNull('property1', '30')
   145              .addIfNull('property2', '30')
   146              .addIfNull('property3', '30')
   147              .addIfNull('property4', '30')
   148              .use()
   149          // asserts
   150          Assert.assertThat(config, hasEntry('property1', '29'))
   151          Assert.assertThat(config, hasEntry('property2', ''))
   152          Assert.assertThat(config, hasEntry('property3', '30'))
   153          Assert.assertThat(config, hasEntry('property4', '30'))
   154      }
   155  
   156      @Test
   157      void testConfigurationHelperDependingOn() {
   158          Map config = ConfigurationHelper.newInstance(mockScript, [:])
   159              .mixin([deep: [deeper: 'test'], scanType: 'maven', maven: [path: 'test2']])
   160              .dependingOn('scanType').mixin('deep/path')
   161              .use()
   162          // asserts
   163          Assert.assertThat(config, hasKey('deep'))
   164          Assert.assertThat(config.deep, allOf(hasEntry('deeper', 'test'), hasEntry('path', 'test2')))
   165          Assert.assertThat(config, hasEntry('scanType', 'maven'))
   166          Assert.assertThat(config, hasKey('maven'))
   167          Assert.assertThat(config.maven, hasEntry('path', 'test2'))
   168      }
   169  
   170      @Test
   171      void testConfigurationHelperWithPropertyInValues() {
   172          ConfigurationHelper.newInstance(mockScript, [:])
   173              .mixin([test: 'allowed'])
   174              .withPropertyInValues('test', ['allowed', 'allowed2'] as Set)
   175              .use()
   176      }
   177  
   178      @Test
   179      void testConfigurationHelperWithPropertyInValuesException() {
   180          def errorCaught = false
   181          try {
   182          ConfigurationHelper.newInstance(mockScript, [:])
   183              .mixin([test: 'disallowed'])
   184              .withPropertyInValues('test', ['allowed', 'allowed2'] as Set)
   185              .use()
   186          } catch (e) {
   187              errorCaught = true
   188              assertThat(e, isA(IllegalArgumentException))
   189              assertThat(e.getMessage(), is('Invalid test = \'disallowed\'. Valid \'test\' values are: [allowed, allowed2].'))
   190          }
   191          assertThat(errorCaught, is(true))
   192      }
   193  
   194      @Test
   195      void testConfigurationLoaderWithBooleanValue() {
   196          Map config = ConfigurationHelper.newInstance(mockScript, [property1: '27'])
   197              .mixin([property1: false])
   198              .mixin([property2: false])
   199              .use()
   200          // asserts
   201          Assert.assertThat(config, hasEntry('property1', false))
   202          Assert.assertThat(config, hasEntry('property2', false))
   203      }
   204  
   205      @Test
   206      void testConfigurationLoaderWithMixinDependent() {
   207          Map config = ConfigurationHelper.newInstance(mockScript, [
   208                  type: 'maven',
   209                  maven: [dockerImage: 'mavenImage', dockerWorkspace: 'mavenWorkspace'],
   210                  npm: [dockerImage: 'npmImage', dockerWorkspace: 'npmWorkspace', executeDocker: true, executeDocker3: false],
   211                  executeDocker1: true
   212              ])
   213              .mixin([dockerImage: 'anyImage', type: 'npm', type2: 'npm', type3: '', executeDocker: false, executeDocker1: false, executeDocker2: false])
   214              .dependingOn('type').mixin('dockerImage')
   215              // test with empty dependent value
   216              .dependingOn('type3').mixin('dockerWorkspace')
   217              // test with empty dependent key
   218              .dependingOn('type4').mixin('dockerWorkspace')
   219              // test with empty default dependent value
   220              .dependingOn('type2').mixin('dockerWorkspace')
   221              // test with boolean value
   222              .dependingOn('type').mixin('executeDocker')
   223              .dependingOn('type').mixin('executeDocker2')
   224              .dependingOn('type').mixin('executeDocker3')
   225              .use()
   226          // asserts
   227          Assert.assertThat(config, hasEntry('dockerImage', 'anyImage'))
   228          Assert.assertThat(config, hasEntry('dockerWorkspace', 'npmWorkspace'))
   229          Assert.assertThat(config, hasEntry('executeDocker', false))
   230          Assert.assertThat(config, hasEntry('executeDocker1', false))
   231          Assert.assertThat(config, hasEntry('executeDocker2', false))
   232          Assert.assertThat(config, hasEntry('executeDocker3', false))
   233      }
   234  
   235      @Test
   236      void testHandleCompatibility() {
   237          def configuration = ConfigurationHelper.newInstance(mockScript)
   238              .mixin([old1: 'oldValue1', old2: 'oldValue2', test: 'testValue'], null, [newStructure: [new1: 'old1', new2: 'old2']])
   239              .use()
   240  
   241          Assert.assertThat(configuration.size(), is(4))
   242          Assert.assertThat(configuration.newStructure.new1, is('oldValue1'))
   243          Assert.assertThat(configuration.newStructure.new2, is('oldValue2'))
   244      }
   245  
   246      @Test
   247      void testHandleCompatibilityFlat() {
   248          def configuration = ConfigurationHelper.newInstance(mockScript)
   249              .mixin([old1: 'oldValue1', old2: 'oldValue2', test: 'testValue'], null, [new1: 'old1', new2: 'old2'])
   250              .use()
   251  
   252          Assert.assertThat(configuration.size(), is(5))
   253          Assert.assertThat(configuration.new1, is('oldValue1'))
   254          Assert.assertThat(configuration.new2, is('oldValue2'))
   255      }
   256  
   257      @Test
   258      void testHandleCompatibilityDeepSource() {
   259          def configuration = ConfigurationHelper.newInstance(mockScript)
   260              .mixin([features: [parallelTestExecution: true]], null, [parallelExecution: 'features/parallelTestExecution'])
   261              .use()
   262  
   263          Assert.assertThat(configuration.size(), is(2))
   264          Assert.assertThat(configuration.parallelExecution, is(true))
   265      }
   266  
   267      @Test
   268      void testHandleCompatibilityDeepDestination() {
   269          def configuration = ConfigurationHelper.newInstance(mockScript)
   270              .mixin([old1: 'oldValue1', old2: 'oldValue2', test: 'testValue'], null, [deep:[deeper:[newStructure: [new1: 'old1', new2: 'old2']]]])
   271              .use()
   272  
   273          Assert.assertThat(configuration.size(), is(4))
   274          Assert.assertThat(configuration.deep.deeper.newStructure.new1, is('oldValue1'))
   275          Assert.assertThat(configuration.deep.deeper.newStructure.new2, is('oldValue2'))
   276      }
   277  
   278      @Test
   279      void testHandleCompatibilityNewAvailable() {
   280          def configuration = ConfigurationHelper.newInstance(mockScript, [old1: 'oldValue1', newStructure: [new1: 'newValue1'], test: 'testValue'])
   281              .mixin([old1: 'oldValue1', newStructure: [new1: 'newValue1'], test: 'testValue'], null, [newStructure: [new1: 'old1', new2: 'old2']])
   282              .use()
   283  
   284          Assert.assertThat(configuration.size(), is(3))
   285          Assert.assertThat(configuration.newStructure.new1, is('newValue1'))
   286      }
   287  
   288      @Test
   289      void testHandleCompatibilityOldNotSet() {
   290          def configuration = ConfigurationHelper.newInstance(mockScript, [old1: null, test: 'testValue'])
   291              .mixin([old1: null, test: 'testValue'], null, [newStructure: [new1: 'old1', new2: 'old2']])
   292              .use()
   293  
   294          Assert.assertThat(configuration.size(), is(2))
   295          Assert.assertThat(configuration.newStructure.new1, is(null))
   296      }
   297  
   298      @Test
   299      void testHandleCompatibilityNoneAvailable() {
   300          def configuration = ConfigurationHelper.newInstance(mockScript, [old1: null, test: 'testValue'])
   301              .mixin([test: 'testValue'], null, [newStructure: [new1: 'old1', new2: 'old2']])
   302              .use()
   303  
   304          Assert.assertThat(configuration.size(), is(2))
   305          Assert.assertThat(configuration.newStructure.new1, is(null))
   306      }
   307  
   308      @Test
   309      void testHandleCompatibilityPremigratedValues() {
   310          def configuration = ConfigurationHelper.newInstance(mockScript, [old1: null, test: 'testValue'])
   311              .mixin([someValueToMigrate: 'testValue2'], null, [someValueToMigrateSecondTime: 'someValueToMigrate', newStructure: [new1: 'old1', new2: 'someValueToMigrateSecondTime']])
   312              .use()
   313  
   314          Assert.assertThat(configuration.size(), is(4))
   315          Assert.assertThat(configuration.newStructure.new1, is(null))
   316          Assert.assertThat(configuration.newStructure.new2, is('testValue2'))
   317      }
   318  
   319      @Test
   320      public void testWithMandoryParameterReturnDefaultFailureMessage() {
   321  
   322          thrown.expect(IllegalArgumentException)
   323          thrown.expectMessage('ERROR - NO VALUE AVAILABLE FOR myKey')
   324  
   325          ConfigurationHelper.newInstance(mockScript).withMandatoryProperty('myKey')
   326      }
   327  
   328      @Test
   329      public void testWithMandoryParameterReturnCustomerFailureMessage() {
   330  
   331          thrown.expect(IllegalArgumentException)
   332          thrown.expectMessage('My error message')
   333  
   334          ConfigurationHelper.newInstance(mockScript).withMandatoryProperty('myKey', 'My error message')
   335      }
   336  
   337      @Test
   338      public void testWithMandoryParameterDefaultCustomFailureMessageProvidedSucceeds() {
   339          ConfigurationHelper.newInstance(mockScript, [myKey: 'myValue']).withMandatoryProperty('myKey', 'My error message')
   340      }
   341  
   342      @Test
   343      public void testWithMandoryParameterDefaultCustomFailureMessageNotProvidedSucceeds() {
   344          ConfigurationHelper.newInstance(mockScript, [myKey: 'myValue']).withMandatoryProperty('myKey')
   345      }
   346  
   347      @Test
   348      public void testWithMandoryWithFalseCondition() {
   349          ConfigurationHelper.newInstance(mockScript, [verify: false])
   350              .withMandatoryProperty('missingKey', null, { c -> return c.get('verify') })
   351      }
   352  
   353      @Test
   354      public void testWithMandoryWithTrueConditionMissingValue() {
   355          thrown.expect(IllegalArgumentException)
   356          thrown.expectMessage('ERROR - NO VALUE AVAILABLE FOR missingKey')
   357  
   358          ConfigurationHelper.newInstance(mockScript, [verify: true])
   359              .withMandatoryProperty('missingKey', null, { c -> return c.get('verify') })
   360      }
   361  
   362      @Test
   363      public void testWithMandoryWithTrueConditionExistingValue() {
   364          ConfigurationHelper.newInstance(mockScript, [existingKey: 'anyValue', verify: true])
   365              .withMandatoryProperty('existingKey', null, { c -> return c.get('verify') })
   366      }
   367  
   368      @Test
   369      public void testTelemetryConfigurationAvailable() {
   370          Set filter = ['test']
   371          def configuration = ConfigurationHelper.newInstance(mockScript, [test: 'testValue'])
   372              .mixin([collectTelemetryData: false], filter)
   373              .use()
   374  
   375          Assert.assertThat(configuration, hasEntry('collectTelemetryData', false))
   376      }
   377  
   378      @Test
   379      public void testGStringsAreReplacedByJavaLangStrings() {
   380          //
   381          // needed in order to ensure we have real GStrings.
   382          // a GString not containing variables might be optimized to
   383          // a java.lang.String from the very beginning.
   384          def dummy = 'Dummy',
   385              aGString = "a${dummy}",
   386              bGString = "b${dummy}",
   387              cGString = "c${dummy}"
   388  
   389          assert aGString instanceof GString
   390          assert bGString instanceof GString
   391          assert cGString instanceof GString
   392  
   393          def config = ConfigurationHelper.newInstance(mockScript, [a: aGString,
   394                                                nextLevel: [b: bGString]])
   395                       .mixin([c : cGString])
   396                       .use()
   397  
   398          assert config == [a: 'aDummy',
   399                            c: 'cDummy',
   400                         nextLevel: [b: 'bDummy']]
   401          assert config.a instanceof java.lang.String
   402          assert config.c instanceof java.lang.String
   403          assert config.nextLevel.b instanceof java.lang.String
   404      }
   405  
   406      @Test
   407      public void testWithMandatoryParameterCollectFailuresAllParamtersArePresentResultsInNoExceptionThrown() {
   408          ConfigurationHelper.newInstance(mockScript, [myKey1: 'a', myKey2: 'b'])
   409                                     .collectValidationFailures()
   410                                     .withMandatoryProperty('myKey1')
   411                                     .withMandatoryProperty('myKey2')
   412                                     .use()
   413      }
   414  
   415      @Test
   416      public void testWithMandatoryParameterCollectFailuresMultipleMissingParametersDoNotResultInFailuresDuringWithMandatoryProperties() {
   417          ConfigurationHelper.newInstance(mockScript, [:]).collectValidationFailures()
   418                                      .withMandatoryProperty('myKey1')
   419                                      .withMandatoryProperty('myKey2')
   420      }
   421  
   422      @Test
   423      public void testWithMandatoryParameterCollectFailuresMultipleMissingParametersResultsInFailureDuringUse() {
   424          thrown.expect(IllegalArgumentException)
   425          thrown.expectMessage('ERROR - NO VALUE AVAILABLE FOR: myKey2, myKey3')
   426          ConfigurationHelper.newInstance(mockScript, [myKey1:'a']).collectValidationFailures()
   427                                     .withMandatoryProperty('myKey1')
   428                                     .withMandatoryProperty('myKey2')
   429                                     .withMandatoryProperty('myKey3')
   430                                     .use()
   431      }
   432  
   433      @Test
   434      public void testWithMandatoryParameterCollectFailuresOneMissingParametersResultsInFailureDuringUse() {
   435          thrown.expect(IllegalArgumentException)
   436          thrown.expectMessage('ERROR - NO VALUE AVAILABLE FOR myKey2')
   437          ConfigurationHelper.newInstance(mockScript, [myKey1:'a']).collectValidationFailures()
   438                                     .withMandatoryProperty('myKey1')
   439                                     .withMandatoryProperty('myKey2')
   440                                     .use()
   441      }
   442  
   443      @Test
   444      public void testWithPropertyInValuesString() {
   445          Map config = ['key1':'value1']
   446          Set possibleValues = ['value1', 'value2', 'value3']
   447  
   448          ConfigurationHelper.newInstance(mockScript, config).collectValidationFailures()
   449                                     .withPropertyInValues('key1', possibleValues)
   450                                     .use()
   451      }
   452  
   453      @Test
   454      public void testWithPropertyInValuesGString() {
   455          String value = 'value1'
   456          Map config = ['key1':"$value"]
   457          Set possibleValues = ['value1', 'value2', 'value3']
   458  
   459          ConfigurationHelper.newInstance(mockScript, config).collectValidationFailures()
   460                                     .withPropertyInValues('key1', possibleValues)
   461                                     .use()
   462      }
   463  
   464      @Test
   465      public void testWithPropertyInValuesInt() {
   466          Map config = ['key1':3]
   467          Set possibleValues = [1, 2, 3]
   468  
   469          ConfigurationHelper.newInstance(mockScript, config).collectValidationFailures()
   470                                     .withPropertyInValues('key1', possibleValues)
   471                                     .use()
   472      }
   473  
   474  }