Skip to content

Commit

Permalink
Don't check the same file twice. Fixes #48
Browse files Browse the repository at this point in the history
  • Loading branch information
willcrichton committed Sep 6, 2024
1 parent e4b2798 commit 4eeda22
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 28 deletions.
4 changes: 2 additions & 2 deletions crates/mdbook-quiz-validate/src/impls/markdown.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ prompt.prompt = "Hello **world**"
answer.answer = ""
prompt.distractors = [""]
"#;
assert!(crate::harness(contents).is_ok());
assert!(crate::test::harness(contents).is_ok());
}

#[test]
Expand All @@ -89,5 +89,5 @@ answer.answer = ""
prompt.distractors = [""]
"#;
// TODO: right now this test is just verified looking at stderr
assert!(crate::harness(contents).is_ok());
assert!(crate::test::harness(contents).is_ok());
}
6 changes: 3 additions & 3 deletions crates/mdbook-quiz-validate/src/impls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ prompt.prompt = ""
answer.answer = ""
prompt.distractors = [""]
"#;
assert!(crate::harness(contents).is_err());
assert!(crate::test::harness(contents).is_err());
}

#[test]
Expand All @@ -116,7 +116,7 @@ prompt.distractors = [""]
"#;

// TODO: right now this test is just verified looking at stderr
assert!(crate::harness(contents).is_ok());
assert!(crate::test::harness(contents).is_ok());
}

#[test]
Expand All @@ -134,5 +134,5 @@ prompt.prompt = ""
answer.answer = ""
prompt.distractors = [""]
"#;
assert!(crate::harness(contents).is_err());
assert!(crate::test::harness(contents).is_err());
}
4 changes: 2 additions & 2 deletions crates/mdbook-quiz-validate/src/impls/multiple_choice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ prompt.prompt = ""
answer.answer = ""
prompt.distractors = [""]
"#;
assert!(crate::harness(contents).is_ok());
assert!(crate::test::harness(contents).is_ok());
}

#[test]
Expand All @@ -87,5 +87,5 @@ prompt.distractors = [""]
prompt.answerIndex = 0
prompt.sortAnswers = true
"#;
assert!(crate::harness(contents).is_err());
assert!(crate::test::harness(contents).is_err());
}
6 changes: 3 additions & 3 deletions crates/mdbook-quiz-validate/src/impls/tracing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ fn main() {
answer.doesCompile = true
answer.stdout = "Hello world"
"#;
assert!(crate::harness(contents).is_ok());
assert!(crate::test::harness(contents).is_ok());
}

#[test]
Expand All @@ -123,7 +123,7 @@ fn main() {
answer.doesCompile = true
answer.stdout = ""
"#;
assert!(crate::harness(contents).is_err());
assert!(crate::test::harness(contents).is_err());
}

#[test]
Expand All @@ -139,5 +139,5 @@ fn main() {
answer.doesCompile = true
answer.stdout = "meep meep"
"#;
assert!(crate::harness(contents).is_err());
assert!(crate::test::harness(contents).is_err());
}
60 changes: 46 additions & 14 deletions crates/mdbook-quiz-validate/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,15 @@ pub use toml_spanned_value::SpannedValue;
mod impls;
mod spellcheck;

/// A thread-safe mutable set of question identifiers.
pub type IdSet = Arc<Mutex<HashSet<String>>>;
#[derive(Default)]
struct ValidatedInner {
ids: HashSet<String>,
paths: HashSet<PathBuf>,
}

#[derive(Default, Clone)]
/// A thread-safe mutable set of already-validated identifiers and paths.
pub struct Validated(Arc<Mutex<ValidatedInner>>);

