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.ddmlib.Log.LogLevel; 19 import com.android.tradefed.build.BuildRetrievalError; 20 import com.android.tradefed.build.IBuildProvider; 21 import com.android.tradefed.command.CommandOptions; 22 import com.android.tradefed.command.ICommandOptions; 23 import com.android.tradefed.config.ConfigurationDef.OptionDef; 24 import com.android.tradefed.device.DeviceNotAvailableException; 25 import com.android.tradefed.device.IDeviceRecovery; 26 import com.android.tradefed.device.IDeviceSelection; 27 import com.android.tradefed.invoker.InvocationContext; 28 import com.android.tradefed.log.ILeveledLogOutput; 29 import com.android.tradefed.result.ITestInvocationListener; 30 import com.android.tradefed.result.TextResultReporter; 31 import com.android.tradefed.targetprep.ITargetPreparer; 32 import com.android.tradefed.testtype.IRemoteTest; 33 import com.android.tradefed.util.FileUtil; 34 import com.android.tradefed.util.MultiMap; 35 36 import junit.framework.TestCase; 37 38 import org.easymock.EasyMock; 39 import org.json.JSONArray; 40 import org.json.JSONException; 41 import org.json.JSONObject; 42 43 import java.io.ByteArrayOutputStream; 44 import java.io.File; 45 import java.io.IOException; 46 import java.io.PrintStream; 47 import java.io.PrintWriter; 48 import java.util.ArrayList; 49 import java.util.HashMap; 50 import java.util.List; 51 import java.util.Map; 52 53 /** 54 * Unit tests for {@link Configuration}. 55 */ 56 public class ConfigurationTest extends TestCase { 57 58 private static final String CONFIG_NAME = "name"; 59 private static final String CONFIG_DESCRIPTION = "config description"; 60 private static final String CONFIG_OBJECT_TYPE_NAME = "object_name"; 61 private static final String OPTION_DESCRIPTION = "bool description"; 62 private static final String OPTION_NAME = "bool"; 63 private static final String ALT_OPTION_NAME = "map"; 64 65 /** 66 * Interface for test object stored in a {@link IConfiguration}. 67 */ 68 private static interface TestConfig { 69 getBool()70 public boolean getBool(); 71 } 72 73 private static class TestConfigObject implements TestConfig { 74 75 @Option(name = OPTION_NAME, description = OPTION_DESCRIPTION) 76 private boolean mBool; 77 78 @Option(name = ALT_OPTION_NAME, description = OPTION_DESCRIPTION) 79 private Map<String, Boolean> mBoolMap = new HashMap<String, Boolean>(); 80 81 @Override getBool()82 public boolean getBool() { 83 return mBool; 84 } 85 getMap()86 public Map<String, Boolean> getMap() { 87 return mBoolMap; 88 } 89 } 90 91 private Configuration mConfig; 92 93 /** 94 * {@inheritDoc} 95 */ 96 @Override setUp()97 protected void setUp() throws Exception { 98 super.setUp(); 99 mConfig = new Configuration(CONFIG_NAME, CONFIG_DESCRIPTION); 100 } 101 102 /** 103 * Test that {@link Configuration#getConfigurationObject(String)} can retrieve 104 * a previously stored object. 105 */ testGetConfigurationObject()106 public void testGetConfigurationObject() throws ConfigurationException { 107 TestConfigObject testConfigObject = new TestConfigObject(); 108 mConfig.setConfigurationObject(CONFIG_OBJECT_TYPE_NAME, testConfigObject); 109 Object fromConfig = mConfig.getConfigurationObject(CONFIG_OBJECT_TYPE_NAME); 110 assertEquals(testConfigObject, fromConfig); 111 } 112 113 /** 114 * Test {@link Configuration#getConfigurationObjectList(String)} 115 */ 116 @SuppressWarnings("unchecked") testGetConfigurationObjectList()117 public void testGetConfigurationObjectList() throws ConfigurationException { 118 TestConfigObject testConfigObject = new TestConfigObject(); 119 mConfig.setConfigurationObject(CONFIG_OBJECT_TYPE_NAME, testConfigObject); 120 List<TestConfig> configList = (List<TestConfig>)mConfig.getConfigurationObjectList( 121 CONFIG_OBJECT_TYPE_NAME); 122 assertEquals(testConfigObject, configList.get(0)); 123 } 124 125 /** 126 * Test that {@link Configuration#getConfigurationObject(String)} with a name that does 127 * not exist. 128 */ testGetConfigurationObject_wrongname()129 public void testGetConfigurationObject_wrongname() { 130 assertNull(mConfig.getConfigurationObject("non-existent")); 131 } 132 133 /** 134 * Test that calling {@link Configuration#getConfigurationObject(String)} for a built-in config 135 * type that supports lists. 136 */ testGetConfigurationObject_typeIsList()137 public void testGetConfigurationObject_typeIsList() { 138 try { 139 mConfig.getConfigurationObject(Configuration.TEST_TYPE_NAME); 140 fail("IllegalStateException not thrown"); 141 } catch (IllegalStateException e) { 142 // expected 143 } 144 } 145 146 /** 147 * Test that calling {@link Configuration#getConfigurationObject(String)} for a config type 148 * that is a list. 149 */ testGetConfigurationObject_forList()150 public void testGetConfigurationObject_forList() throws ConfigurationException { 151 List<TestConfigObject> list = new ArrayList<TestConfigObject>(); 152 list.add(new TestConfigObject()); 153 list.add(new TestConfigObject()); 154 mConfig.setConfigurationObjectList(CONFIG_OBJECT_TYPE_NAME, list); 155 try { 156 mConfig.getConfigurationObject(CONFIG_OBJECT_TYPE_NAME); 157 fail("IllegalStateException not thrown"); 158 } catch (IllegalStateException e) { 159 // expected 160 } 161 } 162 163 /** 164 * Test that setConfigurationObject throws a ConfigurationException when config object provided 165 * is not the correct type 166 */ testSetConfigurationObject_wrongtype()167 public void testSetConfigurationObject_wrongtype() { 168 try { 169 // arbitrarily, use the "Test" type as expected type 170 mConfig.setConfigurationObject(Configuration.TEST_TYPE_NAME, new TestConfigObject()); 171 fail("setConfigurationObject did not throw ConfigurationException"); 172 } catch (ConfigurationException e) { 173 // expected 174 } 175 } 176 177 /** 178 * Test {@link Configuration#getConfigurationObjectList(String)} when config object 179 * with given name does not exist. 180 */ testGetConfigurationObjectList_wrongname()181 public void testGetConfigurationObjectList_wrongname() { 182 assertNull(mConfig.getConfigurationObjectList("non-existent")); 183 } 184 185 /** 186 * Test {@link Configuration#setConfigurationObjectList(String, List)} when config object 187 * is the wrong type 188 */ testSetConfigurationObjectList_wrongtype()189 public void testSetConfigurationObjectList_wrongtype() { 190 try { 191 List<TestConfigObject> myList = new ArrayList<TestConfigObject>(1); 192 myList.add(new TestConfigObject()); 193 // arbitrarily, use the "Test" type as expected type 194 mConfig.setConfigurationObjectList(Configuration.TEST_TYPE_NAME, myList); 195 fail("setConfigurationObject did not throw ConfigurationException"); 196 } catch (ConfigurationException e) { 197 // expected 198 } 199 } 200 201 /** 202 * Test method for {@link Configuration#getBuildProvider()}. 203 */ testGetBuildProvider()204 public void testGetBuildProvider() throws BuildRetrievalError { 205 // check that the default provider is present and doesn't blow up 206 assertNotNull(mConfig.getBuildProvider().getBuild()); 207 // check set and get 208 final IBuildProvider provider = EasyMock.createMock(IBuildProvider.class); 209 mConfig.setBuildProvider(provider); 210 assertEquals(provider, mConfig.getBuildProvider()); 211 } 212 213 /** 214 * Test method for {@link Configuration#getTargetPreparers()}. 215 */ testGetTargetPreparers()216 public void testGetTargetPreparers() throws Exception { 217 // check that the callback is working and doesn't blow up 218 assertEquals(0, mConfig.getTargetPreparers().size()); 219 // test set and get 220 final ITargetPreparer prep = EasyMock.createMock(ITargetPreparer.class); 221 mConfig.setTargetPreparer(prep); 222 assertEquals(prep, mConfig.getTargetPreparers().get(0)); 223 } 224 225 /** 226 * Test method for {@link Configuration#getTests()}. 227 */ testGetTests()228 public void testGetTests() throws DeviceNotAvailableException { 229 // check that the default test is present and doesn't blow up 230 mConfig.getTests().get(0).run(new TextResultReporter()); 231 IRemoteTest test1 = EasyMock.createMock(IRemoteTest.class); 232 mConfig.setTest(test1); 233 assertEquals(test1, mConfig.getTests().get(0)); 234 } 235 236 /** 237 * Test method for {@link Configuration#getDeviceRecovery()}. 238 */ testGetDeviceRecovery()239 public void testGetDeviceRecovery() { 240 // check that the default recovery is present 241 assertNotNull(mConfig.getDeviceRecovery()); 242 final IDeviceRecovery recovery = EasyMock.createMock(IDeviceRecovery.class); 243 mConfig.setDeviceRecovery(recovery); 244 assertEquals(recovery, mConfig.getDeviceRecovery()); 245 } 246 247 /** 248 * Test method for {@link Configuration#getLogOutput()}. 249 */ testGetLogOutput()250 public void testGetLogOutput() { 251 // check that the default logger is present and doesn't blow up 252 mConfig.getLogOutput().printLog(LogLevel.INFO, "testGetLogOutput", "test"); 253 final ILeveledLogOutput logger = EasyMock.createMock(ILeveledLogOutput.class); 254 mConfig.setLogOutput(logger); 255 assertEquals(logger, mConfig.getLogOutput()); 256 } 257 258 /** 259 * Test method for {@link Configuration#getTestInvocationListeners()}. 260 * @throws ConfigurationException 261 */ testGetTestInvocationListeners()262 public void testGetTestInvocationListeners() throws ConfigurationException { 263 // check that the default listener is present and doesn't blow up 264 ITestInvocationListener defaultListener = mConfig.getTestInvocationListeners().get(0); 265 defaultListener.invocationStarted(new InvocationContext()); 266 defaultListener.invocationEnded(1); 267 268 final ITestInvocationListener listener1 = EasyMock.createMock( 269 ITestInvocationListener.class); 270 mConfig.setTestInvocationListener(listener1); 271 assertEquals(listener1, mConfig.getTestInvocationListeners().get(0)); 272 } 273 274 /** 275 * Test method for {@link Configuration#getCommandOptions()}. 276 */ testGetCommandOptions()277 public void testGetCommandOptions() { 278 // check that the default object is present 279 assertNotNull(mConfig.getCommandOptions()); 280 final ICommandOptions cmdOptions = EasyMock.createMock(ICommandOptions.class); 281 mConfig.setCommandOptions(cmdOptions); 282 assertEquals(cmdOptions, mConfig.getCommandOptions()); 283 } 284 285 /** 286 * Test method for {@link Configuration#getDeviceRequirements()}. 287 */ testGetDeviceRequirements()288 public void testGetDeviceRequirements() { 289 // check that the default object is present 290 assertNotNull(mConfig.getDeviceRequirements()); 291 final IDeviceSelection deviceSelection = EasyMock.createMock( 292 IDeviceSelection.class); 293 mConfig.setDeviceRequirements(deviceSelection); 294 assertEquals(deviceSelection, mConfig.getDeviceRequirements()); 295 } 296 297 /** 298 * Test {@link Configuration#setConfigurationObject(String, Object)} with a 299 * {@link IConfigurationReceiver} 300 */ testSetConfigurationObject_configReceiver()301 public void testSetConfigurationObject_configReceiver() throws ConfigurationException { 302 final IConfigurationReceiver mockConfigReceiver = EasyMock.createMock( 303 IConfigurationReceiver.class); 304 mockConfigReceiver.setConfiguration(mConfig); 305 EasyMock.replay(mockConfigReceiver); 306 mConfig.setConfigurationObject("example", mockConfigReceiver); 307 EasyMock.verify(mockConfigReceiver); 308 } 309 310 /** 311 * Test {@link Configuration#injectOptionValue(String, String)} 312 */ testInjectOptionValue()313 public void testInjectOptionValue() throws ConfigurationException { 314 TestConfigObject testConfigObject = new TestConfigObject(); 315 mConfig.setConfigurationObject(CONFIG_OBJECT_TYPE_NAME, testConfigObject); 316 mConfig.injectOptionValue(OPTION_NAME, Boolean.toString(true)); 317 assertTrue(testConfigObject.getBool()); 318 } 319 320 /** 321 * Test {@link Configuration#injectOptionValue(String, String, String)} 322 */ testInjectMapOptionValue()323 public void testInjectMapOptionValue() throws ConfigurationException { 324 final String key = "hello"; 325 326 TestConfigObject testConfigObject = new TestConfigObject(); 327 mConfig.setConfigurationObject(CONFIG_OBJECT_TYPE_NAME, testConfigObject); 328 assertEquals(0, testConfigObject.getMap().size()); 329 mConfig.injectOptionValue(ALT_OPTION_NAME, key, Boolean.toString(true)); 330 331 Map<String, Boolean> map = testConfigObject.getMap(); 332 assertEquals(1, map.size()); 333 assertNotNull(map.get(key)); 334 assertTrue(map.get(key).booleanValue()); 335 } 336 337 /** 338 * Test {@link Configuration#injectOptionValue(String, String)} is throwing an exception 339 * for map options without no map key provided in the option value 340 */ testInjectParsedMapOptionValueNoKey()341 public void testInjectParsedMapOptionValueNoKey() throws ConfigurationException { 342 TestConfigObject testConfigObject = new TestConfigObject(); 343 mConfig.setConfigurationObject(CONFIG_OBJECT_TYPE_NAME, testConfigObject); 344 assertEquals(0, testConfigObject.getMap().size()); 345 346 try { 347 mConfig.injectOptionValue(ALT_OPTION_NAME, "wrong_value"); 348 fail("ConfigurationException is not thrown for a map option without retrievable key"); 349 } catch (ConfigurationException ignore) { 350 // expected 351 } 352 } 353 354 /** 355 * Test {@link Configuration#injectOptionValue(String, String)} is throwing an exception 356 * for map options with ambiguous map key provided in the option value (multiple equal signs) 357 */ testInjectParsedMapOptionValueAmbiguousKey()358 public void testInjectParsedMapOptionValueAmbiguousKey() throws ConfigurationException { 359 TestConfigObject testConfigObject = new TestConfigObject(); 360 mConfig.setConfigurationObject(CONFIG_OBJECT_TYPE_NAME, testConfigObject); 361 assertEquals(0, testConfigObject.getMap().size()); 362 363 try { 364 mConfig.injectOptionValue(ALT_OPTION_NAME, "a=b=c"); 365 fail("ConfigurationException is not thrown for a map option with ambiguous key"); 366 } catch (ConfigurationException ignore) { 367 // expected 368 } 369 } 370 371 /** 372 * Test {@link Configuration#injectOptionValue(String, String)} is correctly parsing map options 373 */ testInjectParsedMapOptionValue()374 public void testInjectParsedMapOptionValue() throws ConfigurationException { 375 final String key = "hello\\=key"; 376 377 TestConfigObject testConfigObject = new TestConfigObject(); 378 mConfig.setConfigurationObject(CONFIG_OBJECT_TYPE_NAME, testConfigObject); 379 assertEquals(0, testConfigObject.getMap().size()); 380 mConfig.injectOptionValue(ALT_OPTION_NAME, key + "=" + Boolean.toString(true)); 381 382 Map<String, Boolean> map = testConfigObject.getMap(); 383 assertEquals(1, map.size()); 384 assertNotNull(map.get(key)); 385 assertTrue(map.get(key)); 386 } 387 388 /** 389 * Test {@link Configuration#injectOptionValues(List)} 390 */ testInjectOptionValues()391 public void testInjectOptionValues() throws ConfigurationException { 392 final String key = "hello"; 393 List<OptionDef> options = new ArrayList<>(); 394 options.add(new OptionDef(OPTION_NAME, Boolean.toString(true), null)); 395 options.add(new OptionDef(ALT_OPTION_NAME, key, Boolean.toString(true), null)); 396 397 TestConfigObject testConfigObject = new TestConfigObject(); 398 mConfig.setConfigurationObject(CONFIG_OBJECT_TYPE_NAME, testConfigObject); 399 mConfig.injectOptionValues(options); 400 401 assertTrue(testConfigObject.getBool()); 402 Map<String, Boolean> map = testConfigObject.getMap(); 403 assertEquals(1, map.size()); 404 assertNotNull(map.get(key)); 405 assertTrue(map.get(key).booleanValue()); 406 } 407 408 /** 409 * Basic test for {@link Configuration#printCommandUsage(boolean, java.io.PrintStream)}. 410 */ testPrintCommandUsage()411 public void testPrintCommandUsage() throws ConfigurationException { 412 TestConfigObject testConfigObject = new TestConfigObject(); 413 mConfig.setConfigurationObject(CONFIG_OBJECT_TYPE_NAME, testConfigObject); 414 // dump the print stream results to the ByteArrayOutputStream, so contents can be evaluated 415 ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 416 PrintStream mockPrintStream = new PrintStream(outputStream); 417 mConfig.printCommandUsage(false, mockPrintStream); 418 419 // verifying exact contents would be prone to high-maintenance, so instead, just validate 420 // all expected names are present 421 final String usageString = outputStream.toString(); 422 assertTrue("Usage text does not contain config name", usageString.contains(CONFIG_NAME)); 423 assertTrue("Usage text does not contain config description", usageString.contains( 424 CONFIG_DESCRIPTION)); 425 assertTrue("Usage text does not contain object name", usageString.contains( 426 CONFIG_OBJECT_TYPE_NAME)); 427 assertTrue("Usage text does not contain option name", usageString.contains(OPTION_NAME)); 428 assertTrue("Usage text does not contain option description", 429 usageString.contains(OPTION_DESCRIPTION)); 430 431 // ensure help prints out options from default config types 432 assertTrue("Usage text does not contain --serial option name", 433 usageString.contains("serial")); 434 435 } 436 437 /** 438 * Basic test for {@link Configuration#getJsonCommandUsage()}. 439 */ testGetJsonCommandUsage()440 public void testGetJsonCommandUsage() throws ConfigurationException, JSONException { 441 TestConfigObject testConfigObject = new TestConfigObject(); 442 mConfig.setConfigurationObject(CONFIG_OBJECT_TYPE_NAME, testConfigObject); 443 mConfig.injectOptionValue(ALT_OPTION_NAME, "foo", Boolean.toString(true)); 444 mConfig.injectOptionValue(ALT_OPTION_NAME, "bar", Boolean.toString(false)); 445 446 // General validation of usage elements 447 JSONArray usage = mConfig.getJsonCommandUsage(); 448 JSONObject jsonConfigObject = null; 449 for (int i = 0; i < usage.length(); i++) { 450 JSONObject optionClass = usage.getJSONObject(i); 451 452 // Each element should contain 'name', 'class', and 'options' values 453 assertTrue("Usage element does not contain a 'name' value", optionClass.has("name")); 454 assertTrue("Usage element does not contain a 'class' value", optionClass.has("class")); 455 assertTrue("Usage element does not contain a 'options' value", 456 optionClass.has("options")); 457 458 // General validation of each field 459 JSONArray options = optionClass.getJSONArray("options"); 460 for (int j = 0; j < options.length(); j++) { 461 JSONObject field = options.getJSONObject(j); 462 463 // Each field should at least have 'name', 'description', 'mandatory', 464 // 'javaClass', and 'updateRule' values 465 assertTrue("Option field does not have a 'name' value", field.has("name")); 466 assertTrue("Option field does not have a 'description' value", 467 field.has("description")); 468 assertTrue("Option field does not have a 'mandatory' value", 469 field.has("mandatory")); 470 assertTrue("Option field does not have a 'javaClass' value", 471 field.has("javaClass")); 472 assertTrue("Option field does not have an 'updateRule' value", 473 field.has("updateRule")); 474 } 475 476 // The only elements should either be built-in types, or the configuration object we 477 // added. 478 String name = optionClass.getString("name"); 479 if (name.equals(CONFIG_OBJECT_TYPE_NAME)) { 480 // The object we added should only appear once 481 assertNull("Duplicate JSON usage element", jsonConfigObject); 482 jsonConfigObject = optionClass; 483 } else { 484 assertTrue(String.format("Unexpected JSON usage element: %s", name), 485 Configuration.isBuiltInObjType(name)); 486 } 487 } 488 489 // Verify that the configuration element we added has the expected values 490 assertNotNull("Missing JSON usage element", jsonConfigObject); 491 JSONArray options = jsonConfigObject.getJSONArray("options"); 492 JSONObject jsonOptionField = null; 493 JSONObject jsonAltOptionField = null; 494 for (int i = 0; i < options.length(); i++) { 495 JSONObject field = options.getJSONObject(i); 496 497 if (OPTION_NAME.equals(field.getString("name"))) { 498 assertNull("Duplicate option field", jsonOptionField); 499 jsonOptionField = field; 500 } else if (ALT_OPTION_NAME.equals(field.getString("name"))) { 501 assertNull("Duplication option field", jsonAltOptionField); 502 jsonAltOptionField = field; 503 } 504 } 505 assertNotNull(jsonOptionField); 506 assertEquals(OPTION_DESCRIPTION, jsonOptionField.getString("description")); 507 assertNotNull(jsonAltOptionField); 508 assertEquals(OPTION_DESCRIPTION, jsonAltOptionField.getString("description")); 509 510 // Verify that generics have the fully resolved javaClass name 511 assertEquals("java.util.Map<java.lang.String, java.lang.Boolean>", 512 jsonAltOptionField.getString("javaClass")); 513 } 514 findConfigObjectByName(JSONArray usage, String name)515 private JSONObject findConfigObjectByName(JSONArray usage, String name) throws JSONException { 516 for (int i = 0; i < usage.length(); i++) { 517 JSONObject configObject = usage.getJSONObject(i); 518 if (name != null && name.equals(configObject.getString("name"))) { 519 return configObject; 520 } 521 } 522 return null; 523 } 524 525 /** 526 * Test that {@link Configuration#getJsonCommandUsage()} expands {@link MultiMap} values. 527 */ testGetJsonCommandUsageMapValueExpansion()528 public void testGetJsonCommandUsageMapValueExpansion() throws ConfigurationException, 529 JSONException { 530 531 // Inject a simple config object with a map 532 final MultiMap<String, Integer> mapOption = new MultiMap<>(); 533 mapOption.put("foo", 1); 534 mapOption.put("foo", 2); 535 mapOption.put("foo", 3); 536 mapOption.put("bar", 4); 537 mapOption.put("bar", 5); 538 Object testConfig = new Object() { 539 @Option(name = "map-option") 540 MultiMap<String, Integer> mMapOption = mapOption; 541 }; 542 mConfig.setConfigurationObject(CONFIG_OBJECT_TYPE_NAME, testConfig); 543 544 // Get the JSON usage and find our config object 545 JSONArray usage = mConfig.getJsonCommandUsage(); 546 JSONObject jsonTestConfig = findConfigObjectByName(usage, CONFIG_OBJECT_TYPE_NAME); 547 548 // Get the map option 549 JSONArray options = jsonTestConfig.getJSONArray("options"); 550 JSONObject jsonMapOption = options.getJSONObject(0); 551 552 // Validate the map option value 553 JSONObject jsonMapValue = jsonMapOption.getJSONObject("value"); 554 assertEquals(mapOption.get("foo"), jsonMapValue.get("foo")); 555 assertEquals(mapOption.get("bar"), jsonMapValue.get("bar")); 556 } 557 558 /** 559 * Test that {@link Configuration#validateOptions()} doesn't throw when all mandatory fields 560 * are set. 561 */ testValidateOptions()562 public void testValidateOptions() throws ConfigurationException { 563 mConfig.validateOptions(); 564 } 565 566 /** 567 * Test that {@link Configuration#validateOptions()} throws a config exception when shard 568 * count is negative number. 569 */ testValidateOptionsShardException()570 public void testValidateOptionsShardException() throws ConfigurationException { 571 ICommandOptions option = new CommandOptions() { 572 @Override 573 public Integer getShardCount() {return -1;} 574 }; 575 mConfig.setConfigurationObject(Configuration.CMD_OPTIONS_TYPE_NAME, option); 576 try { 577 mConfig.validateOptions(); 578 fail("Should have thrown an exception."); 579 } catch(ConfigurationException expected) { 580 assertEquals("a shard count must be a positive number", expected.getMessage()); 581 } 582 } 583 584 /** 585 * Test that {@link Configuration#validateOptions()} throws a config exception when shard 586 * index is not valid. 587 */ testValidateOptionsShardIndexException()588 public void testValidateOptionsShardIndexException() throws ConfigurationException { 589 ICommandOptions option = new CommandOptions() { 590 @Override 591 public Integer getShardIndex() { 592 return -1; 593 } 594 }; 595 mConfig.setConfigurationObject(Configuration.CMD_OPTIONS_TYPE_NAME, option); 596 try { 597 mConfig.validateOptions(); 598 fail("Should have thrown an exception."); 599 } catch(ConfigurationException expected) { 600 assertEquals("a shard index must be in range [0, shard count)", expected.getMessage()); 601 } 602 } 603 604 /** 605 * Test that {@link Configuration#validateOptions()} throws a config exception when shard 606 * index is above the shard count. 607 */ testValidateOptionsShardIndexAboveShardCount()608 public void testValidateOptionsShardIndexAboveShardCount() throws ConfigurationException { 609 ICommandOptions option = new CommandOptions() { 610 @Override 611 public Integer getShardIndex() { 612 return 3; 613 } 614 @Override 615 public Integer getShardCount() { 616 return 2; 617 } 618 }; 619 mConfig.setConfigurationObject(Configuration.CMD_OPTIONS_TYPE_NAME, option); 620 try { 621 mConfig.validateOptions(); 622 fail("Should have thrown an exception."); 623 } catch(ConfigurationException expected) { 624 assertEquals("a shard index must be in range [0, shard count)", expected.getMessage()); 625 } 626 } 627 628 /** 629 * Test that {@link Configuration#dumpXml(PrintWriter)} produce the xml output. 630 */ testDumpXml()631 public void testDumpXml() throws IOException { 632 File test = FileUtil.createTempFile("dumpxml", "xml"); 633 try { 634 PrintWriter out = new PrintWriter(test); 635 mConfig.dumpXml(out); 636 out.flush(); 637 String content = FileUtil.readStringFromFile(test); 638 assertTrue(content.length() > 100); 639 assertTrue(content.contains("<configuration>")); 640 assertTrue(content.contains("<test class")); 641 } finally { 642 FileUtil.deleteFile(test); 643 } 644 } 645 646 /** 647 * Test that {@link Configuration#dumpXml(PrintWriter)} produce the xml output without objects 648 * that have been filtered. 649 */ testDumpXml_withFilter()650 public void testDumpXml_withFilter() throws IOException { 651 File test = FileUtil.createTempFile("dumpxml", "xml"); 652 try { 653 PrintWriter out = new PrintWriter(test); 654 List<String> filters = new ArrayList<>(); 655 filters.add(Configuration.TEST_TYPE_NAME); 656 mConfig.dumpXml(out, filters); 657 out.flush(); 658 String content = FileUtil.readStringFromFile(test); 659 assertTrue(content.length() > 100); 660 assertTrue(content.contains("<configuration>")); 661 assertFalse(content.contains("<test class")); 662 } finally { 663 FileUtil.deleteFile(test); 664 } 665 } 666 667 /** 668 * Test that {@link Configuration#dumpXml(PrintWriter)} produce the xml output even for a multi 669 * device situation. 670 */ testDumpXml_multi_device()671 public void testDumpXml_multi_device() throws Exception { 672 List<IDeviceConfiguration> deviceObjectList = new ArrayList<IDeviceConfiguration>(); 673 deviceObjectList.add(new DeviceConfigurationHolder("device1")); 674 deviceObjectList.add(new DeviceConfigurationHolder("device2")); 675 mConfig.setConfigurationObjectList(Configuration.DEVICE_NAME, deviceObjectList); 676 File test = FileUtil.createTempFile("dumpxml", "xml"); 677 try { 678 PrintWriter out = new PrintWriter(test); 679 mConfig.dumpXml(out); 680 out.flush(); 681 String content = FileUtil.readStringFromFile(test); 682 assertTrue(content.length() > 100); 683 assertTrue(content.contains("<device name=\"device1\">")); 684 assertTrue(content.contains("<device name=\"device2\">")); 685 } finally { 686 FileUtil.deleteFile(test); 687 } 688 } 689 } 690