summaryrefslogtreecommitdiff
path: root/tests/src/run.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tests/src/run.rs')
-rw-r--r--tests/src/run.rs74
1 files changed, 42 insertions, 32 deletions
diff --git a/tests/src/run.rs b/tests/src/run.rs
index 4d08362c..a34e38db 100644
--- a/tests/src/run.rs
+++ b/tests/src/run.rs
@@ -10,10 +10,11 @@ use typst::layout::{Abs, Frame, FrameItem, PagedDocument, Transform};
use typst::visualize::Color;
use typst::{Document, WorldExt};
use typst_pdf::PdfOptions;
+use typst_syntax::FileId;
use crate::collect::{Attr, FileSize, NoteKind, Test};
use crate::logger::TestResult;
-use crate::world::TestWorld;
+use crate::world::{system_path, TestWorld};
/// Runs a single test.
///
@@ -117,7 +118,7 @@ impl<'a> Runner<'a> {
if seen {
continue;
}
- let note_range = self.format_range(&note.range);
+ let note_range = self.format_range(note.file, &note.range);
if first {
log!(self, "not emitted");
first = false;
@@ -208,10 +209,6 @@ impl<'a> Runner<'a> {
/// Compare a subset of notes with a given kind against diagnostics of
/// that same kind.
fn check_diagnostic(&mut self, kind: NoteKind, diag: &SourceDiagnostic) {
- // Ignore diagnostics from other sources than the test file itself.
- if diag.span.id().is_some_and(|id| id != self.test.source.id()) {
- return;
- }
// TODO: remove this once HTML export is stable
if diag.message == "html export is under active development and incomplete" {
return;
@@ -219,11 +216,11 @@ impl<'a> Runner<'a> {
let message = diag.message.replace("\\", "/");
let range = self.world.range(diag.span);
- self.validate_note(kind, range.clone(), &message);
+ self.validate_note(kind, diag.span.id(), range.clone(), &message);
// Check hints.
for hint in &diag.hints {
- self.validate_note(NoteKind::Hint, range.clone(), hint);
+ self.validate_note(NoteKind::Hint, diag.span.id(), range.clone(), hint);
}
}
@@ -235,15 +232,18 @@ impl<'a> Runner<'a> {
fn validate_note(
&mut self,
kind: NoteKind,
+ file: Option<FileId>,
range: Option<Range<usize>>,
message: &str,
) {
// Try to find perfect match.
+ let file = file.unwrap_or(self.test.source.id());
if let Some((i, _)) = self.test.notes.iter().enumerate().find(|&(i, note)| {
!self.seen[i]
&& note.kind == kind
&& note.range == range
&& note.message == message
+ && note.file == file
}) {
self.seen[i] = true;
return;
@@ -257,7 +257,7 @@ impl<'a> Runner<'a> {
&& (note.range == range || note.message == message)
}) else {
// Not even a close match, diagnostic is not annotated.
- let diag_range = self.format_range(&range);
+ let diag_range = self.format_range(file, &range);
log!(into: self.not_annotated, " {kind}: {diag_range} {}", message);
return;
};
@@ -267,10 +267,10 @@ impl<'a> Runner<'a> {
// Range is wrong.
if range != note.range {
- let note_range = self.format_range(&note.range);
- let note_text = self.text_for_range(&note.range);
- let diag_range = self.format_range(&range);
- let diag_text = self.text_for_range(&range);
+ let note_range = self.format_range(note.file, &note.range);
+ let note_text = self.text_for_range(note.file, &note.range);
+ let diag_range = self.format_range(file, &range);
+ let diag_text = self.text_for_range(file, &range);
log!(self, "mismatched range ({}):", note.pos);
log!(self, " message | {}", note.message);
log!(self, " annotated | {note_range:<9} | {note_text}");
@@ -286,39 +286,49 @@ impl<'a> Runner<'a> {
}
/// Display the text for a range.
- fn text_for_range(&self, range: &Option<Range<usize>>) -> String {
+ fn text_for_range(&self, file: FileId, range: &Option<Range<usize>>) -> String {
let Some(range) = range else { return "No text".into() };
if range.is_empty() {
- "(empty)".into()
- } else {
- format!("`{}`", self.test.source.text()[range.clone()].replace('\n', "\\n"))
+ return "(empty)".into();
}
+
+ let lines = self.world.lookup(file);
+ lines.text()[range.clone()].replace('\n', "\\n").replace('\r', "\\r")
}
/// Display a byte range as a line:column range.
- fn format_range(&self, range: &Option<Range<usize>>) -> String {
+ fn format_range(&self, file: FileId, range: &Option<Range<usize>>) -> String {
let Some(range) = range else { return "No range".into() };
+
+ let mut preamble = String::new();
+ if file != self.test.source.id() {
+ preamble = format!("\"{}\" ", system_path(file).unwrap().display());
+ }
+
if range.start == range.end {
- self.format_pos(range.start)
+ format!("{preamble}{}", self.format_pos(file, range.start))
} else {
- format!("{}-{}", self.format_pos(range.start,), self.format_pos(range.end,))
+ format!(
+ "{preamble}{}-{}",
+ self.format_pos(file, range.start),
+ self.format_pos(file, range.end)
+ )
}
}
/// Display a position as a line:column pair.
- fn format_pos(&self, pos: usize) -> String {
- if let (Some(line_idx), Some(column_idx)) =
- (self.test.source.byte_to_line(pos), self.test.source.byte_to_column(pos))
- {
- let line = self.test.pos.line + line_idx;
- let column = column_idx + 1;
- if line == 1 {
- format!("{column}")
- } else {
- format!("{line}:{column}")
- }
+ fn format_pos(&self, file: FileId, pos: usize) -> String {
+ let lines = self.world.lookup(file);
+
+ let res = lines.byte_to_line_column(pos).map(|(line, col)| (line + 1, col + 1));
+ let Some((line, col)) = res else {
+ return "oob".into();
+ };
+
+ if line == 1 {
+ format!("{col}")
} else {
- "oob".into()
+ format!("{line}:{col}")
}
}
}