/* * Copyright 2012 the original author or authors. * * 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 org.gradle.api.internal.tasks.testing.junit.result; import org.gradle.api.Action; import org.gradle.api.UncheckedIOException; import org.gradle.api.tasks.testing.TestResult; import org.gradle.internal.UncheckedException; import org.gradle.internal.serialize.Decoder; import org.gradle.internal.serialize.Encoder; import org.gradle.internal.serialize.FlushableEncoder; import org.gradle.internal.serialize.kryo.KryoBackedDecoder; import org.gradle.internal.serialize.kryo.KryoBackedEncoder; import java.io.*; import java.util.Collection; public class TestResultSerializer { private static final int RESULT_VERSION = 3; private final File resultsFile; public TestResultSerializer(File resultsDir) { this.resultsFile = new File(resultsDir, "results.bin"); } public void write(Collection<TestClassResult> results) { try { OutputStream outputStream = new FileOutputStream(resultsFile); try { if (!results.isEmpty()) { // only write if we have results, otherwise truncate FlushableEncoder encoder = new KryoBackedEncoder(outputStream); encoder.writeSmallInt(RESULT_VERSION); write(results, encoder); encoder.flush(); } } finally { outputStream.close(); } } catch (IOException e) { throw new UncheckedIOException(e); } } private void write(Collection<TestClassResult> results, Encoder encoder) throws IOException { encoder.writeSmallInt(results.size()); for (TestClassResult result : results) { write(result, encoder); } } private void write(TestClassResult classResult, Encoder encoder) throws IOException { encoder.writeSmallLong(classResult.getId()); encoder.writeString(classResult.getClassName()); encoder.writeLong(classResult.getStartTime()); encoder.writeSmallInt(classResult.getResults().size()); for (TestMethodResult methodResult : classResult.getResults()) { write(methodResult, encoder); } } private void write(TestMethodResult methodResult, Encoder encoder) throws IOException { encoder.writeSmallLong(methodResult.getId()); encoder.writeString(methodResult.getName()); encoder.writeSmallInt(methodResult.getResultType().ordinal()); encoder.writeSmallLong(methodResult.getDuration()); encoder.writeLong(methodResult.getEndTime()); encoder.writeSmallInt(methodResult.getFailures().size()); for (TestFailure testFailure : methodResult.getFailures()) { encoder.writeString(testFailure.getExceptionType()); encoder.writeString(testFailure.getMessage()); encoder.writeString(testFailure.getStackTrace()); } } public void read(Action<? super TestClassResult> visitor) { if (!isHasResults()) { return; } try { InputStream inputStream = new FileInputStream(resultsFile); try { Decoder decoder = new KryoBackedDecoder(inputStream); int version = decoder.readSmallInt(); if (version != RESULT_VERSION) { throw new IllegalArgumentException(String.format("Unexpected result file version %d found in %s.", version, resultsFile)); } readResults(decoder, visitor); } finally { inputStream.close(); } } catch (Exception e) { throw UncheckedException.throwAsUncheckedException(e); } } public boolean isHasResults() { return resultsFile.exists() && resultsFile.length() > 0; } private void readResults(Decoder decoder, Action<? super TestClassResult> visitor) throws ClassNotFoundException, IOException { int classCount = decoder.readSmallInt(); for (int i = 0; i < classCount; i++) { TestClassResult classResult = readClassResult(decoder); visitor.execute(classResult); } } private TestClassResult readClassResult(Decoder decoder) throws IOException, ClassNotFoundException { long id = decoder.readSmallLong(); String className = decoder.readString(); long startTime = decoder.readLong(); TestClassResult result = new TestClassResult(id, className, startTime); int testMethodCount = decoder.readSmallInt(); for (int i = 0; i < testMethodCount; i++) { TestMethodResult methodResult = readMethodResult(decoder); result.add(methodResult); } return result; } private TestMethodResult readMethodResult(Decoder decoder) throws ClassNotFoundException, IOException { long id = decoder.readSmallLong(); String name = decoder.readString(); TestResult.ResultType resultType = TestResult.ResultType.values()[decoder.readSmallInt()]; long duration = decoder.readSmallLong(); long endTime = decoder.readLong(); TestMethodResult methodResult = new TestMethodResult(id, name, resultType, duration, endTime); int failures = decoder.readSmallInt(); for (int i = 0; i < failures; i++) { String exceptionType = decoder.readString(); String message = decoder.readString(); String stackTrace = decoder.readString(); methodResult.addFailure(message, stackTrace, exceptionType); } return methodResult; } }