//! * `src/bin/*.rs` are binaries
//! * `examples/*.rs` are examples
//! * `tests/*.rs` are integration tests
+//! * `benches/*.rs` are benchmarks
//!
//! It is a bit tricky because we need match explicit information from `Cargo.toml`
//! with implicit info in directory layout.
package_root: &Path,
errors: &mut Vec<String>)
-> CargoResult<Vec<Target>> {
+
+ let inferred = infer_from_directory(&package_root.join("examples"));
+
let targets = clean_targets("example", "example",
- toml_examples, inferred_examples(package_root),
+ toml_examples, inferred,
package_root, errors)?;
let mut result = Vec::new();
fn clean_tests(toml_tests: Option<&Vec<TomlTestTarget>>,
package_root: &Path,
errors: &mut Vec<String>) -> CargoResult<Vec<Target>> {
+
+ let inferred = infer_from_directory(&package_root.join("tests"));
+
let targets = clean_targets("test", "test",
- toml_tests, inferred_tests(package_root),
+ toml_tests, inferred,
package_root, errors)?;
let mut result = Vec::new();
Some(legacy_path)
};
+ let inferred = infer_from_directory(&package_root.join("benches"));
+
let targets = clean_targets_with_legacy_path("benchmark", "bench",
- toml_benches, inferred_benches(package_root),
+ toml_benches, inferred,
package_root,
errors,
&mut legacy_bench_path)?;
}
result.extend(infer_from_directory(&package_root.join("src").join("bin")));
- if let Ok(entries) = fs::read_dir(&package_root.join("src").join("bin")) {
- let multifile_bins = entries
- .filter_map(|e| e.ok())
- .filter(is_not_dotfile)
- .filter(|e| match e.file_type() {
- Ok(t) if t.is_dir() => true,
- _ => false
- })
- .filter_map(|entry| {
- let dir = entry.path();
- let main = dir.join("main.rs");
- let name = dir.file_name().and_then(|n| n.to_str());
- match (main.exists(), name) {
- (true, Some(name)) => Some((name.to_owned(), main)),
- _ => None
- }
- });
- result.extend(multifile_bins);
- }
-
result
}
-fn inferred_examples(package_root: &Path) -> Vec<(String, PathBuf)> {
- infer_from_directory(&package_root.join("examples"))
-}
-
-fn inferred_tests(package_root: &Path) -> Vec<(String, PathBuf)> {
- infer_from_directory(&package_root.join("tests"))
-}
-
-fn inferred_benches(package_root: &Path) -> Vec<(String, PathBuf)> {
- infer_from_directory(&package_root.join("benches"))
-}
-
fn infer_from_directory(directory: &Path) -> Vec<(String, PathBuf)> {
let entries = match fs::read_dir(directory) {
Err(_) => return Vec::new(),
entries
.filter_map(|e| e.ok())
.filter(is_not_dotfile)
- .map(|e| e.path())
- .filter(|f| f.extension().and_then(|s| s.to_str()) == Some("rs"))
- .filter_map(|f| {
- f.file_stem().and_then(|s| s.to_str())
- .map(|s| (s.to_owned(), f.clone()))
- })
+ .filter_map(infer_any)
.collect()
}
+
+fn infer_any(entry: DirEntry) -> Option<(String, PathBuf)> {
+ if entry.path().extension().and_then(|p| p.to_str()) == Some("rs") {
+ infer_file(entry)
+ } else if entry.file_type().map(|t| t.is_dir()).ok() == Some(true) {
+ infer_subdirectory(entry)
+ } else {
+ None
+ }
+}
+
+
+fn infer_file(entry: DirEntry) -> Option<(String, PathBuf)> {
+ let path = entry.path();
+ path
+ .file_stem()
+ .and_then(|p| p.to_str())
+ .map(|p| (p.to_owned(), path.clone()))
+}
+
+
+fn infer_subdirectory(entry: DirEntry) -> Option<(String, PathBuf)> {
+ let path = entry.path();
+ let main = path.join("main.rs");
+ let name = path.file_name().and_then(|n| n.to_str());
+ match (name, main.exists()) {
+ (Some(name), true) => Some((name.to_owned(), main)),
+ _ => None
+ }
+}
+
+
fn is_not_dotfile(entry: &DirEntry) -> bool {
entry.file_name().to_str().map(|s| s.starts_with('.')) == Some(false)
}
Your project can optionally contain folders named `examples`, `tests`, and
`benches`, which Cargo will treat as containing examples,
-integration tests, and benchmarks respectively.
+integration tests, and benchmarks respectively. Analogous to `bin` targets, they
+may be composed of single files or directories with a `main.rs` file.
```notrust
▾ src/ # directory containing source files
main.rs
▾ examples/ # (optional) examples
*.rs
+ ▾ */ # (optional) directories containing multi-file examples
+ main.rs
▾ tests/ # (optional) integration tests
*.rs
+ ▾ */ # (optional) directories containing multi-file tests
+ main.rs
▾ benches/ # (optional) benchmarks
*.rs
+ ▾ */ # (optional) directories containing multi-file benchmarks
+ main.rs
```
To structure your code after you've created the files and folders for your
.file("src/bin/foo.rs", "fn main() {}")
.file("src/bin/foo/main.rs", "fn main() {}");
- assert_that(p.cargo_process("build"),
+ assert_that(p.cargo_process("build"),
execs().with_status(101)
.with_stderr_contains("\
[..]found duplicate binary name foo, but all binary targets must have a unique name[..]
assert_that(&p.bin("bar"), existing_file());
}
+#[test]
+fn inferred_examples() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "fn main() {}")
+ .file("examples/bar.rs", "fn main() {}")
+ .file("examples/baz/main.rs", "fn main() {}");
+
+ assert_that(p.cargo_process("test"), execs().with_status(0));
+ assert_that(&p.bin("examples/bar"), existing_file());
+ assert_that(&p.bin("examples/baz"), existing_file());
+}
+
+#[test]
+fn inferred_tests() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "fn main() {}")
+ .file("tests/bar.rs", "fn main() {}")
+ .file("tests/baz/main.rs", "fn main() {}");
+
+ assert_that(
+ p.cargo_process("test").arg("--test=bar").arg("--test=baz"),
+ execs().with_status(0));
+}
+
+#[test]
+fn inferred_benchmark() {
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "fn main() {}")
+ .file("benches/bar.rs", "fn main() {}");
+
+ assert_that(
+ p.cargo_process("bench").arg("--bench=bar"),
+ execs().with_status(0));
+}
+
+#[test]
+fn inferred_benchmark_from_directory() {
+ //FIXME: merge with `inferred_benchmark` after fixing #4504
+ let p = project("foo")
+ .file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.1.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "fn main() {}")
+ .file("benches/bar/main.rs", "fn main() {}");
+
+ assert_that(
+ p.cargo_process("bench").arg("--bench=bar"),
+ execs().with_status(0));
+}
+
#[test]
fn same_metadata_different_directory() {
// A top-level crate built in two different workspaces should have the