1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.tradefed.config; 17 18 import com.android.tradefed.config.Option.Importance; 19 import com.android.tradefed.util.keystore.IKeyStoreClient; 20 import com.android.tradefed.util.keystore.StubKeyStoreClient; 21 22 import junit.framework.TestCase; 23 24 import org.easymock.EasyMock; 25 26 import java.util.ArrayList; 27 import java.util.Collection; 28 import java.util.HashMap; 29 import java.util.List; 30 import java.util.Map; 31 32 /** 33 * Unit tests for {@link ArgsOptionParser}. 34 */ 35 @SuppressWarnings("unused") 36 public class ArgsOptionParserTest extends TestCase { 37 38 /** 39 * An option source with one {@link Option} specified. 40 */ 41 private static class OneOptionSource { 42 43 private static final String DEFAULT_VALUE = "default"; 44 private static final String OPTION_NAME = "my_option"; 45 private static final String OPTION_DESC = "option description"; 46 47 @Option(name=OPTION_NAME, shortName='o', description=OPTION_DESC) 48 private String mMyOption = DEFAULT_VALUE; 49 } 50 51 /** 52 * An option source with one {@link Option} specified. 53 */ 54 private static class MapOptionSource { 55 56 private static final String OPTION_NAME = "my_option"; 57 private static final String OPTION_DESC = "option description"; 58 59 @Option(name=OPTION_NAME, shortName='o', description=OPTION_DESC) 60 private Map<Integer, Boolean> mMyOption = new HashMap<Integer, Boolean>(); 61 } 62 63 /** 64 * An option source with one {@link Option} specified. 65 */ 66 private static class MapStringOptionSource { 67 68 private static final String OPTION_NAME = "my_option"; 69 private static final String OPTION_DESC = "option description"; 70 71 @Option(name=OPTION_NAME, shortName='o', description=OPTION_DESC) 72 private Map<String, String> mMyOption = new HashMap<String, String>(); 73 } 74 75 /** 76 * An option source with boolean {@link Option} specified. 77 */ 78 private static class BooleanOptionSource { 79 80 private static final boolean DEFAULT_BOOL = false; 81 private static final String DEFAULT_VALUE = "default"; 82 83 @Option(name="my_boolean", shortName='b') 84 private boolean mMyBool = DEFAULT_BOOL; 85 86 @Option(name="my_option", shortName='o') 87 protected String mMyOption = DEFAULT_VALUE; 88 } 89 90 /** 91 * An option source with boolean {@link Option} specified with default = true. 92 */ 93 private static class BooleanTrueOptionSource { 94 95 private static final boolean DEFAULT_BOOL = true; 96 97 @Option(name="my_boolean", shortName='b') 98 private boolean mMyBool = DEFAULT_BOOL; 99 } 100 101 /** 102 * An option source that has a superclass with options 103 */ 104 private static class InheritedOptionSource extends OneOptionSource { 105 106 private static final String OPTION_NAME = "my_sub_option"; 107 private static final String OPTION_DESC = "sub description"; 108 109 @Option(name=OPTION_NAME, description=OPTION_DESC) 110 private String mMySubOption = ""; 111 } 112 113 /** 114 * An option source for testing the {@link Option#importance()} settings 115 */ 116 private static class ImportantOptionSource { 117 118 private static final String IMPORTANT_OPTION_NAME = "important_option"; 119 private static final String IMPORTANT_UNSET_OPTION_NAME = "unset_important_option"; 120 private static final String UNIMPORTANT_OPTION_NAME = "unimportant_option"; 121 122 @Option(name = IMPORTANT_OPTION_NAME, description = IMPORTANT_OPTION_NAME, 123 importance = Importance.ALWAYS) 124 private String mImportantOption = "foo"; 125 126 @Option(name = IMPORTANT_UNSET_OPTION_NAME, description = IMPORTANT_UNSET_OPTION_NAME, 127 importance = Importance.IF_UNSET) 128 private String mImportantUnsetOption = null; 129 130 @Option(name = UNIMPORTANT_OPTION_NAME, description = UNIMPORTANT_OPTION_NAME, 131 importance = Importance.NEVER) 132 private String mUnimportantOption = null; 133 134 ImportantOptionSource(String setOption) { 135 mImportantUnsetOption = setOption; 136 } 137 138 ImportantOptionSource() { 139 } 140 } 141 142 /** 143 * Option source whose options shouldn't end up in the global namespace 144 */ 145 @OptionClass(alias = "ngos", global_namespace = false) 146 private static class NonGlobalOptionSource { 147 @Option(name = "option") 148 Boolean mOption = null; 149 } 150 151 /** 152 * Option source with mandatory options 153 */ 154 private static class MandatoryOptionSourceNoDefault { 155 @Option(name = "no-default", mandatory = true) 156 private String mNoDefaultOption; 157 } 158 159 /** 160 * Option source with mandatory options 161 */ 162 private static class MandatoryOptionSourceNull { 163 @Option(name = "null", mandatory = true) 164 private String mNullOption = null; 165 } 166 167 /** 168 * Option source with mandatory options 169 */ 170 private static class MandatoryOptionSourceEmptyCollection { 171 @Option(name = "empty-collection", mandatory = true) 172 private Collection<String> mEmptyCollection = new ArrayList<String>(0); 173 } 174 175 /** 176 * Option source with mandatory options 177 */ 178 private static class MandatoryOptionSourceEmptyMap { 179 @Option(name = "empty-map", mandatory = true) 180 private Map<String, String> mEmptyMap = new HashMap<String, String>(); 181 } 182 183 /** 184 * An option source that exercises the {@link OptionUpdateRule}s. 185 */ 186 private static class OptionUpdateRuleSource { 187 188 public static final String DEFAULT_VALUE = "5 default"; 189 public static final String BIGGER_VALUE = "9 bigger"; 190 public static final String SMALLER_VALUE = "0 smaller"; 191 192 @Option(name = "default") 193 private String mDefaultOption = DEFAULT_VALUE; 194 195 @Option(name = "first", updateRule = OptionUpdateRule.FIRST) 196 private String mFirstOption = DEFAULT_VALUE; 197 198 @Option(name = "last", updateRule = OptionUpdateRule.LAST) 199 private String mLastOption = DEFAULT_VALUE; 200 201 @Option(name = "greatest", updateRule = OptionUpdateRule.GREATEST) 202 private String mGreatestOption = DEFAULT_VALUE; 203 204 @Option(name = "least", updateRule = OptionUpdateRule.LEAST) 205 private String mLeastOption = DEFAULT_VALUE; 206 207 @Option(name = "immutable", updateRule = OptionUpdateRule.IMMUTABLE) 208 private String mImmutableOption = DEFAULT_VALUE; 209 210 @Option(name = "null-immutable", updateRule = OptionUpdateRule.IMMUTABLE) 211 private String mNullImmutableOption = null; 212 } 213 214 215 // SECTION: option update rule validation 216 /** 217 * Verify that {@link OptionUpdateRule}s work properly when the update compares to greater-than 218 * the default value. 219 */ 220 public void testOptionUpdateRule_greater() throws Exception { 221 OptionUpdateRuleSource object = new OptionUpdateRuleSource(); 222 ArgsOptionParser parser = new ArgsOptionParser(object); 223 final String current = OptionUpdateRuleSource.DEFAULT_VALUE; 224 final String big = OptionUpdateRuleSource.BIGGER_VALUE; 225 226 parser.parse(new String[] {"--default", big, "--first", big, "--last", big, 227 "--greatest", big, "--least", big}); 228 assertEquals(current, object.mFirstOption); 229 assertEquals(big, object.mLastOption); 230 assertEquals(big, object.mDefaultOption); // default should be LAST 231 assertEquals(big, object.mGreatestOption); 232 assertEquals(current, object.mLeastOption); 233 } 234 235 /** 236 * Verify that {@link OptionUpdateRule}s work properly when the update compares to greater-than 237 * the default value. 238 */ 239 public void testOptionUpdateRule_lesser() throws Exception { 240 OptionUpdateRuleSource object = new OptionUpdateRuleSource(); 241 ArgsOptionParser parser = new ArgsOptionParser(object); 242 final String current = OptionUpdateRuleSource.DEFAULT_VALUE; 243 final String small = OptionUpdateRuleSource.SMALLER_VALUE; 244 245 parser.parse(new String[] {"--default", small, "--first", small, "--last", small, 246 "--greatest", small, "--least", small}); 247 assertEquals(current, object.mFirstOption); 248 assertEquals(small, object.mLastOption); 249 assertEquals(small, object.mDefaultOption); // default should be LAST 250 assertEquals(current, object.mGreatestOption); 251 assertEquals(small, object.mLeastOption); 252 } 253 254 /** 255 * Verify that {@link OptionUpdateRule}s work properly when the update compares to greater-than 256 * the default value. 257 */ 258 public void testOptionUpdateRule_immutable() throws Exception { 259 OptionUpdateRuleSource object = new OptionUpdateRuleSource(); 260 ArgsOptionParser parser = new ArgsOptionParser(object); 261 final String update = OptionUpdateRuleSource.BIGGER_VALUE; 262 263 try { 264 parser.parse(new String[] {"--immutable", update}); 265 fail("ConfigurationException not thrown when updating an IMMUTABLE option"); 266 } catch (ConfigurationException e) { 267 // expected 268 } 269 270 assertNull(object.mNullImmutableOption); 271 parser.parse(new String[] {"--null-immutable", update}); 272 assertEquals(update, object.mNullImmutableOption); 273 274 try { 275 parser.parse(new String[] {"--null-immutable", update}); 276 fail("ConfigurationException not thrown when updating an IMMUTABLE option"); 277 } catch (ConfigurationException e) { 278 // expected 279 } 280 } 281 282 /** 283 * Setting an option with a namespace alias should work fine 284 */ 285 public void testNonGlobalOptionSource_alias() throws Exception { 286 NonGlobalOptionSource source = new NonGlobalOptionSource(); 287 ArgsOptionParser parser = new ArgsOptionParser(source); 288 289 assertNull(source.mOption); 290 parser.parse(new String[] {"--ngos:option"}); 291 assertTrue(source.mOption); 292 parser.parse(new String[] {"--ngos:no-option"}); 293 assertFalse(source.mOption); 294 } 295 296 /** 297 * Setting an option with a classname namespace should work fine 298 */ 299 public void testNonGlobalOptionSource_className() throws Exception { 300 NonGlobalOptionSource source = new NonGlobalOptionSource(); 301 ArgsOptionParser parser = new ArgsOptionParser(source); 302 303 assertNull(source.mOption); 304 parser.parse(new String[] {String.format("--%s:option", source.getClass().getName())}); 305 assertTrue(source.mOption); 306 parser.parse(new String[] {String.format("--%s:no-option", source.getClass().getName())}); 307 assertFalse(source.mOption); 308 } 309 310 /** 311 * Setting an option without a namespace should fail 312 */ 313 public void testNonGlobalOptionSource_global() throws Exception { 314 NonGlobalOptionSource source = new NonGlobalOptionSource(); 315 ArgsOptionParser parser = new ArgsOptionParser(source); 316 317 assertNull(source.mOption); 318 try { 319 parser.parse(new String[] {"--option"}); 320 fail("ConfigurationException not thrown when assigning a global option to an @Option " + 321 "field in a non-global-namespace class"); 322 } catch (ConfigurationException e) { 323 // expected 324 } 325 326 try { 327 parser.parse(new String[] {"--no-option"}); 328 fail("ConfigurationException not thrown when assigning a global option to an @Option " + 329 "field in a non-global-namespace class"); 330 } catch (ConfigurationException e) { 331 // expected 332 } 333 } 334 335 336 // SECTION: tests for #parse(...) 337 /** 338 * Test passing an empty argument list for an object that has one option specified. 339 * <p/> 340 * Expected that the option field should retain its default value. 341 */ 342 public void testParse_noArg() throws ConfigurationException { 343 OneOptionSource object = new OneOptionSource(); 344 ArgsOptionParser parser = new ArgsOptionParser(object); 345 parser.parse(new String[] {}); 346 assertEquals(OneOptionSource.DEFAULT_VALUE, object.mMyOption); 347 } 348 349 /** 350 * Test passing an single argument for an object that has one option specified. 351 */ 352 public void testParse_oneArg() throws ConfigurationException { 353 OneOptionSource object = new OneOptionSource(); 354 ArgsOptionParser parser = new ArgsOptionParser(object); 355 final String expectedValue = "set"; 356 parser.parse(new String[] {"--my_option", expectedValue}); 357 assertEquals(expectedValue, object.mMyOption); 358 } 359 360 /** 361 * Test passing an single argument for an object that has one option specified. 362 */ 363 public void testParse_oneMapArg() throws ConfigurationException { 364 MapOptionSource object = new MapOptionSource(); 365 ArgsOptionParser parser = new ArgsOptionParser(object); 366 final int expectedKey = 13; 367 final boolean expectedValue = true; 368 parser.parse(new String[] {"--my_option", Integer.toString(expectedKey), 369 Boolean.toString(expectedValue)}); 370 assertNotNull(object.mMyOption); 371 assertEquals(1, object.mMyOption.size()); 372 assertEquals(expectedValue, (boolean) object.mMyOption.get(expectedKey)); 373 } 374 375 /** 376 * Test passing an single argument for an object that has one option specified. 377 */ 378 public void testParseMapArg_mismatchKeyType() throws ConfigurationException { 379 MapOptionSource object = new MapOptionSource(); 380 ArgsOptionParser parser = new ArgsOptionParser(object); 381 final String expectedKey = "istanbul"; 382 final boolean expectedValue = true; 383 try { 384 parser.parse(new String[] {"--my_option", expectedKey, Boolean.toString(expectedValue)}); 385 fail("ConfigurationException not thrown"); 386 } catch (ConfigurationException e) { 387 // expect an exception that explicitly mentions that the "key" is incorrect 388 assertTrue(String.format("Expected exception message to contain 'key': %s", 389 e.getMessage()), e.getMessage().contains("key")); 390 assertTrue(String.format("Expected exception message to contain '%s': %s", 391 expectedKey, e.getMessage()), e.getMessage().contains(expectedKey)); 392 } 393 } 394 395 /** 396 * Test passing an single argument for an object that has one option specified. 397 */ 398 public void testParseMapArg_mismatchValueType() throws ConfigurationException { 399 MapOptionSource object = new MapOptionSource(); 400 ArgsOptionParser parser = new ArgsOptionParser(object); 401 final int expectedKey = 13; 402 final String expectedValue = "notconstantinople"; 403 try { 404 parser.parse(new String[] {"--my_option", Integer.toString(expectedKey), expectedValue}); 405 fail("ConfigurationException not thrown"); 406 } catch (ConfigurationException e) { 407 // expect an exception that explicitly mentions that the "value" is incorrect 408 assertTrue(String.format("Expected exception message to contain 'value': '%s'", 409 e.getMessage()), e.getMessage().contains("value")); 410 assertTrue(String.format("Expected exception message to contain '%s': %s", 411 expectedValue, e.getMessage()), e.getMessage().contains(expectedValue)); 412 } 413 } 414 415 /** 416 * Test passing an single argument for an object that has one option specified. 417 */ 418 public void testParseMapArg_missingKey() throws ConfigurationException { 419 MapOptionSource object = new MapOptionSource(); 420 ArgsOptionParser parser = new ArgsOptionParser(object); 421 try { 422 parser.parse(new String[] {"--my_option"}); 423 fail("ConfigurationException not thrown"); 424 } catch (ConfigurationException e) { 425 // expect an exception that explicitly mentions that the "key" is incorrect 426 assertTrue(String.format("Expected exception message to contain 'key': '%s'", 427 e.getMessage()), e.getMessage().contains("key")); 428 } 429 } 430 431 /** 432 * Test passing an single argument for an object that has one option specified. 433 */ 434 public void testParseMapArg_missingValue() throws ConfigurationException { 435 MapOptionSource object = new MapOptionSource(); 436 ArgsOptionParser parser = new ArgsOptionParser(object); 437 final int expectedKey = 13; 438 try { 439 parser.parse(new String[] {"--my_option", Integer.toString(expectedKey)}); 440 fail("ConfigurationException not thrown"); 441 } catch (ConfigurationException e) { 442 // expect an exception that explicitly mentions that the "value" is incorrect 443 assertTrue(String.format("Expected exception message to contain 'value': '%s'", 444 e.getMessage()), e.getMessage().contains("value")); 445 } 446 } 447 448 /** 449 * Test passing an single argument for an object that has one option specified, using the 450 * option=value notation. 451 */ 452 public void testParse_oneArgEquals() throws ConfigurationException { 453 OneOptionSource object = new OneOptionSource(); 454 ArgsOptionParser parser = new ArgsOptionParser(object); 455 final String expectedValue = "set"; 456 parser.parse(new String[] {String.format("--my_option=%s", expectedValue)}); 457 assertEquals(expectedValue, object.mMyOption); 458 } 459 460 /** 461 * Test passing a single argument for an object that has one option specified, using the 462 * short option notation. 463 */ 464 public void testParse_oneShortArg() throws ConfigurationException { 465 OneOptionSource object = new OneOptionSource(); 466 ArgsOptionParser parser = new ArgsOptionParser(object); 467 final String expectedValue = "set"; 468 parser.parse(new String[] {"-o", expectedValue}); 469 assertEquals(expectedValue, object.mMyOption); 470 } 471 472 /** 473 * Test that "--" marks the beginning of positional arguments 474 */ 475 public void testParse_posArgs() throws ConfigurationException { 476 OneOptionSource object = new OneOptionSource(); 477 ArgsOptionParser parser = new ArgsOptionParser(object); 478 final String expectedValue = "set"; 479 // have a position argument with a long option prefix, to try to confuse the parser 480 final String posArg = "--unused"; 481 List<String> leftOver = parser.parse(new String[] {"-o", expectedValue, "--", posArg}); 482 assertEquals(expectedValue, object.mMyOption); 483 assertTrue(leftOver.contains(posArg)); 484 } 485 486 /** 487 * Test passing a single boolean argument. 488 */ 489 public void testParse_boolArg() throws ConfigurationException { 490 BooleanOptionSource object = new BooleanOptionSource(); 491 ArgsOptionParser parser = new ArgsOptionParser(object); 492 parser.parse(new String[] {"-b"}); 493 assertTrue(object.mMyBool); 494 } 495 496 /** 497 * Test passing a boolean argument with another short argument. 498 */ 499 public void testParse_boolTwoArg() throws ConfigurationException { 500 BooleanOptionSource object = new BooleanOptionSource(); 501 ArgsOptionParser parser = new ArgsOptionParser(object); 502 final String expectedValue = "set"; 503 parser.parse(new String[] {"-bo", expectedValue}); 504 assertTrue(object.mMyBool); 505 assertEquals(expectedValue, object.mMyOption); 506 } 507 508 /** 509 * Test passing a boolean argument with another short argument, with value concatenated. 510 * e.g -bovalue 511 */ 512 public void testParse_boolTwoArgValue() throws ConfigurationException { 513 BooleanOptionSource object = new BooleanOptionSource(); 514 ArgsOptionParser parser = new ArgsOptionParser(object); 515 final String expectedValue = "set"; 516 parser.parse(new String[] {String.format("-bo%s", expectedValue)}); 517 assertTrue(object.mMyBool); 518 assertEquals(expectedValue, object.mMyOption); 519 } 520 521 /** 522 * Test the "--no-(bool option)" syntax 523 */ 524 public void testParse_boolFalse() throws ConfigurationException { 525 BooleanTrueOptionSource object = new BooleanTrueOptionSource(); 526 ArgsOptionParser parser = new ArgsOptionParser(object); 527 parser.parse(new String[] {"--no-my_boolean"}); 528 assertFalse(object.mMyBool); 529 } 530 531 /** 532 * Test the boolean long option syntax 533 */ 534 public void testParse_boolLong() throws ConfigurationException { 535 BooleanOptionSource object = new BooleanOptionSource(); 536 ArgsOptionParser parser = new ArgsOptionParser(object); 537 parser.parse(new String[] {"--my_boolean"}); 538 assertTrue(object.mMyBool); 539 } 540 541 /** 542 * Test passing arg string where value is missing 543 */ 544 public void testParse_missingValue() throws ConfigurationException { 545 OneOptionSource object = new OneOptionSource(); 546 ArgsOptionParser parser = new ArgsOptionParser(object); 547 try { 548 parser.parse(new String[] {"--my_option"}); 549 fail("ConfigurationException not thrown"); 550 } catch (ConfigurationException e) { 551 // expected 552 } 553 } 554 555 /** 556 * Test parsing args for an option that does not exist. 557 */ 558 public void testParse_optionNotPresent() throws ConfigurationException { 559 OneOptionSource object = new OneOptionSource(); 560 ArgsOptionParser parser = new ArgsOptionParser(object); 561 try { 562 parser.parse(new String[] {"--my_option", "set", "--not_here", "value"}); 563 fail("ConfigurationException not thrown"); 564 } catch (ConfigurationException e) { 565 // expected 566 } 567 } 568 569 570 // SECTION: tests for #parseBestEffort(...) 571 /** 572 * Test passing an single argument for an object that has one option specified. 573 */ 574 public void testParseBestEffort_oneArg() throws ConfigurationException { 575 OneOptionSource object = new OneOptionSource(); 576 ArgsOptionParser parser = new ArgsOptionParser(object); 577 final String option = "--my_option"; 578 final String value = "set"; 579 final List<String> leftovers = parser.parseBestEffort( 580 new String[] {option, value}); 581 assertEquals(value, object.mMyOption); 582 assertEquals(0, leftovers.size()); 583 } 584 585 /** 586 * Make sure that overwriting arguments works as expected. 587 */ 588 public void testParseBestEffort_oneArg_overwrite() throws ConfigurationException { 589 OneOptionSource object = new OneOptionSource(); 590 ArgsOptionParser parser = new ArgsOptionParser(object); 591 final String option = "--my_option"; 592 final String value1 = "set"; 593 final String value2 = "game"; 594 final List<String> leftovers = parser.parseBestEffort( 595 new String[] {option, value1, option, value2}); 596 assertEquals(value2, object.mMyOption); 597 assertEquals(0, leftovers.size()); 598 } 599 600 /** 601 * Test passing a usable argument followed by an unusable one. 602 */ 603 public void testParseBestEffort_oneArg_oneLeftover() throws ConfigurationException { 604 OneOptionSource object = new OneOptionSource(); 605 ArgsOptionParser parser = new ArgsOptionParser(object); 606 final String expectedValue = "set"; 607 final String leftoverOption = "--no_exist"; 608 final List<String> leftovers = parser.parseBestEffort( 609 new String[] {"--my_option", expectedValue, leftoverOption}); 610 assertEquals(expectedValue, object.mMyOption); 611 assertEquals(1, leftovers.size()); 612 assertEquals(leftoverOption, leftovers.get(0)); 613 } 614 615 /** 616 * Test passing an unusable argument followed by a usable one. Basically verifies that the 617 * parse attempt stops wholesale, and doesn't merely skip the unusable arg. 618 */ 619 public void testParseBestEffort_oneLeftover_oneArg() throws ConfigurationException { 620 OneOptionSource object = new OneOptionSource(); 621 ArgsOptionParser parser = new ArgsOptionParser(object); 622 final String goodOption = "--my_option"; 623 final String value = "set"; 624 final String badOption = "--no_exist"; 625 final List<String> leftovers = parser.parseBestEffort( 626 new String[] {badOption, goodOption, value}); 627 assertEquals(OneOptionSource.DEFAULT_VALUE, object.mMyOption); 628 assertEquals(3, leftovers.size()); 629 assertEquals(badOption, leftovers.get(0)); 630 assertEquals(goodOption, leftovers.get(1)); 631 assertEquals(value, leftovers.get(2)); 632 } 633 634 /** 635 * Make sure that parsing stops when a bare option prefix, "--", is encountered. That prefix 636 * should _not_ be returned as one of the leftover args. 637 */ 638 public void testParseBestEffort_manualStop() throws ConfigurationException { 639 OneOptionSource object = new OneOptionSource(); 640 ArgsOptionParser parser = new ArgsOptionParser(object); 641 final String goodOption = "--my_option"; 642 final String value = "set"; 643 final String badOption = "--no_exist"; 644 final List<String> leftovers = parser.parseBestEffort( 645 new String[] {"--", badOption, goodOption, value}); 646 assertEquals(OneOptionSource.DEFAULT_VALUE, object.mMyOption); 647 assertEquals(3, leftovers.size()); 648 assertEquals(badOption, leftovers.get(0)); 649 assertEquals(goodOption, leftovers.get(1)); 650 assertEquals(value, leftovers.get(2)); 651 } 652 653 /** 654 * Make sure that parsing stops when a bare word is encountered. Unlike a bare option prefix, 655 * the bare word _should_ be returned as one of the leftover args. 656 */ 657 public void testParseBestEffort_bareWord() throws ConfigurationException { 658 OneOptionSource object = new OneOptionSource(); 659 ArgsOptionParser parser = new ArgsOptionParser(object); 660 final String goodOption = "--my_option"; 661 final String value = "set"; 662 final String badOption = "--no_exist"; 663 final String bareWord = "configName"; 664 final List<String> leftovers = parser.parseBestEffort( 665 new String[] {bareWord, badOption, goodOption, value}); 666 assertEquals(OneOptionSource.DEFAULT_VALUE, object.mMyOption); 667 assertEquals(4, leftovers.size()); 668 assertEquals(bareWord, leftovers.get(0)); 669 assertEquals(badOption, leftovers.get(1)); 670 assertEquals(goodOption, leftovers.get(2)); 671 assertEquals(value, leftovers.get(3)); 672 } 673 674 /** 675 * Make sure that parsing stops when a bare option prefix, "--", is encountered. That prefix 676 * should _not_ be returned as one of the leftover args. 677 */ 678 public void testParseBestEffort_oneArg_manualStop() throws ConfigurationException { 679 OneOptionSource object = new OneOptionSource(); 680 ArgsOptionParser parser = new ArgsOptionParser(object); 681 final String option = "--my_option"; 682 final String value1 = "set"; 683 final String value2 = "game"; 684 final List<String> leftovers = parser.parseBestEffort( 685 new String[] {option, value1, "--", option, value2}); 686 assertEquals(value1, object.mMyOption); 687 assertEquals(2, leftovers.size()); 688 assertEquals(option, leftovers.get(0)); 689 assertEquals(value2, leftovers.get(1)); 690 } 691 692 /** 693 * Make sure that parsing stops when a bare word is encountered. Unlike a bare option prefix, 694 * the bare word _should_ be returned as one of the leftover args. 695 */ 696 public void testParseBestEffort_oneArg_bareWord() throws ConfigurationException { 697 OneOptionSource object = new OneOptionSource(); 698 ArgsOptionParser parser = new ArgsOptionParser(object); 699 final String option = "--my_option"; 700 final String value1 = "set"; 701 final String value2 = "game"; 702 final String bareWord = "configName"; 703 final List<String> leftovers = parser.parseBestEffort( 704 new String[] {option, value1, bareWord, option, value2}); 705 assertEquals(value1, object.mMyOption); 706 assertEquals(3, leftovers.size()); 707 assertEquals(bareWord, leftovers.get(0)); 708 assertEquals(option, leftovers.get(1)); 709 assertEquals(value2, leftovers.get(2)); 710 } 711 712 /** 713 * Test passing an single argument for an object that has one option specified. 714 */ 715 public void testParseBestEffort_oneArg_twoLeftovers() throws ConfigurationException { 716 OneOptionSource object = new OneOptionSource(); 717 ArgsOptionParser parser = new ArgsOptionParser(object); 718 final String expectedValue = "set"; 719 final String leftover1 = "--no_exist"; 720 final String leftover2 = "--me_neither"; 721 final List<String> leftovers = parser.parseBestEffort( 722 new String[] {"--my_option", expectedValue, leftover1, leftover2}); 723 assertEquals(expectedValue, object.mMyOption); 724 assertEquals(2, leftovers.size()); 725 assertEquals(leftover1, leftovers.get(0)); 726 assertEquals(leftover2, leftovers.get(1)); 727 } 728 729 /** 730 * Make sure that map option parsing works as expected. 731 */ 732 public void testParseBestEffort_mapOption() throws ConfigurationException { 733 MapOptionSource object = new MapOptionSource(); 734 ArgsOptionParser parser = new ArgsOptionParser(object); 735 final String option = "--my_option"; 736 final String key = "123"; // Integer is the key type 737 final String value = "true"; // Boolean is the value type 738 final String key2 = "345"; // Integer is the key type 739 final String value2 = "false"; // Boolean is the value type 740 final Integer expKey = 123; 741 final Boolean expValue = Boolean.TRUE; 742 final Integer expKey2 = 345; 743 final Boolean expValue2 = Boolean.FALSE; 744 745 final List<String> leftovers = parser.parseBestEffort( 746 new String[] {option, key, value, option, key2, value2}); 747 748 assertEquals(0, leftovers.size()); 749 assertNotNull(object.mMyOption); 750 assertEquals(2, object.mMyOption.size()); 751 assertTrue(object.mMyOption.containsKey(expKey)); 752 assertEquals(expValue, object.mMyOption.get(expKey)); 753 assertTrue(object.mMyOption.containsKey(expKey2)); 754 assertEquals(expValue2, object.mMyOption.get(expKey2)); 755 } 756 757 /** 758 * Make sure that the single value map option parsing works as expected. 759 */ 760 public void testParseBestEffort_mapOption_singleValue() throws ConfigurationException { 761 MapOptionSource object = new MapOptionSource(); 762 ArgsOptionParser parser = new ArgsOptionParser(object); 763 final String option = "--my_option"; 764 final String value = "123=true"; // Integer is the key type 765 final Integer expKey = 123; 766 final Boolean expValue = Boolean.TRUE; 767 768 final List<String> leftovers = parser.parseBestEffort( 769 new String[] {option, value}); 770 771 assertEquals(0, leftovers.size()); 772 assertNotNull(object.mMyOption); 773 assertEquals(1, object.mMyOption.size()); 774 assertTrue(object.mMyOption.containsKey(expKey)); 775 assertEquals(expValue, object.mMyOption.get(expKey)); 776 } 777 778 /** 779 * Make sure that the single map option parsing works as expected with escaped value. 780 */ 781 public void testParseBestEffort_mapOption_escaping() throws ConfigurationException { 782 MapStringOptionSource object = new MapStringOptionSource(); 783 ArgsOptionParser parser = new ArgsOptionParser(object); 784 final String option = "--my_option"; 785 final String key = "hello\\=bar"; 786 final String value = "123\\=true"; 787 final String expKey = "hello=bar"; 788 final String expValue = "123=true"; 789 790 final List<String> leftovers = parser.parseBestEffort( 791 new String[] {option, key, value}); 792 793 assertEquals(0, leftovers.size()); 794 assertNotNull(object.mMyOption); 795 assertEquals(1, object.mMyOption.size()); 796 assertTrue(object.mMyOption.containsKey(expKey)); 797 assertEquals(expValue, object.mMyOption.get(expKey)); 798 } 799 800 /** 801 * Make sure that the single map option parsing works as expected with escaped value. 802 */ 803 public void testParseBestEffort_mapOption_singleValue_escaping() throws ConfigurationException { 804 MapStringOptionSource object = new MapStringOptionSource(); 805 ArgsOptionParser parser = new ArgsOptionParser(object); 806 final String option = "--my_option"; 807 final String value = "hello\\=bar=123\\=true\\=more"; 808 // Note that the actual value we store, is escaped. 809 final String expKey = "hello=bar"; 810 final String expValue = "123=true=more"; 811 812 final List<String> leftovers = parser.parseBestEffort( 813 new String[] {option, value}); 814 815 assertEquals(0, leftovers.size()); 816 assertNotNull(object.mMyOption); 817 assertEquals(1, object.mMyOption.size()); 818 assertTrue(object.mMyOption.containsKey(expKey)); 819 assertEquals(expValue, object.mMyOption.get(expKey)); 820 } 821 822 /** 823 * Make sure that the both map option parsing work together as expected. 824 */ 825 public void testParseBestEffort_mapOption_bothFormat() throws ConfigurationException { 826 MapOptionSource object = new MapOptionSource(); 827 ArgsOptionParser parser = new ArgsOptionParser(object); 828 final String option = "--my_option"; 829 final String value = "123=true"; // Integer is the key type 830 final String key2 = "234"; 831 final String value2 = "false"; 832 final Integer expKey = 123; 833 final Boolean expValue = Boolean.TRUE; 834 final Integer expKey2 = 234; 835 final Boolean expValue2 = Boolean.FALSE; 836 837 final List<String> leftovers = parser.parseBestEffort( 838 new String[] {option, value, option, key2, value2}); 839 840 assertEquals(0, leftovers.size()); 841 assertNotNull(object.mMyOption); 842 assertEquals(2, object.mMyOption.size()); 843 assertTrue(object.mMyOption.containsKey(expKey)); 844 assertEquals(expValue, object.mMyOption.get(expKey)); 845 assertTrue(object.mMyOption.containsKey(expKey2)); 846 assertEquals(expValue2, object.mMyOption.get(expKey2)); 847 } 848 849 /** 850 * Make sure that we backtrack the appropriate amount when a Map option parse fails in the 851 * middle 852 */ 853 public void testParseBestEffort_mapOption_missingValue() throws ConfigurationException { 854 MapOptionSource object = new MapOptionSource(); 855 ArgsOptionParser parser = new ArgsOptionParser(object); 856 final String option = "--my_option"; 857 final String key = "123"; // Integer is the key type 858 final List<String> leftovers = parser.parseBestEffort( 859 new String[] {option, key}); 860 assertTrue(object.mMyOption.isEmpty()); 861 assertEquals(2, leftovers.size()); 862 assertEquals(option, leftovers.get(0)); 863 assertEquals(key, leftovers.get(1)); 864 } 865 866 /** 867 * Make sure that we backtrack the appropriate amount when a Map option parse fails in the 868 * middle 869 */ 870 public void testParseBestEffort_mapOption_badValue() throws ConfigurationException { 871 MapOptionSource object = new MapOptionSource(); 872 ArgsOptionParser parser = new ArgsOptionParser(object); 873 final String option = "--my_option"; 874 final String key = "123"; // Integer is the key type 875 final String value = "notBoolean"; // Boolean is the value type 876 final List<String> leftovers = parser.parseBestEffort( 877 new String[] {option, key, value}); 878 assertTrue(object.mMyOption.isEmpty()); 879 assertEquals(3, leftovers.size()); 880 assertEquals(option, leftovers.get(0)); 881 assertEquals(key, leftovers.get(1)); 882 assertEquals(value, leftovers.get(2)); 883 } 884 885 /** 886 * Make sure that we backtrack the appropriate amount when a Map option parse fails in the 887 * middle 888 */ 889 public void testParseBestEffort_mapOption_badKey() throws ConfigurationException { 890 MapOptionSource object = new MapOptionSource(); 891 ArgsOptionParser parser = new ArgsOptionParser(object); 892 final String option = "--my_option"; 893 final String key = "NotANumber"; // Integer is the key type 894 final String value = "true"; // Boolean is the value type 895 final List<String> leftovers = parser.parseBestEffort( 896 new String[] {option, key, value}); 897 assertTrue(object.mMyOption.isEmpty()); 898 assertEquals(3, leftovers.size()); 899 assertEquals(option, leftovers.get(0)); 900 assertEquals(key, leftovers.get(1)); 901 assertEquals(value, leftovers.get(2)); 902 } 903 904 /** 905 * Make sure that the single key value for map works. 906 */ 907 public void testParseBestEffort_mapOption_singleValue_badValue() throws ConfigurationException { 908 MapOptionSource object = new MapOptionSource(); 909 ArgsOptionParser parser = new ArgsOptionParser(object); 910 final String option = "--my_option"; 911 final String value = "too=many=equals"; 912 final List<String> leftovers = parser.parseBestEffort( 913 new String[] {option, value}); 914 915 assertTrue(object.mMyOption.isEmpty()); 916 assertEquals(2, leftovers.size()); 917 assertEquals(option, leftovers.get(0)); 918 assertEquals(value, leftovers.get(1)); 919 } 920 921 922 // SECTION: help-related tests 923 /** 924 * Test that help text is displayed for all fields 925 */ 926 public void testGetOptionHelp() { 927 String help = ArgsOptionParser.getOptionHelp(false, new InheritedOptionSource()); 928 assertTrue(help.contains(InheritedOptionSource.OPTION_NAME)); 929 assertTrue(help.contains(InheritedOptionSource.OPTION_DESC)); 930 assertTrue(help.contains(OneOptionSource.OPTION_NAME)); 931 assertTrue(help.contains(OneOptionSource.OPTION_DESC)); 932 assertTrue(help.contains(OneOptionSource.DEFAULT_VALUE)); 933 } 934 935 /** 936 * Test displaying important only help text 937 */ 938 public void testGetOptionHelp_important() { 939 String help = ArgsOptionParser.getOptionHelp(true, new ImportantOptionSource()); 940 assertTrue(help.contains(ImportantOptionSource.IMPORTANT_OPTION_NAME)); 941 assertTrue(help.contains(ImportantOptionSource.IMPORTANT_UNSET_OPTION_NAME)); 942 assertFalse(help.contains(ImportantOptionSource.UNIMPORTANT_OPTION_NAME)); 943 } 944 945 /** 946 * Test that {@link Importance#IF_UNSET} {@link Option}s are hidden from help if set. 947 */ 948 public void testGetOptionHelp_importantUnset() { 949 String help = ArgsOptionParser.getOptionHelp(true, new ImportantOptionSource("foo")); 950 assertTrue(help.contains(ImportantOptionSource.IMPORTANT_OPTION_NAME)); 951 assertFalse(help.contains(ImportantOptionSource.IMPORTANT_UNSET_OPTION_NAME)); 952 assertFalse(help.contains(ImportantOptionSource.UNIMPORTANT_OPTION_NAME)); 953 } 954 955 956 // SECTION: mandatory option tests 957 public void testMandatoryOption_noDefault() throws Exception { 958 MandatoryOptionSourceNoDefault object = new MandatoryOptionSourceNoDefault(); 959 ArgsOptionParser parser = new ArgsOptionParser(object); 960 // expect success 961 parser.parse(new String[] {}); 962 try { 963 parser.validateMandatoryOptions(); 964 fail("ConfigurationException not thrown"); 965 } catch (ConfigurationException e) { 966 // expected 967 } 968 } 969 970 public void testMandatoryOption_null() throws Exception { 971 MandatoryOptionSourceNull object = new MandatoryOptionSourceNull(); 972 ArgsOptionParser parser = new ArgsOptionParser(object); 973 parser.parse(new String[] {}); 974 try { 975 parser.validateMandatoryOptions(); 976 fail("ConfigurationException not thrown"); 977 } catch (ConfigurationException e) { 978 // expected 979 } 980 } 981 982 public void testMandatoryOption_emptyCollection() throws Exception { 983 MandatoryOptionSourceEmptyCollection object = new MandatoryOptionSourceEmptyCollection(); 984 ArgsOptionParser parser = new ArgsOptionParser(object); 985 parser.parse(new String[] {}); 986 try { 987 parser.validateMandatoryOptions(); 988 fail("ConfigurationException not thrown"); 989 } catch (ConfigurationException e) { 990 // expected 991 } 992 } 993 994 public void testMandatoryOption_emptyMap() throws Exception { 995 MandatoryOptionSourceEmptyMap object = new MandatoryOptionSourceEmptyMap(); 996 ArgsOptionParser parser = new ArgsOptionParser(object); 997 parser.parse(new String[] {}); 998 try { 999 parser.validateMandatoryOptions(); 1000 fail("ConfigurationException not thrown"); 1001 } catch (ConfigurationException e) { 1002 // expected 1003 } 1004 } 1005 1006 // Key Store related 1007 public void testKeyStore_string() throws Exception { 1008 final String expectedValue = "set"; 1009 // Mock key store 1010 IKeyStoreClient c = EasyMock.createNiceMock(IKeyStoreClient.class); 1011 EasyMock.expect(c.isAvailable()).andReturn(true); 1012 EasyMock.expect(c.containsKey("foo")).andStubReturn(true); 1013 EasyMock.expect(c.fetchKey("foo")).andReturn(expectedValue); 1014 EasyMock.replay(c); 1015 OneOptionSource object = new OneOptionSource(); 1016 ArgsOptionParser parser = new ArgsOptionParser(object); 1017 parser.setKeyStore(c); 1018 parser.parse(new String[] {"--my_option", "USE_KEYSTORE@foo"}); 1019 // Key store value is set for the option as expected. 1020 assertEquals(expectedValue, object.mMyOption); 1021 EasyMock.verify(c); 1022 } 1023 1024 public void testKeyStore_stringWithNullKeyStore() throws Exception { 1025 final String expectedValue = "set"; 1026 OneOptionSource object = new OneOptionSource(); 1027 ArgsOptionParser parser = new ArgsOptionParser(object); 1028 parser.setKeyStore(null); 1029 // An null key store should not affect normal operations. 1030 parser.parse(new String[] {"--my_option", expectedValue}); 1031 assertEquals(expectedValue, object.mMyOption); 1032 } 1033 1034 public void testKeyStore_stringWithNullKeyStoreAndKey() throws Exception { 1035 final String expectedValue = ""; 1036 OneOptionSource object = new OneOptionSource(); 1037 ArgsOptionParser parser = new ArgsOptionParser(object); 1038 parser.setKeyStore(null); 1039 // We try to fetch a key store value with null key store this should return an empty value. 1040 try { 1041 parser.parse(new String[] {"--my_option", "USE_KEYSTORE@foo"}); 1042 } catch (ConfigurationException e) { 1043 //expected 1044 return; 1045 } 1046 fail("ConfigurationException not thrown for attempted use of null keystore."); 1047 } 1048 1049 public void testKeyStore_stringWithUnavalableKeyStore() throws Exception { 1050 final String expectedValue = "set"; 1051 // Mock key store 1052 IKeyStoreClient c = EasyMock.createNiceMock(IKeyStoreClient.class); 1053 EasyMock.expect(c.isAvailable()).andStubReturn(false); 1054 EasyMock.replay(c); 1055 OneOptionSource object = new OneOptionSource(); 1056 ArgsOptionParser parser = new ArgsOptionParser(object); 1057 parser.setKeyStore(c); 1058 // An unavailable key store should not affect normal operations. 1059 parser.parse(new String[] {"--my_option", expectedValue}); 1060 assertEquals(expectedValue, object.mMyOption); 1061 EasyMock.verify(c); 1062 } 1063 1064 public void testKeyStore_stringWithUnavalableKeyStoreWithKey() throws Exception { 1065 final String expectedValue = ""; 1066 // Mock key store 1067 IKeyStoreClient c = EasyMock.createNiceMock(IKeyStoreClient.class); 1068 EasyMock.expect(c.isAvailable()).andReturn(false); 1069 EasyMock.replay(c); 1070 OneOptionSource object = new OneOptionSource(); 1071 ArgsOptionParser parser = new ArgsOptionParser(object); 1072 parser.setKeyStore(c); 1073 // We try to fetch a key store value with unavailable key store this should throw an 1074 // exception 1075 try { 1076 parser.parse(new String[] {"--my_option", "USE_KEYSTORE@foo"}); 1077 } catch (ConfigurationException e) { 1078 //expected 1079 EasyMock.verify(c); 1080 return; 1081 } 1082 fail("ConfiguationException not thrown for attempted use of unavailable keystore."); 1083 } 1084 1085 public void testKeyStore_stringWithUnavalableKey() throws Exception { 1086 final String expectedValue = ""; 1087 // Mock key store 1088 IKeyStoreClient c = EasyMock.createNiceMock(IKeyStoreClient.class); 1089 EasyMock.expect(c.isAvailable()).andReturn(true); 1090 EasyMock.expect(c.containsKey("foobar")).andStubReturn(true); 1091 EasyMock.replay(c); 1092 OneOptionSource object = new OneOptionSource(); 1093 ArgsOptionParser parser = new ArgsOptionParser(object); 1094 parser.setKeyStore(c); 1095 // We try to fetch a key store value with unavailable key this should throw an exception 1096 try { 1097 parser.parse(new String[] {"--my_option", "USE_KEYSTORE@foo"}); 1098 } catch (ConfigurationException e) { 1099 //expected 1100 EasyMock.verify(c); 1101 return; 1102 } 1103 fail("ConfiguationException not thrown for attempted use of unavailable keystore."); 1104 } 1105 1106 public void testKeyStore_mapOptions() throws Exception { 1107 final String option = "--my_option"; 1108 final String key = "hello"; 1109 final String value = "USE_KEYSTORE@foobar"; 1110 final String expKey = "hello"; 1111 final String expValue = "123"; 1112 1113 // Mock key store 1114 IKeyStoreClient c = EasyMock.createNiceMock(IKeyStoreClient.class); 1115 EasyMock.expect(c.isAvailable()).andReturn(true); 1116 EasyMock.expect(c.containsKey("foobar")).andStubReturn(true); 1117 EasyMock.expect(c.fetchKey("foobar")).andReturn(expValue); 1118 EasyMock.replay(c); 1119 MapStringOptionSource object = new MapStringOptionSource(); 1120 ArgsOptionParser parser = new ArgsOptionParser(object); 1121 parser.setKeyStore(c); 1122 // --option hello USE_KEYSTORE@foobar should give --option hello 123; 1123 // where hello is set to 123 1124 final List<String> leftovers = parser.parseBestEffort( 1125 new String[] {option, key, value}); 1126 1127 assertEquals(0, leftovers.size()); 1128 assertNotNull(object.mMyOption); 1129 assertEquals(1, object.mMyOption.size()); 1130 assertTrue(object.mMyOption.containsKey(expKey)); 1131 assertEquals(expValue, object.mMyOption.get(expKey)); 1132 EasyMock.verify(c); 1133 } 1134 1135 public void testKeyStore_mapOptionsSingleValue() throws Exception { 1136 final String option = "--my_option"; 1137 final String value = "hello=USE_KEYSTORE@foobar"; 1138 final String expKey = "hello"; 1139 final String expValue = "123"; 1140 1141 // Mock key store 1142 IKeyStoreClient c = EasyMock.createNiceMock(IKeyStoreClient.class); 1143 EasyMock.expect(c.isAvailable()).andReturn(true); 1144 EasyMock.expect(c.containsKey("foobar")).andStubReturn(true); 1145 EasyMock.expect(c.fetchKey("foobar")).andReturn(expValue); 1146 EasyMock.replay(c); 1147 MapStringOptionSource object = new MapStringOptionSource(); 1148 ArgsOptionParser parser = new ArgsOptionParser(object); 1149 parser.setKeyStore(c); 1150 // --option hello=USE_KEYSTORE@foobar should give --option hello=123 1151 final List<String> leftovers = parser.parseBestEffort( 1152 new String[] {option, value}); 1153 1154 assertEquals(0, leftovers.size()); 1155 assertNotNull(object.mMyOption); 1156 assertEquals(1, object.mMyOption.size()); 1157 assertTrue(object.mMyOption.containsKey(expKey)); 1158 assertEquals(expValue, object.mMyOption.get(expKey)); 1159 EasyMock.verify(c); 1160 1161 } 1162 1163 public void testKeyStore_mapOptionsMixedValue() throws Exception { 1164 final String option = "--my_option"; 1165 final String value = "hello=123"; 1166 final String key2 = "byebye"; 1167 final String value2 = "USE_KEYSTORE@bar"; 1168 final String expKey = "hello"; 1169 final String expValue = "123"; 1170 final String expKey2 = "byebye"; 1171 final String expValue2 = "456"; 1172 1173 // Mock key store 1174 IKeyStoreClient c = EasyMock.createNiceMock(IKeyStoreClient.class); 1175 EasyMock.expect(c.isAvailable()).andReturn(true); 1176 EasyMock.expect(c.containsKey("bar")).andStubReturn(true); 1177 EasyMock.expect(c.fetchKey("bar")).andReturn(expValue2); 1178 EasyMock.replay(c); 1179 MapStringOptionSource object = new MapStringOptionSource(); 1180 ArgsOptionParser parser = new ArgsOptionParser(object); 1181 parser.setKeyStore(c); 1182 1183 final List<String> leftovers = parser.parseBestEffort( 1184 new String[] {option, key2, value2, option, value}); 1185 1186 assertEquals(0, leftovers.size()); 1187 assertNotNull(object.mMyOption); 1188 assertEquals(2, object.mMyOption.size()); 1189 1190 assertTrue(object.mMyOption.containsKey(expKey2)); 1191 assertEquals(expValue2, object.mMyOption.get(expKey2)); 1192 assertTrue(object.mMyOption.containsKey(expKey)); 1193 assertEquals(expValue, object.mMyOption.get(expKey)); 1194 EasyMock.verify(c); 1195 } 1196 1197 public void testKeyStore_mapOptionsMixedValue_allKeys() throws Exception { 1198 final String option = "--my_option"; 1199 final String value = "hello=USE_KEYSTORE@foobar"; 1200 final String key2 = "byebye"; 1201 final String value2 = "USE_KEYSTORE@bar"; 1202 final String expKey = "hello"; 1203 final String expValue = "123"; 1204 final String expKey2 = "byebye"; 1205 final String expValue2 = "456"; 1206 1207 // Mock key store 1208 IKeyStoreClient c = EasyMock.createNiceMock(IKeyStoreClient.class); 1209 EasyMock.expect(c.isAvailable()).andStubReturn(true); 1210 EasyMock.expect(c.containsKey("foobar")).andStubReturn(true); 1211 EasyMock.expect(c.fetchKey("foobar")).andReturn(expValue); 1212 EasyMock.expect(c.containsKey("bar")).andStubReturn(true); 1213 EasyMock.expect(c.fetchKey("bar")).andReturn(expValue2); 1214 EasyMock.replay(c); 1215 MapStringOptionSource object = new MapStringOptionSource(); 1216 ArgsOptionParser parser = new ArgsOptionParser(object); 1217 parser.setKeyStore(c); 1218 1219 final List<String> leftovers = parser.parseBestEffort( 1220 new String[] {option, key2, value2, option, value}); 1221 1222 assertEquals(0, leftovers.size()); 1223 assertNotNull(object.mMyOption); 1224 assertEquals(2, object.mMyOption.size()); 1225 1226 assertTrue(object.mMyOption.containsKey(expKey2)); 1227 assertEquals(expValue2, object.mMyOption.get(expKey2)); 1228 assertTrue(object.mMyOption.containsKey(expKey)); 1229 assertEquals(expValue, object.mMyOption.get(expKey)); 1230 EasyMock.verify(c); 1231 } 1232 1233 /** 1234 * Test that when the default {@link StubKeyStoreClient} is used and a keystore option is 1235 * requested, we throw a configuration exception and no crash. 1236 */ 1237 public void testKeyStore_StubKeystore_optionRequested() throws Exception { 1238 final String expectedValue = ""; 1239 OneOptionSource object = new OneOptionSource(); 1240 ArgsOptionParser parser = new ArgsOptionParser(object); 1241 parser.setKeyStore(new StubKeyStoreClient()); 1242 // We try to fetch a key store value with unavailable key this should throw an exception 1243 try { 1244 parser.parse(new String[] {"--my_option", "USE_KEYSTORE@foo"}); 1245 } catch (ConfigurationException e) { 1246 //expected 1247 return; 1248 } 1249 fail("ConfiguationException not thrown for attempted use of unavailable keystore."); 1250 } 1251 } 1252