fn main()

in GaiaXStretch/scripts/gentest/src/main.rs [14:151]


fn main() {
    env_logger::init();
    // this requires being run by cargo, which is iffy
    let root_dir = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap());
    let repo_root = root_dir.parent().and_then(Path::parent).unwrap();

    let fixtures_root = repo_root.join("test_fixtures");
    let fixtures = fs::read_dir(fixtures_root).unwrap();

    info!("reading test fixtures from disk");
    let mut fixtures: Vec<_> = fixtures
        .into_iter()
        .filter_map(|a| a.ok())
        .filter(|f| f.path().is_file() && f.path().extension().map(|p| p == "html").unwrap_or(false))
        .map(|f| {
            let fixture_path = f.path().to_path_buf();
            let name = fixture_path.file_stem().unwrap().to_str().unwrap().to_string();
            (name, fixture_path)
        })
        .collect();
    fixtures.sort_unstable_by_key(|f| f.0.clone());

    info!("starting webdriver instance");
    let webdriver_url = "http://localhost:4444";
    let mut webdriver_handle = Command::new("chromedriver").arg("--port=4444").spawn().unwrap();

    // this is silly, but it works
    std::thread::sleep(std::time::Duration::from_secs(1));

    let mut caps = serde_json::map::Map::new();
    let chrome_opts = serde_json::json!({ "args": ["--headless", "--disable-gpu"] });
    caps.insert("goog:chromeOptions".to_string(), chrome_opts.clone());

    use indicatif::ProgressBar;
    let pb = ProgressBar::new(fixtures.len() as u64);
    let (test_descs_sink, mut test_descs) = channel();

    info!("spawning webdriver client and collecting test descriptions");
    tokio::run(
        Client::with_capabilities(webdriver_url, caps.clone())
            .map_err(|e| Error::from(e))
            .and_then(move |client| {
                futures::stream::iter_ok(pb.wrap_iter(fixtures.into_iter()))
                    .and_then(move |(name, fixture_path)| {
                        pb.set_message(&name);
                        test_root_element(client.clone(), name, fixture_path)
                    })
                    .collect()
                    .map(move |descs| {
                        info!("finished collecting descriptions, sending them back to main");
                        let _ = test_descs_sink.send(descs);
                    })
            })
            .map_err(|e| {
                error!("top-level error encountered: {:?}", e);
            }),
    );

    info!("killing webdriver instance...");
    webdriver_handle.kill().unwrap();

    info!("collecting test descriptions from async runtime...");
    let test_descs = loop {
        if let Ok(Some(descs)) = test_descs.try_recv() {
            break descs;
        }
    };

    info!("generating test sources and concatenating...");

    let bench_descs: Vec<_> = test_descs
        .iter()
        .map(|(name, description)| {
            debug!("generating bench contents for {}", &name);
            (name.clone(), generate_bench(description))
        })
        .collect();

    let test_descs: Vec<_> = test_descs
        .iter()
        .map(|(name, description)| {
            debug!("generating test contents for {}", &name);
            (name.clone(), generate_test(name, description))
        })
        .collect();

    let benchmarks: Vec<_> = test_descs
        .iter()
        .map(|(name, _)| {
            let bench_mod = Ident::new(name, Span::call_site());
            quote!(#bench_mod::compute())
        })
        .collect();

    let test_mods = test_descs
        .iter()
        .map(|(name, _)| {
            let name = Ident::new(name, Span::call_site());
            quote!(mod #name;)
        })
        .fold(quote!(), |a, b| quote!(#a #b));

    for (name, bench_body) in bench_descs {
        let mut bench_filename = repo_root.join("benches").join("generated").join(&name);
        bench_filename.set_extension("rs");
        debug!("writing {} to disk...", &name);
        fs::write(bench_filename, bench_body.to_string()).unwrap();
    }

    for (name, test_body) in test_descs {
        let mut test_filename = repo_root.join("tests").join("generated").join(&name);
        test_filename.set_extension("rs");
        debug!("writing {} to disk...", &name);
        fs::write(test_filename, test_body.to_string()).unwrap();
    }

    let bench_mods = quote!(
        use criterion::{criterion_group, criterion_main, Criterion};

        #test_mods

        fn benchmark(c: &mut Criterion) {
            c.bench_function("generated benchmarks", |b| {
                b.iter(|| { #(#benchmarks;)* })
            });
        }

        criterion_group!(benches, benchmark);
        criterion_main!(benches);
    );

    info!("writing generated test file to disk...");
    fs::write(repo_root.join("benches").join("generated").join("mod.rs"), bench_mods.to_string()).unwrap();
    fs::write(repo_root.join("tests").join("generated").join("mod.rs"), test_mods.to_string()).unwrap();

    info!("formatting the source directory");
    Command::new("cargo").arg("fmt").current_dir(repo_root).status().unwrap();
}