Merge pull request #806 from rust-lang-nursery/serialize-checks

Add some round-trip checks for preprocessor input serialization
This commit is contained in:
Michael Bryan 2018-10-20 14:17:03 +08:00 committed by GitHub
commit dfb6e3cb10
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 454 additions and 278 deletions

664
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -26,7 +26,7 @@ pulldown-cmark = "0.1.2"
lazy_static = "1.0"
log = "0.4"
env_logger = "0.5"
toml = "0.4"
toml = "0.4.8"
memchr = "2.0"
open = "1.1"
regex = "1.0.0"

View File

@ -65,9 +65,13 @@ impl CmdPreprocessor {
}
}
fn write_input<W: Write>(&self, writer: W, book: &Book, ctx: &PreprocessorContext) -> Result<()> {
serde_json::to_writer(writer, &(ctx, book))
.map_err(Into::into)
fn write_input<W: Write>(
&self,
writer: W,
book: &Book,
ctx: &PreprocessorContext,
) -> Result<()> {
serde_json::to_writer(writer, &(ctx, book)).map_err(Into::into)
}
/// The command this `Preprocessor` will invoke.
@ -105,7 +109,12 @@ impl Preprocessor for CmdPreprocessor {
.stdout(Stdio::piped())
.stderr(Stdio::inherit())
.spawn()
.chain_err(|| format!("Unable to start the \"{}\" preprocessor. Is it installed?", self.name()))?;
.chain_err(|| {
format!(
"Unable to start the \"{}\" preprocessor. Is it installed?",
self.name()
)
})?;
self.write_input_to_child(&mut child, &book, ctx);
@ -114,13 +123,21 @@ impl Preprocessor for CmdPreprocessor {
.chain_err(|| "Error waiting for the preprocessor to complete")?;
trace!("{} exited with output: {:?}", self.cmd, output);
ensure!(output.status.success(), "The preprocessor exited unsuccessfully");
ensure!(
output.status.success(),
"The preprocessor exited unsuccessfully"
);
serde_json::from_slice(&output.stdout).chain_err(|| "Unable to parse the preprocessed book")
serde_json::from_slice(&output.stdout)
.chain_err(|| "Unable to parse the preprocessed book")
}
fn supports_renderer(&self, renderer: &str) -> bool {
debug!("Checking if the \"{}\" preprocessor supports \"{}\"", self.name(), renderer);
debug!(
"Checking if the \"{}\" preprocessor supports \"{}\"",
self.name(),
renderer
);
let mut cmd = match self.command() {
Ok(c) => c,
@ -152,3 +169,36 @@ impl Preprocessor for CmdPreprocessor {
outcome.unwrap_or(false)
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::path::Path;
use MDBook;
fn book_example() -> MDBook {
let example =
Path::new(env!("CARGO_MANIFEST_DIR")).join("book-example");
MDBook::load(example).unwrap()
}
#[test]
fn round_trip_write_and_parse_input() {
let cmd = CmdPreprocessor::new("test".to_string(), "test".to_string());
let md = book_example();
let ctx = PreprocessorContext::new(
md.root.clone(),
md.config.clone(),
"some-renderer".to_string(),
);
let mut buffer = Vec::new();
cmd.write_input(&mut buffer, &md.book, &ctx).unwrap();
let (got_ctx, got_book) =
CmdPreprocessor::parse_input(buffer.as_slice()).unwrap();
assert_eq!(got_book, md.book);
assert_eq!(got_ctx, ctx);
}
}

View File

@ -26,6 +26,7 @@ pub struct PreprocessorContext {
pub renderer: String,
/// The calling `mdbook` version.
pub mdbook_version: String,
#[serde(skip)]
__non_exhaustive: (),
}

View File

@ -64,6 +64,7 @@ pub struct RenderContext {
/// renderers to cache intermediate results, this directory is not
/// guaranteed to be empty or even exist.
pub destination: PathBuf,
#[serde(skip)]
__non_exhaustive: (),
}