diff options
author | Julien Desprez <jdesprez@google.com> | 2017-09-18 17:17:34 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2017-09-18 17:17:34 +0000 |
commit | 9bb93530cd94ee5a1971cb9af720a86f43936c9d (patch) | |
tree | 9eb3b93ef855cd7e2e2c6fc0b10f1b359e669674 | |
parent | d71b225027b0800cd78598ce78a2486c87991b46 (diff) | |
parent | 9d45b589f877525175701fe5895e56973b15f622 (diff) | |
download | tradefederation-9bb93530cd94ee5a1971cb9af720a86f43936c9d.tar.gz |
Merge "Create SandboxConfigurationFactory" into oc-dev am: bd4ec445c3
am: 9d45b589f8
Change-Id: I6b1b201a2824882a9e285c2b8176862ecc0bd8de
7 files changed, 241 insertions, 55 deletions
diff --git a/src/com/android/tradefed/command/CommandScheduler.java b/src/com/android/tradefed/command/CommandScheduler.java index 3cc7e3220..8cdb7e2e5 100644 --- a/src/com/android/tradefed/command/CommandScheduler.java +++ b/src/com/android/tradefed/command/CommandScheduler.java @@ -36,6 +36,7 @@ import com.android.tradefed.config.IConfigurationFactory; import com.android.tradefed.config.IDeviceConfiguration; import com.android.tradefed.config.IGlobalConfiguration; import com.android.tradefed.config.Option; +import com.android.tradefed.config.SandboxConfigurationFactory; import com.android.tradefed.device.DeviceAllocationState; import com.android.tradefed.device.DeviceManager; import com.android.tradefed.device.DeviceNotAvailableException; @@ -60,7 +61,6 @@ import com.android.tradefed.log.LogUtil.CLog; import com.android.tradefed.result.ITestInvocationListener; import com.android.tradefed.result.ResultForwarder; import com.android.tradefed.sandbox.ISandbox; -import com.android.tradefed.sandbox.SandboxConfigUtil; import com.android.tradefed.sandbox.TradefedSandbox; import com.android.tradefed.util.ArrayUtil; import com.android.tradefed.util.FileUtil; @@ -1122,8 +1122,8 @@ public class CommandScheduler extends Thread implements ICommandScheduler, IComm if (isCommandSandboxed(args)) { // Create an sandboxed configuration based on the sandbox of the scheduler. ISandbox sandbox = createSandbox(); - return SandboxConfigUtil.createSandboxConfiguration( - args, sandbox, getConfigFactory(), getKeyStoreClient()); + return SandboxConfigurationFactory.getInstance() + .createConfigurationFromArgs(args, getKeyStoreClient(), sandbox, new RunUtil()); } return getConfigFactory().createConfigurationFromArgs(args, null, getKeyStoreClient()); } diff --git a/src/com/android/tradefed/config/ConfigurationFactory.java b/src/com/android/tradefed/config/ConfigurationFactory.java index d200b1f6c..ab30f6454 100644 --- a/src/com/android/tradefed/config/ConfigurationFactory.java +++ b/src/com/android/tradefed/config/ConfigurationFactory.java @@ -414,13 +414,14 @@ public class ConfigurationFactory implements IConfigurationFactory { /** * Retrieve the {@link ConfigurationDef} for the given name * - * @param name the name of a built-in configuration to load or a file path - * to configuration xml to load + * @param name the name of a built-in configuration to load or a file path to configuration xml + * to load * @return {@link ConfigurationDef} * @throws ConfigurationException if an error occurred loading the config */ - private ConfigurationDef getConfigurationDef(String name, boolean isGlobal, - Map<String, String> templateMap) throws ConfigurationException { + ConfigurationDef getConfigurationDef( + String name, boolean isGlobal, Map<String, String> templateMap) + throws ConfigurationException { return new ConfigLoader(isGlobal).getConfigurationDef(name, templateMap); } diff --git a/src/com/android/tradefed/config/GlobalConfiguration.java b/src/com/android/tradefed/config/GlobalConfiguration.java index 80d26cb3e..cef3da655 100644 --- a/src/com/android/tradefed/config/GlobalConfiguration.java +++ b/src/com/android/tradefed/config/GlobalConfiguration.java @@ -64,13 +64,13 @@ public class GlobalConfiguration implements IGlobalConfiguration { public static final String KEY_STORE_TYPE_NAME = "key_store"; public static final String SHARDING_STRATEGY_TYPE_NAME = "sharding_strategy"; + public static final String GLOBAL_CONFIG_VARIABLE = "TF_GLOBAL_CONFIG"; + private static final String GLOBAL_CONFIG_FILENAME = "tf_global_config.xml"; + private static Map<String, ObjTypeInfo> sObjTypeMap = null; private static IGlobalConfiguration sInstance = null; private static final Object sInstanceLock = new Object(); - private static final String GLOBAL_CONFIG_VARIABLE = "TF_GLOBAL_CONFIG"; - private static final String GLOBAL_CONFIG_FILENAME = "tf_global_config.xml"; - // Empty embedded configuration available by default private static final String DEFAULT_EMPTY_CONFIG_NAME = "empty"; diff --git a/src/com/android/tradefed/config/SandboxConfigurationFactory.java b/src/com/android/tradefed/config/SandboxConfigurationFactory.java new file mode 100644 index 000000000..b4d06baea --- /dev/null +++ b/src/com/android/tradefed/config/SandboxConfigurationFactory.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.tradefed.config; + +import com.android.tradefed.log.LogUtil.CLog; +import com.android.tradefed.sandbox.ISandbox; +import com.android.tradefed.sandbox.SandboxConfigDump.DumpCmd; +import com.android.tradefed.sandbox.SandboxConfigUtil; +import com.android.tradefed.util.FileUtil; +import com.android.tradefed.util.IRunUtil; +import com.android.tradefed.util.keystore.IKeyStoreClient; + +import java.io.File; +import java.util.Map; + +/** Special Configuration factory to handle creation of configurations for Sandboxing purpose. */ +public class SandboxConfigurationFactory extends ConfigurationFactory { + + private static SandboxConfigurationFactory sInstance = null; + + /** Get the singleton {@link IConfigurationFactory} instance. */ + public static SandboxConfigurationFactory getInstance() { + if (sInstance == null) { + sInstance = new SandboxConfigurationFactory(); + } + return sInstance; + } + + /** {@inheritDoc} */ + @Override + ConfigurationDef getConfigurationDef( + String name, boolean isGlobal, Map<String, String> templateMap) + throws ConfigurationException { + // TODO: Extend ConfigurationDef to possibly create a different IConfiguration type and + // handle more elegantly the parent/subprocess incompatibilities. + ConfigurationDef def = new ConfigurationDef(name); + new ConfigLoader(isGlobal).loadConfiguration(name, def, templateMap); + return def; + } + + /** + * Create a {@link IConfiguration} based on the command line and sandbox provided. + * + * @param args the command line for the run. + * @param keyStoreClient the {@link IKeyStoreClient} where to load the key from. + * @param sandbox the {@link ISandbox} used for the run. + * @param runUtil the {@link IRunUtil} to run commands. + * @return a {@link IConfiguration} valid for the sandbox. + * @throws ConfigurationException + */ + public IConfiguration createConfigurationFromArgs( + String[] args, IKeyStoreClient keyStoreClient, ISandbox sandbox, IRunUtil runUtil) + throws ConfigurationException { + IConfiguration config = null; + File xmlConfig = null; + try { + runUtil.unsetEnvVariable(GlobalConfiguration.GLOBAL_CONFIG_VARIABLE); + File tfDir = sandbox.getTradefedEnvironment(args); + // TODO: dump using the keystore too + xmlConfig = + SandboxConfigUtil.dumpConfigForVersion( + tfDir, runUtil, args, DumpCmd.NON_VERSIONED_CONFIG); + // Get the non version part of the configuration in order to do proper allocation + // of devices and such. + config = + super.createConfigurationFromArgs( + new String[] {xmlConfig.getAbsolutePath()}, null, keyStoreClient); + // Reset the command line to the original one. + config.setCommandLine(args); + config.setConfigurationObject(Configuration.SANDBOX_TYPE_NAME, sandbox); + } catch (ConfigurationException e) { + CLog.e(e); + sandbox.tearDown(); + throw e; + } finally { + FileUtil.deleteFile(xmlConfig); + } + return config; + } +} diff --git a/src/com/android/tradefed/sandbox/SandboxConfigUtil.java b/src/com/android/tradefed/sandbox/SandboxConfigUtil.java index e0c0159d2..5aaa4e71d 100644 --- a/src/com/android/tradefed/sandbox/SandboxConfigUtil.java +++ b/src/com/android/tradefed/sandbox/SandboxConfigUtil.java @@ -15,18 +15,13 @@ */ package com.android.tradefed.sandbox; -import com.android.tradefed.config.Configuration; import com.android.tradefed.config.ConfigurationException; import com.android.tradefed.config.IConfiguration; -import com.android.tradefed.config.IConfigurationFactory; -import com.android.tradefed.log.LogUtil.CLog; import com.android.tradefed.sandbox.SandboxConfigDump.DumpCmd; import com.android.tradefed.util.CommandResult; import com.android.tradefed.util.CommandStatus; import com.android.tradefed.util.FileUtil; import com.android.tradefed.util.IRunUtil; -import com.android.tradefed.util.RunUtil; -import com.android.tradefed.util.keystore.IKeyStoreClient; import java.io.File; import java.io.IOException; @@ -75,44 +70,4 @@ public class SandboxConfigUtil { FileUtil.deleteFile(destination); throw new ConfigurationException(result.getStderr()); } - - /** - * Create a {@link IConfiguration} based on the command line and sandbox provided. - * - * @param args the command line for the run. - * @param sandbox the {@link ISandbox} used for the run. - * @param configFactory the {@link IConfigurationFactory} used to load the config on parent side - * @param keystore the {@link IKeyStoreClient} where to load the key from. - * @return a {@link IConfiguration} valid for the sandbox. - * @throws ConfigurationException - */ - public static IConfiguration createSandboxConfiguration( - String args[], - ISandbox sandbox, - IConfigurationFactory configFactory, - IKeyStoreClient keystore) - throws ConfigurationException { - IConfiguration config = null; - File xmlConfig = null; - try { - File tfDir = sandbox.getTradefedEnvironment(args); - xmlConfig = - dumpConfigForVersion(tfDir, new RunUtil(), args, DumpCmd.NON_VERSIONED_CONFIG); - // Get the non version part of the configuration in order to do proper allocation - // of devices and such. - config = - configFactory.createConfigurationFromArgs( - new String[] {xmlConfig.getAbsolutePath()}, null, keystore); - // Reset the command line to the original one. - config.setCommandLine(args); - config.setConfigurationObject(Configuration.SANDBOX_TYPE_NAME, sandbox); - } catch (ConfigurationException e) { - CLog.e(e); - sandbox.tearDown(); - throw e; - } finally { - FileUtil.deleteFile(xmlConfig); - } - return config; - } } diff --git a/tests/src/com/android/tradefed/UnitTests.java b/tests/src/com/android/tradefed/UnitTests.java index 1b34b75ef..5b9e12e1f 100644 --- a/tests/src/com/android/tradefed/UnitTests.java +++ b/tests/src/com/android/tradefed/UnitTests.java @@ -45,6 +45,7 @@ import com.android.tradefed.config.GlobalConfigurationTest; import com.android.tradefed.config.OptionCopierTest; import com.android.tradefed.config.OptionSetterTest; import com.android.tradefed.config.OptionUpdateRuleTest; +import com.android.tradefed.config.SandboxConfigurationFactoryTest; import com.android.tradefed.device.BackgroundDeviceActionTest; import com.android.tradefed.device.CpuStatsCollectorTest; import com.android.tradefed.device.DeviceManagerTest; @@ -274,6 +275,7 @@ import org.junit.runners.Suite.SuiteClasses; OptionCopierTest.class, OptionSetterTest.class, OptionUpdateRuleTest.class, + SandboxConfigurationFactoryTest.class, // device BackgroundDeviceActionTest.class, diff --git a/tests/src/com/android/tradefed/config/SandboxConfigurationFactoryTest.java b/tests/src/com/android/tradefed/config/SandboxConfigurationFactoryTest.java new file mode 100644 index 000000000..c61065c96 --- /dev/null +++ b/tests/src/com/android/tradefed/config/SandboxConfigurationFactoryTest.java @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.tradefed.config; + +import static org.easymock.EasyMock.eq; +import static org.junit.Assert.*; + +import com.android.tradefed.sandbox.ISandbox; +import com.android.tradefed.sandbox.SandboxConfigDump; +import com.android.tradefed.sandbox.SandboxConfigDump.DumpCmd; +import com.android.tradefed.util.CommandResult; +import com.android.tradefed.util.CommandStatus; +import com.android.tradefed.util.FileUtil; +import com.android.tradefed.util.IRunUtil; +import com.android.tradefed.util.keystore.StubKeyStoreClient; + +import org.easymock.EasyMock; +import org.easymock.IAnswer; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import java.io.File; +import java.io.IOException; + +/** Unit tests for {@link SandboxConfigurationFactory}. */ +@RunWith(JUnit4.class) +public class SandboxConfigurationFactoryTest { + + private SandboxConfigurationFactory mFactory; + private File mConfig; + private File mTmpEnvDir; + private ISandbox mFakeSandbox; + private IRunUtil mMockRunUtil; + + @Before + public void setUp() throws IOException { + mFactory = SandboxConfigurationFactory.getInstance(); + mConfig = FileUtil.createTempFile("sandbox-config-test", ".xml"); + mTmpEnvDir = FileUtil.createTempDir("sandbox-tmp-dir"); + mFakeSandbox = EasyMock.createMock(ISandbox.class); + mMockRunUtil = EasyMock.createMock(IRunUtil.class); + } + + @After + public void tearDown() { + FileUtil.recursiveDelete(mTmpEnvDir); + FileUtil.deleteFile(mConfig); + } + + private void expectDumpCmd(CommandResult res) { + EasyMock.expect( + mMockRunUtil.runTimedCmd( + EasyMock.anyLong(), + eq("java"), + eq("-cp"), + eq(new File(mTmpEnvDir, "*").getAbsolutePath()), + eq(SandboxConfigDump.class.getCanonicalName()), + eq(DumpCmd.NON_VERSIONED_CONFIG.toString()), + EasyMock.anyObject(), + eq(mConfig.getAbsolutePath()))) + .andAnswer( + new IAnswer<CommandResult>() { + @Override + public CommandResult answer() throws Throwable { + String resFile = (String) EasyMock.getCurrentArguments()[6]; + FileUtil.writeToFile( + "<configuration><test class=\"com.android.tradefed.test" + + "type.StubTest\" /></configuration>", + new File(resFile)); + return res; + } + }); + } + + /** + * Test that creating a configuration using a sandbox properly create a {@link IConfiguration}. + */ + @Test + public void testCreateConfigurationFromArgs() throws ConfigurationException { + String[] args = new String[] {mConfig.getAbsolutePath()}; + EasyMock.expect(mFakeSandbox.getTradefedEnvironment(EasyMock.anyObject())) + .andReturn(mTmpEnvDir); + mMockRunUtil.unsetEnvVariable(GlobalConfiguration.GLOBAL_CONFIG_VARIABLE); + CommandResult results = new CommandResult(); + results.setStatus(CommandStatus.SUCCESS); + expectDumpCmd(results); + EasyMock.replay(mFakeSandbox, mMockRunUtil); + IConfiguration config = + mFactory.createConfigurationFromArgs( + args, new StubKeyStoreClient(), mFakeSandbox, mMockRunUtil); + EasyMock.verify(mFakeSandbox, mMockRunUtil); + assertNotNull(config.getConfigurationObject(Configuration.SANDBOX_TYPE_NAME)); + assertEquals(mFakeSandbox, config.getConfigurationObject(Configuration.SANDBOX_TYPE_NAME)); + } + + /** Test that when the dump config failed, we throw a ConfigurationException. */ + @Test + public void testCreateConfigurationFromArgs_fail() throws ConfigurationException { + String[] args = new String[] {mConfig.getAbsolutePath()}; + EasyMock.expect(mFakeSandbox.getTradefedEnvironment(EasyMock.anyObject())) + .andReturn(mTmpEnvDir); + mMockRunUtil.unsetEnvVariable(GlobalConfiguration.GLOBAL_CONFIG_VARIABLE); + CommandResult results = new CommandResult(); + results.setStatus(CommandStatus.FAILED); + results.setStderr("I failed"); + expectDumpCmd(results); + // in case of failure, tearDown is called right away for cleaning up + mFakeSandbox.tearDown(); + EasyMock.replay(mFakeSandbox, mMockRunUtil); + try { + mFactory.createConfigurationFromArgs( + args, new StubKeyStoreClient(), mFakeSandbox, mMockRunUtil); + fail("Should have thrown an exception."); + } catch (ConfigurationException expected) { + // expected + } + EasyMock.verify(mFakeSandbox, mMockRunUtil); + } +} |