subplotlib 0.1.1

Utility functions and types for `subplot codegen` generated Rust based test suites. Relies on `subplotlib-derive` for associated macros.
Documentation
use subplotlib::prelude::*;

// --------------------------------
// This came from helpers/subplotlib_context.rs

use std::collections::HashMap;

struct Context {
    counter: usize,
    files: HashMap<String, SubplotDataFile>,
    this_file: Option<SubplotDataFile>,
}

impl Default for Context {
    fn default() -> Self {
        Self {
            counter: 0,
            files: HashMap::new(),
            this_file: None,
        }
    }
}

impl Context {
    fn remember_file(&mut self, name: &str, content: SubplotDataFile) {
        self.files.insert(name.to_string(), content);
    }
}

impl ContextElement for Context {
    // An empty implementation is sufficient for now
}

// --------------------------------
// This came from helpers/subplotlib_impl.rs

#[step]
fn a_trivial_setup(context: &mut Context, initial: usize) {
    context.counter = initial;
}

#[step]
fn a_trivial_cleanup(context: &mut Context, _initial: usize) {}

#[step]
fn increment_counter(context: &mut Context) {
    context.counter += 1;
}

#[step]
fn internal_check_counter(context: &Context, num: usize) {
    if context.counter != num {
        throw!(format!(
            "Counter was wrong, it was {} but {} was expected",
            context.counter, num
        ));
    }
}

#[step]
fn check_counter(context: &ScenarioContext, num: usize) {
    internal_check_counter::call(context, num)?;
}

#[step]
fn acquire_file_content(context: &mut Context, somename: &str, file: SubplotDataFile) {
    context.remember_file(somename, file);
}

#[step]
fn remember_target(context: &mut Context, somename: &str) {
    if let Some(file) = context.files.get(somename) {
        context.this_file = Some(file.clone());
    } else {
        throw!(format!("Unknown file {}", somename));
    }
}

#[step]
fn check_contents(context: &mut Context, text: &str) {
    if let Some(file) = context.this_file.as_ref() {
        let body_as_text = String::from_utf8_lossy(file.data());
        if !body_as_text.as_ref().contains(text) {
            throw!(format!(
                "Failed to find {} when looking at {}",
                text,
                file.name().display()
            ));
        }
    } else {
        throw!("Not looking at a file");
    }
}

// --------------------------------

lazy_static! {
    static ref SUBPLOT_EMBEDDED_FILES: Vec<SubplotDataFile> = vec![SubplotDataFile::new(
        "ZXhhbXBsZS50eHQ=",
        "VGhpcyBkYXRhIGZpbGUgd2lsbCBiZSBlbWJlZGRlZCBpbnRvIHRoZSB0ZXN0IHN1aXRlCg=="
    ),];
}

// ---------------------------------

// Fundamentals
#[test]
fn fundamentals() {
    let mut scenario = Scenario::new(&base64_decode("RnVuZGFtZW50YWxz"));

    let step = a_trivial_setup::Builder::default().initial(0).build();
    let cleanup = a_trivial_cleanup::Builder::default().initial(0).build();
    scenario.add_step(step, Some(cleanup));

    let step = increment_counter::Builder::default().build();
    scenario.add_step(step, None);

    let step = check_counter::Builder::default().num(1).build();
    scenario.add_step(step, None);

    let step = increment_counter::Builder::default().build();
    scenario.add_step(step, None);

    let step = check_counter::Builder::default().num(2).build();
    scenario.add_step(step, None);

    scenario.run().unwrap();
}

// ---------------------------------

// Embedded files
#[test]
fn embedded_files() {
    let mut scenario = Scenario::new(&base64_decode("RW1iZWRkZWQgZmlsZXM="));

    let step = acquire_file_content::Builder::default()
        .file({
            use std::path::PathBuf;
            // example.txt
            let target_name: PathBuf = base64_decode("ZXhhbXBsZS50eHQ=").into();
            SUBPLOT_EMBEDDED_FILES
                .iter()
                .find(|df| df.name() == target_name)
                .expect("Unable to find file at runtime")
                .clone()
        })
        .somename(
            // "EXAMPLE"
            &base64_decode("RVhBTVBMRQ=="),
        )
        .build();
    scenario.add_step(step, None);

    let step = remember_target::Builder::default()
        .somename(
            // "EXAMPLE"
            &base64_decode("RVhBTVBMRQ=="),
        )
        .build();
    scenario.add_step(step, None);

    let step = check_contents::Builder::default()
        .text(
            // "will be embedded"
            &base64_decode("d2lsbCBiZSBlbWJlZGRlZA=="),
        )
        .build();
    scenario.add_step(step, None);

    scenario.run().unwrap();
}

// ---------------------------------

// Data directory
#[test]
fn data_directory() {
    let mut scenario = Scenario::new(&base64_decode("RGF0YSBkaXJlY3Rvcnk="));

    let step = subplotlib::steplibrary::datadir::datadir_has_enough_space::Builder::default()
        .bytes(1024000)
        .build();
    scenario.add_step(step, None);

    let step =
        subplotlib::steplibrary::datadir::datadir_has_enough_space_megabytes::Builder::default()
            .megabytes(1)
            .build();
    scenario.add_step(step, None);

    scenario.run().unwrap();
}