Skip to content

Commit

Permalink
Merge pull request #509 from moonbitlang/update_doc_test
Browse files Browse the repository at this point in the history
internal: polish doc test
  • Loading branch information
Young-Flash authored Dec 4, 2024
2 parents 68c0ee8 + d0522bf commit f14566e
Show file tree
Hide file tree
Showing 12 changed files with 338 additions and 182 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion crates/moon/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ tokio.workspace = true
futures.workspace = true
clap_complete.workspace = true
indexmap.workspace = true
regex.workspace = true

[target.'cfg(not(windows))'.dependencies]
openssl = { version = "0.10.66", features = ["vendored"] }
Expand Down
152 changes: 2 additions & 150 deletions crates/moon/src/cli/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,14 @@

use anyhow::Context;
use colored::Colorize;
use doc_test::DocTestExtractor;
use doc_test::PatchJSON;
use moonbuild::dry_run;
use moonbuild::entry;
use mooncake::pkg::sync::auto_sync;
use moonutil::common::backend_filter;
use moonutil::common::lower_surface_targets;
use moonutil::common::FileLock;
use moonutil::common::GeneratedTestDriver;
use moonutil::common::MooncOpt;
use moonutil::common::RunMode;
use moonutil::common::MOON_DOC_TEST_POSTFIX;
use moonutil::common::{MoonbuildOpt, TestOpt};
use moonutil::dirs::mk_arch_mode_dir;
use moonutil::dirs::PackageDirs;
Expand Down Expand Up @@ -90,7 +86,7 @@ pub struct TestSubcommand {
pub patch_file: Option<PathBuf>,

/// Run doc test
#[clap(long = "doc", conflicts_with = "update")]
#[clap(long = "doc")]
pub doc_test: bool,
}

Expand Down Expand Up @@ -302,31 +298,7 @@ fn run_test_internal(
pkg.patch_file = cmd.patch_file.clone();

if cmd.doc_test {
let mbt_files = backend_filter(
&pkg.files,
moonc_opt.build_opt.debug_flag,
moonc_opt.build_opt.target_backend,
);

let mut doc_tests = vec![];
let doc_test_extractor = DocTestExtractor::new();
for file in mbt_files {
let doc_test_in_mbt_file = doc_test_extractor.extract_from_file(&file)?;
if !doc_test_in_mbt_file.is_empty() {
doc_tests.push(doc_test_in_mbt_file);
}
}

let pj = PatchJSON::from_doc_tests(doc_tests);
let pj_path = pkg
.artifact
.with_file_name(format!("{}.json", MOON_DOC_TEST_POSTFIX));
if !pj_path.parent().unwrap().exists() {
std::fs::create_dir_all(pj_path.parent().unwrap())?;
}
std::fs::write(&pj_path, serde_json::to_string_pretty(&pj)?)
.context(format!("failed to write {}", &pj_path.display()))?;

let pj_path = moonutil::doc_test::gen_doc_test_patch(pkg, &moonc_opt)?;
pkg.doc_test_patch_file = Some(pj_path);
}

Expand Down Expand Up @@ -434,123 +406,3 @@ fn do_run_test(
Ok(2)
}
}

