diff --git a/src/main/groovy/net/rdrei/android/buildtimetracker/BuildTimeTrackerPlugin.groovy b/src/main/groovy/net/rdrei/android/buildtimetracker/BuildTimeTrackerPlugin.groovy index b77cee0..1ce578e 100644 --- a/src/main/groovy/net/rdrei/android/buildtimetracker/BuildTimeTrackerPlugin.groovy +++ b/src/main/groovy/net/rdrei/android/buildtimetracker/BuildTimeTrackerPlugin.groovy @@ -3,6 +3,7 @@ package net.rdrei.android.buildtimetracker import net.rdrei.android.buildtimetracker.reporters.AbstractBuildTimeTrackerReporter import net.rdrei.android.buildtimetracker.reporters.CSVSummaryReporter import net.rdrei.android.buildtimetracker.reporters.JSONReporter +import net.rdrei.android.buildtimetracker.reporters.NetworkReporter import net.rdrei.android.buildtimetracker.reporters.SummaryReporter import net.rdrei.android.buildtimetracker.reporters.CSVReporter import org.gradle.api.NamedDomainObjectCollection @@ -12,10 +13,11 @@ import org.gradle.api.logging.Logger class BuildTimeTrackerPlugin implements Plugin { def REPORTERS = [ - summary: SummaryReporter, - csv: CSVReporter, - csvSummary: CSVSummaryReporter, - json: JSONReporter + summary : SummaryReporter, + csv : CSVReporter, + csvSummary: CSVSummaryReporter, + json : JSONReporter, + network : NetworkReporter ] Logger logger diff --git a/src/main/groovy/net/rdrei/android/buildtimetracker/reporters/HttpClient.groovy b/src/main/groovy/net/rdrei/android/buildtimetracker/reporters/HttpClient.groovy new file mode 100644 index 0000000..7df2546 --- /dev/null +++ b/src/main/groovy/net/rdrei/android/buildtimetracker/reporters/HttpClient.groovy @@ -0,0 +1,57 @@ +package net.rdrei.android.buildtimetracker.reporters + +import groovy.json.JsonBuilder + +interface HttpClient { + def openConnection(String urlString) + def closeConnection() + def send(Map data) + String read() +} + +class DefaultHttpClient implements HttpClient { + + HttpURLConnection connection + OutputStreamWriter writer + + @Override + def openConnection(String urlString) { + def url = new URL(urlString) + connection = url.openConnection() as HttpURLConnection + connection.with { + doInput = true + doOutput = true + requestMethod = "POST" + setRequestProperty("Accept", "application/json") + setRequestProperty("Content-Type", "application/json; charset=UTF-8") + } + writer = new OutputStreamWriter(connection.outputStream, "UTF-8") + } + + @Override + def send(Map data) { + writer.write(new JsonBuilder(data).toString()) + writer.close() + } + + @Override + String read() { + def bufferedReader = new BufferedReader(new InputStreamReader(connection.inputStream)) + def jsonString = new StringBuffer() + String line + + while (bufferedReader.readLine() != null) { + line = bufferedReader.readLine() + jsonString.append(line) + } + + bufferedReader.close() + + return jsonString + } + + @Override + def closeConnection() { + connection.disconnect() + } +} diff --git a/src/main/groovy/net/rdrei/android/buildtimetracker/reporters/NetworkReporter.groovy b/src/main/groovy/net/rdrei/android/buildtimetracker/reporters/NetworkReporter.groovy new file mode 100644 index 0000000..ee2075d --- /dev/null +++ b/src/main/groovy/net/rdrei/android/buildtimetracker/reporters/NetworkReporter.groovy @@ -0,0 +1,60 @@ +package net.rdrei.android.buildtimetracker.reporters + +import net.rdrei.android.buildtimetracker.Timing +import org.gradle.api.logging.Logger + +class NetworkReporter extends AbstractBuildTimeTrackerReporter { + + private HttpClient httpClient + + NetworkReporter(Map options, Logger logger, HttpClient httpClient) { + super(options, logger) + this.httpClient = httpClient + } + + NetworkReporter(Map options, Logger logger) { + this(options, logger, new DefaultHttpClient()) + } + + @Override + def run(List timings) { + String urlString = getOption("url", "") + + if (urlString == "") { + throw new ReporterConfigurationError( + ReporterConfigurationError.ErrorType.REQUIRED, + this.getClass().getSimpleName(), + "url" + ) + } + + try { + httpClient.openConnection(urlString) + + def measurements = [] + timings.eachWithIndex { it, index -> + measurements << [ + order: index, + task: it.path, + success: it.success, + did_work: it.didWork, + skipped: it.skipped, + ms: it.ms + ] + } + + def data = [ + success: timings.every { it.success }, + count: timings.size(), + measurements: measurements, + ] + + httpClient.send(data) + logger.lifecycle("Server's response: ${httpClient.read()}") + httpClient.closeConnection() + + } catch (Exception exception) { + logger.lifecycle("There was an exception... $exception") + } + } +} diff --git a/src/test/groovy/net/rdrei/android/buildtimetracker/reporters/NetworkReporterTest.groovy b/src/test/groovy/net/rdrei/android/buildtimetracker/reporters/NetworkReporterTest.groovy new file mode 100644 index 0000000..4bef21b --- /dev/null +++ b/src/test/groovy/net/rdrei/android/buildtimetracker/reporters/NetworkReporterTest.groovy @@ -0,0 +1,90 @@ +package net.rdrei.android.buildtimetracker.reporters + +import groovy.mock.interceptor.MockFor +import net.rdrei.android.buildtimetracker.Timing +import org.gradle.api.logging.Logger +import org.junit.Test + +import static org.junit.Assert.assertEquals +import static org.junit.Assert.assertNotNull + +class NetworkReporterTest { + + @Test + void writeJsonToOutStream() { + def mockLogger = new MockFor(Logger) + mockLogger.demand.lifecycle(1) {} + + def testHttpClient = new TestHttpClient() + NetworkReporter reporter = new NetworkReporter([url: "www.some-url.com"], mockLogger.proxyInstance(), testHttpClient) + + reporter.run([ + new Timing(100, "task1", true, false, true), + new Timing(200, "task2", false, true, false) + ]) + + def expectedData = [ + success : false, + count : 2, + measurements: [ + [ + order : 0, + task : "task1", + success : true, + did_work: false, + skipped : true, + ms : 100 + ], + [ + order : 1, + task : "task2", + success : false, + did_work: true, + skipped : false, + ms : 200 + ] + ], + ] + + assert testHttpClient.data == expectedData + } + + @Test + void testThrowsErrorWhenWithNoUrl() { + def mockLogger = new MockFor(Logger) + NetworkReporter reporter = new NetworkReporter([:], mockLogger.proxyInstance()) + + def error = null + try { + reporter.run([]) + } catch (ReporterConfigurationError e) { + error = e + } + + assertNotNull error + assertEquals ReporterConfigurationError.ErrorType.REQUIRED, error.errorType + assertEquals "url", error.optionName + } +} + + +class TestHttpClient implements HttpClient { + + Map data = new HashMap() + + @Override + def openConnection(String urlString) {} + + @Override + def closeConnection() {} + + @Override + def send(Map data) { + this.data = data + } + + @Override + String read() { + return "" + } +}