tests/
lib.rs

1use abstio::MapName;
2use abstutil::Timer;
3use anyhow::{anyhow, bail, Result};
4use map_model::Map;
5use prettydiff::text::diff_lines;
6use std::path::PathBuf;
7
8/// Run the contents of a .osm through the full map importer with default options.
9pub fn import_map(path: String) -> Map {
10    let mut timer = Timer::new("convert synthetic map");
11    let name = MapName::new("zz", "oneshot", &abstutil::basename(&path));
12    let clip = None;
13    let raw = convert_osm::convert(
14        path,
15        name,
16        clip,
17        convert_osm::Options::default(),
18        &mut timer,
19    );
20    Map::create_from_raw(raw, map_model::RawToMapOptions::default(), &mut timer)
21}
22
23/// Obtains a path to a test file (test code only!)
24/// This is a convenience function for writing test code. It allow tests code from anywhere in the
25/// workspace to access test files (eg input .osm files, golden outputfiles etc) which are stored within
26/// the `tests` package.
27/// This function make direct reference to the location of this source file (using the `file!()` marco)
28/// and hence should only be used in test code and not in any production code.
29pub fn get_test_file_path(path: String) -> Result<String> {
30    // Get the absolute path to the crate that called was invoked at the cli (or equivalent)
31    let maybe_workspace_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap();
32    let maybe_workspace_dir = std::path::Path::new(&maybe_workspace_dir);
33    // Get the relative path to this source file within the workspace
34    let this_source_file = String::from(file!());
35
36    // Try a find a suitable way to join the two paths to find something that exists
37    let test_file = next_test_file_path(maybe_workspace_dir, &this_source_file);
38    if test_file.is_ok() {
39        // Now try and match the workspace path with the user requested path
40        match next_test_file_path(test_file.as_ref().unwrap(), &path) {
41            Ok(pb) => Ok(String::from(pb.to_str().unwrap())),
42            Err(e) => Err(e),
43        }
44    } else {
45        panic!("Cannot find the absolute path to {}. Check that this function being called from test code, not production code.", this_source_file);
46    }
47}
48
49fn next_test_file_path(
50    maybe_absolute_dir: &std::path::Path,
51    file_path: &String,
52) -> Result<PathBuf> {
53    let path_to_test = maybe_absolute_dir.join(file_path);
54    if path_to_test.exists() {
55        Ok(path_to_test)
56    } else if maybe_absolute_dir.parent().is_some() {
57        next_test_file_path(maybe_absolute_dir.parent().unwrap(), file_path)
58    } else {
59        Err(anyhow!("Cannot locate file '{}'", file_path))
60    }
61}
62
63/// Compares a string to the contents of the relevant goldenfile.
64/// Pretty prints the differences if necessary
65pub fn compare_with_goldenfile(actual: String, goldenfile_path: String) -> Result<()> {
66    let goldenfile_path = get_test_file_path(goldenfile_path).unwrap();
67    // let expected = String::from_utf8(abstio::slurp_file(&goldenfile_path)?).unwrap().clone().trim();
68    let binding = String::from_utf8(abstio::slurp_file(&goldenfile_path)?)
69        .unwrap()
70        .clone();
71    let expected = binding.trim();
72    let actual_str = actual.trim();
73    if actual_str != expected {
74        let lcs = diff_lines(&actual_str, &expected);
75        bail!(
76            "contents differ from goldenfile {}:\n{}",
77            &goldenfile_path,
78            lcs
79        );
80    }
81    Ok(())
82}