Skip to content

Commit

Permalink
Get rid of the model dependency
Browse files Browse the repository at this point in the history
Not really well maintained. Replace by manual code + get rid of the
linearizability test (it's not that useful and it would be complex to
replicate).

Closes #31.
  • Loading branch information
vorner committed Apr 20, 2020
1 parent 79acd3f commit e3f8538
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 54 deletions.
3 changes: 1 addition & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,9 @@ members = ["benchmarks"]
[dev-dependencies]
crossbeam-utils = "~0.6"
itertools = "~0.8"
model = "~0.1"
num_cpus = "~1"
once_cell = "~1"
proptest = "~0.8"
proptest = "~0.9"
version-sync = "~0.8"

[profile.bench]
Expand Down
137 changes: 85 additions & 52 deletions tests/random.rs
Original file line number Diff line number Diff line change
@@ -1,73 +1,61 @@
//! Let it torture the implementation with some randomized operations.
extern crate arc_swap;
#[macro_use]
extern crate model;
extern crate crossbeam_utils;
extern crate once_cell;
#[macro_use]
extern crate proptest;

use std::mem;
use std::sync::Arc;

use arc_swap::ArcSwap;
use once_cell::sync::Lazy;
use proptest::prelude::*;

#[test]
fn ops() {
model! {
Model => let mut u = 0usize,
Implementation => let a: ArcSwap<usize> = ArcSwap::from(Arc::new(0usize)),
Store(usize)(v in any::<usize>()) => {
u = v;
a.store(Arc::new(v));
},
LoadFull(())(() in any::<()>()) => {
assert_eq!(u, *a.load_full());
},
LoadSignalSafe(())(() in any::<()>()) => {
assert_eq!(u, **a.load_signal_safe());
},
Load(())(() in any::<()>()) => {
assert_eq!(u, **a.load());
},
Swap(usize)(v in any::<usize>()) => {
let expected = u;
u = v;
let actual = a.swap(Arc::new(v));
assert_eq!(expected, *actual);
}
}
#[derive(Copy, Clone, Debug)]
enum OpsInstruction {
Store(usize),
Swap(usize),
LoadFull,
LoadSignalSafe,
Load,
}

const LIMIT: usize = 5;

static ARCS: Lazy<Vec<Arc<usize>>> = Lazy::new(|| (0..LIMIT).map(Arc::new).collect());
impl OpsInstruction {
fn random() -> impl Strategy<Value = Self> {
prop_oneof![
any::<usize>().prop_map(Self::Store),
any::<usize>().prop_map(Self::Swap),
Just(Self::LoadFull),
Just(Self::LoadSignalSafe),
Just(Self::Load),
]
}
}

#[test]
fn selection() {
model! {
Model => let mut bare = Arc::clone(&ARCS[0]),
Implementation => let a: ArcSwap<usize> = ArcSwap::from(Arc::clone(&ARCS[0])),
Swap(usize)(idx in 0..LIMIT) => {
let mut expected = Arc::clone(&ARCS[idx]);
mem::swap(&mut expected, &mut bare);
let actual = a.swap(Arc::clone(&ARCS[idx]));
assert!(Arc::ptr_eq(&expected, &actual));
},
Cas((usize, usize))((current, new) in (0..LIMIT, 0..LIMIT)) => {
let expected = Arc::clone(&bare);
if bare == ARCS[current] {
bare = Arc::clone(&ARCS[new]);
proptest! {
#[test]
fn ops(instructions in proptest::collection::vec(OpsInstruction::random(), 1..100)) {
use OpsInstruction::*;
let mut m = 0;
let a = ArcSwap::from_pointee(0usize);
for ins in instructions {
match ins {
Store(v) => {
m = v;
a.store(Arc::new(v));
}
Swap(v) => {
let old = mem::replace(&mut m, v);
assert_eq!(old, *a.swap(Arc::new(v)));
}
Load => assert_eq!(m, **a.load()),
LoadFull => assert_eq!(m, *a.load_full()),
LoadSignalSafe => assert_eq!(m, **a.load_signal_safe()),
}
let actual = a.compare_and_swap(&ARCS[current], Arc::clone(&ARCS[new]));
assert!(Arc::ptr_eq(&expected, &actual));
}
}
}

#[test]
fn linearize() {
/*
use model::Shared;
linearizable! {
Expand All @@ -83,4 +71,49 @@ fn linearize() {
**a.compare_and_swap(&ARCS[current], new)
}
}
}
*/
}

const LIMIT: usize = 5;
static ARCS: Lazy<Vec<Arc<usize>>> = Lazy::new(|| (0..LIMIT).map(Arc::new).collect());

#[derive(Copy, Clone, Debug)]
enum SelInstruction {
Swap(usize),
Cas(usize, usize),
}

impl SelInstruction {
fn random() -> impl Strategy<Value = Self> {
prop_oneof![
(0..LIMIT).prop_map(Self::Swap),
(0..LIMIT, 0..LIMIT).prop_map(|(cur, new)| Self::Cas(cur, new)),
]
}
}

proptest! {
#[test]
fn selection(instructions in proptest::collection::vec(SelInstruction::random(), 1..100)) {
let mut bare = Arc::clone(&ARCS[0]);
let a = ArcSwap::from(Arc::clone(&ARCS[0]));
for ins in instructions {
match ins {
SelInstruction::Swap(idx) => {
let expected = mem::replace(&mut bare, Arc::clone(&ARCS[idx]));
let actual = a.swap(Arc::clone(&ARCS[idx]));
assert!(Arc::ptr_eq(&expected, &actual));
}
SelInstruction::Cas(cur, new) => {
let expected = Arc::clone(&bare);
if bare == ARCS[cur] {
bare = Arc::clone(&ARCS[new]);
}
let actual = a.compare_and_swap(&ARCS[cur], Arc::clone(&ARCS[new]));
assert!(Arc::ptr_eq(&expected, &actual));
}
}
}
}
}

0 comments on commit e3f8538

Please sign in to comment.