diff options
author | Julien Desprez <jdesprez@google.com> | 2019-10-01 12:56:54 -0700 |
---|---|---|
committer | Julien Desprez <jdesprez@google.com> | 2019-10-01 12:58:57 -0700 |
commit | f1494dd7e1e223995bca590b4138e265d3ce3c8a (patch) | |
tree | 03df5f2849c1a9ecefbda3ca4affedc08467b8cf | |
parent | 2e3c27b74a903f647ed4e4bdd51d945c135fea01 (diff) | |
download | tradefederation-f1494dd7e1e223995bca590b4138e265d3ce3c8a.tar.gz |
In case of run interruption still report module in progress
Ensure we don't lose the module in progress when reporting
the not-executed in case of JVM interruption.
Test: unit tests
local runs
Bug: 141752087
Change-Id: Ic8e260a450ce2a0cb8d585fdb674f07034ccc925
4 files changed, 77 insertions, 2 deletions
diff --git a/src/com/android/tradefed/testtype/suite/ITestSuite.java b/src/com/android/tradefed/testtype/suite/ITestSuite.java index f5a20ac2a..7ff6fab96 100644 --- a/src/com/android/tradefed/testtype/suite/ITestSuite.java +++ b/src/com/android/tradefed/testtype/suite/ITestSuite.java @@ -337,6 +337,7 @@ public abstract class ITestSuite // Current modules to run, null if not started to run yet. private List<ModuleDefinition> mRunModules = null; + private ModuleDefinition mModuleInProgress = null; // Logger to be used to files. private ITestLogger mCurrentLogger = null; // Whether or not we are currently in split @@ -656,6 +657,7 @@ public abstract class ITestSuite .addDeviceBuildInfo(deviceName, mContext.getBuildInfo(deviceName)); } listener.testModuleStarted(module.getModuleInvocationContext()); + mModuleInProgress = module; // Trigger module start on module level listener too new ResultForwarder(moduleListeners) .testModuleStarted(module.getModuleInvocationContext()); @@ -667,6 +669,7 @@ public abstract class ITestSuite // clear out module invocation context since we are now done with module // execution listener.testModuleEnded(); + mModuleInProgress = null; } // Module isolation routine moduleIsolation(mContext, listener); @@ -1113,6 +1116,16 @@ public abstract class ITestSuite runModules = createExecutionList(); } + if (mModuleInProgress != null) { + // TODO: Ensure in-progress data make sense + String inProgressMessage = + String.format( + "Module %s was interrupted after starting. Results might not be " + + "accurate or complete.", + mModuleInProgress.getId()); + mModuleInProgress.reportNotExecuted(listener, inProgressMessage); + } + while (!runModules.isEmpty()) { ModuleDefinition module = runModules.remove(0); module.reportNotExecuted(listener, message); @@ -1376,4 +1389,9 @@ public abstract class ITestSuite void disableAutoRetryTimeReporting() { mDisableAutoRetryTimeReporting = true; } + + @VisibleForTesting + void setModuleInProgress(ModuleDefinition moduleInProgress) { + mModuleInProgress = moduleInProgress; + } } diff --git a/src/com/android/tradefed/testtype/suite/ModuleDefinition.java b/src/com/android/tradefed/testtype/suite/ModuleDefinition.java index 385e06ae6..f80e2d15f 100644 --- a/src/com/android/tradefed/testtype/suite/ModuleDefinition.java +++ b/src/com/android/tradefed/testtype/suite/ModuleDefinition.java @@ -136,6 +136,7 @@ public class ModuleDefinition implements Comparable<ModuleDefinition>, ITestColl private long mElapsedTearDown = 0l; private long mStartTestTime = 0l; + private Long mStartModuleRunDate = null; // Tracking of retry performance private List<RetryStatistics> mRetryStats = new ArrayList<>(); @@ -326,6 +327,7 @@ public class ModuleDefinition implements Comparable<ModuleDefinition>, ITestColl TestFailureListener failureListener, int maxRunLimit) throws DeviceNotAvailableException { + mStartModuleRunDate = System.currentTimeMillis(); // Load extra configuration for the module from module_controller // TODO: make module_controller a full TF object boolean skipTestCases = false; @@ -929,7 +931,9 @@ public class ModuleDefinition implements Comparable<ModuleDefinition>, ITestColl /** Report completely not executed modules. */ public final void reportNotExecuted(ITestInvocationListener listener, String message) { - listener.testModuleStarted(getModuleInvocationContext()); + if (mStartModuleRunDate == null) { + listener.testModuleStarted(getModuleInvocationContext()); + } listener.testRunStarted(getId(), 0, 0, System.currentTimeMillis()); listener.testRunFailed(message); listener.testRunEnded(0, new HashMap<String, Metric>()); diff --git a/src/com/android/tradefed/util/SubprocessEventHelper.java b/src/com/android/tradefed/util/SubprocessEventHelper.java index 50028d93f..be182b138 100644 --- a/src/com/android/tradefed/util/SubprocessEventHelper.java +++ b/src/com/android/tradefed/util/SubprocessEventHelper.java @@ -546,7 +546,7 @@ public class SubprocessEventHelper { mModuleContext .getAttributes() .getUniqueMap() - .get(ModuleDefinition.MODULE_NAME); + .get(ModuleDefinition.MODULE_ID); if (moduleName != null) { tags.put(MODULE_NAME, moduleName); } diff --git a/tests/src/com/android/tradefed/testtype/suite/ITestSuiteTest.java b/tests/src/com/android/tradefed/testtype/suite/ITestSuiteTest.java index 13df991b8..05326a58b 100644 --- a/tests/src/com/android/tradefed/testtype/suite/ITestSuiteTest.java +++ b/tests/src/com/android/tradefed/testtype/suite/ITestSuiteTest.java @@ -1804,4 +1804,57 @@ public class ITestSuiteTest { mTestSuite.run(mMockListener); EasyMock.verify(mockBuildInfo); } + + /** Test for {@link ITestSuite#reportNotExecuted(ITestInvocationListener, String)}. */ + @Test + public void testReportNotExecuted() { + mMockListener.testModuleStarted(EasyMock.anyObject()); + mMockListener.testRunStarted( + EasyMock.eq(TEST_CONFIG_NAME), EasyMock.eq(0), EasyMock.eq(0), EasyMock.anyLong()); + mMockListener.testRunFailed("Injected message"); + mMockListener.testRunEnded( + EasyMock.anyLong(), EasyMock.<HashMap<String, Metric>>anyObject()); + mMockListener.testModuleEnded(); + + EasyMock.replay(mMockListener); + mTestSuite.reportNotExecuted(mMockListener, "Injected message"); + EasyMock.verify(mMockListener); + } + + /** + * Test for {@link ITestSuite#reportNotExecuted(ITestInvocationListener, String)} with a module + * in progress. + */ + @Test + public void testReportNotExecuted_moduleInProgress() { + ModuleDefinition m = + new ModuleDefinition( + "in-progress", + new ArrayList<>(), + new HashMap<>(), + new ArrayList<>(), + new Configuration("", "")); + mTestSuite.setModuleInProgress(m); + mMockListener.testModuleStarted(EasyMock.anyObject()); + mMockListener.testRunStarted( + EasyMock.eq("in-progress"), EasyMock.eq(0), EasyMock.eq(0), EasyMock.anyLong()); + mMockListener.testRunFailed( + "Module in-progress was interrupted after starting. Results might not be " + + "accurate or complete."); + mMockListener.testRunEnded( + EasyMock.anyLong(), EasyMock.<HashMap<String, Metric>>anyObject()); + mMockListener.testModuleEnded(); + // The non-executed module gets reported too. + mMockListener.testModuleStarted(EasyMock.anyObject()); + mMockListener.testRunStarted( + EasyMock.eq(TEST_CONFIG_NAME), EasyMock.eq(0), EasyMock.eq(0), EasyMock.anyLong()); + mMockListener.testRunFailed("Injected message"); + mMockListener.testRunEnded( + EasyMock.anyLong(), EasyMock.<HashMap<String, Metric>>anyObject()); + mMockListener.testModuleEnded(); + + EasyMock.replay(mMockListener); + mTestSuite.reportNotExecuted(mMockListener, "Injected message"); + EasyMock.verify(mMockListener); + } } |