Add more information when XmlTestResultParser.parse() fails.
Summary: Hopefully this will provide better insight if this fails in the wild again.
Test Plan: `XmlTestResultParserTest.testParseMalformedXml()`
diff --git a/src/com/facebook/buck/test/XmlTestResultParser.java b/src/com/facebook/buck/test/XmlTestResultParser.java
index 889d41a..666b059 100644
--- a/src/com/facebook/buck/test/XmlTestResultParser.java
+++ b/src/com/facebook/buck/test/XmlTestResultParser.java
@@ -17,21 +17,38 @@
package com.facebook.buck.test;
import com.facebook.buck.util.XmlDomParser;
+import com.google.common.base.Charsets;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
+import com.google.common.io.Files;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
import java.io.File;
import java.io.IOException;
+import java.io.StringReader;
import java.util.List;
public class XmlTestResultParser {
- public static TestCaseSummary parse(File xml) throws IOException {
- Document doc = XmlDomParser.parse(xml);
+ public static TestCaseSummary parse(File xmlFile) throws IOException {
+ String xmlFileContents = Files.toString(xmlFile, Charsets.UTF_8);
+
+ try {
+ return doParse(xmlFileContents);
+ } catch (NumberFormatException e) {
+ // This is an attempt to track down an inexplicable error that we have observed in the wild.
+ String message = createDetailedExceptionMessage(xmlFile, xmlFileContents);
+ throw new RuntimeException(message, e);
+ }
+ }
+
+ private static TestCaseSummary doParse(String xml) throws IOException {
+ Document doc = XmlDomParser.parse(new InputSource(new StringReader(xml)),
+ /* namespaceAware */ false);
Element root = doc.getDocumentElement();
Preconditions.checkState("testcase".equals(root.getTagName()));
String testCaseName = root.getAttribute("name");
@@ -84,4 +101,10 @@
return new TestCaseSummary(testCaseName, testResults);
}
+
+ private static String createDetailedExceptionMessage(File xmlFile, String xmlFileContents) {
+ String message = "Error parsing test result data in " + xmlFile.getAbsolutePath() + ".\n" +
+ "File contents:\n" + xmlFileContents;
+ return message;
+ }
}
diff --git a/test/com/facebook/buck/test/BUCK b/test/com/facebook/buck/test/BUCK
index 556e300..24e4103 100644
--- a/test/com/facebook/buck/test/BUCK
+++ b/test/com/facebook/buck/test/BUCK
@@ -2,6 +2,7 @@
name = 'test',
srcs = glob(['*Test.java']),
deps = [
+ '//lib:guava',
'//lib:junit',
'//src/com/facebook/buck/test:test',
],
diff --git a/test/com/facebook/buck/test/XmlTestResultParserTest.java b/test/com/facebook/buck/test/XmlTestResultParserTest.java
new file mode 100644
index 0000000..a6ad65f
--- /dev/null
+++ b/test/com/facebook/buck/test/XmlTestResultParserTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2013-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.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import com.google.common.base.Charsets;
+import com.google.common.io.Files;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import java.io.File;
+import java.io.IOException;
+
+public class XmlTestResultParserTest {
+
+ @Rule
+ public TemporaryFolder tmp = new TemporaryFolder();
+
+ @Test
+ public void testParseMalformedXml() throws IOException {
+ String xml =
+ "<?xml version='1.1' encoding='UTF-8' standalone='no'?>\n" +
+ "<testcase name='com.facebook.buck.test.XmlTestResultParserTest'>\n" +
+ " <test name='testParseMalformedXml' success='true' time='too meta'/>\n" +
+ "</testcase>\n";
+ File xmlFile = tmp.newFile("result.xml");
+ Files.write(xml, xmlFile, Charsets.UTF_8);
+
+ try {
+ XmlTestResultParser.parse(xmlFile);
+ fail("Should throw RuntimeException.");
+ } catch (RuntimeException e) {
+ assertTrue("The RuntimeException should wrap the NumberFormatException.",
+ e.getCause() instanceof NumberFormatException);
+
+ assertEquals(
+ "Exception should include the path to the file as well as its contents.",
+ "Error parsing test result data in " + xmlFile.getAbsolutePath() + ".\n" +
+ "File contents:\n" + xml,
+ e.getMessage());
+ }
+ }
+}