/*
* Copyright 2015-present Facebook, Inc.
*
* 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 com.facebook.buck.apple;
import static org.hamcrest.Matchers.closeTo;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertThat;
import com.facebook.buck.test.TestStatusMessage;
import com.facebook.buck.testutil.integration.TestDataHelper;
import java.io.Reader;
import java.io.StringReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.logging.Level;
import org.junit.Test;
public class XctoolOutputParsingTest {
private static final double EPSILON = 1e-6;
private static XctoolOutputParsing.XctoolEventCallback eventCallbackAddingEventsToList(
final List<Object> streamedObjects) {
return new XctoolOutputParsing.XctoolEventCallback() {
@Override
public void handleBeginOcunitEvent(XctoolOutputParsing.BeginOcunitEvent event) {
streamedObjects.add(event);
}
@Override
public void handleEndOcunitEvent(XctoolOutputParsing.EndOcunitEvent event) {
streamedObjects.add(event);
}
@Override
public void handleBeginTestSuiteEvent(XctoolOutputParsing.BeginTestSuiteEvent event) {
streamedObjects.add(event);
}
@Override
public void handleEndTestSuiteEvent(XctoolOutputParsing.EndTestSuiteEvent event) {
streamedObjects.add(event);
}
@Override
public void handleBeginStatusEvent(XctoolOutputParsing.StatusEvent event) {
streamedObjects.add(event);
}
@Override
public void handleEndStatusEvent(XctoolOutputParsing.StatusEvent event) {
streamedObjects.add(event);
}
@Override
public void handleBeginTestEvent(XctoolOutputParsing.BeginTestEvent event) {
streamedObjects.add(event);
}
@Override
public void handleEndTestEvent(XctoolOutputParsing.EndTestEvent event) {
streamedObjects.add(event);
}
};
}
@Test
public void streamingSimpleSuccess() throws Exception {
Path jsonPath =
TestDataHelper.getTestDataDirectory(this).resolve("xctool-output/simple-success.json");
final List<Object> streamedObjects = new ArrayList<>();
try (Reader jsonReader = Files.newBufferedReader(jsonPath, StandardCharsets.UTF_8)) {
XctoolOutputParsing.streamOutputFromReader(
jsonReader, eventCallbackAddingEventsToList(streamedObjects));
}
assertThat(streamedObjects, hasSize(8));
Iterator<Object> iter = streamedObjects.iterator();
Object nextStreamedObject;
nextStreamedObject = iter.next();
assertThat(nextStreamedObject, instanceOf(XctoolOutputParsing.StatusEvent.class));
XctoolOutputParsing.StatusEvent beginStatusEvent =
(XctoolOutputParsing.StatusEvent) nextStreamedObject;
assertThat(beginStatusEvent.timestamp, closeTo(1432065853.406129, EPSILON));
assertThat(beginStatusEvent.message, equalTo("Collecting info for testables..."));
assertThat(beginStatusEvent.level, equalTo("Info"));
nextStreamedObject = iter.next();
assertThat(nextStreamedObject, instanceOf(XctoolOutputParsing.StatusEvent.class));
XctoolOutputParsing.StatusEvent endStatusEvent =
(XctoolOutputParsing.StatusEvent) nextStreamedObject;
assertThat(endStatusEvent.timestamp, closeTo(1432065854.077704, EPSILON));
assertThat(endStatusEvent.message, equalTo("Collecting info for testables..."));
assertThat(endStatusEvent.level, equalTo("Info"));
nextStreamedObject = iter.next();
assertThat(nextStreamedObject, instanceOf(XctoolOutputParsing.BeginOcunitEvent.class));
XctoolOutputParsing.BeginOcunitEvent beginOcunitEvent =
(XctoolOutputParsing.BeginOcunitEvent) nextStreamedObject;
assertThat(beginOcunitEvent.timestamp, closeTo(1432065854.07812, EPSILON));
nextStreamedObject = iter.next();
assertThat(nextStreamedObject, instanceOf(XctoolOutputParsing.BeginTestSuiteEvent.class));
XctoolOutputParsing.BeginTestSuiteEvent beginTestSuiteEvent =
(XctoolOutputParsing.BeginTestSuiteEvent) nextStreamedObject;
assertThat(beginTestSuiteEvent.timestamp, closeTo(1432065854.736793, EPSILON));
assertThat(beginTestSuiteEvent.suite, equalTo("Toplevel Test Suite"));
nextStreamedObject = iter.next();
assertThat(nextStreamedObject, instanceOf(XctoolOutputParsing.BeginTestEvent.class));
XctoolOutputParsing.BeginTestEvent beginTestEvent =
(XctoolOutputParsing.BeginTestEvent) nextStreamedObject;
assertThat(beginTestEvent.timestamp, closeTo(1432065854.739917, EPSILON));
assertThat(beginTestEvent.test, equalTo("-[FooXCTest testTwoPlusTwoEqualsFour]"));
assertThat(beginTestEvent.className, equalTo("FooXCTest"));
assertThat(beginTestEvent.methodName, equalTo("testTwoPlusTwoEqualsFour"));
nextStreamedObject = iter.next();
assertThat(nextStreamedObject, instanceOf(XctoolOutputParsing.EndTestEvent.class));
XctoolOutputParsing.EndTestEvent endTestEvent =
(XctoolOutputParsing.EndTestEvent) nextStreamedObject;
assertThat(endTestEvent.timestamp, closeTo(1432065854.740184, EPSILON));
assertThat(endTestEvent.test, equalTo("-[FooXCTest testTwoPlusTwoEqualsFour]"));
assertThat(endTestEvent.className, equalTo("FooXCTest"));
assertThat(endTestEvent.methodName, equalTo("testTwoPlusTwoEqualsFour"));
assertThat(endTestEvent.succeeded, is(true));
assertThat(endTestEvent.exceptions, empty());
assertThat(endTestEvent.totalDuration, closeTo(0.003052949905395508, EPSILON));
nextStreamedObject = iter.next();
assertThat(nextStreamedObject, instanceOf(XctoolOutputParsing.EndTestSuiteEvent.class));
XctoolOutputParsing.EndTestSuiteEvent endTestSuiteEvent =
(XctoolOutputParsing.EndTestSuiteEvent) nextStreamedObject;
assertThat(endTestSuiteEvent.timestamp, closeTo(1432065854.740343, EPSILON));
assertThat(endTestSuiteEvent.suite, equalTo("Toplevel Test Suite"));
assertThat(endTestSuiteEvent.testCaseCount, equalTo(1));
assertThat(endTestSuiteEvent.totalFailureCount, equalTo(0));
assertThat(endTestSuiteEvent.unexpectedExceptionCount, equalTo(0));
assertThat(endTestSuiteEvent.totalDuration, closeTo(0.003550052642822266, EPSILON));
nextStreamedObject = iter.next();
assertThat(nextStreamedObject, instanceOf(XctoolOutputParsing.EndOcunitEvent.class));
XctoolOutputParsing.EndOcunitEvent endOcunitEvent =
(XctoolOutputParsing.EndOcunitEvent) nextStreamedObject;
assertThat(endOcunitEvent.timestamp, closeTo(1432065854.806839, EPSILON));
assertThat(endOcunitEvent.message, nullValue(String.class));
assertThat(endOcunitEvent.succeeded, is(true));
}
@Test
public void streamingSimpleFailure() throws Exception {
Path jsonPath =
TestDataHelper.getTestDataDirectory(this).resolve("xctool-output/simple-failure.json");
final List<Object> streamedObjects = new ArrayList<>();
try (Reader jsonReader = Files.newBufferedReader(jsonPath, StandardCharsets.UTF_8)) {
XctoolOutputParsing.streamOutputFromReader(
jsonReader, eventCallbackAddingEventsToList(streamedObjects));
}
assertThat(streamedObjects, hasSize(8));
Iterator<Object> iter = streamedObjects.iterator();
Object nextStreamedObject;
nextStreamedObject = iter.next();
assertThat(nextStreamedObject, instanceOf(XctoolOutputParsing.StatusEvent.class));
XctoolOutputParsing.StatusEvent beginStatusEvent =
(XctoolOutputParsing.StatusEvent) nextStreamedObject;
assertThat(beginStatusEvent.timestamp, closeTo(1432065858.258645, EPSILON));
assertThat(beginStatusEvent.message, equalTo("Collecting info for testables..."));
assertThat(beginStatusEvent.level, equalTo("Info"));
nextStreamedObject = iter.next();
assertThat(nextStreamedObject, instanceOf(XctoolOutputParsing.StatusEvent.class));
XctoolOutputParsing.StatusEvent endStatusEvent =
(XctoolOutputParsing.StatusEvent) nextStreamedObject;
assertThat(endStatusEvent.timestamp, closeTo(1432065859.00568, EPSILON));
assertThat(endStatusEvent.message, equalTo("Collecting info for testables..."));
assertThat(endStatusEvent.level, equalTo("Info"));
nextStreamedObject = iter.next();
assertThat(nextStreamedObject, instanceOf(XctoolOutputParsing.BeginOcunitEvent.class));
XctoolOutputParsing.BeginOcunitEvent beginOcunitEvent =
(XctoolOutputParsing.BeginOcunitEvent) nextStreamedObject;
assertThat(beginOcunitEvent.timestamp, closeTo(1432065859.006029, EPSILON));
nextStreamedObject = iter.next();
assertThat(nextStreamedObject, instanceOf(XctoolOutputParsing.BeginTestSuiteEvent.class));
XctoolOutputParsing.BeginTestSuiteEvent beginTestSuiteEvent =
(XctoolOutputParsing.BeginTestSuiteEvent) nextStreamedObject;
assertThat(beginTestSuiteEvent.timestamp, closeTo(1432065859.681727, EPSILON));
assertThat(beginTestSuiteEvent.suite, equalTo("Toplevel Test Suite"));
nextStreamedObject = iter.next();
assertThat(nextStreamedObject, instanceOf(XctoolOutputParsing.BeginTestEvent.class));
XctoolOutputParsing.BeginTestEvent beginTestEvent =
(XctoolOutputParsing.BeginTestEvent) nextStreamedObject;
assertThat(beginTestEvent.timestamp, closeTo(1432065859.684965, EPSILON));
assertThat(beginTestEvent.test, equalTo("-[FooXCTest testTwoPlusTwoEqualsFive]"));
assertThat(beginTestEvent.className, equalTo("FooXCTest"));
assertThat(beginTestEvent.methodName, equalTo("testTwoPlusTwoEqualsFive"));
nextStreamedObject = iter.next();
assertThat(nextStreamedObject, instanceOf(XctoolOutputParsing.EndTestEvent.class));
XctoolOutputParsing.EndTestEvent endTestEvent =
(XctoolOutputParsing.EndTestEvent) nextStreamedObject;
assertThat(endTestEvent.timestamp, closeTo(1432065859.685524, EPSILON));
assertThat(endTestEvent.totalDuration, closeTo(0.003522038459777832, EPSILON));
assertThat(endTestEvent.test, equalTo("-[FooXCTest testTwoPlusTwoEqualsFive]"));
assertThat(endTestEvent.className, equalTo("FooXCTest"));
assertThat(endTestEvent.methodName, equalTo("testTwoPlusTwoEqualsFive"));
assertThat(endTestEvent.succeeded, is(false));
assertThat(endTestEvent.exceptions, hasSize(1));
nextStreamedObject = iter.next();
XctoolOutputParsing.TestException testException = endTestEvent.exceptions.get(0);
assertThat(testException.lineNumber, equalTo(9));
assertThat(testException.filePathInProject, equalTo("FooXCTest.m"));
assertThat(
testException.reason,
equalTo(
"((2 + 2) equal to (5)) failed: (\"4\") is not equal to (\"5\") - Two plus two "
+ "equals five"));
assertThat(nextStreamedObject, instanceOf(XctoolOutputParsing.EndTestSuiteEvent.class));
XctoolOutputParsing.EndTestSuiteEvent endTestSuiteEvent =
(XctoolOutputParsing.EndTestSuiteEvent) nextStreamedObject;
assertThat(endTestSuiteEvent.timestamp, closeTo(1432065859.685689, EPSILON));
assertThat(endTestSuiteEvent.suite, equalTo("Toplevel Test Suite"));
assertThat(endTestSuiteEvent.testCaseCount, equalTo(1));
assertThat(endTestSuiteEvent.totalFailureCount, equalTo(1));
assertThat(endTestSuiteEvent.unexpectedExceptionCount, equalTo(0));
assertThat(endTestSuiteEvent.totalDuration, closeTo(0.003962039947509766, EPSILON));
nextStreamedObject = iter.next();
assertThat(nextStreamedObject, instanceOf(XctoolOutputParsing.EndOcunitEvent.class));
XctoolOutputParsing.EndOcunitEvent endOcunitEvent =
(XctoolOutputParsing.EndOcunitEvent) nextStreamedObject;
assertThat(endOcunitEvent.timestamp, closeTo(1432065859.751992, EPSILON));
assertThat(endOcunitEvent.message, nullValue(String.class));
assertThat(endOcunitEvent.succeeded, is(false));
}
@Test
public void streamingEmptyReaderDoesNotCauseFailure() {
final List<Object> streamedObjects = new ArrayList<>();
XctoolOutputParsing.streamOutputFromReader(
new StringReader(""), eventCallbackAddingEventsToList(streamedObjects));
assertThat(streamedObjects, is(empty()));
}
@Test
public void validEventParsesToStatusMessage() {
XctoolOutputParsing.StatusEvent statusEvent = new XctoolOutputParsing.StatusEvent();
statusEvent.message = "Hello world";
statusEvent.level = "Info";
statusEvent.timestamp = 123.456;
Optional<TestStatusMessage> testStatusMessage =
XctoolOutputParsing.testStatusMessageForStatusEvent(statusEvent);
assertThat(
testStatusMessage,
equalTo(Optional.of(TestStatusMessage.of("Hello world", Level.INFO, 123456L))));
}
@Test
public void invalidEventLevelParsesToAbsent() {
XctoolOutputParsing.StatusEvent statusEvent = new XctoolOutputParsing.StatusEvent();
statusEvent.message = "Hello world";
statusEvent.level = "BALEETED";
statusEvent.timestamp = 123.456;
Optional<TestStatusMessage> testStatusMessage =
XctoolOutputParsing.testStatusMessageForStatusEvent(statusEvent);
assertThat(testStatusMessage, equalTo(Optional.empty()));
}
@Test
public void invalidEventMessageParsesToAbsent() {
XctoolOutputParsing.StatusEvent statusEvent = new XctoolOutputParsing.StatusEvent();
statusEvent.message = null;
statusEvent.level = "Info";
statusEvent.timestamp = 123.456;
Optional<TestStatusMessage> testStatusMessage =
XctoolOutputParsing.testStatusMessageForStatusEvent(statusEvent);
assertThat(testStatusMessage, equalTo(Optional.empty()));
}
}