Make core serialized enum shapes exhaustive
This commit is contained in:
parent
5376aa90f9
commit
77ba5319ce
2 changed files with 319 additions and 0 deletions
|
|
@ -699,6 +699,8 @@ mod credentials;
|
||||||
mod documents;
|
mod documents;
|
||||||
#[path = "schema_records/encoding.rs"]
|
#[path = "schema_records/encoding.rs"]
|
||||||
mod encoding;
|
mod encoding;
|
||||||
|
#[path = "schema_records/enum_shapes.rs"]
|
||||||
|
mod enum_shapes;
|
||||||
#[path = "schema_records/participant_transitions.rs"]
|
#[path = "schema_records/participant_transitions.rs"]
|
||||||
mod participant_transitions;
|
mod participant_transitions;
|
||||||
#[path = "schema_records/process_evidence.rs"]
|
#[path = "schema_records/process_evidence.rs"]
|
||||||
|
|
|
||||||
317
crates/lazaret-core/tests/schema_records/enum_shapes.rs
Normal file
317
crates/lazaret-core/tests/schema_records/enum_shapes.rs
Normal file
|
|
@ -0,0 +1,317 @@
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
macro_rules! enum_corpus {
|
||||||
|
($digest:expr, $type:ty, { $($pattern:pat => $value:expr),+ $(,)? }) => {{
|
||||||
|
let values: Vec<$type> = vec![$($value),+];
|
||||||
|
let mut tags = HashSet::new();
|
||||||
|
for value in values {
|
||||||
|
let tag = match &value {
|
||||||
|
$($pattern => stringify!($pattern)),+
|
||||||
|
};
|
||||||
|
assert!(tags.insert(tag));
|
||||||
|
let encoded = postcard::to_stdvec(&value).unwrap();
|
||||||
|
$digest.update(stringify!($type).len().to_be_bytes());
|
||||||
|
$digest.update(stringify!($type).as_bytes());
|
||||||
|
$digest.update(tag.len().to_be_bytes());
|
||||||
|
$digest.update(tag.as_bytes());
|
||||||
|
$digest.update(encoded.len().to_be_bytes());
|
||||||
|
$digest.update(encoded);
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lifecycle_corpus(digest: &mut Sha256) {
|
||||||
|
enum_corpus!(digest, DurableDecision, {
|
||||||
|
DurableDecision::None => DurableDecision::None,
|
||||||
|
DurableDecision::Preparing => DurableDecision::Preparing,
|
||||||
|
DurableDecision::Published => DurableDecision::Published,
|
||||||
|
DurableDecision::Clean => DurableDecision::Clean,
|
||||||
|
});
|
||||||
|
enum_corpus!(digest, ParticipantRole, {
|
||||||
|
ParticipantRole::PreparedLower => ParticipantRole::PreparedLower,
|
||||||
|
ParticipantRole::StateAnchor => ParticipantRole::StateAnchor,
|
||||||
|
ParticipantRole::GitRouting => ParticipantRole::GitRouting,
|
||||||
|
ParticipantRole::Network => ParticipantRole::Network,
|
||||||
|
ParticipantRole::Helper => ParticipantRole::Helper,
|
||||||
|
ParticipantRole::Sandbox => ParticipantRole::Sandbox,
|
||||||
|
ParticipantRole::Publication => ParticipantRole::Publication,
|
||||||
|
});
|
||||||
|
enum_corpus!(digest, ParticipantState, {
|
||||||
|
ParticipantState::Intent => ParticipantState::Intent,
|
||||||
|
ParticipantState::LeaseHeld => ParticipantState::LeaseHeld,
|
||||||
|
ParticipantState::Prepared => ParticipantState::Prepared,
|
||||||
|
ParticipantState::Committed => ParticipantState::Committed,
|
||||||
|
ParticipantState::ReleaseIntent => ParticipantState::ReleaseIntent,
|
||||||
|
ParticipantState::Clean => ParticipantState::Clean,
|
||||||
|
});
|
||||||
|
enum_corpus!(digest, PersistedHostProcessOwnership, {
|
||||||
|
PersistedHostProcessOwnership::Unassigned => PersistedHostProcessOwnership::unassigned(),
|
||||||
|
PersistedHostProcessOwnership::Staged(_) => PersistedHostProcessOwnership::staged(process(1)),
|
||||||
|
PersistedHostProcessOwnership::Committed(_) => PersistedHostProcessOwnership::committed(process(2)),
|
||||||
|
});
|
||||||
|
enum_corpus!(digest, ProcessOwnershipMessageVersion, {
|
||||||
|
ProcessOwnershipMessageVersion::V1 => ProcessOwnershipMessageVersion::V1,
|
||||||
|
});
|
||||||
|
enum_corpus!(digest, SessionPhase, {
|
||||||
|
SessionPhase::New => SessionPhase::New,
|
||||||
|
SessionPhase::Waiting => SessionPhase::Waiting,
|
||||||
|
SessionPhase::Registering => SessionPhase::Registering,
|
||||||
|
SessionPhase::Attached => SessionPhase::Attached,
|
||||||
|
SessionPhase::Prompting => SessionPhase::Prompting,
|
||||||
|
SessionPhase::HostExecuting => SessionPhase::HostExecuting,
|
||||||
|
SessionPhase::Closed => SessionPhase::Closed,
|
||||||
|
SessionPhase::Failed => SessionPhase::Failed,
|
||||||
|
});
|
||||||
|
enum_corpus!(digest, SessionTerminalState, {
|
||||||
|
SessionTerminalState::Intent => SessionTerminalState::Intent,
|
||||||
|
SessionTerminalState::Running => SessionTerminalState::Running,
|
||||||
|
SessionTerminalState::ReleaseIntent => SessionTerminalState::ReleaseIntent,
|
||||||
|
SessionTerminalState::Clean => SessionTerminalState::Clean,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ownership_slot_corpus(digest: &mut Sha256) {
|
||||||
|
enum_corpus!(digest, HostProcessOwnershipSlot, {
|
||||||
|
HostProcessOwnershipSlot::SandboxHostCoordinator => HostProcessOwnershipSlot::SandboxHostCoordinator,
|
||||||
|
HostProcessOwnershipSlot::SandboxRuntimeSupervisor => HostProcessOwnershipSlot::SandboxRuntimeSupervisor,
|
||||||
|
HostProcessOwnershipSlot::SandboxAttachedRunsc => HostProcessOwnershipSlot::SandboxAttachedRunsc,
|
||||||
|
HostProcessOwnershipSlot::StateAnchorDaemon => HostProcessOwnershipSlot::StateAnchorDaemon,
|
||||||
|
HostProcessOwnershipSlot::GitRoutingDaemon => HostProcessOwnershipSlot::GitRoutingDaemon,
|
||||||
|
HostProcessOwnershipSlot::NetworkRuntimeSupervisor => HostProcessOwnershipSlot::NetworkRuntimeSupervisor,
|
||||||
|
HostProcessOwnershipSlot::HelperConnectivityHelper => HostProcessOwnershipSlot::HelperConnectivityHelper,
|
||||||
|
HostProcessOwnershipSlot::HelperRuntimeSupervisor => HostProcessOwnershipSlot::HelperRuntimeSupervisor,
|
||||||
|
HostProcessOwnershipSlot::SessionTerminalHostCoordinator(_) => HostProcessOwnershipSlot::SessionTerminalHostCoordinator(session_id()),
|
||||||
|
HostProcessOwnershipSlot::SessionTerminalExecClient(_) => HostProcessOwnershipSlot::SessionTerminalExecClient(session_id()),
|
||||||
|
HostProcessOwnershipSlot::EscalationHostProcess(_) => HostProcessOwnershipSlot::EscalationHostProcess(RequestId::new(opaque(3))),
|
||||||
|
});
|
||||||
|
enum_corpus!(digest, ParticipantOwnership, {
|
||||||
|
ParticipantOwnership::PreparedLower(_) => ParticipantOwnership::empty(ParticipantRole::PreparedLower),
|
||||||
|
ParticipantOwnership::StateAnchor(_) => ParticipantOwnership::empty(ParticipantRole::StateAnchor),
|
||||||
|
ParticipantOwnership::GitRouting(_) => ParticipantOwnership::empty(ParticipantRole::GitRouting),
|
||||||
|
ParticipantOwnership::Network(_) => ParticipantOwnership::empty(ParticipantRole::Network),
|
||||||
|
ParticipantOwnership::Helper(_) => ParticipantOwnership::empty(ParticipantRole::Helper),
|
||||||
|
ParticipantOwnership::Sandbox(_) => ParticipantOwnership::empty(ParticipantRole::Sandbox),
|
||||||
|
ParticipantOwnership::Publication(_) => ParticipantOwnership::empty(ParticipantRole::Publication),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn terminal_value(seed: u8) -> TerminalOutput {
|
||||||
|
TerminalOutput {
|
||||||
|
session_id: session_id(),
|
||||||
|
bytes: vec![seed],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn terminal_corpus(digest: &mut Sha256) {
|
||||||
|
let resize = TerminalResize {
|
||||||
|
session_id: session_id(),
|
||||||
|
rows: NonZeroU16::new(24).unwrap(),
|
||||||
|
columns: NonZeroU16::new(80).unwrap(),
|
||||||
|
pixel_width: 640,
|
||||||
|
pixel_height: 480,
|
||||||
|
};
|
||||||
|
enum_corpus!(digest, TerminalSignalKind, {
|
||||||
|
TerminalSignalKind::Interrupt => TerminalSignalKind::Interrupt,
|
||||||
|
TerminalSignalKind::Quit => TerminalSignalKind::Quit,
|
||||||
|
TerminalSignalKind::Suspend => TerminalSignalKind::Suspend,
|
||||||
|
});
|
||||||
|
enum_corpus!(digest, SessionTerminalEvent, {
|
||||||
|
SessionTerminalEvent::Input(_) => SessionTerminalEvent::Input(TerminalInput { session_id: session_id(), bytes: vec![1] }),
|
||||||
|
SessionTerminalEvent::Resize(_) => SessionTerminalEvent::Resize(resize),
|
||||||
|
SessionTerminalEvent::Signal(_) => SessionTerminalEvent::Signal(TerminalSignal { session_id: session_id(), signal: TerminalSignalKind::Interrupt }),
|
||||||
|
SessionTerminalEvent::Close(_) => SessionTerminalEvent::Close(SessionClose { session_id: session_id() }),
|
||||||
|
});
|
||||||
|
enum_corpus!(digest, SessionExitOutcome, {
|
||||||
|
SessionExitOutcome::Exited => SessionExitOutcome::Exited,
|
||||||
|
SessionExitOutcome::Terminated => SessionExitOutcome::Terminated,
|
||||||
|
SessionExitOutcome::RuntimeLost => SessionExitOutcome::RuntimeLost,
|
||||||
|
});
|
||||||
|
enum_corpus!(digest, SessionTerminalMessage, {
|
||||||
|
SessionTerminalMessage::Output(_) => SessionTerminalMessage::Output(terminal_value(2)),
|
||||||
|
SessionTerminalMessage::Exit(_) => SessionTerminalMessage::Exit(SessionExit::exited(session_id(), 3)),
|
||||||
|
});
|
||||||
|
enum_corpus!(digest, InteractiveSessionEvent, {
|
||||||
|
InteractiveSessionEvent::Terminal(_) => InteractiveSessionEvent::Terminal(SessionTerminalEvent::Resize(resize)),
|
||||||
|
InteractiveSessionEvent::PromptDecision { .. } => InteractiveSessionEvent::PromptDecision { session_id: session_id(), signed_decision: vec![4] },
|
||||||
|
InteractiveSessionEvent::Poll { .. } => InteractiveSessionEvent::Poll { session_id: session_id() },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn session_message_corpus(digest: &mut Sha256) {
|
||||||
|
let prompt = TerminalPrompt {
|
||||||
|
session_id: session_id(),
|
||||||
|
request_id: RequestId::new(opaque(5)),
|
||||||
|
request_sha256: RequestDigest::new(opaque(6)),
|
||||||
|
agent_profile: "trusted".into(),
|
||||||
|
command_argv: vec![b"tool".to_vec()],
|
||||||
|
justification: "needed".into(),
|
||||||
|
};
|
||||||
|
enum_corpus!(digest, InteractiveSessionMessage, {
|
||||||
|
InteractiveSessionMessage::Terminal(_) => InteractiveSessionMessage::Terminal(SessionTerminalMessage::Output(terminal_value(7))),
|
||||||
|
InteractiveSessionMessage::Prompt(_) => InteractiveSessionMessage::Prompt(prompt),
|
||||||
|
});
|
||||||
|
enum_corpus!(digest, NonInteractiveSessionMessage, {
|
||||||
|
NonInteractiveSessionMessage::Stdout(_) => NonInteractiveSessionMessage::Stdout(NonInteractiveOutput { session_id: session_id(), bytes: vec![8] }),
|
||||||
|
NonInteractiveSessionMessage::Stderr(_) => NonInteractiveSessionMessage::Stderr(NonInteractiveOutput { session_id: session_id(), bytes: vec![9] }),
|
||||||
|
NonInteractiveSessionMessage::Exit(_) => NonInteractiveSessionMessage::Exit(SessionExit::runtime_lost(session_id())),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn enrollment_request() -> ClientEnrollmentRequest {
|
||||||
|
ClientEnrollmentRequest {
|
||||||
|
protocol_version: ProtocolVersion::V1,
|
||||||
|
generation_identity: generation_identity(),
|
||||||
|
cli_id: ClientId::new(opaque(10)),
|
||||||
|
certificate_signing_request_der: vec![11],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn enrollment_response() -> ClientEnrollmentResponse {
|
||||||
|
ClientEnrollmentResponse {
|
||||||
|
protocol_version: ProtocolVersion::V1,
|
||||||
|
credential: TlsCredential::client_cli(
|
||||||
|
generation_identity(),
|
||||||
|
ClientId::new(opaque(10)),
|
||||||
|
vec![12],
|
||||||
|
CertificateDigest::new(opaque(13)),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn registration_request() -> SessionRegistrationRequest {
|
||||||
|
SessionRegistrationRequest {
|
||||||
|
protocol_version: ProtocolVersion::V1,
|
||||||
|
session_binding: session_binding(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn registration_response() -> SessionRegistrationResponse {
|
||||||
|
SessionRegistrationResponse {
|
||||||
|
protocol_version: ProtocolVersion::V1,
|
||||||
|
session_capability: session_capability(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn control_corpus(digest: &mut Sha256) {
|
||||||
|
let resize = TerminalResize {
|
||||||
|
session_id: session_id(),
|
||||||
|
rows: NonZeroU16::new(24).unwrap(),
|
||||||
|
columns: NonZeroU16::new(80).unwrap(),
|
||||||
|
pixel_width: 0,
|
||||||
|
pixel_height: 0,
|
||||||
|
};
|
||||||
|
enum_corpus!(digest, ControlRequest, {
|
||||||
|
ControlRequest::Enroll(_) => ControlRequest::Enroll(enrollment_request()),
|
||||||
|
ControlRequest::Register(_) => ControlRequest::Register(registration_request()),
|
||||||
|
ControlRequest::Execute(_) => ControlRequest::Execute(NonInteractiveSessionRequest { protocol_version: ProtocolVersion::V1, session_id: session_id(), argv: vec![b"tool".to_vec()] }),
|
||||||
|
ControlRequest::ExecuteInteractive(_) => ControlRequest::ExecuteInteractive(InteractiveSessionRequest { protocol_version: ProtocolVersion::V1, session_id: session_id(), argv: vec![b"tool".to_vec()], initial_size: resize }),
|
||||||
|
});
|
||||||
|
enum_corpus!(digest, ControlResponse, {
|
||||||
|
ControlResponse::Enrolled(_) => ControlResponse::Enrolled(enrollment_response()),
|
||||||
|
ControlResponse::Registered(_) => ControlResponse::Registered(registration_response()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn credential_corpus(digest: &mut Sha256) {
|
||||||
|
enum_corpus!(digest, ProtocolVersion, {
|
||||||
|
ProtocolVersion::V1 => ProtocolVersion::V1,
|
||||||
|
});
|
||||||
|
enum_corpus!(digest, TlsRole, {
|
||||||
|
TlsRole::SessionCoordinator => TlsRole::SessionCoordinator,
|
||||||
|
TlsRole::ClientCli => TlsRole::ClientCli,
|
||||||
|
});
|
||||||
|
enum_corpus!(digest, TlsSubjectId, {
|
||||||
|
TlsSubjectId::SessionCoordinator(_) => TlsSubjectId::SessionCoordinator(coordinator_id()),
|
||||||
|
TlsSubjectId::ClientCli(_) => TlsSubjectId::ClientCli(ClientId::new(opaque(14))),
|
||||||
|
});
|
||||||
|
enum_corpus!(digest, ProtocolCredentialRole, {
|
||||||
|
ProtocolCredentialRole::SessionCoordinator => ProtocolCredentialRole::SessionCoordinator,
|
||||||
|
ProtocolCredentialRole::AgentSandbox => ProtocolCredentialRole::AgentSandbox,
|
||||||
|
});
|
||||||
|
enum_corpus!(digest, ProtocolSubjectId, {
|
||||||
|
ProtocolSubjectId::SessionCoordinator(_) => ProtocolSubjectId::SessionCoordinator(coordinator_id()),
|
||||||
|
ProtocolSubjectId::AgentSandbox(_) => ProtocolSubjectId::AgentSandbox(sandbox_id()),
|
||||||
|
});
|
||||||
|
enum_corpus!(digest, DeveloperDecisionKind, {
|
||||||
|
DeveloperDecisionKind::Approve => DeveloperDecisionKind::Approve,
|
||||||
|
DeveloperDecisionKind::Deny => DeveloperDecisionKind::Deny,
|
||||||
|
});
|
||||||
|
enum_corpus!(digest, EscalationOutcome, {
|
||||||
|
EscalationOutcome::Completed => EscalationOutcome::Completed,
|
||||||
|
EscalationOutcome::Denied => EscalationOutcome::Denied,
|
||||||
|
EscalationOutcome::TimedOut => EscalationOutcome::TimedOut,
|
||||||
|
EscalationOutcome::Cancelled => EscalationOutcome::Cancelled,
|
||||||
|
EscalationOutcome::Failed => EscalationOutcome::Failed,
|
||||||
|
});
|
||||||
|
enum_corpus!(digest, ResultStream, {
|
||||||
|
ResultStream::Stdout => ResultStream::Stdout,
|
||||||
|
ResultStream::Stderr => ResultStream::Stderr,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn network_corpus(digest: &mut Sha256) {
|
||||||
|
enum_corpus!(digest, AddressFamily, {
|
||||||
|
AddressFamily::Ipv4 => AddressFamily::Ipv4,
|
||||||
|
AddressFamily::Ipv6 => AddressFamily::Ipv6,
|
||||||
|
});
|
||||||
|
enum_corpus!(digest, AddressFamilyDispositionValue, {
|
||||||
|
AddressFamilyDispositionValue::Enabled => AddressFamilyDispositionValue::Enabled,
|
||||||
|
AddressFamilyDispositionValue::Disabled => AddressFamilyDispositionValue::Disabled,
|
||||||
|
});
|
||||||
|
enum_corpus!(digest, IpAddress, {
|
||||||
|
IpAddress::V4(_) => IpAddress::V4([1, 2, 3, 4]),
|
||||||
|
IpAddress::V6(_) => IpAddress::V6([5; 16]),
|
||||||
|
});
|
||||||
|
enum_corpus!(digest, PolicyAction, {
|
||||||
|
PolicyAction::Allow => PolicyAction::Allow,
|
||||||
|
PolicyAction::Deny => PolicyAction::Deny,
|
||||||
|
});
|
||||||
|
enum_corpus!(digest, PolicyDelivery, {
|
||||||
|
PolicyDelivery::SealedMemfd => PolicyDelivery::SealedMemfd,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn storage_configuration_waiter_corpus(digest: &mut Sha256) {
|
||||||
|
enum_corpus!(digest, ArtifactState, {
|
||||||
|
ArtifactState::Available => ArtifactState::Available,
|
||||||
|
ArtifactState::Reclaiming => ArtifactState::Reclaiming,
|
||||||
|
});
|
||||||
|
enum_corpus!(digest, PrepareStageState, {
|
||||||
|
PrepareStageState::Intent => PrepareStageState::Intent,
|
||||||
|
PrepareStageState::Owned => PrepareStageState::Owned,
|
||||||
|
});
|
||||||
|
enum_corpus!(digest, VolumeKind, {
|
||||||
|
VolumeKind::File => VolumeKind::File,
|
||||||
|
VolumeKind::Directory => VolumeKind::Directory,
|
||||||
|
});
|
||||||
|
enum_corpus!(digest, VolumeAccess, {
|
||||||
|
VolumeAccess::ReadOnly => VolumeAccess::ReadOnly,
|
||||||
|
VolumeAccess::ReadWrite => VolumeAccess::ReadWrite,
|
||||||
|
});
|
||||||
|
enum_corpus!(digest, BootstrapWaitOutcome, {
|
||||||
|
BootstrapWaitOutcome::Waiting => BootstrapWaitOutcome::Waiting,
|
||||||
|
BootstrapWaitOutcome::Published => BootstrapWaitOutcome::Published,
|
||||||
|
BootstrapWaitOutcome::Failed => BootstrapWaitOutcome::Failed,
|
||||||
|
BootstrapWaitOutcome::Refused => BootstrapWaitOutcome::Refused,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn every_serialized_enum_variant_has_fixed_shape_evidence() {
|
||||||
|
let mut digest = Sha256::new();
|
||||||
|
lifecycle_corpus(&mut digest);
|
||||||
|
ownership_slot_corpus(&mut digest);
|
||||||
|
terminal_corpus(&mut digest);
|
||||||
|
session_message_corpus(&mut digest);
|
||||||
|
control_corpus(&mut digest);
|
||||||
|
credential_corpus(&mut digest);
|
||||||
|
network_corpus(&mut digest);
|
||||||
|
storage_configuration_waiter_corpus(&mut digest);
|
||||||
|
assert_eq!(
|
||||||
|
digest.finalize().as_slice(),
|
||||||
|
[
|
||||||
|
91, 180, 216, 8, 22, 13, 86, 141, 24, 220, 203, 225, 25, 175, 149, 91, 254, 88, 90,
|
||||||
|
142, 176, 169, 45, 94, 24, 209, 70, 185, 116, 120, 58, 128,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue