From 4181e8e5dbb63fa76f15bbc31a2583fe4feffe30 Mon Sep 17 00:00:00 2001 From: Andrei NICOLAE Date: Fri, 20 Apr 2018 18:33:04 +0300 Subject: [PATCH 1/6] Fix some lint warnings. --- .../java/com/squareup/spoon/SpoonLogger.java | 4 +- .../java/com/squareup/spoon/SpoonRunner.java | 37 ++++++++----------- .../java/com/squareup/spoon/SpoonUtils.java | 5 +-- .../squareup/spoon/XmlTestRunListener.java | 3 +- .../com/squareup/spoon/html/HtmlIndex.java | 6 ++- .../java/com/squareup/spoon/html/HtmlTv.java | 2 +- .../squareup/spoon/html/HtmlUtilsTest.java | 2 +- 7 files changed, 25 insertions(+), 34 deletions(-) diff --git a/spoon-runner/src/main/java/com/squareup/spoon/SpoonLogger.java b/spoon-runner/src/main/java/com/squareup/spoon/SpoonLogger.java index de9c7414..f88c77ab 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/SpoonLogger.java +++ b/spoon-runner/src/main/java/com/squareup/spoon/SpoonLogger.java @@ -24,10 +24,10 @@ static void logDebug(boolean debug, String message, Object... args) { private static String getPrefix() { StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); - if (stackTrace == null || stackTrace.length < 4) return "[BOGUS]"; + if (stackTrace.length < 4) return "[BOGUS]"; String className = stackTrace[3].getClassName(); String methodName = stackTrace[3].getMethodName(); - className = className.replaceAll("[a-z\\.]", ""); + className = className.replaceAll("[a-z.]", ""); String timestamp = DATE_FORMAT.get().format(new Date()); return String.format("%s [%s.%s] ", timestamp, className, methodName); } diff --git a/spoon-runner/src/main/java/com/squareup/spoon/SpoonRunner.java b/spoon-runner/src/main/java/com/squareup/spoon/SpoonRunner.java index ecfb6b7f..e874768d 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/SpoonRunner.java +++ b/spoon-runner/src/main/java/com/squareup/spoon/SpoonRunner.java @@ -109,9 +109,7 @@ private SpoonRunner(String title, File androidSdk, File testApk, List othe * @return {@code true} if there were no test failures or exceptions thrown. */ public boolean run() { - otherApks.forEach(otherApk -> { - checkArgument(otherApk.exists(), "Could not find other APK: " + otherApk); - }); + otherApks.forEach(otherApk -> checkArgument(otherApk.exists(), "Could not find other APK: " + otherApk)); checkArgument(testApk.exists(), "Could not find test APK: " + testApk); AndroidDebugBridge adb = SpoonUtils.initAdb(androidSdk, adbTimeout); @@ -165,11 +163,8 @@ private SpoonSummary runTests(AndroidDebugBridge adb, Set serials, throw new RuntimeException("Unable to clean output directory: " + output, e); } - logDebug(debug, "Instrumentation: %s from %s", testInfo.getInstrumentationPackage(), - testApk.getAbsolutePath()); - otherApks.forEach(otherApk -> { - logDebug(debug, "Other: %s", otherApk.getAbsolutePath()); - }); + logDebug(debug, "Instrumentation: %s from %s", testInfo.getInstrumentationPackage(), testApk.getAbsolutePath()); + otherApks.forEach(otherApk -> logDebug(debug, "Other: %s", otherApk.getAbsolutePath())); final SpoonSummary.Builder summary = new SpoonSummary.Builder().setTitle(title).start(); @@ -204,20 +199,18 @@ private SpoonSummary runTests(AndroidDebugBridge adb, Set serials, final String safeSerial = SpoonUtils.sanitizeSerial(serial); logDebug(debug, "[%s] Starting execution.", serial); final int safeShardIndex = shardIndex; - Runnable runnable = new Runnable() { - @Override public void run() { - try { - summary.addResult(safeSerial, - getTestRunner(serial, safeShardIndex, numShards, testInfo).run(adb)); - } catch (Exception e) { - e.printStackTrace(System.out); - summary.addResult(safeSerial, new DeviceResult.Builder().addException(e).build()); - } finally { - done.countDown(); - remaining.remove(serial); - logDebug(debug, "[%s] Execution done. (%s remaining %s)", serial, done.getCount(), - remaining); - } + Runnable runnable = () -> { + try { + summary.addResult(safeSerial, + getTestRunner(serial, safeShardIndex, numShards, testInfo).run(adb)); + } catch (Exception e) { + e.printStackTrace(System.out); + summary.addResult(safeSerial, new DeviceResult.Builder().addException(e).build()); + } finally { + done.countDown(); + remaining.remove(serial); + logDebug(debug, "[%s] Execution done. (%s remaining %s)", serial, done.getCount(), + remaining); } }; if (shard) { diff --git a/spoon-runner/src/main/java/com/squareup/spoon/SpoonUtils.java b/spoon-runner/src/main/java/com/squareup/spoon/SpoonUtils.java index 93393de0..ad09be48 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/SpoonUtils.java +++ b/spoon-runner/src/main/java/com/squareup/spoon/SpoonUtils.java @@ -74,10 +74,7 @@ static FileEntry obtainDirectoryFileEntry(String path) { lastEntry = c.newInstance(lastEntry, part, TYPE_DIRECTORY, lastEntry == null); } return lastEntry; - } catch (NoSuchMethodException ignored) { - } catch (InvocationTargetException ignored) { - } catch (InstantiationException ignored) { - } catch (IllegalAccessException ignored) { + } catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException ignored) { } return null; } diff --git a/spoon-runner/src/main/java/com/squareup/spoon/XmlTestRunListener.java b/spoon-runner/src/main/java/com/squareup/spoon/XmlTestRunListener.java index 94761baf..f6862b14 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/XmlTestRunListener.java +++ b/spoon-runner/src/main/java/com/squareup/spoon/XmlTestRunListener.java @@ -1,7 +1,6 @@ package com.squareup.spoon; import java.io.File; -import java.io.IOException; /** * An {@link com.android.ddmlib.testrunner.XmlTestRunListener XmlTestRunListener} that points @@ -22,7 +21,7 @@ public void testRunStarted(String runName, int numTests) { getRunResult().testRunStarted(runName, numTests); } - @Override protected File getResultFile(File reportDir) throws IOException { + @Override protected File getResultFile(File reportDir) { file.getParentFile().mkdirs(); return file; } diff --git a/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlIndex.java b/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlIndex.java index cee8f82e..6e46d255 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlIndex.java +++ b/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlIndex.java @@ -6,6 +6,8 @@ import com.squareup.spoon.DeviceTest; import com.squareup.spoon.DeviceTestResult; import com.squareup.spoon.SpoonSummary; +import org.jetbrains.annotations.NotNull; + import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -94,7 +96,7 @@ static Device from(String serial, DeviceResult result) { this.executionFailed = executionFailed; } - @Override public int compareTo(Device other) { + @Override public int compareTo(@NotNull Device other) { if (name == null && other.name == null) { return serial.compareTo(other.serial); } @@ -137,7 +139,7 @@ static TestResult from(String serial, DeviceTest test, DeviceTestResult testResu this.status = status; } - @Override public int compareTo(TestResult other) { + @Override public int compareTo(@NotNull TestResult other) { return 0; } } diff --git a/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlTv.java b/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlTv.java index dc402ce2..5f4c4fb9 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlTv.java +++ b/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlTv.java @@ -73,7 +73,7 @@ static Device from(String serial, DeviceResult result, File outputPath) { this.testResults = testResults; } - @Override public int compareTo(Device other) { + @Override public int compareTo(@NotNull Device other) { if (name == null && other.name == null) { return serial.compareTo(other.serial); } diff --git a/spoon-runner/src/test/java/com/squareup/spoon/html/HtmlUtilsTest.java b/spoon-runner/src/test/java/com/squareup/spoon/html/HtmlUtilsTest.java index a5a43860..a231dd09 100644 --- a/spoon-runner/src/test/java/com/squareup/spoon/html/HtmlUtilsTest.java +++ b/spoon-runner/src/test/java/com/squareup/spoon/html/HtmlUtilsTest.java @@ -37,7 +37,7 @@ public void relativeUriCreationFailsIfSame() { } /** - * This test is similar to {@link StackTraceTest#nestedCustomExceptionUnexpectedFormat}. + * This test is similar to {@code StackTraceTest#nestedCustomExceptionUnexpectedFormat}. * * The intent of this test is to check that unexpected format exceptions still print something * useful to the user in the test results. From c90d29a25982e4245b796752ff21b0a06b667bd6 Mon Sep 17 00:00:00 2001 From: Andrei NICOLAE Date: Fri, 20 Apr 2018 18:33:18 +0300 Subject: [PATCH 2/6] Optimize imports. --- .../java/com/squareup/spoon/DeviceResult.java | 8 ++---- .../com/squareup/spoon/DeviceTestResult.java | 1 + .../spoon/LogRecordingTestRunListener.kt | 2 +- .../com/squareup/spoon/SpoonDeviceLogger.java | 1 + .../com/squareup/spoon/SpoonDeviceRunner.java | 27 ++++--------------- .../spoon/SpoonInstrumentationInfo.java | 3 ++- .../java/com/squareup/spoon/SpoonRunner.java | 8 +----- .../java/com/squareup/spoon/SpoonSummary.java | 4 +-- .../squareup/spoon/SpoonTestRunListener.java | 1 + .../java/com/squareup/spoon/SpoonUtils.java | 7 ++--- .../com/squareup/spoon/html/HtmlDevice.java | 1 + .../com/squareup/spoon/html/HtmlIndex.java | 6 +---- .../java/com/squareup/spoon/html/HtmlLog.java | 1 + .../com/squareup/spoon/html/HtmlRenderer.java | 22 +++++---------- .../com/squareup/spoon/html/HtmlTest.java | 7 ++--- .../java/com/squareup/spoon/html/HtmlTv.java | 2 ++ .../com/squareup/spoon/html/HtmlUtils.java | 3 ++- .../com/squareup/spoon/misc/StackTrace.java | 3 ++- .../java/com/squareup/spoon/CliArgsTest.kt | 2 +- .../squareup/spoon/SpoonHtmlRendererTest.java | 9 ++++--- .../squareup/spoon/html/HtmlIndexTest.java | 3 ++- .../squareup/spoon/html/HtmlUtilsTest.java | 11 ++++---- .../squareup/spoon/misc/StackTraceTest.java | 3 ++- 23 files changed, 51 insertions(+), 84 deletions(-) diff --git a/spoon-runner/src/main/java/com/squareup/spoon/DeviceResult.java b/spoon-runner/src/main/java/com/squareup/spoon/DeviceResult.java index 966a79d3..367f7c99 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/DeviceResult.java +++ b/spoon-runner/src/main/java/com/squareup/spoon/DeviceResult.java @@ -1,12 +1,8 @@ package com.squareup.spoon; import com.squareup.spoon.misc.StackTrace; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; + +import java.util.*; import java.util.concurrent.TimeUnit; import static com.google.common.base.Preconditions.checkArgument; diff --git a/spoon-runner/src/main/java/com/squareup/spoon/DeviceTestResult.java b/spoon-runner/src/main/java/com/squareup/spoon/DeviceTestResult.java index bce465a3..f606a077 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/DeviceTestResult.java +++ b/spoon-runner/src/main/java/com/squareup/spoon/DeviceTestResult.java @@ -2,6 +2,7 @@ import com.android.ddmlib.logcat.LogCatMessage; import com.squareup.spoon.misc.StackTrace; + import java.io.File; import java.util.ArrayList; import java.util.Collections; diff --git a/spoon-runner/src/main/java/com/squareup/spoon/LogRecordingTestRunListener.kt b/spoon-runner/src/main/java/com/squareup/spoon/LogRecordingTestRunListener.kt index 528579ab..104397c9 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/LogRecordingTestRunListener.kt +++ b/spoon-runner/src/main/java/com/squareup/spoon/LogRecordingTestRunListener.kt @@ -3,7 +3,7 @@ package com.squareup.spoon import com.android.ddmlib.testrunner.ITestRunListener import com.android.ddmlib.testrunner.TestIdentifier import com.google.common.collect.ImmutableList -import java.util.LinkedHashSet +import java.util.* /** * Listens to an instrumentation invocation where `log=true` is set and records information about diff --git a/spoon-runner/src/main/java/com/squareup/spoon/SpoonDeviceLogger.java b/spoon-runner/src/main/java/com/squareup/spoon/SpoonDeviceLogger.java index f322661a..be066d38 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/SpoonDeviceLogger.java +++ b/spoon-runner/src/main/java/com/squareup/spoon/SpoonDeviceLogger.java @@ -4,6 +4,7 @@ import com.android.ddmlib.logcat.LogCatListener; import com.android.ddmlib.logcat.LogCatMessage; import com.android.ddmlib.logcat.LogCatReceiverTask; + import java.util.ArrayList; import java.util.HashMap; import java.util.List; diff --git a/spoon-runner/src/main/java/com/squareup/spoon/SpoonDeviceRunner.java b/spoon-runner/src/main/java/com/squareup/spoon/SpoonDeviceRunner.java index 3ac0fec4..2283eee9 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/SpoonDeviceRunner.java +++ b/spoon-runner/src/main/java/com/squareup/spoon/SpoonDeviceRunner.java @@ -1,10 +1,6 @@ package com.squareup.spoon; -import com.android.ddmlib.AndroidDebugBridge; -import com.android.ddmlib.CollectingOutputReceiver; -import com.android.ddmlib.DdmPreferences; -import com.android.ddmlib.IDevice; -import com.android.ddmlib.InstallException; +import com.android.ddmlib.*; import com.android.ddmlib.logcat.LogCatMessage; import com.android.ddmlib.testrunner.IRemoteAndroidTestRunner; import com.android.ddmlib.testrunner.ITestRunListener; @@ -13,32 +9,19 @@ import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Multimap; - import org.apache.commons.io.FileUtils; import org.apache.commons.io.filefilter.TrueFileFilter; -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; +import java.io.*; import java.time.Duration; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.concurrent.TimeUnit; import static com.android.ddmlib.FileListingService.FileEntry; import static com.android.ddmlib.SyncService.getNullProgressMonitor; import static com.google.common.base.Strings.isNullOrEmpty; -import static com.squareup.spoon.SpoonLogger.logDebug; -import static com.squareup.spoon.SpoonLogger.logError; -import static com.squareup.spoon.SpoonLogger.logInfo; -import static com.squareup.spoon.SpoonUtils.createAnimatedGif; -import static com.squareup.spoon.SpoonUtils.obtainDirectoryFileEntry; -import static com.squareup.spoon.SpoonUtils.obtainRealDevice; +import static com.squareup.spoon.SpoonLogger.*; +import static com.squareup.spoon.SpoonUtils.*; import static com.squareup.spoon.internal.Constants.SPOON_FILES; import static com.squareup.spoon.internal.Constants.SPOON_SCREENSHOTS; import static java.util.Collections.emptyMap; diff --git a/spoon-runner/src/main/java/com/squareup/spoon/SpoonInstrumentationInfo.java b/spoon-runner/src/main/java/com/squareup/spoon/SpoonInstrumentationInfo.java index d5dcf45e..51aa6d44 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/SpoonInstrumentationInfo.java +++ b/spoon-runner/src/main/java/com/squareup/spoon/SpoonInstrumentationInfo.java @@ -1,12 +1,13 @@ package com.squareup.spoon; import com.squareup.spoon.internal.thirdparty.axmlparser.AXMLParser; +import org.apache.commons.lang3.builder.ToStringBuilder; + import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; -import org.apache.commons.lang3.builder.ToStringBuilder; import static com.google.common.base.Preconditions.checkNotNull; diff --git a/spoon-runner/src/main/java/com/squareup/spoon/SpoonRunner.java b/spoon-runner/src/main/java/com/squareup/spoon/SpoonRunner.java index e874768d..a6615678 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/SpoonRunner.java +++ b/spoon-runner/src/main/java/com/squareup/spoon/SpoonRunner.java @@ -7,7 +7,6 @@ import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.squareup.spoon.html.HtmlRenderer; - import org.apache.commons.io.FileUtils; import java.io.BufferedReader; @@ -15,12 +14,7 @@ import java.io.IOException; import java.io.InputStreamReader; import java.time.Duration; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; diff --git a/spoon-runner/src/main/java/com/squareup/spoon/SpoonSummary.java b/spoon-runner/src/main/java/com/squareup/spoon/SpoonSummary.java index 14e69de6..5707b09d 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/SpoonSummary.java +++ b/spoon-runner/src/main/java/com/squareup/spoon/SpoonSummary.java @@ -7,9 +7,7 @@ import java.util.Map; import java.util.concurrent.TimeUnit; -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Preconditions.checkState; +import static com.google.common.base.Preconditions.*; import static java.util.Collections.unmodifiableMap; /** Result summary of executing instrumentation on multiple devices. */ diff --git a/spoon-runner/src/main/java/com/squareup/spoon/SpoonTestRunListener.java b/spoon-runner/src/main/java/com/squareup/spoon/SpoonTestRunListener.java index da582b10..2d2c2323 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/SpoonTestRunListener.java +++ b/spoon-runner/src/main/java/com/squareup/spoon/SpoonTestRunListener.java @@ -2,6 +2,7 @@ import com.android.ddmlib.testrunner.ITestRunListener; import com.android.ddmlib.testrunner.TestIdentifier; + import java.util.HashMap; import java.util.Map; diff --git a/spoon-runner/src/main/java/com/squareup/spoon/SpoonUtils.java b/spoon-runner/src/main/java/com/squareup/spoon/SpoonUtils.java index ad09be48..07cb6fff 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/SpoonUtils.java +++ b/spoon-runner/src/main/java/com/squareup/spoon/SpoonUtils.java @@ -9,7 +9,10 @@ import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonWriter; import com.madgag.gif.fmsware.AnimatedGifEncoder; -import java.awt.Color; +import org.apache.commons.io.FileUtils; + +import javax.imageio.ImageIO; +import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; @@ -21,8 +24,6 @@ import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.regex.Pattern; -import javax.imageio.ImageIO; -import org.apache.commons.io.FileUtils; import static com.android.ddmlib.FileListingService.FileEntry; import static com.android.ddmlib.FileListingService.TYPE_DIRECTORY; diff --git a/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlDevice.java b/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlDevice.java index ca691272..86cdcfcf 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlDevice.java +++ b/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlDevice.java @@ -4,6 +4,7 @@ import com.squareup.spoon.DeviceResult; import com.squareup.spoon.DeviceTest; import com.squareup.spoon.DeviceTestResult; + import java.io.File; import java.util.ArrayList; import java.util.List; diff --git a/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlIndex.java b/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlIndex.java index 6e46d255..5a820a8a 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlIndex.java +++ b/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlIndex.java @@ -1,11 +1,7 @@ package com.squareup.spoon.html; import com.android.ddmlib.testrunner.IRemoteAndroidTestRunner; -import com.squareup.spoon.DeviceDetails; -import com.squareup.spoon.DeviceResult; -import com.squareup.spoon.DeviceTest; -import com.squareup.spoon.DeviceTestResult; -import com.squareup.spoon.SpoonSummary; +import com.squareup.spoon.*; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; diff --git a/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlLog.java b/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlLog.java index 2277df6f..ed8823b4 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlLog.java +++ b/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlLog.java @@ -3,6 +3,7 @@ import com.android.ddmlib.logcat.LogCatMessage; import com.squareup.spoon.DeviceTest; import com.squareup.spoon.DeviceTestResult; + import java.util.List; import static java.util.stream.Collectors.toList; diff --git a/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlRenderer.java b/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlRenderer.java index 2ba67ce9..31e82d57 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlRenderer.java +++ b/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlRenderer.java @@ -6,26 +6,16 @@ import com.github.mustachejava.MustacheFactory; import com.google.common.io.Resources; import com.google.gson.Gson; -import com.squareup.spoon.DeviceDetails; -import com.squareup.spoon.DeviceResult; -import com.squareup.spoon.DeviceTest; -import com.squareup.spoon.DeviceTestResult; -import com.squareup.spoon.SpoonSummary; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.Writer; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Set; +import com.squareup.spoon.*; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.lesscss.LessCompiler; +import java.io.*; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; + import static java.nio.charset.StandardCharsets.UTF_8; /** Renders a {@link com.squareup.spoon.SpoonSummary} as static HTML to an output directory. */ diff --git a/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlTest.java b/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlTest.java index b4f7dc67..fb79fcb9 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlTest.java +++ b/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlTest.java @@ -1,10 +1,7 @@ package com.squareup.spoon.html; -import com.squareup.spoon.DeviceDetails; -import com.squareup.spoon.DeviceResult; -import com.squareup.spoon.DeviceTest; -import com.squareup.spoon.DeviceTestResult; -import com.squareup.spoon.SpoonSummary; +import com.squareup.spoon.*; + import java.io.File; import java.util.ArrayList; import java.util.List; diff --git a/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlTv.java b/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlTv.java index 5f4c4fb9..7a1a298c 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlTv.java +++ b/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlTv.java @@ -5,6 +5,8 @@ import com.squareup.spoon.DeviceResult; import com.squareup.spoon.DeviceTestResult; import com.squareup.spoon.SpoonSummary; +import org.jetbrains.annotations.NotNull; + import java.io.File; import java.util.List; import java.util.stream.Collectors; diff --git a/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlUtils.java b/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlUtils.java index edada80a..d58f38ac 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlUtils.java +++ b/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlUtils.java @@ -3,6 +3,8 @@ import com.squareup.spoon.DeviceDetails; import com.squareup.spoon.DeviceTestResult; import com.squareup.spoon.misc.StackTrace; +import org.apache.commons.lang3.StringEscapeUtils; + import java.io.File; import java.io.IOException; import java.text.Format; @@ -11,7 +13,6 @@ import java.util.List; import java.util.Locale; import java.util.concurrent.atomic.AtomicLong; -import org.apache.commons.lang3.StringEscapeUtils; import static java.util.stream.Collectors.toList; diff --git a/spoon-runner/src/main/java/com/squareup/spoon/misc/StackTrace.java b/spoon-runner/src/main/java/com/squareup/spoon/misc/StackTrace.java index 431fc3b8..e2acf5af 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/misc/StackTrace.java +++ b/spoon-runner/src/main/java/com/squareup/spoon/misc/StackTrace.java @@ -1,12 +1,13 @@ package com.squareup.spoon.misc; import com.google.common.collect.ImmutableList; +import org.apache.commons.lang3.StringUtils; + import java.util.ArrayDeque; import java.util.Deque; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.apache.commons.lang3.StringUtils; import static com.google.common.base.Preconditions.checkNotNull; diff --git a/spoon-runner/src/test/java/com/squareup/spoon/CliArgsTest.kt b/spoon-runner/src/test/java/com/squareup/spoon/CliArgsTest.kt index 79719eb5..a7c26fd3 100644 --- a/spoon-runner/src/test/java/com/squareup/spoon/CliArgsTest.kt +++ b/spoon-runner/src/test/java/com/squareup/spoon/CliArgsTest.kt @@ -3,8 +3,8 @@ package com.squareup.spoon import com.google.common.truth.Truth.assertThat import com.xenomachina.argparser.ArgParser import com.xenomachina.argparser.SystemExitException -import java.io.File; import org.junit.Test +import java.io.File class CliArgsTest { diff --git a/spoon-runner/src/test/java/com/squareup/spoon/SpoonHtmlRendererTest.java b/spoon-runner/src/test/java/com/squareup/spoon/SpoonHtmlRendererTest.java index cc674ecc..9f007a7b 100644 --- a/spoon-runner/src/test/java/com/squareup/spoon/SpoonHtmlRendererTest.java +++ b/spoon-runner/src/test/java/com/squareup/spoon/SpoonHtmlRendererTest.java @@ -1,6 +1,11 @@ package com.squareup.spoon; import com.squareup.spoon.html.HtmlRenderer; +import org.apache.commons.io.FileUtils; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + import java.io.File; import java.io.FileInputStream; import java.io.IOException; @@ -12,10 +17,6 @@ import java.nio.charset.MalformedInputException; import java.nio.charset.StandardCharsets; import java.util.Iterator; -import org.apache.commons.io.FileUtils; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; public final class SpoonHtmlRendererTest { diff --git a/spoon-runner/src/test/java/com/squareup/spoon/html/HtmlIndexTest.java b/spoon-runner/src/test/java/com/squareup/spoon/html/HtmlIndexTest.java index 84a4ddb5..e77832ed 100644 --- a/spoon-runner/src/test/java/com/squareup/spoon/html/HtmlIndexTest.java +++ b/spoon-runner/src/test/java/com/squareup/spoon/html/HtmlIndexTest.java @@ -1,9 +1,10 @@ package com.squareup.spoon.html; +import org.junit.Test; + import java.util.Arrays; import java.util.Collections; import java.util.List; -import org.junit.Test; import static com.google.common.truth.Truth.assertThat; import static com.squareup.spoon.html.HtmlIndex.Device; diff --git a/spoon-runner/src/test/java/com/squareup/spoon/html/HtmlUtilsTest.java b/spoon-runner/src/test/java/com/squareup/spoon/html/HtmlUtilsTest.java index a231dd09..9e215adb 100644 --- a/spoon-runner/src/test/java/com/squareup/spoon/html/HtmlUtilsTest.java +++ b/spoon-runner/src/test/java/com/squareup/spoon/html/HtmlUtilsTest.java @@ -1,15 +1,14 @@ package com.squareup.spoon.html; +import com.squareup.spoon.html.HtmlUtils.*; +import com.squareup.spoon.misc.StackTrace; +import org.junit.Test; + import java.io.File; import java.util.List; -import org.junit.Test; -import com.squareup.spoon.html.HtmlUtils.ExceptionInfo; -import com.squareup.spoon.misc.StackTrace; import static com.google.common.truth.Truth.assertThat; -import static com.squareup.spoon.html.HtmlUtils.createRelativeUri; -import static com.squareup.spoon.html.HtmlUtils.processStackTrace; -import static com.squareup.spoon.html.HtmlUtils.humanReadableDuration; +import static com.squareup.spoon.html.HtmlUtils.*; public final class HtmlUtilsTest { @Test public void relativeUriCreation() { diff --git a/spoon-runner/src/test/java/com/squareup/spoon/misc/StackTraceTest.java b/spoon-runner/src/test/java/com/squareup/spoon/misc/StackTraceTest.java index b41ed830..98858ad1 100644 --- a/spoon-runner/src/test/java/com/squareup/spoon/misc/StackTraceTest.java +++ b/spoon-runner/src/test/java/com/squareup/spoon/misc/StackTraceTest.java @@ -1,8 +1,9 @@ package com.squareup.spoon.misc; +import org.junit.Test; + import java.util.ArrayDeque; import java.util.Deque; -import org.junit.Test; import static com.google.common.truth.Truth.assertThat; From 93ba1cd31073000deff7b78a5d15b76ca3561583 Mon Sep 17 00:00:00 2001 From: Andrei NICOLAE Date: Mon, 23 Apr 2018 12:10:29 +0300 Subject: [PATCH 3/6] Determine active and ignored tests only if necessary. --- .../com/squareup/spoon/SpoonDeviceRunner.java | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/spoon-runner/src/main/java/com/squareup/spoon/SpoonDeviceRunner.java b/spoon-runner/src/main/java/com/squareup/spoon/SpoonDeviceRunner.java index 2283eee9..2d6ebe5a 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/SpoonDeviceRunner.java +++ b/spoon-runner/src/main/java/com/squareup/spoon/SpoonDeviceRunner.java @@ -186,22 +186,6 @@ public DeviceResult run(AndroidDebugBridge adb) { // Create the output directory, if it does not already exist. work.mkdirs(); - // Determine the test set that is applicable for this device. - LogRecordingTestRunListener recorder; - List activeTests; - List ignoredTests; - try { - recorder = queryTestSet(testPackage, testRunner, device); - activeTests = recorder.activeTests(); - ignoredTests = recorder.ignoredTests(); - logDebug(debug, "Active tests: %s", activeTests); - logDebug(debug, "Ignored tests: %s", ignoredTests); - } catch (Exception e) { - return result - .addException(e) - .build(); - } - // Initiate device logging. SpoonDeviceLogger deviceLogger = new SpoonDeviceLogger(device); @@ -222,6 +206,23 @@ public DeviceResult run(AndroidDebugBridge adb) { result.addException(e); } } else { + + // Determine the test set that is applicable for this device. + LogRecordingTestRunListener recorder; + List activeTests; + List ignoredTests; + try { + recorder = queryTestSet(testPackage, testRunner, device); + activeTests = recorder.activeTests(); + ignoredTests = recorder.ignoredTests(); + logDebug(debug, "Active tests: %s", activeTests); + logDebug(debug, "Ignored tests: %s", ignoredTests); + } catch (Exception e) { + return result + .addException(e) + .build(); + } + MultiRunITestListener multiRunListener = new MultiRunITestListener(listeners); multiRunListener.multiRunStarted(recorder.runName(), recorder.testCount()); From 62a8f46ea01ac60fd6e7585c73ceaf52ec34351a Mon Sep 17 00:00:00 2001 From: Andrei NICOLAE Date: Mon, 23 Apr 2018 13:56:42 +0300 Subject: [PATCH 4/6] Add classLevelInstrumentation parameter. This parameter will be used to run tests from each class in a separate instrumentation instance. --- .../src/main/java/com/squareup/spoon/CliArgs.kt | 9 +++++++-- .../java/com/squareup/spoon/SpoonDeviceRunner.java | 14 ++++++++------ .../main/java/com/squareup/spoon/SpoonRunner.java | 14 +++++++++++--- .../src/main/java/com/squareup/spoon/main.kt | 1 + 4 files changed, 27 insertions(+), 11 deletions(-) diff --git a/spoon-runner/src/main/java/com/squareup/spoon/CliArgs.kt b/spoon-runner/src/main/java/com/squareup/spoon/CliArgs.kt index e7ca600e..39681d8c 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/CliArgs.kt +++ b/spoon-runner/src/main/java/com/squareup/spoon/CliArgs.kt @@ -77,13 +77,18 @@ internal class CliArgs(parser: ArgParser) { val singleInstrumentationCall by parser.flagging("--single-instrumentation-call", help = "Run all tests in a single instrumentation call") + val classLevelInstrumentation by parser.flagging("--class-level-instrumentation", + help = "Run each test class in a different instrumentation instance") + private fun validateInstrumentationArgs() { val isTestRunPackageLimited = instrumentationArgs?.contains("package") ?: false - val isTestRunClassLimited = instrumentationArgs?.contains("class") ?: false || className != null - || methodName != null + val isTestRunClassLimited = instrumentationArgs?.contains("class") ?: false || (className != null || methodName != null) if (isTestRunPackageLimited && isTestRunClassLimited) { throw SystemExitException("Ambiguous arguments: cannot provide both test package and test class(es)", 2) } + if (singleInstrumentationCall && classLevelInstrumentation) { + throw SystemExitException("Conflicting arguments: cannot set both single-instrumentation-call and class-level-instrumentation", 2) + } } init { diff --git a/spoon-runner/src/main/java/com/squareup/spoon/SpoonDeviceRunner.java b/spoon-runner/src/main/java/com/squareup/spoon/SpoonDeviceRunner.java index 2d6ebe5a..4e44b0dc 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/SpoonDeviceRunner.java +++ b/spoon-runner/src/main/java/com/squareup/spoon/SpoonDeviceRunner.java @@ -58,6 +58,7 @@ public final class SpoonDeviceRunner { private final SpoonInstrumentationInfo instrumentationInfo; private final boolean codeCoverage; private final boolean singleInstrumentationCall; + private final boolean classLevelInstrumentation; private final List testRunListeners; private final boolean grantAll; @@ -69,11 +70,10 @@ public final class SpoonDeviceRunner { * @param output Path to output directory. * @param serial Device to run the test on. * @param debug Whether or not debug logging is enabled. - * @param adbTimeout time in ms for longest test execution + * @param adbTimeout Time in ms for longest test execution. * @param instrumentationInfo Test apk manifest information. * @param className Test class name to run or {@code null} to run all tests. - * @param methodName Test method name to run or {@code null} to run all tests. Must also pass - * {@code className}. + * @param methodName Test method name to run or {@code null} to run all tests. Must also pass {@code className}. * @param testRunListeners Additional TestRunListener or empty list. */ SpoonDeviceRunner(File testApk, List otherApks, File output, String serial, int shardIndex, @@ -81,7 +81,8 @@ public final class SpoonDeviceRunner { SpoonInstrumentationInfo instrumentationInfo, Map instrumentationArgs, String className, String methodName, IRemoteAndroidTestRunner.TestSize testSize, List testRunListeners, boolean codeCoverage, boolean grantAll, - boolean singleInstrumentationCall) { + boolean singleInstrumentationCall, boolean classLevelInstrumentation) { + this.testApk = testApk; this.otherApks = otherApks; this.serial = serial; @@ -90,14 +91,15 @@ public final class SpoonDeviceRunner { this.debug = debug; this.noAnimations = noAnimations; this.adbTimeout = adbTimeout; - this.instrumentationArgs = ImmutableMap.copyOf(instrumentationArgs != null - ? instrumentationArgs : Collections.emptyMap()); + this.instrumentationArgs = ImmutableMap.copyOf(instrumentationArgs != null ? instrumentationArgs : Collections.emptyMap()); this.className = className; this.methodName = methodName; this.testSize = testSize; this.instrumentationInfo = instrumentationInfo; this.codeCoverage = codeCoverage; this.singleInstrumentationCall = singleInstrumentationCall; + this.classLevelInstrumentation = classLevelInstrumentation; + serial = SpoonUtils.sanitizeSerial(serial); this.work = FileUtils.getFile(output, TEMP_DIR, serial); this.junitReport = FileUtils.getFile(output, JUNIT_DIR, serial + ".xml"); diff --git a/spoon-runner/src/main/java/com/squareup/spoon/SpoonRunner.java b/spoon-runner/src/main/java/com/squareup/spoon/SpoonRunner.java index a6615678..09d9d710 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/SpoonRunner.java +++ b/spoon-runner/src/main/java/com/squareup/spoon/SpoonRunner.java @@ -58,6 +58,7 @@ public final class SpoonRunner { private File initScript; private final boolean grantAll; private final boolean singleInstrumentationCall; + private final boolean classLevelInstrumentation; private SpoonRunner(String title, File androidSdk, File testApk, List otherApks, File output, boolean debug, boolean noAnimations, Duration adbTimeout, Set serials, @@ -65,7 +66,7 @@ private SpoonRunner(String title, File androidSdk, File testApk, List othe String className, String methodName, IRemoteAndroidTestRunner.TestSize testSize, boolean allowNoDevices, List testRunListeners, boolean sequential, File initScript, boolean grantAll, boolean terminateAdb, boolean codeCoverage, - boolean singleInstrumentationCall) { + boolean singleInstrumentationCall, boolean classLevelInstrumentation) { this.title = title; this.androidSdk = androidSdk; this.otherApks = otherApks; @@ -88,6 +89,7 @@ private SpoonRunner(String title, File androidSdk, File testApk, List othe this.initScript = initScript; this.grantAll = grantAll; this.singleInstrumentationCall = singleInstrumentationCall; + this.classLevelInstrumentation = classLevelInstrumentation; if (sequential) { this.threadExecutor = Executors.newSingleThreadExecutor(); @@ -282,7 +284,7 @@ private SpoonDeviceRunner getTestRunner(String serial, int shardIndex, int numSh SpoonInstrumentationInfo testInfo) { return new SpoonDeviceRunner(testApk, otherApks, output, serial, shardIndex, numShards, debug, noAnimations, adbTimeout, testInfo, instrumentationArgs, className, methodName, testSize, - testRunListeners, codeCoverage, grantAll, singleInstrumentationCall); + testRunListeners, codeCoverage, grantAll, singleInstrumentationCall, classLevelInstrumentation); } /** Build a test suite for the specified devices and configuration. */ @@ -310,6 +312,7 @@ public static class Builder { private boolean codeCoverage; private boolean shard = false; private boolean singleInstrumentationCall = false; + private boolean classLevelInstrumentation = false; /** Identifying title for this execution. */ public Builder setTitle(String title) { @@ -451,6 +454,11 @@ public Builder setSingleInstrumentationCall(boolean singleInstrumentationCall) { return this; } + public Builder setClassLevelInstrumentation(Boolean classLevelInstrumentation) { + this.classLevelInstrumentation = classLevelInstrumentation; + return this; + } + public SpoonRunner build() { checkNotNull(androidSdk, "SDK is required."); checkArgument(androidSdk.exists(), "SDK path does not exist."); @@ -464,7 +472,7 @@ public SpoonRunner build() { return new SpoonRunner(title, androidSdk, testApk, otherApks, output, debug, noAnimations, adbTimeout, serials, skipDevices, shard, instrumentationArgs, className, methodName, testSize, allowNoDevices, testRunListeners, sequential, initScript, grantAll, - terminateAdb, codeCoverage, singleInstrumentationCall); + terminateAdb, codeCoverage, singleInstrumentationCall, classLevelInstrumentation); } } diff --git a/spoon-runner/src/main/java/com/squareup/spoon/main.kt b/spoon-runner/src/main/java/com/squareup/spoon/main.kt index e3b5c108..612ca4f2 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/main.kt +++ b/spoon-runner/src/main/java/com/squareup/spoon/main.kt @@ -31,6 +31,7 @@ fun main(vararg args: String) { setDebug(cli.debug) setCodeCoverage(cli.coverage) setSingleInstrumentationCall(cli.singleInstrumentationCall) + setClassLevelInstrumentation(cli.classLevelInstrumentation) }.build() if (!runner.run() && !cli.alwaysZero) { From 78bbf727191de70cafc1ddd3d49a20aae44c98b7 Mon Sep 17 00:00:00 2001 From: Andrei NICOLAE Date: Fri, 27 Apr 2018 17:38:51 +0300 Subject: [PATCH 5/6] Add mechanism for grouping tests by class and running them in separate instrumentations. --- .../com/squareup/spoon/SpoonDeviceRunner.java | 52 ++++++++++++++----- 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/spoon-runner/src/main/java/com/squareup/spoon/SpoonDeviceRunner.java b/spoon-runner/src/main/java/com/squareup/spoon/SpoonDeviceRunner.java index 4e44b0dc..62fca502 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/SpoonDeviceRunner.java +++ b/spoon-runner/src/main/java/com/squareup/spoon/SpoonDeviceRunner.java @@ -16,6 +16,7 @@ import java.time.Duration; import java.util.*; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; import static com.android.ddmlib.FileListingService.FileEntry; import static com.android.ddmlib.SyncService.getNullProgressMonitor; @@ -208,7 +209,6 @@ public DeviceResult run(AndroidDebugBridge adb) { result.addException(e); } } else { - // Determine the test set that is applicable for this device. LogRecordingTestRunListener recorder; List activeTests; @@ -221,25 +221,51 @@ public DeviceResult run(AndroidDebugBridge adb) { logDebug(debug, "Ignored tests: %s", ignoredTests); } catch (Exception e) { return result - .addException(e) - .build(); + .addException(e) + .build(); } MultiRunITestListener multiRunListener = new MultiRunITestListener(listeners); multiRunListener.multiRunStarted(recorder.runName(), recorder.testCount()); - for (TestIdentifier test : activeTests) { - try { - logDebug(debug, "Running %s on [%s]", test, serial); - RemoteAndroidTestRunner runner = createConfiguredRunner(testPackage, testRunner, device); - runner.removeInstrumentationArg("package"); - runner.removeInstrumentationArg("class"); - runner.setMethodName(test.getClassName(), test.getTestName()); - runner.run(listeners); - } catch (Exception e) { - result.addException(e); + if (classLevelInstrumentation) { + // Run tests from each test class in a separate instrumentation instance. + Collection groupedTests = activeTests + .stream() + .collect(Collectors.groupingBy( + TestIdentifier::getClassName, + LinkedHashMap::new, + Collectors.mapping( + testIdentifier -> testIdentifier.getClassName() + "#" + testIdentifier.getTestName(), + Collectors.joining(",")))) + .values(); + + for (String testGroup : groupedTests) { + try { + logDebug(debug, "Running %s on [%s]", testGroup, serial); + RemoteAndroidTestRunner runner = createConfiguredRunner(testPackage, testRunner, device); + runner.removeInstrumentationArg("package"); + runner.setClassName(testGroup); + runner.run(listeners); + } catch (Exception e) { + result.addException(e); + } + } + } else { + // Run every test in a separate instrumentation instance. + for (TestIdentifier test : activeTests) { + try { + logDebug(debug, "Running %s on [%s]", test, serial); + RemoteAndroidTestRunner runner = createConfiguredRunner(testPackage, testRunner, device); + runner.removeInstrumentationArg("package"); + runner.setMethodName(test.getClassName(), test.getTestName()); + runner.run(listeners); + } catch (Exception e) { + result.addException(e); + } } } + for (TestIdentifier ignoredTest : ignoredTests) { multiRunListener.testStarted(ignoredTest); multiRunListener.testIgnored(ignoredTest); From 134f70302963af55b430773fa20a7bde7bd5a21d Mon Sep 17 00:00:00 2001 From: Andrei NICOLAE Date: Fri, 27 Apr 2018 21:44:08 +0300 Subject: [PATCH 6/6] Fix code styling issues. --- .../main/java/com/squareup/spoon/CliArgs.kt | 2 +- .../java/com/squareup/spoon/DeviceResult.java | 7 +- .../spoon/LogRecordingTestRunListener.kt | 2 +- .../com/squareup/spoon/SpoonDeviceRunner.java | 74 +++++++++++++------ .../java/com/squareup/spoon/SpoonRunner.java | 17 ++++- .../java/com/squareup/spoon/SpoonSummary.java | 4 +- .../java/com/squareup/spoon/SpoonUtils.java | 5 +- .../com/squareup/spoon/html/HtmlIndex.java | 6 +- .../com/squareup/spoon/html/HtmlRenderer.java | 15 +++- .../com/squareup/spoon/html/HtmlTest.java | 6 +- .../src/main/java/com/squareup/spoon/main.kt | 2 +- .../squareup/spoon/html/HtmlUtilsTest.java | 6 +- 12 files changed, 106 insertions(+), 40 deletions(-) diff --git a/spoon-runner/src/main/java/com/squareup/spoon/CliArgs.kt b/spoon-runner/src/main/java/com/squareup/spoon/CliArgs.kt index 39681d8c..f4d2e23b 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/CliArgs.kt +++ b/spoon-runner/src/main/java/com/squareup/spoon/CliArgs.kt @@ -78,7 +78,7 @@ internal class CliArgs(parser: ArgParser) { help = "Run all tests in a single instrumentation call") val classLevelInstrumentation by parser.flagging("--class-level-instrumentation", - help = "Run each test class in a different instrumentation instance") + help = "Run each test class in a different instrumentation instance") private fun validateInstrumentationArgs() { val isTestRunPackageLimited = instrumentationArgs?.contains("package") ?: false diff --git a/spoon-runner/src/main/java/com/squareup/spoon/DeviceResult.java b/spoon-runner/src/main/java/com/squareup/spoon/DeviceResult.java index 367f7c99..012f1980 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/DeviceResult.java +++ b/spoon-runner/src/main/java/com/squareup/spoon/DeviceResult.java @@ -2,7 +2,12 @@ import com.squareup.spoon.misc.StackTrace; -import java.util.*; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; import java.util.concurrent.TimeUnit; import static com.google.common.base.Preconditions.checkArgument; diff --git a/spoon-runner/src/main/java/com/squareup/spoon/LogRecordingTestRunListener.kt b/spoon-runner/src/main/java/com/squareup/spoon/LogRecordingTestRunListener.kt index 104397c9..528579ab 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/LogRecordingTestRunListener.kt +++ b/spoon-runner/src/main/java/com/squareup/spoon/LogRecordingTestRunListener.kt @@ -3,7 +3,7 @@ package com.squareup.spoon import com.android.ddmlib.testrunner.ITestRunListener import com.android.ddmlib.testrunner.TestIdentifier import com.google.common.collect.ImmutableList -import java.util.* +import java.util.LinkedHashSet /** * Listens to an instrumentation invocation where `log=true` is set and records information about diff --git a/spoon-runner/src/main/java/com/squareup/spoon/SpoonDeviceRunner.java b/spoon-runner/src/main/java/com/squareup/spoon/SpoonDeviceRunner.java index 62fca502..ad9672f7 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/SpoonDeviceRunner.java +++ b/spoon-runner/src/main/java/com/squareup/spoon/SpoonDeviceRunner.java @@ -1,6 +1,10 @@ package com.squareup.spoon; -import com.android.ddmlib.*; +import com.android.ddmlib.AndroidDebugBridge; +import com.android.ddmlib.CollectingOutputReceiver; +import com.android.ddmlib.DdmPreferences; +import com.android.ddmlib.IDevice; +import com.android.ddmlib.InstallException; import com.android.ddmlib.logcat.LogCatMessage; import com.android.ddmlib.testrunner.IRemoteAndroidTestRunner; import com.android.ddmlib.testrunner.ITestRunListener; @@ -12,17 +16,31 @@ import org.apache.commons.io.FileUtils; import org.apache.commons.io.filefilter.TrueFileFilter; -import java.io.*; +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; import java.time.Duration; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import static com.android.ddmlib.FileListingService.FileEntry; import static com.android.ddmlib.SyncService.getNullProgressMonitor; import static com.google.common.base.Strings.isNullOrEmpty; -import static com.squareup.spoon.SpoonLogger.*; -import static com.squareup.spoon.SpoonUtils.*; +import static com.squareup.spoon.SpoonLogger.logDebug; +import static com.squareup.spoon.SpoonLogger.logError; +import static com.squareup.spoon.SpoonLogger.logInfo; +import static com.squareup.spoon.SpoonUtils.createAnimatedGif; +import static com.squareup.spoon.SpoonUtils.obtainDirectoryFileEntry; +import static com.squareup.spoon.SpoonUtils.obtainRealDevice; import static com.squareup.spoon.internal.Constants.SPOON_FILES; import static com.squareup.spoon.internal.Constants.SPOON_SCREENSHOTS; import static java.util.Collections.emptyMap; @@ -74,7 +92,8 @@ public final class SpoonDeviceRunner { * @param adbTimeout Time in ms for longest test execution. * @param instrumentationInfo Test apk manifest information. * @param className Test class name to run or {@code null} to run all tests. - * @param methodName Test method name to run or {@code null} to run all tests. Must also pass {@code className}. + * @param methodName Test method name to run or {@code null} to run all tests. + * Must also pass {@code className}. * @param testRunListeners Additional TestRunListener or empty list. */ SpoonDeviceRunner(File testApk, List otherApks, File output, String serial, int shardIndex, @@ -92,7 +111,8 @@ public final class SpoonDeviceRunner { this.debug = debug; this.noAnimations = noAnimations; this.adbTimeout = adbTimeout; - this.instrumentationArgs = ImmutableMap.copyOf(instrumentationArgs != null ? instrumentationArgs : Collections.emptyMap()); + this.instrumentationArgs = ImmutableMap.copyOf(instrumentationArgs != null + ? instrumentationArgs : Collections.emptyMap()); this.className = className; this.methodName = methodName; this.testSize = testSize; @@ -122,8 +142,6 @@ private void printStream(InputStream stream, String tag) throws IOException { /** Execute instrumentation on the target device and return a result summary. */ public DeviceResult run(AndroidDebugBridge adb) { - String testPackage = instrumentationInfo.getInstrumentationPackage(); - String testRunner = instrumentationInfo.getTestRunnerClass(); logDebug(debug, "InstrumentationInfo: [%s]", instrumentationInfo); if (debug) { @@ -189,24 +207,32 @@ public DeviceResult run(AndroidDebugBridge adb) { // Create the output directory, if it does not already exist. work.mkdirs(); + return runTests(device, result); + } + + private DeviceResult runTests(IDevice device, DeviceResult.Builder resultBuilder) { + + String testPackage = instrumentationInfo.getInstrumentationPackage(); + String testRunner = instrumentationInfo.getTestRunnerClass(); + // Initiate device logging. SpoonDeviceLogger deviceLogger = new SpoonDeviceLogger(device); List listeners = new ArrayList<>(); - listeners.add(new SpoonTestRunListener(result, debug)); + listeners.add(new SpoonTestRunListener(resultBuilder, debug)); listeners.add(new XmlTestRunListener(junitReport)); if (testRunListeners != null) { listeners.addAll(testRunListeners); } - result.startTests(); + resultBuilder.startTests(); if (singleInstrumentationCall) { try { logDebug(debug, "Running all tests in a single instrumentation call on [%s]", serial); RemoteAndroidTestRunner runner = createConfiguredRunner(testPackage, testRunner, device); runner.run(listeners); } catch (Exception e) { - result.addException(e); + resultBuilder.addException(e); } } else { // Determine the test set that is applicable for this device. @@ -220,7 +246,7 @@ public DeviceResult run(AndroidDebugBridge adb) { logDebug(debug, "Active tests: %s", activeTests); logDebug(debug, "Ignored tests: %s", ignoredTests); } catch (Exception e) { - return result + return resultBuilder .addException(e) .build(); } @@ -243,12 +269,13 @@ public DeviceResult run(AndroidDebugBridge adb) { for (String testGroup : groupedTests) { try { logDebug(debug, "Running %s on [%s]", testGroup, serial); - RemoteAndroidTestRunner runner = createConfiguredRunner(testPackage, testRunner, device); + RemoteAndroidTestRunner runner + = createConfiguredRunner(testPackage, testRunner, device); runner.removeInstrumentationArg("package"); runner.setClassName(testGroup); runner.run(listeners); } catch (Exception e) { - result.addException(e); + resultBuilder.addException(e); } } } else { @@ -256,12 +283,13 @@ public DeviceResult run(AndroidDebugBridge adb) { for (TestIdentifier test : activeTests) { try { logDebug(debug, "Running %s on [%s]", test, serial); - RemoteAndroidTestRunner runner = createConfiguredRunner(testPackage, testRunner, device); + RemoteAndroidTestRunner runner + = createConfiguredRunner(testPackage, testRunner, device); runner.removeInstrumentationArg("package"); runner.setMethodName(test.getClassName(), test.getTestName()); runner.run(listeners); } catch (Exception e) { - result.addException(e); + resultBuilder.addException(e); } } } @@ -274,9 +302,9 @@ public DeviceResult run(AndroidDebugBridge adb) { multiRunListener.multiRunEnded(); } - result.endTests(); + resultBuilder.endTests(); - mapLogsToTests(deviceLogger, result); + mapLogsToTests(deviceLogger, resultBuilder); try { logDebug(debug, "About to grab screenshots and prepare output for [%s]", serial); @@ -285,14 +313,14 @@ public DeviceResult run(AndroidDebugBridge adb) { pullCoverageFile(device); } - cleanScreenshotsDirectory(result); - cleanFilesDirectory(result); + cleanScreenshotsDirectory(resultBuilder); + cleanFilesDirectory(resultBuilder); } catch (Exception e) { - result.addException(e); + resultBuilder.addException(e); } logDebug(debug, "Done running for [%s]", serial); - return result.build(); + return resultBuilder.build(); } private void grantReadWriteExternalStorage(DeviceDetails deviceDetails, IDevice device) diff --git a/spoon-runner/src/main/java/com/squareup/spoon/SpoonRunner.java b/spoon-runner/src/main/java/com/squareup/spoon/SpoonRunner.java index 09d9d710..ae59660f 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/SpoonRunner.java +++ b/spoon-runner/src/main/java/com/squareup/spoon/SpoonRunner.java @@ -14,7 +14,12 @@ import java.io.IOException; import java.io.InputStreamReader; import java.time.Duration; -import java.util.*; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -105,7 +110,9 @@ private SpoonRunner(String title, File androidSdk, File testApk, List othe * @return {@code true} if there were no test failures or exceptions thrown. */ public boolean run() { - otherApks.forEach(otherApk -> checkArgument(otherApk.exists(), "Could not find other APK: " + otherApk)); + otherApks.forEach(otherApk -> checkArgument( + otherApk.exists(), + "Could not find other APK: " + otherApk)); checkArgument(testApk.exists(), "Could not find test APK: " + testApk); AndroidDebugBridge adb = SpoonUtils.initAdb(androidSdk, adbTimeout); @@ -159,7 +166,8 @@ private SpoonSummary runTests(AndroidDebugBridge adb, Set serials, throw new RuntimeException("Unable to clean output directory: " + output, e); } - logDebug(debug, "Instrumentation: %s from %s", testInfo.getInstrumentationPackage(), testApk.getAbsolutePath()); + logDebug(debug, "Instrumentation: %s from %s", + testInfo.getInstrumentationPackage(), testApk.getAbsolutePath()); otherApks.forEach(otherApk -> logDebug(debug, "Other: %s", otherApk.getAbsolutePath())); final SpoonSummary.Builder summary = new SpoonSummary.Builder().setTitle(title).start(); @@ -284,7 +292,8 @@ private SpoonDeviceRunner getTestRunner(String serial, int shardIndex, int numSh SpoonInstrumentationInfo testInfo) { return new SpoonDeviceRunner(testApk, otherApks, output, serial, shardIndex, numShards, debug, noAnimations, adbTimeout, testInfo, instrumentationArgs, className, methodName, testSize, - testRunListeners, codeCoverage, grantAll, singleInstrumentationCall, classLevelInstrumentation); + testRunListeners, codeCoverage, grantAll, singleInstrumentationCall, + classLevelInstrumentation); } /** Build a test suite for the specified devices and configuration. */ diff --git a/spoon-runner/src/main/java/com/squareup/spoon/SpoonSummary.java b/spoon-runner/src/main/java/com/squareup/spoon/SpoonSummary.java index 5707b09d..14e69de6 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/SpoonSummary.java +++ b/spoon-runner/src/main/java/com/squareup/spoon/SpoonSummary.java @@ -7,7 +7,9 @@ import java.util.Map; import java.util.concurrent.TimeUnit; -import static com.google.common.base.Preconditions.*; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; import static java.util.Collections.unmodifiableMap; /** Result summary of executing instrumentation on multiple devices. */ diff --git a/spoon-runner/src/main/java/com/squareup/spoon/SpoonUtils.java b/spoon-runner/src/main/java/com/squareup/spoon/SpoonUtils.java index 07cb6fff..480db441 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/SpoonUtils.java +++ b/spoon-runner/src/main/java/com/squareup/spoon/SpoonUtils.java @@ -12,7 +12,7 @@ import org.apache.commons.io.FileUtils; import javax.imageio.ImageIO; -import java.awt.*; +import java.awt.Color; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; @@ -75,7 +75,8 @@ static FileEntry obtainDirectoryFileEntry(String path) { lastEntry = c.newInstance(lastEntry, part, TYPE_DIRECTORY, lastEntry == null); } return lastEntry; - } catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException ignored) { + } catch (NoSuchMethodException | InvocationTargetException + | InstantiationException | IllegalAccessException ignored) { } return null; } diff --git a/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlIndex.java b/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlIndex.java index 5a820a8a..6e46d255 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlIndex.java +++ b/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlIndex.java @@ -1,7 +1,11 @@ package com.squareup.spoon.html; import com.android.ddmlib.testrunner.IRemoteAndroidTestRunner; -import com.squareup.spoon.*; +import com.squareup.spoon.DeviceDetails; +import com.squareup.spoon.DeviceResult; +import com.squareup.spoon.DeviceTest; +import com.squareup.spoon.DeviceTestResult; +import com.squareup.spoon.SpoonSummary; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; diff --git a/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlRenderer.java b/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlRenderer.java index 31e82d57..0cde2dfd 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlRenderer.java +++ b/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlRenderer.java @@ -6,12 +6,23 @@ import com.github.mustachejava.MustacheFactory; import com.google.common.io.Resources; import com.google.gson.Gson; -import com.squareup.spoon.*; +import com.squareup.spoon.DeviceDetails; +import com.squareup.spoon.DeviceResult; +import com.squareup.spoon.DeviceTest; +import com.squareup.spoon.DeviceTestResult; +import com.squareup.spoon.SpoonSummary; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.lesscss.LessCompiler; -import java.io.*; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; diff --git a/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlTest.java b/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlTest.java index fb79fcb9..5869533e 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlTest.java +++ b/spoon-runner/src/main/java/com/squareup/spoon/html/HtmlTest.java @@ -1,6 +1,10 @@ package com.squareup.spoon.html; -import com.squareup.spoon.*; +import com.squareup.spoon.DeviceDetails; +import com.squareup.spoon.DeviceResult; +import com.squareup.spoon.DeviceTest; +import com.squareup.spoon.DeviceTestResult; +import com.squareup.spoon.SpoonSummary; import java.io.File; import java.util.ArrayList; diff --git a/spoon-runner/src/main/java/com/squareup/spoon/main.kt b/spoon-runner/src/main/java/com/squareup/spoon/main.kt index 612ca4f2..aef35d46 100644 --- a/spoon-runner/src/main/java/com/squareup/spoon/main.kt +++ b/spoon-runner/src/main/java/com/squareup/spoon/main.kt @@ -14,7 +14,7 @@ fun main(vararg args: String) { cli.otherApks.forEach { addOtherApk(it) } cli.sdk?.let(this::setAndroidSdk) cli.title?.let(this::setTitle) - setInstrumentationArgs(cli.instrumentationArgs); + setInstrumentationArgs(cli.instrumentationArgs) cli.className?.let(this::setClassName) cli.methodName?.let(this::setMethodName) cli.size?.let(this::setTestSize) diff --git a/spoon-runner/src/test/java/com/squareup/spoon/html/HtmlUtilsTest.java b/spoon-runner/src/test/java/com/squareup/spoon/html/HtmlUtilsTest.java index 9e215adb..3b9573f5 100644 --- a/spoon-runner/src/test/java/com/squareup/spoon/html/HtmlUtilsTest.java +++ b/spoon-runner/src/test/java/com/squareup/spoon/html/HtmlUtilsTest.java @@ -1,6 +1,6 @@ package com.squareup.spoon.html; -import com.squareup.spoon.html.HtmlUtils.*; +import com.squareup.spoon.html.HtmlUtils.ExceptionInfo; import com.squareup.spoon.misc.StackTrace; import org.junit.Test; @@ -8,7 +8,9 @@ import java.util.List; import static com.google.common.truth.Truth.assertThat; -import static com.squareup.spoon.html.HtmlUtils.*; +import static com.squareup.spoon.html.HtmlUtils.createRelativeUri; +import static com.squareup.spoon.html.HtmlUtils.humanReadableDuration; +import static com.squareup.spoon.html.HtmlUtils.processStackTrace; public final class HtmlUtilsTest { @Test public void relativeUriCreation() {