/*******************************************************************************
* Copyright (c) 2016 Bruno Medeiros and other Contributors.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Bruno Medeiros - initial API and implementation
* Pieter Penninckx - adapted to the case of error output in the Json format
*******************************************************************************/
package com.github.rustdt.tooling;
import static melnorme.utilbox.core.Assert.AssertNamespace.assertFail;
import static melnorme.utilbox.status.Severity.ERROR;
import static melnorme.utilbox.status.Severity.INFO;
import static melnorme.utilbox.status.Severity.WARNING;
import org.junit.Test;
import melnorme.lang.tooling.common.ToolSourceMessage;
import melnorme.lang.utils.parse.StringCharSource;
import melnorme.utilbox.collections.ArrayList2;
import melnorme.utilbox.collections.Indexable;
import melnorme.utilbox.core.CommonException;
public class RustBuildOutputParserJsonTest extends CommonRustMessageParserTest {
public static class TestsRustBuildOutputParser extends RustBuildOutputParser2 {
@Override
protected void handleParseError(CommonException ce) {
assertFail();
}
}
@Test
public void test() throws Exception { test$(); }
public void test$() throws Exception {
testParseMessages("", list()); // Empty
testParseMessages(new TestsRustBuildOutputParser(),
"Compiling my_project v0.1.0 (file:///path/to/my_project)",
list()
);
testParseMessages_WithErrors("{\"message\":null}", list());
testParseMessages_WithErrors("{\"message", list());
testParseMessages(
getClassResource("simple_warning.json"),
list(msg(path("src/main.rs"), 1, 2, 3, 17, WARNING, "BLAH BLAH BLAH")));
testParseMessages(
getClassResource("error_with_children.json"),
list(msg(path("src/main.rs"), 6, 9, 6, 10, ERROR,
"mismatched types [E0308]:\n"+ // message + [Error code]
"expected type `()`\n found type `{integer}`\n" + // (message child 1, message child 2)
"expected (), found integral variable" // Label from span
))
);
testParseMessages(
getClassResource("aborting_due_to_error.json"),
list()
);
testParseMessages(
getClassResource("error_with_multiple_spans.json"),
list(
msg(path("test.rs"), 7, 15, 7, 16, INFO, // First span. Not primary, so INFO
// "cannot borrow `i` as mutable more than once at a time: " + // message
"first mutable borrow occurs here" // Label from first span
),
msg(path("test.rs"), 8, 15, 8, 16, ERROR, // Second span. Primary, so we copy the severity.
"cannot borrow `i` as mutable more than once at a time [E0499]:\n"+ // message + [error code]
"second mutable borrow occurs here" // Label from the second span.
),
msg(path("test.rs"), 9, 1, 9, 2, INFO, // Third span. Not primary, so INFO
// "cannot borrow `i` as mutable more than once at a time: " + // message
"first borrow ends here" // Label from the third span.
)
)
);
testParseMessages(
getClassResource("error_with_single_child.json"),
list(msg(path("test.rs"), 39, 2, 39, 3, ERROR, // Primary span, so copy the severity (ERROR)
"the trait bound `u8: Tr` is not satisfied [E0277]:\n"+ // message + [error code]
"required by `x`\n" + // (message from child)
"trait `u8: Tr` not satisfied" // Label of the span
)
)
);
testParseMessages(
getClassResource("main_function_not_found.json"),
list(msg(path(""), 1, 1, 1, 1, ERROR, "main function not found"))
);
// Test macro errors
String MSG_MISMATCHED_M = "mismatched types [E0308]:\n"+
"expected type `std::option::Option<&usize>`\n"+
" found type `&{integer}`";
testParseMessages(
getClassResource("macro_error.json"),
list(
msg(path(""), 5, 22, 5, 33, ERROR, MSG_MISMATCHED_M
+"\nexpected enum `std::option::Option`, found &{integer}"),
msg(path("src/test.rs"), 331, 2, 331, 33, INFO,
// "(in expansion of `assert_eq!`) "+
MSG_MISMATCHED_M
)
// msg(path(""), 1, 1, 18, 71, ERROR, MSG_MISMATCHED_M)
)
);
testParseMessages(
getClassResource("macro_error2.json"),
list(
msg(path(""), 5, 22, 5, 33, ERROR, MSG_MISMATCHED_M
+"\nexpected enum `std::option::Option`, found &{integer}"
),
msg(path("src/test.rs"), 331, 2, 331, 33, INFO,
// "(in expansion of `assert_eq!`) "+
MSG_MISMATCHED_M
)
// msg(path(""), 1, 1, 18, 71, ERROR, MSG_MISMATCHED_M)
)
);
}
protected void testParseMessages_WithErrors(String stderr, Indexable<ToolSourceMessage> expected)
throws CommonException
{
TestsRustBuildOutputParser buildProcessor = new TestsRustBuildOutputParser() {
@Override
protected void handleParseError(CommonException ce) {
}
};
testParseMessages(buildProcessor, stderr, expected);
}
protected void testParseMessages(String stderr, Indexable<ToolSourceMessage> expected) throws CommonException {
testParseMessages(new TestsRustBuildOutputParser(), stderr, expected);
}
protected void testParseMessages(
RustBuildOutputParser2 buildProcessor, String stderr, Indexable<ToolSourceMessage> expected
) throws CommonException {
buildProcessor.parseStdErr(new StringCharSource(stderr));
ArrayList2<ToolSourceMessage> buildMessages = buildProcessor.getBuildMessages();
assertEqualIndexable(buildMessages, expected);
}
@Deprecated
@Test
public void testCargoErrorMesages() throws Exception { testCargoErrorMesages$(); }
public void testCargoErrorMesages$() throws Exception {
testParseMessages(
new TestsRustBuildOutputParser(),
"Cargo.toml:17:15-18:0 expected `=`, but found `",
list(msg(path("Cargo.toml"), 17, 15, 18, 0, ERROR, "expected `=`, but found `"))
);
}
}