struct QuizDiagnostic {
error: miette::Error,
Expand All @@ -34,17 +41,17 @@ pub(crate) struct ValidationContext {
diagnostics: RefCell<Vec<QuizDiagnostic>>,
path: PathBuf,
contents: String,
ids: IdSet,
validated: Validated,
spellcheck: bool,
}

impl ValidationContext {
pub fn new(path: &Path, contents: &str, ids: IdSet, spellcheck: bool) -> Self {
pub fn new(path: &Path, contents: &str, validated: Validated, spellcheck: bool) -> Self {
ValidationContext {
diagnostics: Default::default(),
path: path.to_owned(),
contents: contents.to_owned(),
ids,
validated,
spellcheck,
}
}
Expand All @@ -71,7 +78,7 @@ impl ValidationContext {
}

pub fn check_id(&mut self, id: &str, value: &SpannedValue) {
let new_id = self.ids.lock().unwrap().insert(id.to_string());
let new_id = self.validated.0.lock().unwrap().ids.insert(id.to_string());
if !new_id {
self.error(miette!(
labels = vec![value.labeled_span()],
Expand Down Expand Up @@ -149,8 +156,18 @@ struct ParseError {
}

/// Runs validation on a quiz with TOML-format `contents` at `path` under the ID set `ids`.
pub fn validate(path: &Path, contents: &str, ids: &IdSet, spellcheck: bool) -> anyhow::Result<()> {
let mut cx = ValidationContext::new(path, contents, Arc::clone(ids), spellcheck);
pub fn validate(
path: &Path,
contents: &str,
validated: &Validated,
spellcheck: bool,
) -> anyhow::Result<()> {
let not_checked = validated.0.lock().unwrap().paths.insert(path.to_path_buf());
if !not_checked {
return Ok(());
}

let mut cx = ValidationContext::new(path, contents, validated.clone(), spellcheck);

let parse_result = toml::from_str::<Quiz>(contents);
match parse_result {
Expand Down Expand Up @@ -180,14 +197,29 @@ pub fn validate(path: &Path, contents: &str, ids: &IdSet, spellcheck: bool) -> a
}

#[cfg(test)]
pub(crate) fn harness(contents: &str) -> anyhow::Result<()> {
validate(Path::new("dummy.rs"), contents, &IdSet::default(), true)
}

#[cfg(test)]
mod test {
pub(crate) mod test {
use super::*;

pub(crate) fn harness(contents: &str) -> anyhow::Result<()> {
validate(Path::new("dummy.rs"), contents, &Validated::default(), true)
}

#[test]
fn validate_twice() -> anyhow::Result<()> {
let contents = r#"
[[questions]]
id = "foobar"
type = "MultipleChoice"
prompt.prompt = ""
answer.answer = ""
prompt.distractors = [""]
"#;
let validated = Validated::default();
validate(Path::new("dummy.rs"), contents, &validated, true)?;
validate(Path::new("dummy.rs"), contents, &validated, true)?;
Ok(())
}

#[test]
fn validate_parse_error() {
let contents = r#"
Expand Down
8 changes: 4 additions & 4 deletions crates/mdbook-quiz/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use mdbook_preprocessor_utils::{
mdbook::preprocess::PreprocessorContext, Asset, SimplePreprocessor,
};

use mdbook_quiz_validate::IdSet;
use mdbook_quiz_validate::Validated;
use regex::Regex;
use std::{
env,
Expand Down Expand Up @@ -61,7 +61,7 @@ struct QuizConfig {

struct QuizPreprocessor {
config: QuizConfig,
question_ids: IdSet,
validated: Validated,
#[cfg(feature = "aquascope")]
aquascope: mdbook_aquascope::AquascopePreprocessor,
}
Expand Down Expand Up @@ -132,7 +132,7 @@ impl QuizPreprocessor {
mdbook_quiz_validate::validate(
&quiz_path_abs,
&content_toml,
&self.question_ids,
&self.validated,
self.config.spellcheck.unwrap_or(false),
)?;

Expand Down Expand Up @@ -215,7 +215,7 @@ impl SimplePreprocessor for QuizPreprocessor {

Ok(QuizPreprocessor {
config,
question_ids: IdSet::default(),
validated: Validated::default(),
#[cfg(feature = "aquascope")]
aquascope: mdbook_aquascope::AquascopePreprocessor::new()
.context("Aquascope failed to initialize")?,
Expand Down

0 comments on commit 4eeda22

Please sign in to comment.