mod doc_test {
use regex::Regex;
use std::fs;
use std::path::Path;

#[derive(Debug)]
pub struct DocTest {
pub content: String,
pub file_name: String,
pub line_number: usize,
pub line_count: usize,
}

pub struct DocTestExtractor {
test_pattern: Regex,
}

impl DocTestExtractor {
pub fn new() -> Self {
// \r\n for windows, \n for unix
let pattern = r#"///\s*```(?:\r?\n)((?:///.*(?:\r?\n))*?)///\s*```"#;
Self {
test_pattern: Regex::new(pattern).expect("Invalid regex pattern"),
}
}

pub fn extract_from_file(&self, file_path: &Path) -> anyhow::Result<Vec<DocTest>> {
let content = fs::read_to_string(file_path)?;

let mut tests = Vec::new();

for cap in self.test_pattern.captures_iter(&content) {
if let Some(test_match) = cap.get(0) {
let line_number = content[..test_match.start()]
.chars()
.filter(|&c| c == '\n')
.count()
+ 1;

if let Some(test_content) = cap.get(1) {
let processed_content = test_content
.as_str()
.lines()
.map(|line| {
format!(" {}", line.trim_start_matches("/// ")).to_string()
})
.collect::<Vec<_>>()
.join("\n");

let line_count = processed_content.split('\n').count();

tests.push(DocTest {
content: processed_content,
file_name: file_path.file_name().unwrap().to_str().unwrap().to_string(),
line_number,
line_count,
});
}
}
}

Ok(tests)
}
}

#[derive(Debug, serde::Serialize)]
pub struct PatchJSON {
pub drops: Vec<String>,
pub patches: Vec<PatchItem>,
}

#[derive(Debug, serde::Serialize)]
pub struct PatchItem {
pub name: String,
pub content: String,
}

impl PatchJSON {
pub fn from_doc_tests(doc_tests: Vec<Vec<DocTest>>) -> Self {
let mut patches = vec![];
for doc_tests_in_mbt_file in doc_tests.iter() {
let mut current_line = 1;
let mut content = String::new();
for doc_test in doc_tests_in_mbt_file {
let test_name = format!(
"{} {} {} {}",
"doc_test", doc_test.file_name, doc_test.line_number, doc_test.line_count
);

let start_line_number = doc_test.line_number;
let empty_lines = "\n".repeat(start_line_number - current_line);

content.push_str(&format!(
"{}test \"{}\" {{\n{}\n}}",
empty_lines, test_name, doc_test.content
));

// +1 for the }
current_line = start_line_number + doc_test.line_count + 1;
}

patches.push(PatchItem {
// xxx.mbt -> xxx_doc_test.mbt
name: format!(
"{}{}.mbt",
doc_tests_in_mbt_file[0].file_name.trim_end_matches(".mbt"),
moonutil::common::MOON_DOC_TEST_POSTFIX,
),
content,
});
}

PatchJSON {
drops: vec![],
patches,
}
}
}
}
51 changes: 39 additions & 12 deletions crates/moon/tests/test_cases/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7975,31 +7975,58 @@ fn test_run_doc_test() {
doc_test 3 from hello.mbt
doc_test
doc_test 1 from greet.mbt
doc_test 2 from greet.mbt
test block 1
test block 2
test block 3
doc_test 3 from greet.mbt
doc_test from greet.mbt
test block 4
test block 5
doc_test 5 from greet.mbt
test username/hello/lib/hello.mbt::1 failed
expect test failed at $ROOT/src/lib/hello.mbt:12:5-12:19
Diff:
----
1256
----
test username/hello/lib/hello.mbt::2 failed: FAILED: $ROOT/src/lib/hello.mbt:22:5-22:31 this is a failure
test username/hello/lib/greet.mbt::3 failed
expect test failed at $ROOT/src/lib/greet.mbt:33:5-33:18
test username/hello/lib/greet.mbt::2 failed
expect test failed at $ROOT/src/lib/greet.mbt:22:7-22:21
Diff:
----
423
1256
----
Total tests: 8, passed: 6, failed: 2.
test username/hello/lib/greet.mbt::3 failed: FAILED: $ROOT/src/lib/greet.mbt:31:7-31:31 another failure
Total tests: 12, passed: 8, failed: 4.
"#]],
);

// --doc conflicts with --update
#[cfg(unix)]
check(
get_err_stderr(&dir, ["test", "--doc", "--update"]),
get_err_stdout(&dir, ["test", "--sort-input", "--doc", "--update"]),
expect![[r#"
error: the argument '--doc' cannot be used with '--update'
doc_test 1 from hello.mbt
doc_test 2 from hello.mbt
doc_test 3 from hello.mbt
doc_test
doc_test 1 from greet.mbt
test block 1
test block 2
test block 3
doc_test 3 from greet.mbt
test block 4
test block 5
doc_test 5 from greet.mbt
Usage: moon test --doc
Auto updating expect tests and retesting ...
For more information, try '--help'.
doc_test 2 from hello.mbt
doc_test 2 from hello.mbt
test username/hello/lib/hello.mbt::2 failed: FAILED: $ROOT/src/lib/hello.mbt:22:5-22:31 this is a failure
test block 2
test block 2
test username/hello/lib/greet.mbt::3 failed: FAILED: $ROOT/src/lib/greet.mbt:31:7-31:31 another failure
Total tests: 12, passed: 10, failed: 2.
"#]],
);

Expand Down
64 changes: 58 additions & 6 deletions crates/moon/tests/test_cases/run_doc_test.in/src/lib/greet.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,38 @@ pub fn greet1() -> String {
}


/// ```
/// println("doc_test 2 from greet.mbt")
/// ```mbt
///
///
///
/// test {
/// println("test block 1")
/// }
///
///
/// test {
///
/// println("test block 2")
///
/// inspect!(1256)
///
///
///
/// }
///
/// test {
/// println("test block 3")
///
/// fail!("another failure")
/// }
///
/// ```
pub fn greet2() -> String {
"greet, world!"
}

/// ```
/// ```moonbit
///
/// println("doc_test 3 from greet.mbt")
///
///
Expand All @@ -26,13 +47,44 @@ pub fn greet3() -> String {
"greet, wor1ld!"
}

/// ```
/// println("doc_test from greet.mbt")
/// ```moonbit
/// test {
///
///
///
/// inspect!(423)
/// println("test block 4")
///
/// }
///
///
/// ```
pub fn greet() -> String {
"greet, wor1ld!"
}


/// ```
/// test {
///
/// println("test block 5")
///
///
/// }
///
///
///
/// ```
pub fn greet4() -> String {
"greet, wor1ld!"
}


/// ```
/// println("doc_test 5 from greet.mbt")
///
///
///
/// ```
pub fn greet5() -> String {
"greet, wor1ld!"
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ pub fn hello1() -> String {
}


/// ```
/// ```mbt
/// println("doc_test 2 from hello.mbt")
///
///
/// inspect!(1256)
///
/// ```
pub fn hello2() -> String {
Expand Down
Loading

0 comments on commit f14566e

Please sign in to comment.