Created
January 30, 2017 10:05
-
-
Save sleekweasel/e8fb0317ed35fa1eab9b2c0ac7806509 to your computer and use it in GitHub Desktop.
~/git/calabash-android (master)$ git show 0acc0d1d98e485336c3a37b599a8b052063e85a4 > patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
commit 0acc0d1d98e485336c3a37b599a8b052063e85a4 | |
Author: Tim Baverstock <tim.baverstock@corp.badoo.com> | |
Date: Fri May 29 18:18:36 2015 +0100 | |
Retrieve Jacoco coverage | |
diff --git a/ruby-gem/lib/calabash-android/helpers.rb b/ruby-gem/lib/calabash-android/helpers.rb | |
index c94c768..485aa31 100755 | |
--- a/ruby-gem/lib/calabash-android/helpers.rb | |
+++ b/ruby-gem/lib/calabash-android/helpers.rb | |
@@ -3,7 +3,7 @@ require 'zip' | |
require 'tempfile' | |
require 'escape' | |
require 'rbconfig' | |
-require 'calabash-android/java_keystore' | |
+require_relative 'java_keystore' | |
def package_name(app) | |
unless File.exist?(app) | |
diff --git a/ruby-gem/lib/calabash-android/operations.rb b/ruby-gem/lib/calabash-android/operations.rb | |
index 753b613..c92bc26 100644 | |
--- a/ruby-gem/lib/calabash-android/operations.rb | |
+++ b/ruby-gem/lib/calabash-android/operations.rb | |
@@ -121,6 +121,10 @@ module Calabash module Android | |
default_device.clear_app_data | |
end | |
+ def collect_coverage_data | |
+ default_device.collect_coverage_data | |
+ end | |
+ | |
def pull(remote, local) | |
default_device.pull(remote, local) | |
end | |
@@ -569,6 +573,7 @@ module Calabash module Android | |
end | |
def clear_app_data | |
+ collect_coverage_data | |
cmd = "#{adb_command} shell am instrument #{package_name(@test_server_path)}/sh.calaba.instrumentationbackend.ClearAppData" | |
raise "Could not clear data" unless system(cmd) | |
end | |
@@ -666,8 +671,30 @@ module Calabash module Android | |
log("Client and server versions match (client: #{client_version}, server: #{server_version}). Proceeding...") | |
end | |
+ def collect_coverage_data | |
+ coverage_dir = ENV['COVERAGE_DIR'] | |
+ return unless coverage_dir && !coverage_dir.empty? | |
+ begin | |
+ res = http('/coverage') | |
+ if res && !res.empty? | |
+ i = 0 | |
+ i += 1 while File.exist?((path = coverage_filename(coverage_dir, i))) | |
+ File.open(path, 'wb') { |f| f.write res } | |
+ end | |
+ rescue StandardError => e | |
+ # Not sure how important failure is here: some folks collect coverage routinely, | |
+ # but only check it periodically. | |
+ log("Failed to retrieve coverage: #{e}") | |
+ end | |
+ end | |
+ | |
+ def coverage_filename(coverage_dir, i) | |
+ File.join(coverage_dir, "coverage.#{serial}.#{i}.ec".gsub(/[^\w.-]/, '_')) | |
+ end | |
+ | |
def shutdown_test_server | |
begin | |
+ collect_coverage_data | |
http("/kill") | |
Timeout::timeout(3) do | |
sleep 0.3 while app_running? | |
diff --git a/ruby-gem/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/HttpServer.java b/ruby-gem/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/HttpServer.java | |
index 3c76cbb..574729f 100644 | |
--- a/ruby-gem/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/HttpServer.java | |
+++ b/ruby-gem/test-server/instrumentation-backend/src/sh/calaba/instrumentationbackend/actions/HttpServer.java | |
@@ -9,6 +9,8 @@ import java.io.StringWriter; | |
import java.lang.InterruptedException; | |
import java.lang.Override; | |
import java.lang.Runnable; | |
+import java.lang.reflect.InvocationTargetException; | |
+import java.lang.reflect.Method; | |
import java.util.ArrayList; | |
import java.util.Collections; | |
import java.util.Enumeration; | |
@@ -53,11 +55,11 @@ public class HttpServer extends NanoHTTPD { | |
private final Condition shutdownCondition = lock.newCondition(); | |
private static HttpServer instance; | |
- | |
+ | |
/** | |
* Creates and returns the singleton instance for HttpServer. | |
- * | |
+ * | |
* Can only be called once. Otherwise, you'll get an IllegalStateException. | |
*/ | |
public synchronized static HttpServer instantiate(int testServerPort) { | |
@@ -96,39 +98,39 @@ public class HttpServer extends NanoHTTPD { | |
else if (uri.endsWith("/dump")) { | |
FranklyResult errorResult = null; | |
try { | |
- | |
- | |
+ | |
+ | |
String json = params.getProperty("json"); | |
- | |
- | |
+ | |
+ | |
if (json == null) | |
- { | |
+ { | |
Map<?,?> dumpTree = new ViewDump().dumpWithoutElements(); | |
return new NanoHTTPD.Response(HTTP_OK, "application/json;charset=utf-8", JSONUtils.asJson(dumpTree)); | |
} | |
- else | |
+ else | |
{ | |
ObjectMapper mapper = new ObjectMapper(); | |
Map dumpSpec = mapper.readValue(json, Map.class); | |
- | |
+ | |
List<Integer> path = (List<Integer>) dumpSpec.get("path"); | |
if (path == null) | |
{ | |
Map<?,?> dumpTree = new ViewDump().dumpWithoutElements(); | |
- return new NanoHTTPD.Response(HTTP_OK, "application/json;charset=utf-8", JSONUtils.asJson(dumpTree)); | |
+ return new NanoHTTPD.Response(HTTP_OK, "application/json;charset=utf-8", JSONUtils.asJson(dumpTree)); | |
} | |
Map<?,?> dumpTree = new ViewDump().dumpPathWithoutElements(path); | |
if (dumpTree == null) { | |
- return new NanoHTTPD.Response(HTTP_NOTFOUND, "application/json;charset=utf-8", "{}"); | |
+ return new NanoHTTPD.Response(HTTP_NOTFOUND, "application/json;charset=utf-8", "{}"); | |
} | |
else { | |
- return new NanoHTTPD.Response(HTTP_OK, "application/json;charset=utf-8", JSONUtils.asJson(dumpTree)); | |
+ return new NanoHTTPD.Response(HTTP_OK, "application/json;charset=utf-8", JSONUtils.asJson(dumpTree)); | |
} | |
- | |
- | |
+ | |
+ | |
} | |
- | |
+ | |
} catch (Exception e ) { | |
e.printStackTrace(); | |
errorResult = FranklyResult.fromThrowable(e); | |
@@ -212,7 +214,7 @@ public class HttpServer extends NanoHTTPD { | |
String commandString = params.getProperty("json"); | |
ObjectMapper mapper = new ObjectMapper(); | |
Map command = mapper.readValue(commandString, Map.class); | |
- | |
+ | |
String uiQuery = (String) command.get("query"); | |
uiQuery = uiQuery.trim(); | |
Map op = (Map) command.get("operation"); | |
@@ -348,8 +350,29 @@ public class HttpServer extends NanoHTTPD { | |
} else if (uri.endsWith("/ready")) { | |
return new Response(HTTP_OK, MIME_HTML, Boolean.toString(ready)); | |
- | |
- } else if (uri.endsWith("/screenshot")) { | |
+ } else if (uri.endsWith("/coverage")) { | |
+ try { | |
+ // Use reflection like Android InstrumentationTestRunner for now. | |
+ ClassLoader classLoader = InstrumentationBackend.instrumentation.getTargetContext().getClassLoader(); | |
+ Class<?> RTClass = classLoader.loadClass("org.jacoco.agent.rt.RT"); | |
+ Method getAgentMethod = RTClass.getMethod("getAgent"); | |
+ Object agent = getAgentMethod.invoke(null); | |
+ Class<?> IAgentClass = classLoader.loadClass("org.jacoco.agent.rt.IAgent"); | |
+ Method dumpCoverageMethod = IAgentClass.getMethod("getExecutionData", boolean.class); | |
+ byte[] executionData = (byte[])dumpCoverageMethod.invoke(agent, true); | |
+ return new NanoHTTPD.Response(HTTP_OK, "application/data", | |
+ new ByteArrayInputStream(executionData)); | |
+ } | |
+ catch (Exception e) { | |
+ StringWriter sw = new StringWriter(); | |
+ PrintWriter pw = new PrintWriter(sw); | |
+ e.printStackTrace(pw); | |
+ System.out.println(sw.toString()); | |
+ return new NanoHTTPD.Response(HTTP_INTERNALERROR, null, | |
+ sw.toString()); | |
+ } | |
+ } | |
+ else if (uri.endsWith("/screenshot")) { | |
try { | |
Bitmap bitmap; | |
View rootView = getRootView(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment