// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

//! Tests for the encode module.

use crate::args::{ArgMap, ArgTypeMap, ArgTypeSelector, ArgValue};
use crate::cbor::tokenize_cbor_for_debug;
use crate::cbor::{
    cbor_decoder_from_message, cbor_encoder_from_message, encode_bytes_prefix,
};
use crate::constants::*;
use crate::crypto::Hash;
use crate::dice::{
    Cdi, Certificate, DiceInput, DiceInputAuthority, DiceInputCode,
    DiceInputConfig, DiceInputMode, InternalInputType, Uds,
};
use crate::encode::*;
use crate::error::{DpeResult, ErrCode};
use crate::memory::{Message, SmallMessage};
use heapless::Vec;
use log::debug;
use minicbor::Decoder;

/// Encodes and logs input args.
pub(crate) fn encode_and_log_args(
    args: &ArgMap,
    encoded_args: &mut Message,
) -> DpeResult<()> {
    encode_args(args, encoded_args)?;
    debug!(
        "Raw input args: {:?}",
        tokenize_cbor_for_debug(encoded_args.as_slice())
    );
    Ok(())
}

/// Encodes and inserts a command message header containing `command_id`.
///
/// This function is for testing and panics on failure.
#[allow(clippy::unwrap_used)]
pub(crate) fn encode_and_insert_command_header(
    command_id: CommandSelector,
    message: &mut Message,
) {
    let mut prefix = SmallMessage::new();
    let _ = cbor_encoder_from_message(&mut prefix)
        .array(MESSAGE_ARRAY_SIZE)
        .unwrap()
        .u32(command_id as u32)
        .unwrap();
    encode_bytes_prefix(&mut prefix, message.len()).unwrap();
    message.insert_prefix(prefix.as_slice()).unwrap();
}

/// Decodes a command response.
///
/// This function is for testing and panics on failure to decode.
#[allow(clippy::unwrap_used)]
pub(crate) fn decode_response<'a>(
    message: &'a Message,
    arg_types: &ArgTypeMap,
) -> DpeResult<ArgMap<'a>> {
    debug!("Raw response: {:?}", tokenize_cbor_for_debug(message.as_slice()));
    let mut decoder = cbor_decoder_from_message(message);
    assert_eq!(decoder.array().unwrap(), Some(MESSAGE_ARRAY_SIZE));
    let err_code = decoder.u32().unwrap();
    if err_code != 0 {
        return Err(err_code.into());
    }
    assert_eq!(decoder.datatype().unwrap(), minicbor::data::Type::Bytes);
    debug!(
        "Raw output args: {:?}",
        tokenize_cbor_for_debug(decoder.probe().bytes().unwrap())
    );
    Ok(decode_args_internal(decoder.bytes().unwrap(), arg_types).unwrap())
}

/// Decodes an error response.
///
/// This function is for testing and panics on failure to decode.
#[allow(clippy::unwrap_used)]
pub(crate) fn decode_error_response(message: &[u8]) -> DpeResult<()> {
    let mut decoder = Decoder::new(message);
    assert_eq!(decoder.array().unwrap(), Some(MESSAGE_ARRAY_SIZE));
    let err_code = decoder.u32().unwrap();
    assert_ne!(err_code, 0);
    Err(err_code.into())
}

/// Decodes a certificate chain.
///
/// This function is for testing and panics on failure to decode.
#[allow(clippy::unwrap_used)]
pub(crate) fn decode_certificate_chain(encoded: &Message) -> CertificateChain {
    let mut decoder = cbor_decoder_from_message(encoded);
    let num_certs = decoder.array().unwrap().unwrap();
    let mut chain: CertificateChain = Default::default();
    for _ in 0..num_certs {
        chain
            .0
            .push(Certificate(
                Vec::from_slice(decoder.bytes().unwrap()).unwrap(),
            ))
            .unwrap();
    }
    chain
}

/// Encodes a `seed` argument for the `InitializeContext` command.
///
/// This function is for testing and panics on failure to encode.
#[allow(unused_results, clippy::unwrap_used)]
pub(crate) fn encode_init_seed(
    init_type: Option<InitTypeSelector>,
    external_uds_seed: Option<&[u8]>,
    cdi_sign: Option<&[u8]>,
    cdi_seal: Option<&[u8]>,
) -> SmallMessage {
    let mut map_size = 0;
    if init_type.is_some() {
        map_size += 1;
    }
    if external_uds_seed.is_some() {
        map_size += 1;
    }
    if cdi_sign.is_some() {
        map_size += 1;
    }
    if cdi_seal.is_some() {
        map_size += 1;
    }

    let mut encoded_seed = SmallMessage::new();
    let mut encoder = cbor_encoder_from_message(&mut encoded_seed);
    encoder.map(map_size).unwrap();
    if let Some(init_type) = init_type {
        encoder.u8(InitTypeMapKey::InitType as u8).unwrap();
        encoder.u8(init_type as u8).unwrap();
    }
    if let Some(seed) = external_uds_seed {
        encoder.u8(InitTypeMapKey::ExternalSeed as u8).unwrap();
        encoder.bytes(seed).unwrap();
    }
    if let Some(cdi) = cdi_sign {
        encoder.u8(InitTypeMapKey::CdiSign as u8).unwrap();
        encoder.bytes(cdi).unwrap();
    }
    if let Some(cdi) = cdi_seal {
        encoder.u8(InitTypeMapKey::CdiSeal as u8).unwrap();
        encoder.bytes(cdi).unwrap();
    }
    encoded_seed
}

/// Encodes a set of [`InternalInputType`]s for the `DeriveContext` command.
///
/// This function is for testing and panics on failure to encode.
#[allow(unused_results, clippy::unwrap_used)]
pub(crate) fn encode_internal_inputs(
    inputs: &[InternalInputType],
) -> SmallMessage {
    let mut encoded_inputs = SmallMessage::new();
    let mut encoder = cbor_encoder_from_message(&mut encoded_inputs);
    encoder.array(inputs.len() as u64).unwrap();
    for input in inputs {
        encoder.u32(*input as u32).unwrap();
    }
    encoded_inputs
}

/// Encodes a [`LocalityId`].
///
/// This function is for testing and panics on failure to encode.
#[allow(unused_results, clippy::unwrap_used)]
pub(crate) fn encode_locality(locality_id: LocalityId) -> SmallMessage {
    let mut encoded_locality = SmallMessage::new();
    cbor_encoder_from_message(&mut encoded_locality)
        .u32(locality_id.try_into().unwrap())
        .unwrap();
    encoded_locality
}

/// Encodes an `input` argument for the `DeriveContext` command.
///
/// The version info indicates a slot and value to populate when processing
/// this input. This function is for testing and panics on failure to
/// encode.
pub(crate) fn encode_dice_input(
    version_info: Option<(usize, u64)>,
    dice_input: &DiceInput,
) -> Message {
    encode_dice_input_with_error(
        version_info,
        dice_input,
        DiceInputEncodingError::NoError,
    )
}

#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
enum DiceInputEncodingError {
    NoError,
    OmitVersionSlot,
    OmitVersionValue,
    OmitCodeValue,
    OmitConfigValue,
    OmitModeValue,
    MultipleVersionSlots,
    MultipleVersionValues,
    MultipleCodeValues,
    MultipleConfigValues,
    MultipleAuthorityValues,
    MultipleModeValues,
    MultipleHiddenValues,
    ShortCodeHash,
    ShortConfigInline,
    ShortAuthorityHash,
    ShortHidden,
    LongCodeHash,
    LongConfigInline,
    LongAuthorityHash,
    LongHidden,
    InvalidVersionSlotType,
    InvalidVersionValueType,
    InvalidCodeType,
    InvalidConfigType,
    InvalidAuthorityType,
    InvalidModeType,
    InvalidHiddenType,
}

fn predict_dice_input_map_size(
    has_version: bool,
    has_authority: bool,
    has_hidden: bool,
    error: DiceInputEncodingError,
) -> u64 {
    let mut map_size: u64 = 7;
    if !has_version {
        map_size -= 2;
    } else if error == DiceInputEncodingError::OmitVersionSlot
        || error == DiceInputEncodingError::OmitVersionValue
    {
        map_size -= 1;
    } else if error == DiceInputEncodingError::MultipleVersionSlots
        || error == DiceInputEncodingError::MultipleVersionValues
    {
        map_size += 1;
    }
    if !has_authority {
        map_size -= 1;
    } else if error == DiceInputEncodingError::MultipleAuthorityValues {
        map_size += 1;
    }
    if !has_hidden {
        map_size -= 1;
    } else if error == DiceInputEncodingError::MultipleHiddenValues {
        map_size += 1;
    }
    match error {
        DiceInputEncodingError::OmitCodeValue
        | DiceInputEncodingError::OmitConfigValue
        | DiceInputEncodingError::OmitModeValue => {
            map_size -= 1;
        }
        DiceInputEncodingError::MultipleCodeValues
        | DiceInputEncodingError::MultipleConfigValues
        | DiceInputEncodingError::MultipleModeValues => {
            map_size += 1;
        }
        _ => {}
    };
    map_size
}

#[allow(unused_results, clippy::unwrap_used)]
fn encode_dice_input_with_error(
    version_info: Option<(usize, u64)>,
    dice_input: &DiceInput,
    error: DiceInputEncodingError,
) -> Message {
    let mut cbor = Message::new();
    let mut encoder = cbor_encoder_from_message(&mut cbor);
    let map_size = predict_dice_input_map_size(
        version_info.is_some(),
        dice_input.authority.is_some(),
        dice_input.hidden.is_some(),
        error,
    );
    let short_hash: [u8; 63] = [0; 63];
    let long_hash: [u8; 65] = [0; 65];
    encoder.map(map_size).unwrap();
    if let Some(version_info) = version_info {
        if error != DiceInputEncodingError::OmitVersionSlot {
            encoder.u32(DiceInputMapKey::VersionSlot as u32).unwrap();
            if error == DiceInputEncodingError::InvalidVersionSlotType {
                encoder.bytes(&[version_info.0 as u8]).unwrap();
            } else {
                encoder.u8(version_info.0 as u8).unwrap();
            }
            if error == DiceInputEncodingError::MultipleVersionSlots {
                encoder.u32(DiceInputMapKey::VersionSlot as u32).unwrap();
                encoder.u8(version_info.0 as u8).unwrap();
            }
        }
        if error != DiceInputEncodingError::OmitVersionValue {
            encoder.u32(DiceInputMapKey::VersionValue as u32).unwrap();
            if error == DiceInputEncodingError::InvalidVersionValueType {
                encoder.bytes(&[version_info.1 as u8]).unwrap();
            } else {
                encoder.u64(version_info.1).unwrap();
            }
            if error == DiceInputEncodingError::MultipleVersionValues {
                encoder.u32(DiceInputMapKey::VersionValue as u32).unwrap();
                encoder.u64(version_info.1).unwrap();
            }
        }
    }
    if error != DiceInputEncodingError::OmitCodeValue {
        match &dice_input.code {
            DiceInputCode::CodeHash(hash) => {
                encoder.u32(DiceInputMapKey::CodeHash as u32).unwrap();
                if error == DiceInputEncodingError::InvalidCodeType {
                    encoder.u32(0).unwrap();
                } else {
                    let value = match error {
                        DiceInputEncodingError::ShortCodeHash => {
                            short_hash.as_slice()
                        }
                        DiceInputEncodingError::LongCodeHash => {
                            long_hash.as_slice()
                        }
                        _ => hash.as_slice(),
                    };
                    encoder.bytes(value).unwrap();
                    if error == DiceInputEncodingError::MultipleCodeValues {
                        encoder
                            .u32(DiceInputMapKey::CodeDescriptor as u32)
                            .unwrap();
                        encoder.bytes(value).unwrap();
                    }
                }
            }
            DiceInputCode::CodeDescriptor(descriptor) => {
                encoder.u32(DiceInputMapKey::CodeDescriptor as u32).unwrap();
                if error == DiceInputEncodingError::InvalidCodeType {
                    encoder.u32(0).unwrap();
                } else {
                    encoder.bytes(descriptor).unwrap();
                    if error == DiceInputEncodingError::MultipleCodeValues {
                        encoder.u32(DiceInputMapKey::CodeHash as u32).unwrap();
                        encoder.bytes(descriptor).unwrap();
                    }
                }
            }
        };
    }
    if error != DiceInputEncodingError::OmitConfigValue {
        match &dice_input.config {
            DiceInputConfig::ConfigInlineValue(hash) => {
                encoder.u32(DiceInputMapKey::ConfigInlineValue as u32).unwrap();
                if error == DiceInputEncodingError::InvalidConfigType {
                    encoder.u32(0).unwrap();
                } else {
                    let value = match error {
                        DiceInputEncodingError::ShortConfigInline => {
                            short_hash.as_slice()
                        }
                        DiceInputEncodingError::LongConfigInline => {
                            long_hash.as_slice()
                        }
                        _ => hash.as_slice(),
                    };
                    encoder.bytes(value).unwrap();
                    if error == DiceInputEncodingError::MultipleConfigValues {
                        encoder
                            .u32(DiceInputMapKey::ConfigDescriptor as u32)
                            .unwrap();
                        encoder.bytes(value).unwrap();
                    }
                }
            }
            DiceInputConfig::ConfigDescriptor(descriptor) => {
                encoder.u32(DiceInputMapKey::ConfigDescriptor as u32).unwrap();
                if error == DiceInputEncodingError::InvalidConfigType {
                    encoder.u32(0).unwrap();
                } else {
                    encoder.bytes(descriptor).unwrap();
                    if error == DiceInputEncodingError::MultipleConfigValues {
                        encoder
                            .u32(DiceInputMapKey::ConfigInlineValue as u32)
                            .unwrap();
                        encoder.bytes(descriptor).unwrap();
                    }
                }
            }
        }
    }
    if let Some(authority) = &dice_input.authority {
        match authority {
            DiceInputAuthority::AuthorityHash(hash) => {
                encoder.u32(DiceInputMapKey::AuthorityHash as u32).unwrap();
                if error == DiceInputEncodingError::InvalidAuthorityType {
                    encoder.u32(0).unwrap();
                } else {
                    let value = match error {
                        DiceInputEncodingError::ShortAuthorityHash => {
                            short_hash.as_slice()
                        }
                        DiceInputEncodingError::LongAuthorityHash => {
                            long_hash.as_slice()
                        }
                        _ => hash.as_slice(),
                    };
                    encoder.bytes(value).unwrap();
                    if error == DiceInputEncodingError::MultipleAuthorityValues
                    {
                        encoder
                            .u32(DiceInputMapKey::AuthorityDescriptor as u32)
                            .unwrap();
                        encoder.bytes(value).unwrap();
                    }
                }
            }
            DiceInputAuthority::AuthorityDescriptor(descriptor) => {
                encoder
                    .u32(DiceInputMapKey::AuthorityDescriptor as u32)
                    .unwrap();
                if error == DiceInputEncodingError::InvalidAuthorityType {
                    encoder.u32(0).unwrap();
                } else {
                    encoder.bytes(descriptor).unwrap();
                    if error == DiceInputEncodingError::MultipleAuthorityValues
                    {
                        encoder
                            .u32(DiceInputMapKey::AuthorityHash as u32)
                            .unwrap();
                        encoder.bytes(descriptor).unwrap();
                    }
                }
            }
        }
    }
    if error != DiceInputEncodingError::OmitModeValue {
        encoder.u32(DiceInputMapKey::Mode as u32).unwrap();
        if error == DiceInputEncodingError::InvalidModeType {
            encoder.bytes(short_hash.as_slice()).unwrap();
        } else {
            encoder.u8(dice_input.mode as u8).unwrap();
            if error == DiceInputEncodingError::MultipleModeValues {
                encoder.u32(DiceInputMapKey::Mode as u32).unwrap();
                encoder.u8(dice_input.mode as u8).unwrap();
            }
        }
    }
    if let Some(hidden) = &dice_input.hidden {
        encoder.u32(DiceInputMapKey::Hidden as u32).unwrap();
        if error == DiceInputEncodingError::InvalidHiddenType {
            encoder.u32(0).unwrap();
        } else {
            let value = match error {
                DiceInputEncodingError::ShortHidden => short_hash.as_slice(),
                DiceInputEncodingError::LongHidden => long_hash.as_slice(),
                _ => hidden.as_slice(),
            };
            encoder.bytes(value).unwrap();
            if error == DiceInputEncodingError::MultipleHiddenValues {
                encoder.u32(DiceInputMapKey::Hidden as u32).unwrap();
                encoder.bytes(value).unwrap();
            }
        }
    }
    cbor
}

/// Encodes an unseal policy argument for the sealing commands.
#[allow(clippy::unwrap_used)]
pub(crate) fn encode_unseal_policy(
    versions: &[u64; DPE_MAX_VERSION_SLOTS],
) -> SmallMessage {
    let mut encoded_policy = SmallMessage::new();
    let mut encoder = cbor_encoder_from_message(&mut encoded_policy);
    let count = versions.iter().filter(|&&v| v != 0).count();
    let _ = encoder.map(count as u64).unwrap();
    for (slot, &value) in
        versions.iter().enumerate().take(DPE_MAX_VERSION_SLOTS)
    {
        if value != 0 {
            let _ = encoder.u16(slot as u16).unwrap();
            let _ = encoder.u64(value).unwrap();
        }
    }
    encoded_policy
}

fn test_init() {
    let _ = env_logger::builder().is_test(true).try_init();
}

#[test]
fn context_handle_decode() {
    test_init();
    assert_eq!(None, ContextHandle::from_slice_to_option(&[]).unwrap());
    assert_ne!(
        None,
        ContextHandle::from_slice_to_option(&[0; DPE_HANDLE_SIZE]).unwrap()
    );
    assert_eq!(
        ErrCode::InvalidArgument,
        ContextHandle::from_slice_to_option(&[0; DPE_HANDLE_SIZE - 1])
            .unwrap_err()
    );
}

#[test]
fn internal_input_decode() {
    test_init();
    assert_eq!(InternalInputType::DpeInfo, 1u32.try_into().unwrap());
    assert_eq!(
        ErrCode::InvalidArgument,
        <InternalInputType as TryFrom<u32>>::try_from(0).unwrap_err()
    );
}

#[test]
fn command_selector_decode() {
    test_init();
    assert_eq!(CommandSelector::GetProfile, 1u32.try_into().unwrap());
    assert_eq!(
        ErrCode::InvalidCommand,
        <CommandSelector as TryFrom<u32>>::try_from(0).unwrap_err()
    );
}

#[test]
fn init_type_map_key_decode() {
    test_init();
    assert_eq!(InitTypeMapKey::InitType, 1u32.try_into().unwrap());
    assert_eq!(
        ErrCode::InvalidArgument,
        <InitTypeMapKey as TryFrom<u32>>::try_from(0).unwrap_err()
    );
}

#[test]
fn init_type_selector_decode() {
    test_init();
    assert_eq!(InitTypeSelector::Uds, 1u32.try_into().unwrap());
    assert_eq!(
        ErrCode::InvalidArgument,
        <InitTypeSelector as TryFrom<u32>>::try_from(0).unwrap_err()
    );
}

#[test]
fn dice_input_mode_decode() {
    test_init();
    assert_eq!(DiceInputMode::Normal, 1u8.try_into().unwrap());
    assert_eq!(
        ErrCode::InvalidArgument,
        <DiceInputMode as TryFrom<u8>>::try_from(10).unwrap_err()
    );
}

#[test]
fn dice_input_map_key_decode() {
    test_init();
    assert_eq!(DiceInputMapKey::VersionSlot, 1u32.try_into().unwrap());
    assert_eq!(
        ErrCode::InvalidArgument,
        <DiceInputMapKey as TryFrom<u32>>::try_from(0).unwrap_err()
    );
}

#[test]
fn internal_inputs_decode() {
    test_init();
    let before =
        [InternalInputType::DpeInfo, InternalInputType::MonotonicCounter];
    let after =
        decode_internal_inputs(encode_internal_inputs(&before).as_slice())
            .unwrap();
    assert_eq!(before, after);
}

#[test]
fn locality_decode() {
    test_init();
    let default = LocalityId::new(0).unwrap();
    let before = LocalityId::new((DPE_NUM_LOCALITIES - 1) as u32).unwrap();
    let after =
        decode_locality(encode_locality(before).as_slice(), default).unwrap();
    assert_eq!(before, after);
    assert_eq!(default, decode_locality(&[], default).unwrap());
}

#[test]
fn init_seed_decode() {
    test_init();
    let uds_value = Uds::from_array(&[0; DICE_UDS_SIZE]);
    let cdi_sign = Cdi::from_array(&[1; DICE_CDI_SIZE]);
    let cdi_seal = Cdi::from_array(&[2; DICE_CDI_SIZE]);
    let invalid_seed = encode_init_seed(None, None, None, None);
    let uds_internal_init = InitType::InternalUds;
    let uds_internal_seed =
        encode_init_seed(Some(InitTypeSelector::Uds), None, None, None);
    let uds_external_init =
        InitType::Uds { external_uds_seed: uds_value.clone() };
    let uds_external_seed = encode_init_seed(
        Some(InitTypeSelector::Uds),
        Some(uds_value.as_slice()),
        None,
        None,
    );
    let cdi_internal_init = InitType::InternalCdis;
    let cdi_internal_seed =
        encode_init_seed(Some(InitTypeSelector::Cdi), None, None, None);
    let cdi_external_init = InitType::Cdis {
        cdi_sign: cdi_sign.clone(),
        cdi_seal: cdi_seal.clone(),
    };
    let cdi_external_seed = encode_init_seed(
        Some(InitTypeSelector::Cdi),
        None,
        Some(cdi_sign.as_slice()),
        Some(cdi_seal.as_slice()),
    );
    let cdi_external_sign_init = InitType::Cdis {
        cdi_sign: cdi_sign.clone(),
        cdi_seal: cdi_sign.clone(),
    };
    let cdi_external_sign_seed = encode_init_seed(
        Some(InitTypeSelector::Cdi),
        None,
        Some(cdi_sign.as_slice()),
        None,
    );
    assert_eq!(
        ErrCode::InvalidArgument,
        decode_init_seed(invalid_seed.as_slice()).unwrap_err()
    );
    assert_eq!(
        uds_internal_init,
        decode_init_seed(uds_internal_seed.as_slice()).unwrap()
    );
    assert_eq!(
        uds_external_init,
        decode_init_seed(uds_external_seed.as_slice()).unwrap()
    );
    assert_eq!(
        cdi_internal_init,
        decode_init_seed(cdi_internal_seed.as_slice()).unwrap()
    );
    assert_eq!(
        cdi_external_init,
        decode_init_seed(cdi_external_seed.as_slice()).unwrap()
    );
    assert_eq!(
        cdi_external_sign_init,
        decode_init_seed(cdi_external_sign_seed.as_slice()).unwrap()
    );
}

