blob: ddb14ea0ae663785940b09ace130dd8adfa37919 [file] [log] [blame]
/*
* Copyright (C) 2019 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.cluster;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;
import com.android.loganalysis.util.ArrayUtil;
import com.android.tradefed.config.Configuration;
import com.android.tradefed.config.ConfigurationException;
import com.android.tradefed.config.IConfiguration;
import com.android.tradefed.config.OptionSetter;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.invoker.IInvocationContext;
import com.android.tradefed.invoker.InvocationContext;
import com.android.tradefed.result.ITestInvocationListener;
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.SubprocessTestResultsParser;
import com.android.tradefed.util.SystemUtil;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.Mockito;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/** Unit tests for {@link ClusterCommandLauncherTest}. */
@RunWith(JUnit4.class)
public class ClusterCommandLauncherTest {
private static final String DEVICE_SERIAL = "device_serial";
private IRunUtil mMockRunUtil;
private SubprocessTestResultsParser mMockSubprocessTestResultsParser;
private ITestInvocationListener mMockListener;
private ITestDevice mMockTestDevice;
private File mTfPath;
private File mTfLibDir;
private File mRootDir;
private IConfiguration mConfiguration;
private IInvocationContext mInvocationContext;
private ClusterCommandLauncher mLauncher;
private OptionSetter mOptionSetter;
private File createTempDir(final String key) throws IOException {
return FileUtil.createTempDir(this.getClass().getName() + "_" + key);
}
private String[] asMatchers(String... strs) {
return Arrays.stream(strs).map(x -> Mockito.eq(x)).toArray(String[]::new);
}
@Before
public void setUp() throws Exception {
mMockRunUtil = Mockito.mock(IRunUtil.class);
mMockSubprocessTestResultsParser = Mockito.mock(SubprocessTestResultsParser.class);
mMockListener = Mockito.mock(ITestInvocationListener.class);
mMockTestDevice = Mockito.mock(ITestDevice.class);
Mockito.doReturn(DEVICE_SERIAL).when(mMockTestDevice).getSerialNumber();
mRootDir = createTempDir("RootDir");
mTfPath = new File(mRootDir, "TfPath");
mTfPath.mkdir();
mTfLibDir = new File(mRootDir, "TfLibDir");
mTfLibDir.mkdir();
mConfiguration = new Configuration("name", "description");
mConfiguration.getCommandOptions().setInvocationTimeout(10000L);
mInvocationContext = new InvocationContext();
mLauncher = Mockito.spy(ClusterCommandLauncher.class);
mLauncher.setConfiguration(mConfiguration);
mLauncher.setInvocationContext(mInvocationContext);
mOptionSetter = new OptionSetter(mLauncher);
mOptionSetter.setOptionValue("cluster:root-dir", mRootDir.getAbsolutePath());
mOptionSetter.setOptionValue("cluster:env-var", "TF_WORK_DIR", mRootDir.getAbsolutePath());
}
@After
public void tearDown() {
FileUtil.recursiveDelete(mRootDir);
}
@Test
public void testRun() throws DeviceNotAvailableException, ConfigurationException {
mInvocationContext.addAllocatedDevice("foo", mMockTestDevice);
final List<String> jars = new ArrayList<>();
jars.add(String.format("%s/*", mTfPath));
jars.add(String.format("%s/*", mTfLibDir));
final String classPath = ArrayUtil.join(":", jars);
final String tfPathValue =
String.format(
"${TF_WORK_DIR}/%s:${TF_WORK_DIR}/%s",
mTfPath.getName(), mTfLibDir.getName());
mOptionSetter.setOptionValue("cluster:env-var", "TF_PATH", tfPathValue);
mOptionSetter.setOptionValue("cluster:java-property", "FOO", "${TF_WORK_DIR}/foo");
mOptionSetter.setOptionValue("cluster:original-command-line", "original-command-line");
mOptionSetter.setOptionValue("cluster:command-line", "command-line");
final String expandedTfPathValue =
String.format("%s:%s", mTfPath.getAbsolutePath(), mTfLibDir.getAbsolutePath());
final CommandResult mockCommandResult = new CommandResult(CommandStatus.SUCCESS);
when(mMockRunUtil.runTimedCmd(
Mockito.anyLong(),
Mockito.<OutputStream>any(),
Mockito.<OutputStream>any(),
Mockito.<String[]>any()))
.thenReturn(mockCommandResult);
Mockito.when(mLauncher.getRunUtil()).thenReturn(mMockRunUtil);
mLauncher.run(mMockListener);
Mockito.verify(mMockRunUtil, Mockito.times(2)).setWorkingDir(mRootDir);
Mockito.verify(mMockRunUtil).unsetEnvVariable("TF_GLOBAL_CONFIG");
Mockito.verify(mMockRunUtil).setEnvVariable("TF_WORK_DIR", mRootDir.getAbsolutePath());
Mockito.verify(mMockRunUtil).setEnvVariable("TF_PATH", expandedTfPathValue);
Mockito.verify(mMockRunUtil)
.runTimedCmd(
Mockito.eq(10000L),
Mockito.<OutputStream>any(),
Mockito.<OutputStream>any(),
asMatchers(
new String[] {
SystemUtil.getRunningJavaBinaryPath().getAbsolutePath(),
"-cp",
classPath,
"-DFOO=" + mRootDir.getAbsolutePath() + "/foo",
"com.android.tradefed.command.CommandRunner",
"command-line",
"--serial",
DEVICE_SERIAL
}));
assertTrue(new File(mRootDir, "original-command-line.xml").exists());
}
@Test
public void testRun_withSetupScripts()
throws DeviceNotAvailableException, ConfigurationException {
mInvocationContext.addAllocatedDevice("foo", mMockTestDevice);
final String classpath = String.format("%s/*", mTfPath);
mOptionSetter.setOptionValue("cluster:env-var", "TF_PATH", mTfPath.getAbsolutePath());
mOptionSetter.setOptionValue("cluster:env-var", "FOO", "foo");
mOptionSetter.setOptionValue("cluster:env-var", "BAR", "bar");
mOptionSetter.setOptionValue("cluster:env-var", "ZZZ", "zzz");
mOptionSetter.setOptionValue("cluster:setup-script", "foo bar zzz");
mOptionSetter.setOptionValue("cluster:setup-script", "${FOO} ${BAR} ${ZZZ}");
mOptionSetter.setOptionValue("cluster:command-line", "command-line");
final CommandResult mockCommandResult = new CommandResult(CommandStatus.SUCCESS);
when(mMockRunUtil.runTimedCmd(
Mockito.anyLong(),
Mockito.<OutputStream>any(),
Mockito.<OutputStream>any(),
Mockito.<String[]>any()))
.thenReturn(mockCommandResult);
Mockito.when(mLauncher.getRunUtil()).thenReturn(mMockRunUtil);
mLauncher.run(mMockListener);
Mockito.verify(mMockRunUtil, Mockito.times(2)).setWorkingDir(mRootDir);
Mockito.verify(mMockRunUtil).unsetEnvVariable("TF_GLOBAL_CONFIG");
Mockito.verify(mMockRunUtil).setEnvVariable("TF_WORK_DIR", mRootDir.getAbsolutePath());
Mockito.verify(mMockRunUtil).setEnvVariable("TF_PATH", mTfPath.getAbsolutePath());
Mockito.verify(mMockRunUtil).setEnvVariable("BAR", "bar");
Mockito.verify(mMockRunUtil).setEnvVariable("FOO", "foo");
Mockito.verify(mMockRunUtil).setEnvVariable("ZZZ", "zzz");
Mockito.verify(mMockRunUtil, Mockito.times(2))
.runTimedCmd(
Mockito.anyLong(),
Mockito.<OutputStream>any(),
Mockito.<OutputStream>any(),
asMatchers(new String[] {"foo", "bar", "zzz"}));
Mockito.verify(mMockRunUtil)
.runTimedCmd(
Mockito.eq(10000L),
Mockito.<OutputStream>any(),
Mockito.<OutputStream>any(),
asMatchers(
new String[] {
SystemUtil.getRunningJavaBinaryPath().getAbsolutePath(),
"-cp",
classpath,
"com.android.tradefed.command.CommandRunner",
"command-line",
"--serial",
DEVICE_SERIAL
}));
}
@Test
public void testRun_withUseSubprocessReporting()
throws DeviceNotAvailableException, ConfigurationException, IOException {
mInvocationContext.addAllocatedDevice("foo", mMockTestDevice);
final String classpath = String.format("%s/*", mTfPath);
mOptionSetter.setOptionValue("cluster:env-var", "TF_PATH", mTfPath.getAbsolutePath());
mOptionSetter.setOptionValue("cluster:command-line", "command-line");
mOptionSetter.setOptionValue("cluster:use-subprocess-reporting", "true");
when(mMockSubprocessTestResultsParser.getSocketServerPort()).thenReturn(123);
Mockito.when(
mLauncher.createSubprocessTestResultsParser(
Mockito.any(), Mockito.anyBoolean(), Mockito.any()))
.thenReturn(mMockSubprocessTestResultsParser);
final CommandResult mockCommandResult = new CommandResult(CommandStatus.SUCCESS);
when(mMockRunUtil.runTimedCmd(
Mockito.anyLong(),
Mockito.<OutputStream>any(),
Mockito.<OutputStream>any(),
Mockito.<String[]>any()))
.thenReturn(mockCommandResult);
final File subprocessReporterConfig = new File(mRootDir, "command-line.xml");
Mockito.when(mLauncher.getRunUtil()).thenReturn(mMockRunUtil);
mLauncher.run(mMockListener);
String subprocessJar =
FileUtil.findFile(mRootDir, "subprocess-results-reporter.jar").getAbsolutePath();
assertTrue(subprocessReporterConfig.exists());
Mockito.verify(mMockRunUtil, Mockito.times(2)).setWorkingDir(mRootDir);
Mockito.verify(mMockRunUtil).unsetEnvVariable("TF_GLOBAL_CONFIG");
Mockito.verify(mMockRunUtil).setEnvVariable("TF_WORK_DIR", mRootDir.getAbsolutePath());
Mockito.verify(mMockRunUtil).setEnvVariable("TF_PATH", mTfPath.getAbsolutePath());
Mockito.verify(mMockRunUtil).unsetEnvVariable("TF_GLOBAL_CONFIG");
Mockito.verify(mMockRunUtil)
.runTimedCmd(
Mockito.eq(10000L),
Mockito.<OutputStream>any(),
Mockito.<OutputStream>any(),
asMatchers(
new String[] {
SystemUtil.getRunningJavaBinaryPath().getAbsolutePath(),
"-cp",
subprocessJar + ":" + classpath,
"com.android.tradefed.command.CommandRunner",
subprocessReporterConfig.getName(),
"--serial",
DEVICE_SERIAL,
}));
}
}