github.com/jenkins-x/jx/v2@v2.1.155/pkg/surveyutils/jsonschema_test.go (about) 1 // +build unit 2 3 package surveyutils_test 4 5 import ( 6 "fmt" 7 "io/ioutil" 8 "path/filepath" 9 "regexp" 10 "testing" 11 "time" 12 13 "github.com/jenkins-x/jx/v2/pkg/secreturl" 14 "github.com/jenkins-x/jx/v2/pkg/util" 15 16 "github.com/jenkins-x/jx/v2/pkg/vault/fake" 17 18 "gopkg.in/AlecAivazis/survey.v1/core" 19 20 expect "github.com/Netflix/go-expect" 21 "github.com/ghodss/yaml" 22 23 "github.com/jenkins-x/jx/v2/pkg/tests" 24 25 "github.com/stretchr/testify/assert" 26 27 "github.com/jenkins-x/jx/v2/pkg/surveyutils" 28 ) 29 30 // TODO Figure out how to test selects (affects arrays, enums, validation keywords for arrays) 31 32 var timeout = 5 * time.Second 33 34 const vaultBasePath = "fake" 35 36 type GeneratedSecret struct { 37 Name string 38 Key string 39 Value string 40 } 41 42 func init() { 43 // disable color output for all prompts to simplify testing 44 core.DisableColor = true 45 } 46 47 func TestObjectType(t *testing.T) { 48 tests.SkipForWindows(t, "go-expect does not work on windows") 49 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 50 values, _, err := GenerateValuesAsYaml(r, "objectType.test.schema.json", make(map[string]interface{}), false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 51 defer close(donec) 52 console.ExpectString("Enter a value for name") 53 console.SendLine("cheese") 54 console.ExpectEOF() 55 }, nil) 56 assert.Equal(r, `nestedObject: 57 anotherNestedObject: 58 name: cheese 59 `, values) 60 assert.NoError(r, err) 61 }) 62 } 63 64 func TestDescriptionAndTitle(t *testing.T) { 65 tests.SkipForWindows(t, "go-expect does not work on windows") 66 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 67 values, _, err := GenerateValuesAsYaml(r, "descriptionAndTitle.test.schema.json", make(map[string]interface{}), false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 68 defer close(donec) 69 // Test explicit question 70 console.ExpectString("What is your name?") 71 console.SendLine("?") 72 // Test explicit description 73 console.ExpectString("Enter your name") 74 console.SendLine("Pete") 75 // Test no description 76 console.ExpectString("What is your address?") 77 console.SendLine("?") 78 // Test no title 79 console.ExpectString("Enter a value for country") 80 console.SendLine("UK") 81 console.ExpectEOF() 82 }, nil) 83 assert.NoError(r, err) 84 assert.Equal(r, `address: '?' 85 country: UK 86 name: Pete 87 `, values) 88 }) 89 } 90 91 func TestAutoAcceptDefaultValues(t *testing.T) { 92 tests.SkipForWindows(t, "go-expect does not work on windows") 93 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 94 values, _, err := GenerateValuesAsYaml(r, "autoAcceptDefaultValues.test.schema.json", make(map[string]interface{}), false, false, true, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 95 defer close(donec) 96 // Test explicit question 97 //console.ExpectString("What is your name? John Smith [Automatically accepted default value]") 98 //console.ExpectEOF() 99 // TODO Fix the console test 100 }, nil) 101 assert.Equal(r, `name: John Smith 102 `, values) 103 assert.NoError(r, err) 104 }) 105 } 106 107 func TestAcceptExisting(t *testing.T) { 108 tests.SkipForWindows(t, "go-expect does not work on windows") 109 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 110 values, _, err := GenerateValuesAsYaml(r, "acceptExisting.test.schema.json", map[string]interface{}{ 111 "name": "John Smith", 112 }, false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 113 defer close(donec) 114 // Test explicit question 115 console.ExpectString("What is your name? John Smith [Automatically accepted existing value]") 116 console.ExpectEOF() 117 }, nil) 118 assert.Equal(r, `name: John Smith 119 `, values) 120 assert.NoError(r, err) 121 }) 122 } 123 124 func TestAskExisting(t *testing.T) { 125 tests.SkipForWindows(t, "go-expect does not work on windows") 126 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 127 values, _, err := GenerateValuesAsYaml(r, "askExisting.test.schema.json", map[string]interface{}{ 128 "name": "John Smith", 129 }, true, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 130 defer close(donec) 131 // Test explicit question 132 console.ExpectString("What is your name? [? for help] (John Smith)") 133 console.SendLine("") 134 console.ExpectEOF() 135 }, nil) 136 assert.NoError(r, err) 137 assert.Equal(r, `name: John Smith 138 `, values) 139 }) 140 } 141 142 func TestNoAskAndAutoAcceptDefaultsWithExisting(t *testing.T) { 143 tests.SkipForWindows(t, "go-expect does not work on windows") 144 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 145 values, _, err := GenerateValuesAsYaml(r, "noAskAndAutoAcceptDefaultsWithExisting.test.schema.json", map[string]interface{}{ 146 "name": "John Smith", 147 "country": "UK", 148 }, false, true, true, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 149 defer close(donec) 150 // Test explicit question 151 // TODO fix this... 152 //console.ExpectString("What is your name? John Smith [Automatically accepted existing value]") 153 //console.ExpectString("Enter a value for country UK [Automatically accepted default value]") 154 //console.ExpectEOF() 155 }, nil) 156 assert.NoError(r, err) 157 assert.Equal(r, `country: UK 158 name: John Smith 159 `, values) 160 }) 161 } 162 163 func TestIgnoreMissingValues(t *testing.T) { 164 tests.SkipForWindows(t, "go-expect does not work on windows") 165 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 166 values, _, err := GenerateValuesAsYaml(r, "ignoreMissingValues.test.schema.json", make(map[string]interface{}), false, true, false, true, func(console *tests.ConsoleWrapper, donec chan struct{}) { 167 defer close(donec) 168 console.ExpectEOF() 169 }, nil) 170 assert.NoError(r, err) 171 assert.Equal(r, `{} 172 `, values) 173 }) 174 } 175 176 func TestErrorMissingValues(t *testing.T) { 177 tests.SkipForWindows(t, "go-expect does not work on windows") 178 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 179 _, _, err := GenerateValuesAsYaml(r, "ignoreMissingValues.test.schema.json", make(map[string]interface{}), false, true, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 180 defer close(donec) 181 console.ExpectEOF() 182 }, nil) 183 assert.NoError(t, err) 184 }) 185 } 186 187 func TestDefaultValues(t *testing.T) { 188 tests.SkipForWindows(t, "go-expect does not work on windows") 189 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 190 values, _, err := GenerateValuesAsYaml(r, "defaultValues.test.schema.json", make(map[string]interface{}), false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 191 defer close(donec) 192 // Test default value 193 console.ExpectString("Enter a value for stringValue (UK)") 194 console.SendLine("") 195 console.ExpectString("Enter a value for booleanValue (y/N)") 196 console.SendLine("") 197 console.ExpectString("Enter a value for numberValue (123.4)") 198 console.SendLine("") 199 console.ExpectString("Enter a value for integerValue (123)") 200 console.SendLine("") 201 console.ExpectEOF() 202 }, nil) 203 assert.NoError(r, err) 204 assert.Equal(r, `booleanValue: false 205 integerValue: 123 206 numberValue: 123.4 207 stringValue: UK 208 `, values) 209 }) 210 } 211 212 func TestConstValues(t *testing.T) { 213 tests.SkipForWindows(t, "go-expect does not work on windows") 214 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 215 values, _, err := GenerateValuesAsYaml(r, "constValues.test.schema.json", make(map[string]interface{}), false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 216 defer close(donec) 217 // Test default value 218 console.ExpectString("Set stringValue to UK") 219 console.ExpectString("Set booleanValue to false") 220 console.ExpectString("Set numberValue to 123.4") 221 console.ExpectString("Set integerValue to 123") 222 }, nil) 223 assert.NoError(r, err) 224 assert.Equal(r, `booleanValue: false 225 integerValue: 123 226 numberValue: 123.4 227 stringValue: UK 228 `, values) 229 }) 230 } 231 232 func TestBasicTypesValidation(t *testing.T) { 233 tests.SkipForWindows(t, "go-expect does not work on windows") 234 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 235 _, _, err := GenerateValuesAsYaml(r, "basicTypesValidation.test.schema.json", make(map[string]interface{}), false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 236 defer close(donec) 237 console.ExpectString("Enter a value for numberValue") 238 console.SendLine("abc") 239 console.ExpectString("Sorry, your reply was invalid: unable to convert abc to float64") 240 console.ExpectString("Enter a value for numberValue") 241 console.SendLine("123.1") 242 console.ExpectString("Enter a value for integerValue") 243 console.SendLine("123.1") 244 console.ExpectString("Sorry, your reply was invalid: unable to convert 123.1 to int") 245 console.ExpectString("Enter a value for integerValue") 246 console.SendLine("123") 247 console.ExpectEOF() 248 }, nil) 249 assert.NoError(r, err) 250 }) 251 } 252 253 func TestBasicTypes(t *testing.T) { 254 tests.SkipForWindows(t, "go-expect does not work on windows") 255 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 256 values, _, err := GenerateValuesAsYaml(r, "basicTypes.test.schema.json", make(map[string]interface{}), false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 257 defer close(donec) 258 // Test boolean type 259 console.ExpectString("Enter a value for booleanValue (y/N)") 260 console.SendLine("Y") 261 console.ExpectString("Enter a value for numberValue") 262 console.SendLine("123.4") 263 console.ExpectString("Enter a value for stringValue") 264 console.SendLine("hello") 265 console.ExpectString("Enter a value for integerValue") 266 console.SendLine("123") 267 console.ExpectEOF() 268 }, nil) 269 assert.Equal(r, `booleanValue: true 270 integerValue: 123 271 nullValue: null 272 numberValue: 123.4 273 stringValue: hello 274 `, values) 275 assert.NoError(r, err) 276 }) 277 } 278 279 func TestMultipleOf(t *testing.T) { 280 tests.SkipForWindows(t, "go-expect does not work on windows") 281 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 282 _, _, err := GenerateValuesAsYaml(r, "multipleOf.test.schema.json", make(map[string]interface{}), false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 283 defer close(donec) 284 // Test boolean type 285 console.ExpectString("Enter a value for numberValue") 286 console.SendLine("11.1") 287 console.ExpectString("Sorry, your reply was invalid: 11.1 cannot be divided by 10") 288 console.ExpectString("Enter a value for numberValue") 289 console.SendLine("10") 290 console.ExpectString("Enter a value for integerValue") 291 console.SendLine("12") 292 console.ExpectString("Sorry, your reply was invalid: 12 cannot be divided by 20") 293 console.ExpectString("Enter a value for integerValue") 294 console.SendLine("20") 295 console.ExpectEOF() 296 }, nil) 297 assert.NoError(r, err) 298 }) 299 } 300 301 func TestMaximum(t *testing.T) { 302 tests.SkipForWindows(t, "go-expect does not work on windows") 303 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 304 _, _, err := GenerateValuesAsYaml(r, "maximum.test.schema.json", make(map[string]interface{}), false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 305 defer close(donec) 306 // Test boolean type 307 console.ExpectString("Enter a value for numberValue") 308 console.SendLine("11.1") 309 console.ExpectString("Sorry, your reply was invalid: 11.1 is not less than or equal to 10.1") 310 console.ExpectString("Enter a value for numberValue") 311 console.SendLine("1") 312 console.ExpectString("Enter a value for integerValue") 313 console.SendLine("21") 314 console.ExpectString("Sorry, your reply was invalid: 21 is not less than or equal to 20") 315 console.ExpectString("Enter a value for integerValue") 316 console.SendLine("2") 317 console.ExpectEOF() 318 }, nil) 319 assert.NoError(r, err) 320 }) 321 } 322 323 func TestExclusiveMaximum(t *testing.T) { 324 tests.SkipForWindows(t, "go-expect does not work on windows") 325 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 326 _, _, err := GenerateValuesAsYaml(r, "exclusiveMaximum.test.schema.json", make(map[string]interface{}), false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 327 defer close(donec) 328 // Test boolean type 329 console.ExpectString("Enter a value for numberValue") 330 console.SendLine("10.1") 331 console.ExpectString("Sorry, your reply was invalid: 10.1 is not less than 10.1") 332 console.ExpectString("Enter a value for numberValue") 333 console.SendLine("1") 334 console.ExpectString("Enter a value for integerValue") 335 console.SendLine("20") 336 console.ExpectString("Sorry, your reply was invalid: 20 is not less than 20") 337 console.ExpectString("Enter a value for integerValue") 338 console.SendLine("2") 339 console.ExpectEOF() 340 }, nil) 341 assert.NoError(r, err) 342 }) 343 } 344 345 func TestMinimum(t *testing.T) { 346 tests.SkipForWindows(t, "go-expect does not work on windows") 347 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 348 _, _, err := GenerateValuesAsYaml(r, "minimum.test.schema.json", make(map[string]interface{}), false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 349 defer close(donec) 350 // Test boolean type 351 console.ExpectString("Enter a value for numberValue") 352 console.SendLine("9.1") 353 console.ExpectString("Sorry, your reply was invalid: 9.1 is not greater than or equal to 10.1") 354 console.ExpectString("Enter a value for numberValue") 355 console.SendLine("11") 356 console.ExpectString("Enter a value for integerValue") 357 console.SendLine("19") 358 console.ExpectString("Sorry, your reply was invalid: 19 is not greater than or equal to 20") 359 console.ExpectString("Enter a value for integerValue") 360 console.SendLine("21") 361 console.ExpectEOF() 362 }, nil) 363 assert.NoError(r, err) 364 }) 365 } 366 367 func TestExclusiveMinimum(t *testing.T) { 368 tests.SkipForWindows(t, "go-expect does not work on windows") 369 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 370 _, _, err := GenerateValuesAsYaml(r, "exclusiveMinimum.test.schema.json", make(map[string]interface{}), false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 371 defer close(donec) 372 // Test boolean type 373 console.ExpectString("Enter a value for numberValue") 374 console.SendLine("10.1") 375 console.ExpectString("Sorry, your reply was invalid: 10.1 is not greater than 10.1") 376 console.ExpectString("Enter a value for numberValue") 377 console.SendLine("11") 378 console.ExpectString("Enter a value for integerValue") 379 console.SendLine("20") 380 console.ExpectString("Sorry, your reply was invalid: 20 is not greater than 20") 381 console.ExpectString("Enter a value for integerValue") 382 console.SendLine("21") 383 console.ExpectEOF() 384 }, nil) 385 assert.NoError(r, err) 386 }) 387 } 388 389 func TestMaxLength(t *testing.T) { 390 tests.SkipForWindows(t, "go-expect does not work on windows") 391 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 392 _, _, err := GenerateValuesAsYaml(r, "maxLength.test.schema.json", make(map[string]interface{}), false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 393 defer close(donec) 394 // Test boolean type 395 console.ExpectString("Enter a value for stringValue") 396 console.SendLine("iamlongerthan10") 397 console.ExpectString("Sorry, your reply was invalid: value is too long. Max length is 10") 398 console.ExpectString("Enter a value for stringValue") 399 console.SendLine("short") 400 console.ExpectEOF() 401 }, nil) 402 assert.NoError(r, err) 403 }) 404 } 405 406 func TestMinLength(t *testing.T) { 407 tests.SkipForWindows(t, "go-expect does not work on windows") 408 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 409 _, _, err := GenerateValuesAsYaml(r, "minLength.test.schema.json", make(map[string]interface{}), false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 410 defer close(donec) 411 // Test boolean type 412 console.ExpectString("Enter a value for stringValue") 413 console.SendLine("short") 414 console.ExpectString("Sorry, your reply was invalid: value is too short. Min length is 10") 415 console.ExpectString("Enter a value for stringValue") 416 console.SendLine("iamlongerthan10") 417 console.ExpectEOF() 418 }, nil) 419 assert.NoError(r, err) 420 }) 421 } 422 423 func TestPattern(t *testing.T) { 424 tests.SkipForWindows(t, "go-expect does not work on windows") 425 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 426 _, _, err := GenerateValuesAsYaml(r, "pattern.test.schema.json", make(map[string]interface{}), false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 427 defer close(donec) 428 // Test boolean type 429 console.ExpectString("Enter a value for stringValue") 430 console.SendLine("HELLO") 431 console.ExpectString("Sorry, your reply was invalid: HELLO does not match [0-9]") 432 console.ExpectString("Enter a value for stringValue") 433 console.SendLine("123") 434 console.ExpectEOF() 435 }, nil) 436 assert.NoError(r, err) 437 }) 438 } 439 440 func TestRequired(t *testing.T) { 441 tests.SkipForWindows(t, "go-expect does not work on windows") 442 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 443 _, _, err := GenerateValuesAsYaml(r, "required.test.schema.json", make(map[string]interface{}), false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 444 defer close(donec) 445 // Test boolean type 446 console.ExpectString("Enter a value for stringValue") 447 console.SendLine("") 448 console.ExpectString("Sorry, your reply was invalid: Value is required") 449 console.ExpectString("Enter a value for stringValue") 450 console.SendLine("Hello") 451 console.ExpectEOF() 452 }, nil) 453 assert.NoError(r, err) 454 }) 455 } 456 457 func TestIfThen(t *testing.T) { 458 tests.SkipForWindows(t, "go-expect does not work on windows") 459 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 460 values, _, err := GenerateValuesAsYaml(r, "ifThenElse.test.schema.json", make(map[string]interface{}), false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 461 defer close(donec) 462 console.ExpectString("Enter a value for enablePersistentStorage") 463 console.SendLine("Y") 464 console.ExpectString("Enter a value for databaseConnectionUrl") 465 console.SendLine("abc") 466 console.ExpectString("Enter a value for databaseUsername") 467 console.SendLine("wensleydale") 468 console.ExpectString("Enter a value for databasePassword") 469 console.SendLine("cranberries") 470 console.ExpectString(" ***********") 471 console.ExpectEOF() 472 }, nil) 473 assert.NoError(r, err) 474 assert.Equal(r, fmt.Sprintf(`databaseConnectionUrl: abc 475 databasePassword: vault:%s:databasePassword 476 databaseUsername: wensleydale 477 enablePersistentStorage: true 478 `, vaultBasePath), values) 479 }) 480 } 481 482 func TestIfElse(t *testing.T) { 483 tests.SkipForWindows(t, "go-expect does not work on windows") 484 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 485 values, _, err := GenerateValuesAsYaml(r, "ifThenElse.test.schema.json", make(map[string]interface{}), false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 486 defer close(donec) 487 console.ExpectString("Enter a value for enablePersistentStorage") 488 console.SendLine("N") 489 console.ExpectString("Enter a value for enableInMemoryDB") 490 console.SendLine("N") 491 console.ExpectEOF() 492 }, nil) 493 assert.NoError(r, err) 494 assert.Equal(r, `enableInMemoryDB: false 495 enablePersistentStorage: false 496 `, values) 497 }) 498 } 499 500 func TestIfElseTrueBoolean(t *testing.T) { 501 tests.SkipForWindows(t, "go-expect does not work on windows") 502 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 503 values, _, err := GenerateValuesAsYaml(r, "ifThenElseTrueBoolean.test.schema.json", make(map[string]interface{}), false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 504 defer close(donec) 505 console.ExpectString("Enter a value for enablePersistentStorage") 506 console.SendLine("N") 507 console.ExpectString("Enter a value for enableInMemoryDB") 508 console.SendLine("N") 509 console.ExpectEOF() 510 }, nil) 511 assert.NoError(r, err) 512 assert.Equal(r, `enableInMemoryDB: false 513 enablePersistentStorage: false 514 `, values) 515 }) 516 } 517 518 func TestIfElseNested(t *testing.T) { 519 tests.SkipForWindows(t, "go-expect does not work on windows") 520 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 521 values, _, err := GenerateValuesAsYaml(r, "ifThenElseNested.test.schema.json", make(map[string]interface{}), false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 522 defer close(donec) 523 console.ExpectString("Enter a value for enablePersistentStorage") 524 console.SendLine("N") 525 console.ExpectString("Enter a value for enableInMemoryDB") 526 console.SendLine("Y") 527 console.ExpectString("Enter a value for nestedString") 528 console.SendLine("Test") 529 console.ExpectEOF() 530 }, nil) 531 assert.NoError(r, err) 532 assert.Equal(r, `nestedObject: 533 enableInMemoryDB: true 534 enablePersistentStorage: false 535 nestedString: Test 536 `, values) 537 }) 538 } 539 540 func TestIfElseWithDefaults(t *testing.T) { 541 tests.SkipForWindows(t, "go-expect does not work on windows") 542 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 543 values, _, err := GenerateValuesAsYaml(r, "ifThenElse.test.schema.json", make(map[string]interface{}), false, false, true, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 544 defer close(donec) 545 console.ExpectString("Enter a value for enablePersistentStorage") 546 console.SendLine("N") 547 console.ExpectEOF() 548 }, nil) 549 assert.NoError(r, err) 550 assert.Equal(r, `enableInMemoryDB: true 551 enablePersistentStorage: false 552 `, values) 553 }) 554 } 555 556 func TestAllOf(t *testing.T) { 557 tests.SkipForWindows(t, "go-expect does not work on windows") 558 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 559 values, _, err := GenerateValuesAsYaml(r, "AllOfIf.test.schema.json", make(map[string]interface{}), false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 560 defer close(donec) 561 console.ExpectString("Enter a value for enablePersistentStorage") 562 console.SendLine("Y") 563 console.ExpectString("Enter a value for databaseConnectionUrl") 564 console.SendLine("abc") 565 console.ExpectString("Enter a value for databaseUsername") 566 console.SendLine("wensleydale") 567 console.ExpectString("Enter a value for databasePassword") 568 console.SendLine("cranberries") 569 console.ExpectString(" ***********") 570 console.ExpectString("Enter a value for enableCheese") 571 console.SendLine("Y") 572 console.ExpectString("Enter a value for cheeseType") 573 console.SendLine("Stilton") 574 console.ExpectEOF() 575 }, nil) 576 assert.NoError(r, err) 577 assert.Equal(r, fmt.Sprintf(`cheeseType: Stilton 578 databaseConnectionUrl: abc 579 databasePassword: vault:%s:databasePassword 580 databaseUsername: wensleydale 581 enableCheese: true 582 enablePersistentStorage: true 583 `, vaultBasePath), values) 584 }) 585 } 586 587 func TestAllOfThen(t *testing.T) { 588 tests.SkipForWindows(t, "go-expect does not work on windows") 589 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 590 values, _, err := GenerateValuesAsYaml(r, "AllOfIf.test.schema.json", make(map[string]interface{}), false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 591 defer close(donec) 592 console.ExpectString("Enter a value for enablePersistentStorage") 593 console.SendLine("Y") 594 console.ExpectString("Enter a value for databaseConnectionUrl") 595 console.SendLine("abc") 596 console.ExpectString("Enter a value for databaseUsername") 597 console.SendLine("wensleydale") 598 console.ExpectString("Enter a value for databasePassword") 599 console.SendLine("cranberries") 600 console.ExpectString(" ***********") 601 console.ExpectString("Enter a value for enableCheese") 602 console.SendLine("N") 603 console.ExpectString("Enter a value for iDontLikeCheese") 604 console.SendLine("Y") 605 console.ExpectEOF() 606 }, nil) 607 assert.NoError(r, err) 608 assert.Equal(r, fmt.Sprintf(`databaseConnectionUrl: abc 609 databasePassword: vault:%s:databasePassword 610 databaseUsername: wensleydale 611 enableCheese: false 612 enablePersistentStorage: true 613 iDontLikeCheese: true 614 `, vaultBasePath), values) 615 }) 616 } 617 618 func TestMinProperties(t *testing.T) { 619 tests.SkipForWindows(t, "go-expect does not work on windows") 620 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 621 _, _, err := GenerateValuesAsYaml(r, "minProperties.test.schema.json", make(map[string]interface{}), false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 622 defer close(donec) 623 // Test boolean type 624 console.ExpectString("Enter a value for stringValue") 625 console.SendLine("") 626 console.ExpectString("Enter a value for stringValue1") 627 console.SendLine("") 628 console.ExpectString("Sorry, your reply was invalid: nestedObject has less than 1 items, has []") 629 console.ExpectString("Enter a value for stringValue") 630 console.SendLine("abc") 631 console.ExpectString("Enter a value for stringValue1") 632 console.SendLine("def") 633 console.ExpectEOF() 634 }, nil) 635 assert.NoError(r, err) 636 }) 637 } 638 639 func TestMaxProperties(t *testing.T) { 640 tests.SkipForWindows(t, "go-expect does not work on windows") 641 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 642 _, _, err := GenerateValuesAsYaml(r, "maxProperties.test.schema.json", make(map[string]interface{}), false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 643 defer close(donec) 644 // Test boolean type 645 console.ExpectString("Enter a value for stringValue") 646 console.SendLine("abc") 647 console.ExpectString("Enter a value for stringValue1") 648 console.SendLine("def") 649 console.ExpectString("Sorry, your reply was invalid: nestedObject has more than 1 items, " + 650 "has [stringValue stringValue1]") 651 console.ExpectString("Enter a value for stringValue") 652 console.SendLine("abc") 653 console.ExpectString("Enter a value for stringValue1") 654 console.SendLine("") 655 console.ExpectEOF() 656 }, nil) 657 assert.NoError(r, err) 658 }) 659 } 660 661 func TestDateTime(t *testing.T) { 662 tests.SkipForWindows(t, "go-expect does not work on windows") 663 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 664 _, _, err := GenerateValuesAsYaml(r, "dateTime.test.schema.json", make(map[string]interface{}), false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 665 defer close(donec) 666 // Test boolean type 667 console.ExpectString("Enter a value for dateTimeValue") 668 console.SendLine("abc") 669 console.ExpectString("Sorry, your reply was invalid: abc is not a RFC 3339 date-time formatted string, " + 670 "it should be like 2006-01-02T15:04:05Z07:00") 671 console.ExpectString("Enter a value for dateTimeValue") 672 console.SendLine("2006-01-02T15:04:05-07:00") 673 console.ExpectEOF() 674 }, nil) 675 assert.NoError(r, err) 676 }) 677 } 678 679 func TestDate(t *testing.T) { 680 tests.SkipForWindows(t, "go-expect does not work on windows") 681 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 682 _, _, err := GenerateValuesAsYaml(r, "date.test.schema.json", make(map[string]interface{}), false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 683 defer close(donec) 684 // Test boolean type 685 console.ExpectString("Enter a value for dateValue") 686 console.SendLine("abc") 687 console.ExpectString("Sorry, your reply was invalid: abc is not a RFC 3339 full-date formatted string, " + 688 "it should be like 2006-01-02") 689 console.ExpectString("Enter a value for dateValue") 690 console.SendLine("2006-01-02") 691 console.ExpectEOF() 692 }, nil) 693 assert.NoError(r, err) 694 }) 695 } 696 697 func TestTime(t *testing.T) { 698 tests.SkipForWindows(t, "go-expect does not work on windows") 699 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 700 _, _, err := GenerateValuesAsYaml(r, "time.test.schema.json", make(map[string]interface{}), false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 701 defer close(donec) 702 // Test boolean type 703 console.ExpectString("Enter a value for timeValue") 704 console.SendLine("abc") 705 console.ExpectString("Sorry, your reply was invalid: abc is not a RFC 3339 full-time formatted string, " + 706 "it should be like 15:04:05Z07:00") 707 console.ExpectString("Enter a value for timeValue") 708 console.SendLine("15:04:05-07:00") 709 console.ExpectEOF() 710 }, nil) 711 assert.NoError(r, err) 712 }) 713 } 714 715 func TestPassword(t *testing.T) { 716 tests.SkipForWindows(t, "go-expect does not work on windows") 717 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 718 values, vaultClient, err := GenerateValuesAsYaml(r, "password.test.schema.json", make(map[string]interface{}), false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 719 defer close(donec) 720 // Test boolean type 721 console.ExpectString("Enter a value for passwordValue") 722 console.SendLine("abc") 723 console.ExpectEOF() 724 }, nil) 725 assert.Equal(r, fmt.Sprintf(`passwordValue: vault:%s:passwordValue 726 `, vaultBasePath), values) 727 secrets, err := vaultClient.Read(vaultBasePath) 728 assert.NoError(t, err) 729 assert.Equal(r, "abc", secrets["passwordValue"]) 730 assert.NoError(r, err) 731 }) 732 } 733 734 func TestExistingPassword(t *testing.T) { 735 tests.SkipForWindows(t, "go-expect does not work on windows") 736 tests.Retry(t, 1, time.Second*10, func(r *tests.R) { 737 values, vaultClient, err := GenerateValuesAsYaml(r, "password.test.schema.json", map[string]interface{}{ 738 "passwordValue": map[string]string{ 739 "password": "vault:/foo/bar", 740 }, 741 }, false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 742 defer close(donec) 743 console.ExpectString("Enter a value for passwordValue") 744 console.SendLine("abc") 745 console.ExpectEOF() 746 }, nil) 747 assert.Equal(r, fmt.Sprintf(`passwordValue: vault:%s:passwordValue 748 `, vaultBasePath), values) 749 secrets, err := vaultClient.Read(vaultBasePath) 750 assert.NoError(t, err) 751 assert.Equal(r, "abc", secrets["passwordValue"]) 752 assert.NoError(r, err) 753 }) 754 } 755 756 func TestToken(t *testing.T) { 757 tests.SkipForWindows(t, "go-expect does not work on windows") 758 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 759 values, vaultClient, err := GenerateValuesAsYaml(r, "token.test.schema.json", make(map[string]interface{}), false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 760 defer close(donec) 761 // Test boolean type 762 console.ExpectString("Enter a value for tokenValue") 763 console.SendLine("abc") 764 console.ExpectEOF() 765 }, nil) 766 assert.Equal(r, fmt.Sprintf(`tokenValue: vault:%s:tokenValue 767 `, vaultBasePath), values) 768 secrets, err := vaultClient.Read(vaultBasePath) 769 assert.NoError(t, err) 770 assert.Equal(r, "abc", secrets["tokenValue"]) 771 assert.NoError(r, err) 772 }) 773 } 774 775 func TestGeneratedToken(t *testing.T) { 776 tests.SkipForWindows(t, "go-expect does not work on windows") 777 tests.Retry(t, 1, time.Second*10, func(r *tests.R) { 778 values, vaultClient, err := GenerateValuesAsYaml(r, "generatedToken.test.schema.json", make(map[string]interface{}), false, 779 false, 780 false, false, 781 func(console *tests.ConsoleWrapper, donec chan struct{}) { 782 defer close(donec) 783 // Test boolean type 784 console.ExpectString("Enter a value for tokenValue") 785 console.SendLine("") 786 console.ExpectEOF() 787 }, nil) 788 assert.Equal(r, fmt.Sprintf(`tokenValue: vault:%s:tokenValue 789 `, vaultBasePath), values) 790 secrets, err := vaultClient.Read(vaultBasePath) 791 assert.NoError(t, err) 792 assert.Len(t, secrets["tokenValue"], 20) 793 assert.NoError(r, err) 794 }) 795 } 796 797 func TestGeneratedHmacToken(t *testing.T) { 798 tests.SkipForWindows(t, "go-expect does not work on windows") 799 tests.Retry(t, 1, time.Second*10, func(r *tests.R) { 800 values, vaultClient, err := GenerateValuesAsYaml(r, "generatedHmacToken.test.schema.json", make(map[string]interface{}), false, 801 false, 802 false, false, 803 func(console *tests.ConsoleWrapper, donec chan struct{}) { 804 defer close(donec) 805 // Test boolean type 806 console.ExpectString("Enter a value for tokenValue") 807 console.SendLine("") 808 console.ExpectEOF() 809 }, nil) 810 assert.Equal(r, fmt.Sprintf(`tokenValue: vault:%s:tokenValue 811 `, vaultBasePath), values) 812 secrets, err := vaultClient.Read(vaultBasePath) 813 assert.NoError(t, err) 814 value := secrets["tokenValue"] 815 valueStr, err := util.AsString(value) 816 assert.NoError(t, err) 817 assert.Len(t, valueStr, 41) 818 hexRegex := regexp.MustCompile(`^(0x|0X)?[a-fA-F0-9]+$`) 819 assert.True(t, hexRegex.MatchString(valueStr), "%s is not a hexadecimal string") 820 assert.NoError(r, err) 821 }) 822 } 823 824 func TestExistingToken(t *testing.T) { 825 tests.SkipForWindows(t, "go-expect does not work on windows") 826 tests.Retry(t, 1, time.Second*10, func(r *tests.R) { 827 vaultClient := fake.NewFakeVaultClient() 828 vaultClient.Write(vaultBasePath, map[string]interface{}{ 829 "tokenValue": "abc", 830 }) 831 values, _, err := GenerateValuesAsYaml(r, "token.test.schema.json", make(map[string]interface{}), false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 832 defer close(donec) 833 // Test boolean type 834 console.ExpectString("Enter a value for tokenValue *** [Automatically accepted existing value]") 835 console.ExpectEOF() 836 }, vaultClient) 837 838 assert.Equal(r, fmt.Sprintf(`tokenValue: vault:%s:tokenValue 839 `, vaultBasePath), values) 840 secrets, err := vaultClient.Read(vaultBasePath) 841 assert.NoError(t, err) 842 assert.Equal(r, "abc", secrets["tokenValue"]) 843 assert.NoError(r, err) 844 }) 845 } 846 847 func TestEmail(t *testing.T) { 848 tests.SkipForWindows(t, "go-expect does not work on windows") 849 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 850 _, _, err := GenerateValuesAsYaml(r, "email.test.schema.json", make(map[string]interface{}), false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 851 defer close(donec) 852 // Test boolean type 853 console.ExpectString("Enter a value for emailValue") 854 console.SendLine("abc") 855 console.ExpectString("Sorry, your reply was invalid: abc is not a RFC 5322 address, " + 856 "it should be like Barry Gibb <bg@example.com>") 857 console.ExpectString("Enter a value for emailValue") 858 console.SendLine("Maurice Gibb <mg@example.com>") 859 console.ExpectEOF() 860 }, nil) 861 assert.NoError(r, err) 862 }) 863 } 864 865 func TestIdnEmail(t *testing.T) { 866 tests.SkipForWindows(t, "go-expect does not work on windows") 867 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 868 _, _, err := GenerateValuesAsYaml(r, "idnemail.test.schema.json", make(map[string]interface{}), false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 869 defer close(donec) 870 // Test boolean type 871 console.ExpectString("Enter a value for emailValue") 872 console.SendLine("abc") 873 console.ExpectString("Sorry, your reply was invalid: abc is not a RFC 5322 address, " + 874 "it should be like Barry Gibb <bg@example.com>") 875 console.ExpectString("Enter a value for emailValue") 876 console.SendLine("Maurice Gibb <mg@example.com>") 877 console.ExpectEOF() 878 }, nil) 879 assert.NoError(r, err) 880 }) 881 } 882 883 func TestHostname(t *testing.T) { 884 tests.SkipForWindows(t, "go-expect does not work on windows") 885 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 886 _, _, err := GenerateValuesAsYaml(r, "hostname.test.schema.json", make(map[string]interface{}), false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 887 defer close(donec) 888 // Test boolean type 889 console.ExpectString("Enter a value for hostnameValue") 890 console.SendLine("*****") 891 console.ExpectString("Sorry, your reply was invalid: ***** is not a RFC 1034 hostname, " + 892 "it should be like example.com") 893 console.ExpectString("Enter a value for hostnameValue") 894 console.SendLine("example.com") 895 console.ExpectEOF() 896 }, nil) 897 assert.NoError(r, err) 898 }) 899 } 900 901 func TestIdnHostname(t *testing.T) { 902 tests.SkipForWindows(t, "go-expect does not work on windows") 903 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 904 _, _, err := GenerateValuesAsYaml(r, "idnhostname.test.schema.json", make(map[string]interface{}), false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 905 defer close(donec) 906 // Test boolean type 907 console.ExpectString("Enter a value for hostnameValue") 908 console.SendLine("*****") 909 console.ExpectString("Sorry, your reply was invalid: ***** is not a RFC 1034 hostname, " + 910 "it should be like example.com") 911 console.ExpectString("Enter a value for hostnameValue") 912 console.SendLine("example.com") 913 console.ExpectEOF() 914 }, nil) 915 assert.NoError(r, err) 916 }) 917 } 918 919 func TestIpv4(t *testing.T) { 920 tests.SkipForWindows(t, "go-expect does not work on windows") 921 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 922 _, _, err := GenerateValuesAsYaml(r, "ipv4.test.schema.json", make(map[string]interface{}), false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 923 defer close(donec) 924 // Test boolean type 925 console.ExpectString("Enter a value for ipv4Value") 926 console.SendLine("abc") 927 console.ExpectString("Sorry, your reply was invalid: abc is not a RFC 2673 IPv4 Address, " + 928 "it should be like 127.0.0.1") 929 console.ExpectString("Enter a value for ipv4Value") 930 console.SendLine("127.0.0.1") 931 console.ExpectEOF() 932 }, nil) 933 assert.NoError(r, err) 934 }) 935 } 936 937 func TestIpv6(t *testing.T) { 938 tests.SkipForWindows(t, "go-expect does not work on windows") 939 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 940 _, _, err := GenerateValuesAsYaml(r, "ipv6.test.schema.json", make(map[string]interface{}), false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 941 defer close(donec) 942 // Test boolean type 943 console.ExpectString("Enter a value for ipv6Value") 944 console.SendLine("abc") 945 console.ExpectString("Sorry, your reply was invalid: abc is not a RFC 4291 IPv6 address, " + 946 "it should be like ::1") 947 console.ExpectString("Enter a value for ipv6Value") 948 console.SendLine("::1") 949 console.ExpectEOF() 950 }, nil) 951 assert.NoError(r, err) 952 }) 953 } 954 955 func TestUri(t *testing.T) { 956 tests.SkipForWindows(t, "go-expect does not work on windows") 957 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 958 _, _, err := GenerateValuesAsYaml(r, "uri.test.schema.json", make(map[string]interface{}), false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 959 defer close(donec) 960 // Test boolean type 961 console.ExpectString("Enter a value for uriValue") 962 console.SendLine("*****") 963 console.ExpectString("Sorry, your reply was invalid: ***** is not a RFC 3986 URI") 964 console.ExpectString("Enter a value for uriValue") 965 console.SendLine("https://example.com") 966 console.ExpectEOF() 967 }, nil) 968 assert.NoError(r, err) 969 }) 970 } 971 972 func TestUriReference(t *testing.T) { 973 tests.SkipForWindows(t, "go-expect does not work on windows") 974 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 975 _, _, err := GenerateValuesAsYaml(r, "uriReference.test.schema.json", make(map[string]interface{}), false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 976 defer close(donec) 977 // Test boolean type 978 console.ExpectString("Enter a value for uriReferenceValue") 979 console.SendLine("http$$://foo") 980 console.ExpectString("Sorry, your reply was invalid: http$$://foo is not a RFC 3986 URI reference") 981 console.ExpectString("Enter a value for uriReferenceValue") 982 console.SendLine("../resource.txt") 983 console.ExpectEOF() 984 }, nil) 985 assert.NoError(r, err) 986 }) 987 } 988 989 func TestJSONPointer(t *testing.T) { 990 tests.SkipForWindows(t, "go-expect does not work on windows") 991 tests.Retry(t, 5, time.Second*10, func(r *tests.R) { 992 _, _, err := GenerateValuesAsYaml(r, "jsonPointer.test.schema.json", make(map[string]interface{}), false, false, false, false, func(console *tests.ConsoleWrapper, donec chan struct{}) { 993 defer close(donec) 994 // Test boolean type 995 console.ExpectString("Enter a value for jsonPointerValue") 996 console.SendLine("~") 997 console.ExpectString("Sorry, your reply was invalid: ~ is not a RFC 6901 JSON pointer") 998 console.ExpectString("Enter a value for jsonPointerValue") 999 console.SendLine("/abc") 1000 console.ExpectEOF() 1001 }, nil) 1002 assert.NoError(r, err) 1003 1004 }) 1005 } 1006 1007 func GenerateValuesAsYaml(r *tests.R, schemaName string, existingValues map[string]interface{}, askExisting bool, noAsk bool, autoAcceptDefaults bool, ignoreMissingValues bool, answerQuestions func( 1008 console *tests.ConsoleWrapper, donec chan struct{}), vaultClient secreturl.Client) (string, secreturl.Client, error) { 1009 1010 //t.Parallel() 1011 console := tests.NewTerminal(r, &timeout) 1012 defer console.Cleanup() 1013 if vaultClient == nil { 1014 vaultClient = fake.NewFakeVaultClient() 1015 } 1016 1017 options := surveyutils.JSONSchemaOptions{ 1018 Out: console.Out, 1019 In: console.In, 1020 OutErr: console.Err, 1021 AskExisting: askExisting, 1022 AutoAcceptDefaults: autoAcceptDefaults, 1023 NoAsk: noAsk, 1024 IgnoreMissingValues: ignoreMissingValues, 1025 VaultClient: vaultClient, 1026 VaultBasePath: vaultBasePath, 1027 VaultScheme: "vault", 1028 } 1029 data, err := ioutil.ReadFile(filepath.Join("test_data", schemaName)) 1030 assert.NoError(r, err) 1031 1032 // Test interactive IO 1033 donec := make(chan struct{}) 1034 go answerQuestions(console, donec) 1035 assert.NoError(r, err) 1036 result, runErr := options.GenerateValues( 1037 data, 1038 existingValues) 1039 console.Close() 1040 <-donec 1041 yaml, err := yaml.JSONToYAML(result) 1042 consoleOut := expect.StripTrailingEmptyLines(console.CurrentState()) 1043 r.Logf(consoleOut) 1044 assert.NoError(r, err) 1045 return string(yaml), vaultClient, runErr 1046 }