#[test]
fn dice_input_decode() {
    test_init();
    let version_info = (0, 1);
    let invalid_version_info = (DPE_MAX_VERSION_SLOTS, 2);
    let hash_value = Hash::from_array(&[0; HASH_SIZE]);
    let descriptor_value = Message::new();
    let hash_dice_input = DiceInput {
        code: DiceInputCode::CodeHash(hash_value.clone()),
        config: DiceInputConfig::ConfigInlineValue(hash_value.clone()),
        authority: Some(DiceInputAuthority::AuthorityHash(hash_value.clone())),
        mode: DiceInputMode::Normal,
        hidden: Some(hash_value.clone()),
    };
    let descriptor_dice_input = DiceInput {
        code: DiceInputCode::CodeDescriptor(descriptor_value.as_slice()),
        config: DiceInputConfig::ConfigDescriptor(descriptor_value.as_slice()),
        authority: Some(DiceInputAuthority::AuthorityDescriptor(
            descriptor_value.as_slice(),
        )),
        mode: DiceInputMode::Normal,
        hidden: Some(hash_value.clone()),
    };

    for dice_input in [&hash_dice_input, &descriptor_dice_input] {
        // Success case
        let encoded_dice_input = encode_dice_input(None, dice_input);
        let (decoded_version_info, decoded_dice_input) =
            decode_dice_input(encoded_dice_input.as_slice()).unwrap();
        assert_eq!(*dice_input, decoded_dice_input);
        assert_eq!(None, decoded_version_info);

        let encoded_dice_input =
            encode_dice_input(Some(version_info), dice_input);
        let (decoded_version_info, decoded_dice_input) =
            decode_dice_input(encoded_dice_input.as_slice()).unwrap();
        assert_eq!(*dice_input, decoded_dice_input);
        assert_eq!(Some(version_info), decoded_version_info);

        let mut input_without_authority = dice_input.clone();
        input_without_authority.authority = None;
        let encoded_dice_input =
            encode_dice_input(Some(version_info), dice_input);
        let (decoded_version_info, decoded_dice_input) =
            decode_dice_input(encoded_dice_input.as_slice()).unwrap();
        assert_eq!(*dice_input, decoded_dice_input);
        assert_eq!(Some(version_info), decoded_version_info);

        let mut input_without_hidden = dice_input.clone();
        input_without_hidden.hidden = None;
        let encoded_dice_input =
            encode_dice_input(Some(version_info), dice_input);
        let (decoded_version_info, decoded_dice_input) =
            decode_dice_input(encoded_dice_input.as_slice()).unwrap();
        assert_eq!(*dice_input, decoded_dice_input);
        assert_eq!(Some(version_info), decoded_version_info);

        // Invalid version case
        let encoded_dice_input =
            encode_dice_input(Some(invalid_version_info), dice_input);
        assert_eq!(
            ErrCode::InvalidArgument,
            decode_dice_input(encoded_dice_input.as_slice(),).unwrap_err()
        );

        // Encoding error cases
        for error in [
            DiceInputEncodingError::OmitVersionSlot,
            DiceInputEncodingError::OmitVersionValue,
            DiceInputEncodingError::OmitCodeValue,
            DiceInputEncodingError::OmitConfigValue,
            DiceInputEncodingError::OmitModeValue,
            DiceInputEncodingError::MultipleVersionSlots,
            DiceInputEncodingError::MultipleVersionValues,
            DiceInputEncodingError::MultipleCodeValues,
            DiceInputEncodingError::MultipleConfigValues,
            DiceInputEncodingError::MultipleAuthorityValues,
            DiceInputEncodingError::MultipleModeValues,
            DiceInputEncodingError::MultipleHiddenValues,
            DiceInputEncodingError::InvalidVersionSlotType,
            DiceInputEncodingError::InvalidVersionValueType,
            DiceInputEncodingError::InvalidCodeType,
            DiceInputEncodingError::InvalidConfigType,
            DiceInputEncodingError::InvalidAuthorityType,
            DiceInputEncodingError::InvalidModeType,
            DiceInputEncodingError::InvalidHiddenType,
        ] {
            let encoded_dice_input = encode_dice_input_with_error(
                Some(version_info),
                dice_input,
                error,
            );
            assert_eq!(
                ErrCode::InvalidArgument,
                decode_dice_input(encoded_dice_input.as_slice()).unwrap_err()
            );
        }
    }

    // Hash length error cases
    for error in [
        DiceInputEncodingError::ShortCodeHash,
        DiceInputEncodingError::ShortConfigInline,
        DiceInputEncodingError::ShortAuthorityHash,
        DiceInputEncodingError::ShortHidden,
        DiceInputEncodingError::LongCodeHash,
        DiceInputEncodingError::LongConfigInline,
        DiceInputEncodingError::LongAuthorityHash,
        DiceInputEncodingError::LongHidden,
    ] {
        let encoded_dice_input = encode_dice_input_with_error(
            Some(version_info),
            &hash_dice_input,
            error,
        );
        assert_eq!(
            ErrCode::InvalidArgument,
            decode_dice_input(encoded_dice_input.as_slice()).unwrap_err()
        );
    }
}

#[test]
fn unseal_policy_decode() {
    test_init();
    let empty_versions = [0; DPE_MAX_VERSION_SLOTS];
    let mut one_version = empty_versions.clone();
    one_version[0] = 1;
    let full_versions = [2; DPE_MAX_VERSION_SLOTS];

    assert_eq!(
        empty_versions,
        decode_unseal_policy(encode_unseal_policy(&empty_versions).as_slice())
            .unwrap()
    );

    assert_eq!(
        one_version,
        decode_unseal_policy(encode_unseal_policy(&one_version).as_slice())
            .unwrap()
    );

    assert_eq!(
        full_versions,
        decode_unseal_policy(encode_unseal_policy(&full_versions).as_slice())
            .unwrap()
    );

    let mut buffer = SmallMessage::new();
    let mut encoder = cbor_encoder_from_message(&mut buffer);
    let _ = encoder.begin_map().unwrap().end().unwrap();
    assert_eq!(
        ErrCode::InvalidArgument,
        decode_unseal_policy(buffer.as_slice()).unwrap_err()
    );

    buffer.clear();
    let mut encoder = cbor_encoder_from_message(&mut buffer);
    let _ = encoder.map(DPE_MAX_VERSION_SLOTS as u64 + 1);
    for i in 0..DPE_MAX_VERSION_SLOTS as u16 + 1 {
        let _ = encoder.u16(i).unwrap().u64(100).unwrap();
    }
    assert_eq!(
        ErrCode::InvalidArgument,
        decode_unseal_policy(buffer.as_slice()).unwrap_err()
    );
}

#[test]
fn check_error_response() {
    let mut buffer = Message::new();
    create_error_response(ErrCode::OutOfMemory, &mut buffer);
    assert_eq!(
        ErrCode::OutOfMemory,
        decode_error_response(buffer.as_slice()).unwrap_err()
    );
    create_plaintext_session_error_response(ErrCode::Canceled, &mut buffer);
    let mut decoder = cbor_decoder_from_message(&buffer);
    assert_eq!(2, decoder.array().unwrap().unwrap());
    assert_eq!(0, decoder.u64().unwrap());
    assert_eq!(
        ErrCode::Canceled,
        decode_error_response(decoder.bytes().unwrap()).unwrap_err()
    );
}

