diff --git a/rs/replicated_state/src/canister_state/tests.rs b/rs/replicated_state/src/canister_state/tests.rs index 2042038950d..09e71b0ec54 100644 --- a/rs/replicated_state/src/canister_state/tests.rs +++ b/rs/replicated_state/src/canister_state/tests.rs @@ -14,7 +14,9 @@ use crate::CallOrigin; use crate::Memory; use ic_base_types::NumSeconds; use ic_logger::replica_logger::no_op_logger; -use ic_management_canister_types::{CanisterChange, CanisterChangeDetails, CanisterChangeOrigin}; +use ic_management_canister_types::{ + CanisterChange, CanisterChangeDetails, CanisterChangeOrigin, CanisterLogRecord, LogVisibility, +}; use ic_metrics::MetricsRegistry; use ic_test_utilities::types::{ ids::canister_test_id, @@ -35,6 +37,7 @@ use ic_types::{ }; use ic_wasm_types::CanisterModule; use prometheus::IntCounter; +use strum::IntoEnumIterator; const CANISTER_ID: CanisterId = CanisterId::from_u64(42); const OTHER_CANISTER_ID: CanisterId = CanisterId::from_u64(13); @@ -575,6 +578,52 @@ fn canister_state_callback_round_trip() { assert_eq!(callback, round_trip); } +#[test] +fn canister_state_log_visibility_i32_round_trip() { + for initial in LogVisibility::iter() { + let encoded = i32::from(initial); + let round_trip = LogVisibility::try_from(encoded).unwrap(); + + assert_eq!(initial, round_trip); + } +} + +#[test] +fn canister_state_log_visibility_i32_default() { + const UNSPECIFIED: i32 = 0; + assert_eq!( + LogVisibility::try_from(UNSPECIFIED).unwrap(), + LogVisibility::default() + ); +} + +#[test] +fn canister_state_log_visibility_round_trip() { + use ic_protobuf::state::canister_state_bits::v1 as pb; + + for initial in LogVisibility::iter() { + let encoded = pb::LogVisibility::from(initial); + let round_trip = LogVisibility::from(encoded); + + assert_eq!(initial, round_trip); + } +} + +#[test] +fn canister_state_canister_log_record_round_trip() { + use ic_protobuf::state::canister_state_bits::v1 as pb; + + let initial = CanisterLogRecord { + idx: 42, + timestamp_nanos: 27, + content: vec![1, 2, 3], + }; + let encoded = pb::CanisterLogRecord::from(initial.clone()); + let round_trip = CanisterLogRecord::from(encoded); + + assert_eq!(initial, round_trip); +} + #[test] fn execution_state_test_partial_eq() { let state_1 = ExecutionState::new( diff --git a/rs/state_layout/src/state_layout.rs b/rs/state_layout/src/state_layout.rs index 7482913ae78..21ea8a33cb9 100644 --- a/rs/state_layout/src/state_layout.rs +++ b/rs/state_layout/src/state_layout.rs @@ -1915,7 +1915,7 @@ impl TryFrom for CanisterStateBits { "CanisterStateBits::total_query_stats", ) .unwrap_or_default(), - log_visibility: value.log_visibility.into(), + log_visibility: value.log_visibility.try_into()?, canister_log_records: value .canister_log_records .into_iter() diff --git a/rs/types/management_canister_types/src/lib.rs b/rs/types/management_canister_types/src/lib.rs index be3f5273b61..e951509cd30 100644 --- a/rs/types/management_canister_types/src/lib.rs +++ b/rs/types/management_canister_types/src/lib.rs @@ -670,7 +670,7 @@ impl Payload<'_> for UninstallCodeArgs {} /// public; /// } /// ``` -#[derive(Default, Clone, Copy, CandidType, Deserialize, Debug, PartialEq, Eq)] +#[derive(Default, Clone, Copy, CandidType, Deserialize, Debug, PartialEq, Eq, EnumIter)] pub enum LogVisibility { #[default] #[serde(rename = "controllers")] @@ -688,13 +688,37 @@ impl From for i32 { } } -impl From for LogVisibility { - fn from(item: i32) -> Self { +impl TryFrom for LogVisibility { + type Error = ProxyDecodeError; + + fn try_from(item: i32) -> Result { + match item { + 0 => Ok(Self::default()), + 1 => Ok(Self::Controllers), + 2 => Ok(Self::Public), + _ => Err(ProxyDecodeError::ValueOutOfRange { + typ: "LogVisibility", + err: format!("Unable to convert {:?} to LogVisibility", item), + }), + } + } +} + +impl From for pb_canister_state_bits::LogVisibility { + fn from(item: LogVisibility) -> Self { + match item { + LogVisibility::Controllers => pb_canister_state_bits::LogVisibility::Controllers, + LogVisibility::Public => pb_canister_state_bits::LogVisibility::Public, + } + } +} + +impl From for LogVisibility { + fn from(item: pb_canister_state_bits::LogVisibility) -> Self { match item { - 0 => Self::default(), - 1 => Self::Controllers, - 2 => Self::Public, - _ => panic!("Unsupported value"), + pb_canister_state_bits::LogVisibility::Unspecified => Self::default(), + pb_canister_state_bits::LogVisibility::Controllers => Self::Controllers, + pb_canister_state_bits::LogVisibility::Public => Self::Public, } } }