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 }