mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-06-26 10:54:26 +02:00
add proptest for action sequences
This commit is contained in:
parent
04f6b1d421
commit
f6ffcc7039
2 changed files with 70 additions and 2 deletions
3
TODO.txt
3
TODO.txt
|
@ -5,11 +5,10 @@
|
|||
- annotations: `annotation.<epoch time> = "annotation"`
|
||||
- tags: `tags.<tag> = ""`
|
||||
* add HTTP API
|
||||
* abstract server, storage, etc. into traits
|
||||
* implement snapshot requests
|
||||
* implement backups
|
||||
* implement client-side encryption
|
||||
* design expiration
|
||||
- need to be sure that create / delete operations don't get reversed
|
||||
* cli tools
|
||||
* prop testing for DB modifications
|
||||
- generate a non-failing sequence of operations with syncs interspersed
|
||||
|
|
69
tests/sync_action_sequences.rs
Normal file
69
tests/sync_action_sequences.rs
Normal file
|
@ -0,0 +1,69 @@
|
|||
use chrono::Utc;
|
||||
use ot::{Operation, Server, DB};
|
||||
use proptest::prelude::*;
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Action {
|
||||
Op(Operation),
|
||||
Sync,
|
||||
}
|
||||
|
||||
fn action_sequence_strategy() -> impl Strategy<Value = Vec<(Action, u8)>> {
|
||||
// Create, Update, Delete, or Sync on client 1, 2, .., followed by a round of syncs
|
||||
"([CUDS][123])*S1S2S3S1S2".prop_map(|seq| {
|
||||
let uuid = Uuid::parse_str("83a2f9ef-f455-4195-b92e-a54c161eebfc").unwrap();
|
||||
seq.as_bytes()
|
||||
.chunks(2)
|
||||
.map(|action_on| {
|
||||
let action = match action_on[0] {
|
||||
b'C' => Action::Op(Operation::Create { uuid }),
|
||||
b'U' => Action::Op(Operation::Update {
|
||||
uuid,
|
||||
property: "title".into(),
|
||||
value: Some("foo".into()),
|
||||
timestamp: Utc::now(),
|
||||
}),
|
||||
b'D' => Action::Op(Operation::Delete { uuid }),
|
||||
b'S' => Action::Sync,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let acton = action_on[1] - b'1';
|
||||
(action, acton)
|
||||
})
|
||||
.collect::<Vec<(Action, u8)>>()
|
||||
})
|
||||
}
|
||||
|
||||
proptest! {
|
||||
#[test]
|
||||
// check that various sequences of operations on mulitple db's do not get the db's into an
|
||||
// incompatible state. The main concern here is that there might be a sequence of create
|
||||
// and delete operations that results in a task existing in one DB but not existing in
|
||||
// another. So, the generated sequences focus on a single task UUID.
|
||||
fn transform_sequences_of_operations(action_sequence in action_sequence_strategy()) {
|
||||
let mut server = Server::new();
|
||||
let mut dbs = [DB::new(), DB::new(), DB::new()];
|
||||
|
||||
for (action, db) in action_sequence {
|
||||
println!("{:?} on db {}", action, db);
|
||||
|
||||
let db = &mut dbs[db as usize];
|
||||
match action {
|
||||
Action::Op(op) => {
|
||||
if let Err(e) = db.apply(op) {
|
||||
println!(" {:?} (ignored)", e);
|
||||
}
|
||||
},
|
||||
Action::Sync => db.sync("me", &mut server),
|
||||
}
|
||||
}
|
||||
|
||||
println!("{:?}", dbs[0].tasks());
|
||||
println!("{:?}", dbs[1].tasks());
|
||||
println!("{:?}", dbs[2].tasks());
|
||||
|
||||
assert_eq!(dbs[0].tasks(), dbs[1].tasks());
|
||||
assert_eq!(dbs[1].tasks(), dbs[2].tasks());
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue