Skip to content

Instantly share code, notes, and snippets.

@moretea
Created May 18, 2019 08:15
Show Gist options
  • Save moretea/45e66341702808b7a246c61776570d7e to your computer and use it in GitHub Desktop.
Save moretea/45e66341702808b7a246c61776570d7e to your computer and use it in GitHub Desktop.
Example of BDD
Feature: Computing actions to take given a set of policies and a current state
Scenario: No policies exist
Given there are no policies
And there are no existing snapshots
And it is monday morning
When actions are computed
Then there are no actions to perform
Scenario: Execute first hourly policy
Given there is a policy named x and it runs every 1 hour on pool/fs with a retention of 24 runs
And there are no existing snapshots
And it is monday morning
When actions are computed
Then there is one action to be executed
Then there is an action to snapshot "pool/fs"
#[macro_use]
extern crate cucumber_rust;
#[macro_use]
extern crate lazy_static;
use zbackup::policy::{SnapshotPolicy, Frequency, Retention};
use zbackup::state::State;
use zbackup::action::{Action, compute_actions};
use chrono::offset::TimeZone;
#[derive(Default)]
pub struct MyWorld {
policies: Option<Vec<SnapshotPolicy>>,
state: Option<State>,
time: Option<chrono::DateTime<chrono::Utc>>,
computed_actions: Option<Vec<Action>>
}
impl MyWorld {
fn add_policy(&mut self, policy: SnapshotPolicy) {
if self.policies.is_none() {
self.policies = Some(Vec::new());
}
self.policies.as_mut().unwrap().push(policy);
}
}
lazy_static! {
static ref MONDAY_MORNING: chrono::DateTime<chrono::Utc> =
chrono::Utc.ymd(2019, 05, 13).and_hms(8, 0, 0);
static ref HOURLY_POLICY: SnapshotPolicy = SnapshotPolicy {
name: "hourly".into(),
filesystem: "pool/fs".into(),
frequency: Frequency::Hours(1),
retention: Retention::Number(24),
};
}
steps!(MyWorld => {
// Policies
given "there are no policies" |world, _step| {
world.policies = Some(Vec::new())
};
given regex r"^there is a policy named (.+) and it runs every (\d+) (.+) on (.+) with a retention of (\d+) runs$" (String, i32, String, String, i32) |world, policy_name, freq_nr, freq_type, filesystem_name, retention_number, _step| {
let policy = SnapshotPolicy {
name: policy_name,
filesystem: filesystem_name,
frequency: match freq_type.as_ref() {
"hourly" | "hour" => Frequency::Hours(freq_nr),
_ => panic!("unexpected frequency {}", freq_type),
},
retention: Retention::Number(retention_number),
};
world.add_policy(policy);
};
// State
given "there are no existing snapshots" |world, _step| {
world.state = Some(State::default())
};
// Date
given "it is monday morning" |world, _step| {
world.time = Some(*MONDAY_MORNING)
};
// Actions to perform
when "actions are computed" |world, _step| {
let policies = world.policies.as_ref().expect("no policies given");
let state = world.state.as_ref().expect("no state given ");
let time = world.time.as_ref().expect("no time given");
world.computed_actions = Some(compute_actions(&policies, &state, &time));
};
//
then "there are no actions to perform" |world, _step| {
let actions = world.computed_actions.as_ref().expect("action computation was not invoked");
assert!(actions.is_empty())
};
then "there is one action to be executed" |world, _step| {
let actions = world.computed_actions.as_ref().expect("action computation was not invoked");
assert_eq!(actions.len(), 1)
};
then regex "there is an action to snapshot \"(.+)\"" (String) |world, fs, _step| {
let actions = world.computed_actions.as_ref().expect("action computation was not invoked");
for action in actions.into_iter() {
let Action::TakeSnapshot(policy) = action;
if policy.filesystem == fs {
return
}
}
panic!("No snapshot was taken on filesystem {}", fs)
};
});
cucumber! {
features: "./features",
world: MyWorld,
steps: &[steps]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment