haematite 0.6.0

Content-addressed, branchable, actor-native storage engine
Documentation
use crate::carrier::adapters::mock::{
    EnvelopeShape, MockAdapter, NativeShape, NativeShapedMock, WasmShape, WasmShapedMock,
};
use crate::carrier::{
    AttemptGeneration, AuthenticatedPeerBinding, Carrier, CarrierConnectFailureCause,
    CarrierConnectFailureDisposition, CarrierConnectFailureStage, CarrierCounterSnapshot,
    CarrierEstablishedCause, CarrierEvent, CarrierLostCause, CarrierMachineInput, CarrierRefusal,
    CarrierSendOutcome, CarrierState, ConnectionId, ConnectionKey, EpisodeId, Incarnation,
    MAX_CARRIER_FRAME_BYTES, OpaqueBytes, encode_frame,
};

#[derive(Clone, Copy, Debug)]
enum Vector {
    LengthZero,
    LengthOne,
    LengthMaxMinusOne,
    LengthMax,
    LengthMaxPlusOne,
    LengthU32Max,
    PrefixZero,
    PrefixOne,
    PrefixTwo,
    PrefixThree,
    ShortBody,
    TrailingBody,
    ConcatenatedEnvelopes,
    Ordering,
    Duplicate,
    StaleGeneration,
    LateAfterLoss,
    InitialDialFailure,
    OpaqueRandomPayload,
    CompressedLookingIdentity,
}

const ALL_VECTORS: [Vector; 20] = [
    Vector::LengthZero,
    Vector::LengthOne,
    Vector::LengthMaxMinusOne,
    Vector::LengthMax,
    Vector::LengthMaxPlusOne,
    Vector::LengthU32Max,
    Vector::PrefixZero,
    Vector::PrefixOne,
    Vector::PrefixTwo,
    Vector::PrefixThree,
    Vector::ShortBody,
    Vector::TrailingBody,
    Vector::ConcatenatedEnvelopes,
    Vector::Ordering,
    Vector::Duplicate,
    Vector::StaleGeneration,
    Vector::LateAfterLoss,
    Vector::InitialDialFailure,
    Vector::OpaqueRandomPayload,
    Vector::CompressedLookingIdentity,
];

#[derive(Debug, Eq, PartialEq)]
struct Outcome {
    events: Vec<CarrierEvent>,
    refusal: Option<CarrierRefusal>,
    state: CarrierState,
    counters: CarrierCounterSnapshot,
}

fn key() -> ConnectionKey {
    ConnectionKey {
        connection_id: ConnectionId::new([0x5a; 16]),
        incarnation: Incarnation::new(12),
    }
}

fn establish<S: EnvelopeShape>(adapter: &mut MockAdapter<S>) -> ConnectionKey {
    adapter.apply(CarrierMachineInput::ExplicitAction);
    let generation = adapter
        .current_attempt()
        .unwrap_or(AttemptGeneration::new(0));
    let established_key = key();
    adapter.apply(CarrierMachineInput::AttemptEstablished {
        generation,
        key: established_key,
        authenticated_peer_binding: AuthenticatedPeerBinding::new(vec![0xa5, 0x5a]),
        cause: CarrierEstablishedCause::ExplicitAction,
    });
    adapter.clear_events();
    established_key
}

fn valid_payload(vector: Vector) -> Option<Vec<u8>> {
    match vector {
        Vector::LengthZero => Some(Vec::new()),
        Vector::LengthOne => Some(vec![7]),
        Vector::LengthMaxMinusOne => Some(vec![0x33; MAX_CARRIER_FRAME_BYTES - 1]),
        Vector::LengthMax => Some(vec![0x44; MAX_CARRIER_FRAME_BYTES]),
        Vector::OpaqueRandomPayload => Some(
            (0_u16..=255)
                .map(|value| ((value * 73 + 19) % 256) as u8)
                .collect(),
        ),
        Vector::CompressedLookingIdentity => Some(vec![
            0x1f, 0x8b, 0x08, 0x00, 0x78, 0x9c, 0x28, 0xb5, 0x2f, 0xfd, 0xff, 0x00,
        ]),
        Vector::LengthMaxPlusOne
        | Vector::LengthU32Max
        | Vector::PrefixZero
        | Vector::PrefixOne
        | Vector::PrefixTwo
        | Vector::PrefixThree
        | Vector::ShortBody
        | Vector::TrailingBody
        | Vector::ConcatenatedEnvelopes
        | Vector::Ordering
        | Vector::Duplicate
        | Vector::StaleGeneration
        | Vector::LateAfterLoss
        | Vector::InitialDialFailure => None,
    }
}

fn malformed_envelope(vector: Vector) -> Option<Vec<u8>> {
    match vector {
        Vector::LengthMaxPlusOne => Some(
            u32::try_from(MAX_CARRIER_FRAME_BYTES + 1)
                .unwrap_or(u32::MAX)
                .to_be_bytes()
                .to_vec(),
        ),
        Vector::LengthU32Max => Some(u32::MAX.to_be_bytes().to_vec()),
        Vector::PrefixZero => Some(Vec::new()),
        Vector::PrefixOne => Some(vec![0]),
        Vector::PrefixTwo => Some(vec![0, 0]),
        Vector::PrefixThree => Some(vec![0, 0, 0]),
        Vector::ShortBody => Some(vec![0, 0, 0, 3, 1, 2]),
        Vector::TrailingBody => Some(vec![0, 0, 0, 1, 7, 8]),
        Vector::ConcatenatedEnvelopes => {
            let first = encode_frame(&[1]).unwrap_or_default();
            let second = encode_frame(&[2]).unwrap_or_default();
            Some(first.into_iter().chain(second).collect())
        }
        Vector::LengthZero
        | Vector::LengthOne
        | Vector::LengthMaxMinusOne
        | Vector::LengthMax
        | Vector::Ordering
        | Vector::Duplicate
        | Vector::StaleGeneration
        | Vector::LateAfterLoss
        | Vector::InitialDialFailure
        | Vector::OpaqueRandomPayload
        | Vector::CompressedLookingIdentity => None,
    }
}

fn run_vector<S: EnvelopeShape>(vector: Vector) -> Outcome {
    let mut adapter = MockAdapter::<S>::new(EpisodeId::new(100));
    let refusal = if let Some(payload) = valid_payload(vector) {
        run_valid_frame(&mut adapter, &payload)
    } else if let Some(envelope) = malformed_envelope(vector) {
        run_malformed_frame(&mut adapter, &envelope)
    } else {
        run_lifecycle_vector(&mut adapter, vector);
        None
    };

    Outcome {
        events: adapter.events().to_vec(),
        refusal,
        state: adapter.state(),
        counters: adapter.counters().snapshot(),
    }
}

fn run_valid_frame<S: EnvelopeShape>(
    adapter: &mut MockAdapter<S>,
    payload: &[u8],
) -> Option<CarrierRefusal> {
    let established_key = establish(adapter);
    let encoded = encode_frame(payload).unwrap_or_default();
    adapter.receive_envelope(established_key, &encoded).err()
}

fn run_malformed_frame<S: EnvelopeShape>(
    adapter: &mut MockAdapter<S>,
    envelope: &[u8],
) -> Option<CarrierRefusal> {
    let established_key = establish(adapter);
    let refusal = adapter.receive_envelope(established_key, envelope).err();
    let event_count = adapter.events().len();
    let valid = encode_frame(&[9]).unwrap_or_default();
    assert_eq!(
        adapter.receive_envelope(established_key, &valid).err(),
        refusal
    );
    assert_eq!(adapter.events().len(), event_count);
    refusal
}

fn run_lifecycle_vector<S: EnvelopeShape>(adapter: &mut MockAdapter<S>, vector: Vector) {
    match vector {
        Vector::Ordering => run_ordering(adapter),
        Vector::Duplicate => {
            let established_key = establish(adapter);
            adapter.apply(CarrierMachineInput::EstablishedFate {
                key: established_key,
                cause: CarrierLostCause::CleanClose,
            });
            adapter.apply(CarrierMachineInput::EstablishedFate {
                key: established_key,
                cause: CarrierLostCause::TransportError,
            });
        }
        Vector::StaleGeneration => {
            adapter.apply(CarrierMachineInput::ExplicitAction);
            let stale = adapter
                .current_attempt()
                .unwrap_or(AttemptGeneration::new(0));
            adapter.apply(CarrierMachineInput::ExplicitAction);
            adapter.clear_events();
            adapter.apply(CarrierMachineInput::AttemptFailed {
                generation: stale,
                cause: CarrierConnectFailureCause::new(
                    CarrierConnectFailureStage::Dial,
                    CarrierConnectFailureDisposition::Park,
                ),
            });
        }
        Vector::LateAfterLoss => {
            let established_key = establish(adapter);
            adapter.apply(CarrierMachineInput::EstablishedFate {
                key: established_key,
                cause: CarrierLostCause::TransportError,
            });
            let late = encode_frame(&[0xde, 0xad]).unwrap_or_default();
            assert_eq!(adapter.receive_envelope(established_key, &late), Ok(()));
        }
        Vector::InitialDialFailure => {
            adapter.apply(CarrierMachineInput::ExplicitAction);
            let generation = adapter
                .current_attempt()
                .unwrap_or(AttemptGeneration::new(0));
            adapter.apply(CarrierMachineInput::AttemptFailed {
                generation,
                cause: CarrierConnectFailureCause::new(
                    CarrierConnectFailureStage::Dial,
                    CarrierConnectFailureDisposition::Park,
                ),
            });
        }
        Vector::LengthZero
        | Vector::LengthOne
        | Vector::LengthMaxMinusOne
        | Vector::LengthMax
        | Vector::LengthMaxPlusOne
        | Vector::LengthU32Max
        | Vector::PrefixZero
        | Vector::PrefixOne
        | Vector::PrefixTwo
        | Vector::PrefixThree
        | Vector::ShortBody
        | Vector::TrailingBody
        | Vector::ConcatenatedEnvelopes
        | Vector::OpaqueRandomPayload
        | Vector::CompressedLookingIdentity => {}
    }
}

fn run_ordering<S: EnvelopeShape>(adapter: &mut MockAdapter<S>) {
    let established_key = establish(adapter);
    let first = encode_frame(&[1, 2]).unwrap_or_default();
    let second = encode_frame(&[3, 4]).unwrap_or_default();
    assert_eq!(adapter.receive_envelope(established_key, &first), Ok(()));
    assert_eq!(adapter.receive_envelope(established_key, &second), Ok(()));
    assert_eq!(
        Carrier::send(adapter, established_key, OpaqueBytes::from(&[5, 6][..])),
        CarrierSendOutcome::Accepted
    );
    assert_eq!(
        Carrier::send(adapter, established_key, OpaqueBytes::from(&[7, 8][..])),
        CarrierSendOutcome::Accepted
    );
    assert!(adapter.flush_one());
    assert!(adapter.flush_one());
}

#[test]
fn native_and_wasm_shaped_mocks_run_identical_vectors() {
    let _: Option<NativeShapedMock> = None;
    let _: Option<WasmShapedMock> = None;
    for vector in ALL_VECTORS {
        let native = run_vector::<NativeShape>(vector);
        let wasm = run_vector::<WasmShape>(vector);
        assert_eq!(native, wasm, "parity vector {vector:?}");
    }
}