Skip to content

Commit 1520823

Browse files
authored
Merge pull request #1180 from CraftSpider/better-tests
Improve testing infrastructure
2 parents da5d190 + 1f0fdc2 commit 1520823

File tree

6 files changed

+238
-66
lines changed

6 files changed

+238
-66
lines changed

dist/azure-generic-build.yml

+16
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,22 @@ steps:
6262
- ${{ if parameters.testIt }}:
6363
- bash: cargo test --all --target $TARGET --release $CARGO_FEATURES_FLAGS --features="$CARGO_FEATURES_EXPLICIT"
6464
displayName: cargo test
65+
- bash: |
66+
artifact_dir="$(Build.ArtifactStagingDirectory)/test_failures"
67+
mkdir -p "$artifact_dir"
68+
mv *.observed "$artifact_dir"
69+
mv *.expected "$artifact_dir"
70+
if [ -n "$(ls -A $artifact_dir)" ]; then
71+
echo "##vso[task.setvariable variable=TEST_FAILURE_ARTIFACTS;]true"
72+
fi
73+
displayName: Package test failure files
74+
condition: failed()
75+
- task: PublishPipelineArtifact@1
76+
displayName: Publish packaged test failures
77+
condition: eq(variables['TEST_FAILURE_ARTIFACTS'], true)
78+
inputs:
79+
targetPath: '$(Build.ArtifactStagingDirectory)/test_failures'
80+
artifactName: test-failures-$(TARGET)
6581

6682
# For non-canary builds, export artifacts.
6783

src/errors.rs