#[test]
fn encode_decode_args() {
    let mut buffer = Message::new();
    let empty: [u8; 0] = Default::default();
    let small = [0xFF; 50];
    let large = [0xAA; 2000];
    let arg_map = ArgMap::from_iter([
        (1, ArgValue::Bool(true)),
        (2, ArgValue::Bytes(&empty)),
        (3, ArgValue::Bytes(&small)),
        (4, ArgValue::Bytes(&large)),
        (5, ArgValue::Int(5)),
        (6, ArgValue::Int(2)),
    ]);
    let arg_types = ArgTypeMap::from_iter([
        (4, ArgTypeSelector::Bytes),
        (5, ArgTypeSelector::Int),
        (6, ArgTypeSelector::Int),
        (1, ArgTypeSelector::Bool(false)),
        (2, ArgTypeSelector::Bytes),
        (3, ArgTypeSelector::Bytes),
    ]);
    encode_args(&arg_map, &mut buffer).unwrap();
    {
        let decoded_arg_map =
            decode_args(buffer.as_slice(), &arg_types).unwrap();
        assert_eq!(arg_map, decoded_arg_map);
        // Since all fields are defined, defaults are superfluous.
        let decoded_arg_map =
            decode_args(buffer.as_slice(), &arg_types).unwrap();
        assert_eq!(arg_map, decoded_arg_map);
    }

    let arg_map_empty = ArgMap::new();
    let arg_map_with_defaults = ArgMap::from_iter(
        arg_types
            .clone()
            .into_iter()
            .map(|(id, arg_type)| (id, arg_type.default_value().unwrap())),
    );
    encode_args(&arg_map_empty, &mut buffer).unwrap();
    {
        let decoded_arg_map =
            decode_args(buffer.as_slice(), &arg_types).unwrap();
        assert_eq!(arg_map_with_defaults, decoded_arg_map);
    }
}

#[test]
fn decode_invalid_args() {
    // Empty bytes -> not valid CBOR map
    assert_eq!(
        ErrCode::InvalidCommand,
        decode_args(&[], &ArgTypeMap::new()).unwrap_err()
    );
    let mut buffer = Message::new();
    // CBOR array -> not valid CBOR map
    let _ = cbor_encoder_from_message(&mut buffer)
        .array(MESSAGE_ARRAY_SIZE)
        .unwrap()
        .bool(true)
        .unwrap()
        .u64(7)
        .unwrap();
    let arg_types = ArgTypeMap::from_iter([(1, ArgTypeSelector::Bool(false))]);
    assert_eq!(
        ErrCode::InvalidCommand,
        decode_args(buffer.as_slice(), &arg_types).unwrap_err()
    );
    buffer.clear();
    // CBOR indefinite map -> should be not supported
    let _ = cbor_encoder_from_message(&mut buffer)
        .begin_map()
        .unwrap()
        .end()
        .unwrap();
    assert_eq!(
        ErrCode::InvalidCommand,
        decode_args(buffer.as_slice(), &arg_types).unwrap_err()
    );
    // All args must be represented in arg types
    let unknown_arg = ArgMap::from_iter([(17, ArgValue::Int(17))]);
    encode_args(&unknown_arg, &mut buffer).unwrap();
    assert_eq!(
        ErrCode::InvalidArgument,
        decode_args(buffer.as_slice(), &arg_types).unwrap_err()
    );
}

#[test]
fn cdi_export_encode() {
    let cdi1 = Cdi::from_array(&[0xAA; DICE_CDI_SIZE]);
    let cdi2 = Cdi::from_array(&[0xBB; DICE_CDI_SIZE]);
    let mut buffer = SmallMessage::new();
    encode_cdis_for_export(&cdi1, &cdi2, &mut buffer).unwrap();
    let mut decoder = cbor_decoder_from_message(&buffer);
    assert_eq!(decoder.array().unwrap().unwrap(), 2);
    assert_eq!(cdi1, Cdi::from_slice(decoder.bytes().unwrap()).unwrap());
    assert_eq!(cdi2, Cdi::from_slice(decoder.bytes().unwrap()).unwrap());
}

#[test]
fn certificate_chain_encode() {
    let cert1 = Certificate(
        Vec::from_slice(&[0x11; DPE_MAX_CERTIFICATE_SIZE]).unwrap(),
    );
    let cert2 = Certificate(Vec::from_slice(&[0x22; 1]).unwrap());
    let cert3: Certificate = Default::default();
    let chain = CertificateChain(
        Vec::from_slice(&[cert1.clone(), cert2.clone(), cert3.clone()])
            .unwrap(),
    );
    let mut buffer = Message::new();
    encode_certificate_chain(&chain, &mut buffer).unwrap();
    assert_eq!(chain, decode_certificate_chain(&buffer));
}

#[test]
fn message_header() {
    let session_id = SessionId::new(DPE_MAX_SESSIONS as u32).unwrap();
    let content = [0u8; 100];
    let mut buffer = Message::from_slice(&content).unwrap();
    encode_and_insert_session_message_header(session_id, &mut buffer).unwrap();
    assert!(content.len() < buffer.len());
    assert_eq!(
        session_id,
        decode_and_remove_session_message_header(&mut buffer).unwrap()
    );
    assert_eq!(content, buffer.as_slice());
}