+85
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,23 @@ pub trait DefinitelySame {
201201
// }
202202
//}
203203

204+
impl DefinitelySame for Error {
205+
fn definitely_same(&self, other: &Self) -> bool {
206+
if !self.0.definitely_same(&other.0) {
207+
return false;
208+
}
209+
self.1.definitely_same(&other.1)
210+
}
211+
}
212+
213+
impl DefinitelySame for error_chain::State {
214+
fn definitely_same(&self, other: &Self) -> bool {
215+
// We ignore backtraces
216+
// We have to remove the Send bounds, which current Rust makes a bit annoying
217+
self.next_error.definitely_same(&other.next_error)
218+
}
219+
}
220+
204221
impl DefinitelySame for ErrorKind {
205222
fn definitely_same(&self, other: &Self) -> bool {
206223
match self {
@@ -233,6 +250,23 @@ impl DefinitelySame for NewError {
233250
}
234251
}
235252

253+
impl DefinitelySame for Box<dyn std::error::Error + Send> {
254+
/// Hack alert! We only compare stringifications.
255+
fn definitely_same(&self, other: &Self) -> bool {
256+
self.to_string() == other.to_string()
257+
}
258+
}
259+
260+
impl<T: DefinitelySame> DefinitelySame for Option<T> {
261+
fn definitely_same(&self, other: &Self) -> bool {
262+
match (self, other) {
263+
(None, None) => true,
264+
(Some(a), Some(b)) => a.definitely_same(b),
265+
_ => false,
266+
}
267+
}
268+
}
269+
236270
impl<T: DefinitelySame, E: DefinitelySame> DefinitelySame for StdResult<T, E> {
237271
fn definitely_same(&self, other: &Self) -> bool {
238272
match *self {
@@ -380,3 +414,54 @@ where
380414
self.with_instance(|i| std::fmt::Debug::fmt(&i, f))
381415
}
382416
}
417+
418+
#[cfg(test)]
419+
mod tests {
420+
use super::*;
421+
use error_chain::{ChainedError, State};
422+
use std::error::Error as StdError;
423+
424+
#[test]
425+
fn test_def_same_option() {
426+
let a = Some(Box::from(NewError::msg("A")));
427+
let b = Some(Box::from(NewError::msg("A")));
428+
429+
assert!(a.definitely_same(&b));
430+
assert!(b.definitely_same(&a));
431+
432+
let b = Some(Box::from(NewError::msg("B")));
433+
assert!(!a.definitely_same(&b));
434+
435+
let b = None;
436+
let c = None;
437+
assert!(!a.definitely_same(&b));
438+
assert!(b.definitely_same(&c));
439+
}
440+
441+
#[test]
442+
fn test_def_same_err() {
443+
let a = Error::new(ErrorKind::Msg(String::from("A")), State::default());
444+
let b = Error::new(ErrorKind::Msg(String::from("A")), State::default());
445+
446+
// Different backtraces but should be same
447+
assert!(a.definitely_same(&b));
448+
449+
let b = Error::new(ErrorKind::BadLength(0, 0), State::default());
450+
assert!(!a.definitely_same(&b));
451+
452+
let a = Error::new(ErrorKind::NewStyle(NewError::msg("A")), State::default());
453+
assert!(!a.definitely_same(&b));
454+
455+
let b = Error::new(ErrorKind::NewStyle(NewError::msg("A")), State::default());
456+
assert!(a.definitely_same(&b));
457+
}
458+
459+
#[test]
460+
fn test_def_same_box_err() {
461+
let a: Box<dyn StdError + Send> = Box::from(NewError::msg("A"));
462+
let b: Box<dyn StdError + Send> = Box::from(NewError::msg("B"));
463+
464+
assert!(a.definitely_same(&a));
465+
assert!(!a.definitely_same(&b));
466+
}
467+
}

tests/bibtex.rs

+58-31
Original file line numberDiff line numberDiff line change
@@ -5,48 +5,55 @@ use std::collections::HashSet;
55
use std::path::PathBuf;
66

77
use tectonic::io::{FilesystemIo, IoProvider, IoStack, MemoryIo};
8-
use tectonic::BibtexEngine;
8+
use tectonic::{errors::Result, BibtexEngine};
99
use tectonic_bridge_core::{CoreBridgeLauncher, MinimalDriver};
10+
use tectonic_engine_xetex::TexOutcome;
1011
use tectonic_status_base::NoopStatusBackend;
1112

1213
#[path = "util/mod.rs"]
1314
mod util;
1415
use crate::util::{test_path, Expected, ExpectedFile};
1516

1617
struct TestCase {
17-
stem: String,
18-
subdir: Option<String>,
18+
parts: &'static [&'static str],
1919
test_bbl: bool,
20+
expected_result: Result<TexOutcome>,
2021
}
2122

2223
impl TestCase {
23-
fn new(stem: &str, subdir: Option<&str>) -> Self {
24+
fn new(parts: &'static [&'static str]) -> Self {
25+
assert!(!parts.is_empty());
2426
TestCase {
25-
stem: stem.to_owned(),
26-
subdir: subdir.map(String::from),
27+
parts,
2728
test_bbl: true,
29+
expected_result: Ok(TexOutcome::Spotless),
2830
}
2931
}
3032

33+
fn expect(mut self, result: Result<TexOutcome>) -> Self {
34+
self.expected_result = result;
35+
self
36+
}
37+
3138
fn test_bbl(mut self, test: bool) -> Self {
3239
self.test_bbl = test;
3340
self
3441
}
3542

3643
fn test_dir(&self) -> PathBuf {
3744
let mut p = test_path(&["bibtex"]);
38-
if let Some(subdir) = &self.subdir {
39-
p.push(subdir);
45+
for sub in &self.parts[..self.parts.len() - 1] {
46+
p.push(sub);
4047
}
4148
p
4249
}
4350

44-
fn go(&mut self) {
51+
fn go(self) {
4552
util::set_test_root();
4653

4754
let mut p = self.test_dir();
4855

49-
let auxname = format!("{}.aux", self.stem);
56+
let auxname = format!("{}.aux", self.parts[self.parts.len() - 1]);
5057

5158
// MemoryIo layer that will accept the outputs.
5259
let mut mem = MemoryIo::new(true);
@@ -64,11 +71,11 @@ impl TestCase {
6471

6572
// Check that outputs match expectations.
6673

67-
p.push(&self.stem);
74+
p.push(self.parts[self.parts.len() - 1]);
6875

6976
let files = mem.files.borrow();
7077

71-
let mut expect = Expected::new();
78+
let mut expect = Expected::new().res(self.expected_result, res);
7279

7380
if self.test_bbl {
7481
expect =
@@ -78,109 +85,129 @@ impl TestCase {
7885
expect
7986
.file(ExpectedFile::read_with_extension(&mut p, "blg").collection(&files))
8087
.finish();
81-
82-
res.unwrap();
8388
}
8489
}
8590

8691
#[test]
8792
fn test_single_entry() {
88-
TestCase::new("single_entry", Some("cites")).go()
93+
TestCase::new(&["cites", "single_entry"]).go()
8994
}
9095

9196
#[test]
9297
fn test_brace_string() {
93-
TestCase::new("odd_strings", Some("cites")).go();
98+
TestCase::new(&["cites", "odd_strings"]).go();
9499
}
95100

96101
#[test]
97102
fn test_many() {
98-
TestCase::new("many", Some("cites")).go();
103+
TestCase::new(&["cites", "many"])
104+
.expect(Ok(TexOutcome::Warnings))
105+
.go();
99106
}
100107

101108
#[test]
102109
fn test_colon() {
103-
TestCase::new("colon", Some("cites")).go();
110+
TestCase::new(&["cites", "colon"])
111+
.expect(Ok(TexOutcome::Warnings))
112+
.go();
104113
}
105114

106115
#[test]
107116
fn test_empty_files() {
108-
TestCase::new("empty", None).test_bbl(false).go()
117+
TestCase::new(&["empty"])
118+
.expect(Ok(TexOutcome::Errors))
119+
.test_bbl(false)
120+
.go()
109121
}
110122

111123
#[test]
112124
fn test_mismatched_function() {
113-
TestCase::new("function", Some("mismatched_braces"))
125+
TestCase::new(&["mismatched_braces", "function"])
126+
.expect(Ok(TexOutcome::Errors))
114127
.test_bbl(false)
115128
.go();
116129
}
117130

118131
#[test]
119132
fn test_mismatched_expr() {
120-
TestCase::new("expr", Some("mismatched_braces"))
133+
TestCase::new(&["mismatched_braces", "expr"])
134+
.expect(Ok(TexOutcome::Errors))
121135
.test_bbl(false)
122136
.go();
123137
}
124138

125139
#[test]
126140
fn test_mismatched_data() {
127-
TestCase::new("data", Some("mismatched_braces"))
141+
TestCase::new(&["mismatched_braces", "data"])
142+
.expect(Ok(TexOutcome::Errors))
128143
.test_bbl(false)
129144
.go();
130145
}
131146

132147
#[test]
133148
fn test_mismatched_style() {
134-
TestCase::new("style", Some("mismatched_braces"))
149+
TestCase::new(&["mismatched_braces", "style"])
150+
.expect(Ok(TexOutcome::Errors))
135151
.test_bbl(false)
136152
.go();
137153
}
138154

139155
#[test]
140156
fn test_duplicated_data() {
141-
TestCase::new("data", Some("duplicated"))
157+
TestCase::new(&["duplicated", "data"])
158+
.expect(Ok(TexOutcome::Errors))
142159
.test_bbl(false)
143160
.go();
144161
}
145162

146163
#[test]
147164
fn test_duplicated_style() {
148-
TestCase::new("style", Some("duplicated"))
165+
TestCase::new(&["duplicated", "style"])
166+
.expect(Ok(TexOutcome::Errors))
149167
.test_bbl(false)
150168
.go();
151169
}
152170

153171
#[test]
154172
fn test_bad_crossref() {
155-
TestCase::new("bad", Some("crossref")).go();
173+
TestCase::new(&["crossref", "bad"])
174+
.expect(Ok(TexOutcome::Errors))
175+
.go();
156176
}
157177

158178
#[test]
159179
fn test_min_crossref() {
160-
TestCase::new("min", Some("crossref")).go();
180+
TestCase::new(&["crossref", "min"])
181+
.expect(Ok(TexOutcome::Warnings))
182+
.go();
161183
}
162184

163185
#[test]
164186
fn test_single_preamble() {
165-
TestCase::new("single", Some("preamble")).go();
187+
TestCase::new(&["preamble", "single"])
188+
.expect(Ok(TexOutcome::Warnings))
189+
.go();
166190
}
167191

168192
#[test]
169193
fn test_many_preamble() {
170-
TestCase::new("many", Some("preamble")).go();
194+
TestCase::new(&["preamble", "many"])
195+
.expect(Ok(TexOutcome::Warnings))
196+
.go();
171197
}
172198

173199
#[test]
174200
fn test_nested_aux() {
175-
TestCase::new("nested", Some("aux_files")).go();
201+
TestCase::new(&["aux_files", "nested"]).go();
176202
}
177203

178204
/// Test for [#1105](https://github.com/tectonic-typesetting/tectonic/issues/1105), with enough
179205
/// citations in the aux and fields in the bst to require more than one allocation of field space
180206
/// at once.
181207
#[test]
182208
fn test_lots_of_cites() {
183-
TestCase::new("lots_of_cites", Some("aux_files"))
209+
TestCase::new(&["aux_files", "lots_of_cites"])
210+
.expect(Ok(TexOutcome::Warnings))
184211
.test_bbl(false)
185212
.go();
186213
}

0 commit comments

Comments
 (0)