#[test]
fn decode_invalid_message_header() {
    let mut buffer = Message::new();
    assert_eq!(
        ErrCode::InvalidCommand,
        decode_and_remove_session_message_header(&mut buffer).unwrap_err()
    );
    let mut buffer = Message::from_slice(&[0; 14]).unwrap();
    assert_eq!(
        ErrCode::InvalidCommand,
        decode_and_remove_session_message_header(&mut buffer).unwrap_err()
    );
    // Add an unexpected array element.
    buffer.clear();
    let _ = cbor_encoder_from_message(&mut buffer)
        .array(3)
        .unwrap()
        .u32(1)
        .unwrap()
        .u32(2)
        .unwrap()
        .u32(3)
        .unwrap();
    assert_eq!(
        ErrCode::InvalidCommand,
        decode_and_remove_session_message_header(&mut buffer).unwrap_err()
    );
    // Use an invalid id type.
    buffer.clear();
    let _ = cbor_encoder_from_message(&mut buffer)
        .array(MESSAGE_ARRAY_SIZE)
        .unwrap()
        .bytes(&[])
        .unwrap()
        .u32(2)
        .unwrap();
    assert_eq!(
        ErrCode::InvalidCommand,
        decode_and_remove_session_message_header(&mut buffer).unwrap_err()
    );
}

#[test]
fn command_header() {
    let command_id = CommandSelector::RotateContextHandle;
    let content = [0u8; 100];
    let mut buffer = Message::from_slice(&content).unwrap();
    encode_and_insert_command_header(command_id, &mut buffer);
    assert!(content.len() < buffer.len());
    assert_eq!(
        command_id,
        decode_and_remove_command_header(&mut buffer).unwrap()
    );
    assert_eq!(content, buffer.as_slice());
}

#[test]
fn decode_invalid_command_header() {
    let mut buffer = Message::new();
    assert_eq!(
        ErrCode::InvalidCommand,
        decode_and_remove_command_header(&mut buffer).unwrap_err()
    );
    let mut buffer = Message::from_slice(&[0; 14]).unwrap();
    assert_eq!(
        ErrCode::InvalidCommand,
        decode_and_remove_command_header(&mut buffer).unwrap_err()
    );
    // Add an unexpected array element.
    buffer.clear();
    let _ = cbor_encoder_from_message(&mut buffer)
        .array(3)
        .unwrap()
        .u32(1)
        .unwrap()
        .u32(2)
        .unwrap()
        .u32(3)
        .unwrap();
    assert_eq!(
        ErrCode::InvalidCommand,
        decode_and_remove_command_header(&mut buffer).unwrap_err()
    );
    // Use an invalid id type.
    buffer.clear();
    let _ = cbor_encoder_from_message(&mut buffer)
        .array(MESSAGE_ARRAY_SIZE)
        .unwrap()
        .bytes(&[])
        .unwrap()
        .u32(2)
        .unwrap();
    assert_eq!(
        ErrCode::InvalidCommand,
        decode_and_remove_command_header(&mut buffer).unwrap_err()
    );
    // Use an invalid command id.
    buffer.clear();
    let _ = cbor_encoder_from_message(&mut buffer)
        .array(MESSAGE_ARRAY_SIZE)
        .unwrap()
        .u32(1000)
        .unwrap()
        .u32(2)
        .unwrap();
    assert_eq!(
        ErrCode::InvalidCommand,
        decode_and_remove_command_header(&mut buffer).unwrap_err()
    );
}

#[test]
fn response_header() {
    let content = [0u8; 100];
    let mut buffer = Message::from_slice(&content).unwrap();
    encode_and_insert_response_header(&mut buffer).unwrap();
    assert!(content.len() < buffer.len());
    let mut decoder = cbor_decoder_from_message(&buffer);
    assert_eq!(2, decoder.array().unwrap().unwrap());
    assert_eq!(0, decoder.u32().unwrap());
    assert_eq!(content, decoder.bytes().unwrap());
    let overflow_content = [0u8; MAX_MESSAGE_SIZE - 2];
    let mut buffer = Message::from_slice(&overflow_content).unwrap();
    assert_eq!(
        ErrCode::OutOfMemory,
        encode_and_insert_response_header(&mut buffer).unwrap_err()
    );
}

#[test]
fn profile_descriptor() {
    let name = "test";
    let mut buffer = Message::new();
    encode_profile_descriptor_from_name(name, &mut buffer).unwrap();
    let mut decoder = cbor_decoder_from_message(&buffer);
    assert_eq!(1, decoder.map().unwrap().unwrap());
    assert_eq!(1, decoder.u32().unwrap());
    assert_eq!(name, decoder.str().unwrap());
}

#[test]
fn handshake_payload() {
    let session_id = SessionId::new(1).unwrap();
    let payload = encode_handshake_payload(session_id).unwrap();
    let mut decoder = cbor_decoder_from_message(&payload);
    assert_eq!(u32::from(session_id), decoder.u32().unwrap());
}
