/*
 * Copyright (c) 2025-2026 The Johns Hopkins University Applied Physics
 * Laboratory LLC.
 *
 * This file is part of the Bundle Protocol Security Library (BSL).
 *
 * 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
 *     http://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.
 *
 * This work was performed for the Jet Propulsion Laboratory, California
 * Institute of Technology, sponsored by the United States Government under
 * the prime contract 80NM0018D0004 between the Caltech and NASA under
 * subcontract 1700763.
 */
#include <unity.h>

#include <BPSecLib_Public.h>
#include <CryptoInterface.h>
#include <backend/SecurityActionSet.h>
#include <backend/SecurityResultSet.h>
#include <policy_provider/SamplePolicyProvider.h>
#include <security_context/rfc9173.h>
#include <mock_bpa/agent.h>
#include <mock_bpa/log.h>

#include "bsl_test_utils.h"

typedef struct
{
    BSL_SecParam_t param_scope_flag;
    BSL_SecParam_t param_scope_flag_7;
    BSL_SecParam_t param_sha_variant_512;
    BSL_SecParam_t param_sha_variant_384;
    BSL_SecParam_t param_aes_variant_128;
    BSL_SecParam_t param_aes_variant_256;
    BSL_SecParam_t param_aad_scope_flag;
    BSL_SecParam_t param_auth_tag;
    BSL_SecParam_t param_iv;
    BSL_SecParam_t param_wrapped_key;
    BSL_SecParam_t param_use_wrap_key;
    BSL_SecParam_t param_dont_use_wrap_key;
    BSL_SecParam_t param_test_bib_key_correct;
    BSL_SecParam_t param_test_bib_key_bad;
    BSL_SecParam_t param_test_bcb_key_correct;
    BSL_SecParam_t param_test_bcb_key_bad;
    BSL_SecParam_t param_test_bcb_2_key_correct;
    BSL_SecParam_t param_test_bcb_2_key_bad;
} BSL_TestPublInterfaceCtx_t;

static BSL_TestContext_t          LocalTestCtx = { 0 };
static BSL_SecurityActionSet_t    action_set   = { 0 };
static BSL_TestPublInterfaceCtx_t ctx          = { 0 };
static BSLP_PolicyProvider_t     *policy_provider;

void suiteSetUp(void)
{
    TEST_ASSERT_EQUAL_INT(0, BSL_HostDescriptors_Set(MockBPA_Agent_Descriptors(NULL)));
    mock_bpa_LogOpen();
}

int suiteTearDown(int failures)
{
    mock_bpa_LogClose();
    BSL_HostDescriptors_Clear();
    return failures;
}

void PublicInterfaceTestCtx_init(BSL_TestPublInterfaceCtx_t *ctx)
{
    BSL_SecParam_Init(&ctx->param_scope_flag);
    BSL_SecParam_Init(&ctx->param_scope_flag_7);
    BSL_SecParam_Init(&ctx->param_sha_variant_512);
    BSL_SecParam_Init(&ctx->param_sha_variant_384);
    BSL_SecParam_Init(&ctx->param_aes_variant_128);
    BSL_SecParam_Init(&ctx->param_aes_variant_256);
    BSL_SecParam_Init(&ctx->param_aad_scope_flag);
    BSL_SecParam_Init(&ctx->param_auth_tag);
    BSL_SecParam_Init(&ctx->param_iv);
    BSL_SecParam_Init(&ctx->param_wrapped_key);
    BSL_SecParam_Init(&ctx->param_use_wrap_key);
    BSL_SecParam_Init(&ctx->param_dont_use_wrap_key);
    BSL_SecParam_Init(&ctx->param_test_bib_key_correct);
    BSL_SecParam_Init(&ctx->param_test_bib_key_bad);
    BSL_SecParam_Init(&ctx->param_test_bcb_key_correct);
    BSL_SecParam_Init(&ctx->param_test_bcb_key_bad);
    BSL_SecParam_Init(&ctx->param_test_bcb_2_key_correct);
    BSL_SecParam_Init(&ctx->param_test_bcb_2_key_bad);
}

void PublicInterfaceTestCtx_deinit(BSL_TestPublInterfaceCtx_t *ctx)
{
    BSL_SecParam_Deinit(&ctx->param_scope_flag);
    BSL_SecParam_Deinit(&ctx->param_scope_flag_7);
    BSL_SecParam_Deinit(&ctx->param_sha_variant_512);
    BSL_SecParam_Deinit(&ctx->param_sha_variant_384);
    BSL_SecParam_Deinit(&ctx->param_aes_variant_128);
    BSL_SecParam_Deinit(&ctx->param_aes_variant_256);
    BSL_SecParam_Deinit(&ctx->param_aad_scope_flag);
    BSL_SecParam_Deinit(&ctx->param_auth_tag);
    BSL_SecParam_Deinit(&ctx->param_iv);
    BSL_SecParam_Deinit(&ctx->param_wrapped_key);
    BSL_SecParam_Deinit(&ctx->param_use_wrap_key);
    BSL_SecParam_Deinit(&ctx->param_dont_use_wrap_key);
    BSL_SecParam_Deinit(&ctx->param_test_bib_key_correct);
    BSL_SecParam_Deinit(&ctx->param_test_bib_key_bad);
    BSL_SecParam_Deinit(&ctx->param_test_bcb_key_correct);
    BSL_SecParam_Deinit(&ctx->param_test_bcb_key_bad);
    BSL_SecParam_Deinit(&ctx->param_test_bcb_2_key_correct);
    BSL_SecParam_Deinit(&ctx->param_test_bcb_2_key_bad);
}

void setUp(void)
{
    setenv("BSL_TEST_LOCAL_IPN_EID", "ipn:2.1", 1);
    BSL_CryptoInit();
    TEST_ASSERT_EQUAL(0, BSL_TestContext_Init(&LocalTestCtx, true));
    PublicInterfaceTestCtx_init(&ctx);
    policy_provider = BSLP_PolicyProvider_Init(1);

    /// Register the policy provider with some rules
    BSL_PolicyDesc_t policy_desc = { 0 };
    policy_desc.user_data        = policy_provider;
    policy_desc.query_fn         = BSLP_QueryPolicy;
    policy_desc.deinit_fn        = BSLP_Deinit;
    policy_desc.finalize_fn      = BSLP_FinalizePolicy;
    TEST_ASSERT_EQUAL(0, BSL_API_RegisterPolicyProvider(&LocalTestCtx.bsl, BSL_SAMPLE_PP_ID, policy_desc));

    BSLP_PolicyProvider_t *policy = BSL_PolicyDict_get(LocalTestCtx.bsl.policy_reg, BSL_SAMPLE_PP_ID)->user_data;

    // FIXME these params need managed lifecycle to ensure Deinit (by some means)
    BSL_SecParam_InitUint64(&ctx.param_scope_flag, RFC9173_BIB_PARAMID_INTEG_SCOPE_FLAG, 0);
    BSL_SecParam_InitUint64(&ctx.param_scope_flag_7, RFC9173_BIB_PARAMID_INTEG_SCOPE_FLAG, 0x7);
    BSL_SecParam_InitUint64(&ctx.param_sha_variant_512, RFC9173_BIB_PARAMID_SHA_VARIANT, RFC9173_BIB_SHA_HMAC512);
    BSL_SecParam_InitUint64(&ctx.param_sha_variant_384, RFC9173_BIB_PARAMID_SHA_VARIANT, RFC9173_BIB_SHA_HMAC384);

    BSL_SecParam_InitUint64(&ctx.param_aes_variant_128, RFC9173_BCB_SECPARAM_AESVARIANT,
                            RFC9173_BCB_AES_VARIANT_A128GCM);
    BSL_SecParam_InitUint64(&ctx.param_aes_variant_256, RFC9173_BCB_SECPARAM_AESVARIANT,
                            RFC9173_BCB_AES_VARIANT_A256GCM);
    BSL_SecParam_InitUint64(&ctx.param_aad_scope_flag, RFC9173_BCB_SECPARAM_AADSCOPE, 0);

    BSL_Data_t authtag_data;
    BSL_Data_Init(&authtag_data);
    authtag_data.ptr = (uint8_t *)ApxA2_AuthTag;
    authtag_data.len = sizeof(ApxA2_AuthTag);
    BSL_SecParam_InitBytestr(&ctx.param_auth_tag, BSL_SECPARAM_TYPE_AUTH_TAG, authtag_data);

    BSL_Data_t iv_data;
    BSL_Data_Init(&iv_data);
    iv_data.ptr = (uint8_t *)ApxA2_InitVec;
    iv_data.len = sizeof(ApxA2_InitVec);
    BSL_SecParam_InitBytestr(&ctx.param_iv, RFC9173_BCB_SECPARAM_IV, iv_data);

    BSL_Data_t wrapkey_data;
    BSL_Data_Init(&wrapkey_data);
    wrapkey_data.ptr = (uint8_t *)ApxA2_WrappedKey;
    wrapkey_data.len = sizeof(ApxA2_WrappedKey);
    BSL_SecParam_InitBytestr(&ctx.param_wrapped_key, RFC9173_BCB_SECPARAM_WRAPPEDKEY, wrapkey_data);

    BSL_SecParam_InitUint64(&ctx.param_use_wrap_key, BSL_SECPARAM_USE_KEY_WRAP, 1);
    BSL_SecParam_InitUint64(&ctx.param_dont_use_wrap_key, BSL_SECPARAM_USE_KEY_WRAP, 0);

    BSL_SecParam_InitTextstr(&ctx.param_test_bib_key_correct, BSL_SECPARAM_TYPE_KEY_ID, RFC9173_EXAMPLE_A1_KEY);
    BSL_SecParam_InitTextstr(&ctx.param_test_bib_key_bad, BSL_SECPARAM_TYPE_KEY_ID, RFC9173_EXAMPLE_A2_KEY);
    BSL_SecParam_InitTextstr(&ctx.param_test_bcb_key_correct, BSL_SECPARAM_TYPE_KEY_ID, RFC9173_EXAMPLE_A2_KEY);
    BSL_SecParam_InitTextstr(&ctx.param_test_bcb_key_bad, BSL_SECPARAM_TYPE_KEY_ID, RFC9173_EXAMPLE_A1_KEY);
    BSL_SecParam_InitTextstr(&ctx.param_test_bcb_2_key_correct, BSL_SECPARAM_TYPE_KEY_ID, RFC9173_EXAMPLE_A4_BCB_KEY);
    BSL_SecParam_InitTextstr(&ctx.param_test_bcb_2_key_bad, BSL_SECPARAM_TYPE_KEY_ID, RFC9173_EXAMPLE_A1_KEY);

    // test bib accepting with good key, bad key (drop bundle), bad key (drop block), bad key (nothing)
    // CLIN, SRC=ipn:1.1, ACCEPTOR, BIB, PAYLOAD, DROP BLOCK, good key
    BSLP_PolicyPredicate_t predicate_1;
    BSLP_PolicyPredicate_InitFrom(&predicate_1, BSL_POLICYLOCATION_CLIN, "ipn:*.1.1", "*:**", "*:**");
    BSLP_PolicyRule_t rule_1;
    BSLP_PolicyRule_InitFrom(&rule_1, "ACCEPT BIB OVER PAYLOAD AT CLIN FILTER(SRC=ipn:1.1) WITH POLICY DROP BLOCK", 1,
                             BSL_SECROLE_ACCEPTOR, BSL_SECBLOCKTYPE_BIB, BSL_BLOCK_TYPE_PAYLOAD,
                             BSL_POLICYACTION_DROP_BLOCK);
    BSLP_PolicyRule_CopyParam(&rule_1, &ctx.param_sha_variant_512);
    BSLP_PolicyRule_CopyParam(&rule_1, &ctx.param_scope_flag);
    BSLP_PolicyRule_CopyParam(&rule_1, &ctx.param_test_bib_key_correct);
    BSLP_PolicyRule_CopyParam(&rule_1, &ctx.param_dont_use_wrap_key);
    BSLP_PolicyProvider_AddRule(policy, &rule_1, &predicate_1);

    // CLIN, SRC=ipn:1.2, ACCEPTOR, BIB, PAYLOAD, DROP BUNDLE, bad key
    BSLP_PolicyPredicate_t predicate_2;
    BSLP_PolicyPredicate_InitFrom(&predicate_2, BSL_POLICYLOCATION_CLIN, "ipn:*.1.2", "*:**", "*:**");
    BSLP_PolicyRule_t rule_2;
    BSLP_PolicyRule_InitFrom(&rule_2, "ACCEPT BIB OVER PAYLOAD AT CLIN FILTER(SRC=ipn:1.2)", 1, BSL_SECROLE_ACCEPTOR,
                             BSL_SECBLOCKTYPE_BIB, BSL_BLOCK_TYPE_PAYLOAD, BSL_POLICYACTION_DROP_BUNDLE);
    BSLP_PolicyRule_CopyParam(&rule_2, &ctx.param_sha_variant_512);
    BSLP_PolicyRule_CopyParam(&rule_2, &ctx.param_scope_flag);
    BSLP_PolicyRule_CopyParam(&rule_2, &ctx.param_test_bib_key_bad);
    BSLP_PolicyRule_CopyParam(&rule_2, &ctx.param_dont_use_wrap_key);
    BSLP_PolicyProvider_AddRule(policy, &rule_2, &predicate_2);

    // CLIN, SRC=ipn:1.3, ACCEPTOR, BIB, PAYLOAD, DROP BLOCK, bad key
    BSLP_PolicyPredicate_t predicate_3;
    BSLP_PolicyPredicate_InitFrom(&predicate_3, BSL_POLICYLOCATION_CLIN, "ipn:*.1.3", "*:**", "*:**");
    BSLP_PolicyRule_t rule_3;
    BSLP_PolicyRule_InitFrom(&rule_3, "ACCEPT BIB OVER PAYLOAD AT CLIN FILTER(SRC=ipn:1.3)", 1, BSL_SECROLE_ACCEPTOR,
                             BSL_SECBLOCKTYPE_BIB, BSL_BLOCK_TYPE_PAYLOAD, BSL_POLICYACTION_DROP_BLOCK);
    BSLP_PolicyRule_CopyParam(&rule_3, &ctx.param_sha_variant_512);
    BSLP_PolicyRule_CopyParam(&rule_3, &ctx.param_scope_flag);
    BSLP_PolicyRule_CopyParam(&rule_3, &ctx.param_test_bib_key_bad);
    BSLP_PolicyRule_CopyParam(&rule_3, &ctx.param_dont_use_wrap_key);
    BSLP_PolicyProvider_AddRule(policy, &rule_3, &predicate_3);

    // CLIN, SRC=ipn:1.4, ACCEPTOR, BIB, PAYLOAD, NOTHING, bad key
    BSLP_PolicyPredicate_t predicate_4;
    BSLP_PolicyPredicate_InitFrom(&predicate_4, BSL_POLICYLOCATION_CLIN, "ipn:*.1.4", "*:**", "*:**");
    BSLP_PolicyRule_t rule_4;
    BSLP_PolicyRule_InitFrom(&rule_4, "ACCEPT BIB OVER PAYLOAD AT CLIN FILTER(SRC=ipn:1.4)", 1, BSL_SECROLE_ACCEPTOR,
                             BSL_SECBLOCKTYPE_BIB, BSL_BLOCK_TYPE_PAYLOAD, BSL_POLICYACTION_NOTHING);
    BSLP_PolicyRule_CopyParam(&rule_4, &ctx.param_sha_variant_512);
    BSLP_PolicyRule_CopyParam(&rule_4, &ctx.param_scope_flag);
    BSLP_PolicyRule_CopyParam(&rule_4, &ctx.param_test_bib_key_bad);
    BSLP_PolicyRule_CopyParam(&rule_4, &ctx.param_dont_use_wrap_key);
    BSLP_PolicyProvider_AddRule(policy, &rule_4, &predicate_4);

    // test bcb accepting with good key, bad key (drop bundle), bad key (drop block), bad key (nothing)
    // CLIN, SRC=ipn:1.5, ACCEPTOR, BCB, PAYLOAD, DROP BLOCK, good key
    BSLP_PolicyPredicate_t predicate_5;
    BSLP_PolicyPredicate_InitFrom(&predicate_5, BSL_POLICYLOCATION_CLIN, "ipn:*.1.5", "*:**", "*:**");
    BSLP_PolicyRule_t rule_5;
    BSLP_PolicyRule_InitFrom(&rule_5, "ACCEPT BCB OVER PAYLOAD AT CLIN FILTER(SRC=ipn:1.5) WITH POLICY DROP BLOCK", 2,
                             BSL_SECROLE_ACCEPTOR, BSL_SECBLOCKTYPE_BCB, BSL_BLOCK_TYPE_PAYLOAD,
                             BSL_POLICYACTION_DROP_BLOCK);
    BSLP_PolicyRule_CopyParam(&rule_5, &ctx.param_test_bcb_key_correct);
    BSLP_PolicyRule_CopyParam(&rule_5, &ctx.param_iv);
    BSLP_PolicyRule_CopyParam(&rule_5, &ctx.param_wrapped_key);
    BSLP_PolicyRule_CopyParam(&rule_5, &ctx.param_auth_tag);
    BSLP_PolicyRule_CopyParam(&rule_5, &ctx.param_aes_variant_128);
    BSLP_PolicyRule_CopyParam(&rule_5, &ctx.param_use_wrap_key);
    BSLP_PolicyProvider_AddRule(policy, &rule_5, &predicate_5);

    // CLIN, SRC=ipn:1.6, ACCEPTOR, BCB, PAYLOAD, DROP BUNDLE, bad key
    BSLP_PolicyPredicate_t predicate_6;
    BSLP_PolicyPredicate_InitFrom(&predicate_6, BSL_POLICYLOCATION_CLIN, "ipn:*.1.6", "*:**", "*:**");
    BSLP_PolicyRule_t rule_6;
    BSLP_PolicyRule_InitFrom(&rule_6, "ACCEPT BCB OVER PAYLOAD AT CLIN FILTER(SRC=ipn:1.6)", 2, BSL_SECROLE_ACCEPTOR,
                             BSL_SECBLOCKTYPE_BCB, BSL_BLOCK_TYPE_PAYLOAD, BSL_POLICYACTION_DROP_BUNDLE);
    BSLP_PolicyRule_CopyParam(&rule_6, &ctx.param_test_bcb_key_bad);
    BSLP_PolicyRule_CopyParam(&rule_6, &ctx.param_iv);
    BSLP_PolicyRule_CopyParam(&rule_6, &ctx.param_wrapped_key);
    BSLP_PolicyRule_CopyParam(&rule_6, &ctx.param_auth_tag);
    BSLP_PolicyRule_CopyParam(&rule_6, &ctx.param_aes_variant_128);
    BSLP_PolicyRule_CopyParam(&rule_6, &ctx.param_use_wrap_key);
    BSLP_PolicyProvider_AddRule(policy, &rule_6, &predicate_6);

    // CLIN, SRC=ipn:1.7, ACCEPTOR, BCB, PAYLOAD, DROP BLOCK, bad key
    BSLP_PolicyPredicate_t predicate_7;
    BSLP_PolicyPredicate_InitFrom(&predicate_7, BSL_POLICYLOCATION_CLIN, "ipn:*.1.7", "*:**", "*:**");
    BSLP_PolicyRule_t rule_7;
    BSLP_PolicyRule_InitFrom(&rule_7, "ACCEPT BCB OVER PAYLOAD AT CLIN FILTER(SRC=ipn:1.7)", 2, BSL_SECROLE_ACCEPTOR,
                             BSL_SECBLOCKTYPE_BCB, BSL_BLOCK_TYPE_PAYLOAD, BSL_POLICYACTION_DROP_BLOCK);
    BSLP_PolicyRule_CopyParam(&rule_7, &ctx.param_test_bcb_key_bad);
    BSLP_PolicyRule_CopyParam(&rule_7, &ctx.param_iv);
    BSLP_PolicyRule_CopyParam(&rule_7, &ctx.param_wrapped_key);
    BSLP_PolicyRule_CopyParam(&rule_7, &ctx.param_auth_tag);
    BSLP_PolicyRule_CopyParam(&rule_7, &ctx.param_aes_variant_128);
    BSLP_PolicyRule_CopyParam(&rule_7, &ctx.param_use_wrap_key);
    BSLP_PolicyProvider_AddRule(policy, &rule_7, &predicate_7);

    // CLIN, SRC=ipn:1.8, ACCEPTOR, BCB, PAYLOAD, NOTHING, bad key
    BSLP_PolicyPredicate_t predicate_8;
    BSLP_PolicyPredicate_InitFrom(&predicate_8, BSL_POLICYLOCATION_CLIN, "ipn:*.1.8", "*:**", "*:**");
    BSLP_PolicyRule_t rule_8;
    BSLP_PolicyRule_InitFrom(&rule_8, "ACCEPT BCB OVER PAYLOAD AT CLIN FILTER(SRC=ipn:1.8)", 2, BSL_SECROLE_ACCEPTOR,
                             BSL_SECBLOCKTYPE_BCB, BSL_BLOCK_TYPE_PAYLOAD, BSL_POLICYACTION_NOTHING);
    BSLP_PolicyRule_CopyParam(&rule_8, &ctx.param_test_bcb_key_bad);
    BSLP_PolicyRule_CopyParam(&rule_8, &ctx.param_iv);
    BSLP_PolicyRule_CopyParam(&rule_8, &ctx.param_wrapped_key);
    BSLP_PolicyRule_CopyParam(&rule_8, &ctx.param_auth_tag);
    BSLP_PolicyRule_CopyParam(&rule_8, &ctx.param_aes_variant_128);
    BSLP_PolicyRule_CopyParam(&rule_8, &ctx.param_use_wrap_key);
    BSLP_PolicyProvider_AddRule(policy, &rule_8, &predicate_8);

    // test bib & bcb accpeting with good key, bad key (drop bundle), bad key (drop block), bad key (nothing)
    // CLIN, SRC=ipn:1.9, ACCEPTOR, BIB, PAYLOAD, DROP BLOCK, good key
    // CLIN, SRC=ipn:1.9, ACCEPTOR, BCB, PAYLOAD, DROP BLOCK, good key
    BSLP_PolicyPredicate_t predicate_9a;
    BSLP_PolicyPredicate_InitFrom(&predicate_9a, BSL_POLICYLOCATION_CLIN, "ipn:*.1.9", "*:**", "*:**");
    BSLP_PolicyRule_t rule_9a;
    BSLP_PolicyRule_InitFrom(&rule_9a, "ACCEPT BIB OVER PAYLOAD AT CLIN FILTER(SRC=ipn:1.9) WITH POLICY DROP BLOCK", 1,
                             BSL_SECROLE_ACCEPTOR, BSL_SECBLOCKTYPE_BIB, BSL_BLOCK_TYPE_PAYLOAD,
                             BSL_POLICYACTION_DROP_BLOCK);
    BSLP_PolicyRule_CopyParam(&rule_9a, &ctx.param_sha_variant_512);
    BSLP_PolicyRule_CopyParam(&rule_9a, &ctx.param_scope_flag);
    BSLP_PolicyRule_CopyParam(&rule_9a, &ctx.param_test_bib_key_correct);
    BSLP_PolicyRule_CopyParam(&rule_9a, &ctx.param_dont_use_wrap_key);
    BSLP_PolicyProvider_AddRule(policy, &rule_9a, &predicate_9a);

    BSLP_PolicyPredicate_t predicate_9b;
    BSLP_PolicyPredicate_InitFrom(&predicate_9b, BSL_POLICYLOCATION_CLIN, "ipn:*.1.9", "*:**", "*:**");
    BSLP_PolicyRule_t rule_9b;
    BSLP_PolicyRule_InitFrom(&rule_9b, "ACCEPT BCB OVER PAYLOAD AT CLIN FILTER(SRC=ipn:1.9) WITH POLICY DROP BLOCK", 2,
                             BSL_SECROLE_ACCEPTOR, BSL_SECBLOCKTYPE_BCB, BSL_BLOCK_TYPE_PAYLOAD,
                             BSL_POLICYACTION_DROP_BLOCK);
    BSLP_PolicyRule_CopyParam(&rule_9b, &ctx.param_test_bcb_key_correct);
    BSLP_PolicyRule_CopyParam(&rule_9b, &ctx.param_iv);
    BSLP_PolicyRule_CopyParam(&rule_9b, &ctx.param_wrapped_key);
    BSLP_PolicyRule_CopyParam(&rule_9b, &ctx.param_auth_tag);
    BSLP_PolicyRule_CopyParam(&rule_9b, &ctx.param_aes_variant_128);
    BSLP_PolicyRule_CopyParam(&rule_9b, &ctx.param_use_wrap_key);
    BSLP_PolicyProvider_AddRule(policy, &rule_9b, &predicate_9b);

    // test bib sourcing with good key
    // CLOUT, DEST=ipn:1.1, SOURCE, BIB, PAYLOAD, DROP BLOCK, good key
    BSLP_PolicyPredicate_t predicate_13;
    BSLP_PolicyPredicate_InitFrom(&predicate_13, BSL_POLICYLOCATION_CLOUT, "*:**", "*:**", "ipn:*.1.1");
    BSLP_PolicyRule_t rule_13;
    BSLP_PolicyRule_InitFrom(&rule_13, "SOURCE BIB OVER PAYLOAD AT CLOUT FILTER(DEST=ipn:1.1) WITH POLICY DROP BLOCK",
                             1, BSL_SECROLE_SOURCE, BSL_SECBLOCKTYPE_BIB, BSL_BLOCK_TYPE_PAYLOAD,
                             BSL_POLICYACTION_DROP_BLOCK);
    BSLP_PolicyRule_CopyParam(&rule_13, &ctx.param_sha_variant_512);
    BSLP_PolicyRule_CopyParam(&rule_13, &ctx.param_scope_flag);
    BSLP_PolicyRule_CopyParam(&rule_13, &ctx.param_test_bib_key_correct);
    BSLP_PolicyRule_CopyParam(&rule_13, &ctx.param_dont_use_wrap_key);
    BSLP_PolicyProvider_AddRule(policy, &rule_13, &predicate_13);

    // test bcb sourcing with good key
    // CLOUT, DEST=ipn:1.5, SOURCE, BCB, PAYLOAD, DROP BLOCK, good key
    BSLP_PolicyPredicate_t predicate_14;
    BSLP_PolicyPredicate_InitFrom(&predicate_14, BSL_POLICYLOCATION_CLOUT, "*:**", "*:**", "ipn:*.1.5");
    BSLP_PolicyRule_t rule_14;
    BSLP_PolicyRule_InitFrom(&rule_14, "SOURCE BCB OVER PAYLOAD AT CLOUT FILTER(DEST=ipn:1.5)", 2, BSL_SECROLE_SOURCE,
                             BSL_SECBLOCKTYPE_BCB, BSL_BLOCK_TYPE_PAYLOAD, BSL_POLICYACTION_DROP_BLOCK);
    BSLP_PolicyRule_CopyParam(&rule_14, &ctx.param_test_bcb_key_correct);
    BSLP_PolicyRule_CopyParam(&rule_14, &ctx.param_aes_variant_128);
    BSLP_PolicyRule_CopyParam(&rule_14, &ctx.param_use_wrap_key);
    BSLP_PolicyProvider_AddRule(policy, &rule_14, &predicate_14);

    // test bib & bcb sourcing with good key
    // CLOUT, DEST=ipn:1.9, SOURCE, BIB, PAYLOAD, DROP BLOCK, good key
    // CLOUT, DEST=ipn:1.9, SOURCE, BCB, PAYLOAD, DROP BLOCK, good key
    BSLP_PolicyPredicate_t predicate_15a;
    BSLP_PolicyPredicate_InitFrom(&predicate_15a, BSL_POLICYLOCATION_CLOUT, "*:**", "*:**", "ipn:*.1.9");
    BSLP_PolicyRule_t rule_15a;
    BSLP_PolicyRule_InitFrom(&rule_15a, "SOURCE BIB OVER PAYLOAD AT CLOUT FILTER(DEST=ipn:1.9) WITH POLICY DROP BLOCK",
                             1, BSL_SECROLE_SOURCE, BSL_SECBLOCKTYPE_BIB, BSL_BLOCK_TYPE_PAYLOAD,
                             BSL_POLICYACTION_DROP_BLOCK);
    BSLP_PolicyRule_CopyParam(&rule_15a, &ctx.param_sha_variant_384);
    BSLP_PolicyRule_CopyParam(&rule_15a, &ctx.param_scope_flag_7);
    BSLP_PolicyRule_CopyParam(&rule_15a, &ctx.param_test_bib_key_correct);
    BSLP_PolicyRule_CopyParam(&rule_15a, &ctx.param_dont_use_wrap_key);
    BSLP_PolicyProvider_AddRule(policy, &rule_15a, &predicate_15a);

    BSLP_PolicyPredicate_t predicate_15b;
    BSLP_PolicyPredicate_InitFrom(&predicate_15b, BSL_POLICYLOCATION_CLOUT, "*:**", "*:**", "ipn:*.1.9");
    BSLP_PolicyRule_t rule_15b;
    BSLP_PolicyRule_InitFrom(&rule_15b, "SOURCE BCB OVER PAYLOAD AT CLOUT FILTER(DEST=ipn:1.9)", 2, BSL_SECROLE_SOURCE,
                             BSL_SECBLOCKTYPE_BCB, BSL_BLOCK_TYPE_PAYLOAD, BSL_POLICYACTION_DROP_BLOCK);
    BSLP_PolicyRule_CopyParam(&rule_15b, &ctx.param_test_bcb_2_key_correct);
    BSLP_PolicyRule_CopyParam(&rule_15b, &ctx.param_aes_variant_256);
    BSLP_PolicyRule_CopyParam(&rule_15b, &ctx.param_dont_use_wrap_key);
    BSLP_PolicyProvider_AddRule(policy, &rule_15b, &predicate_15b);

    // test bib verif with good key, bad key (drop bundle), bad key (drop block), bad key (nothing)
    // APPIN, DEST=ipn:1.1, VERIF, BIB, PAYLOAD, DROP BLOCK, good key
    BSLP_PolicyPredicate_t predicate_17;
    BSLP_PolicyPredicate_InitFrom(&predicate_17, BSL_POLICYLOCATION_APPIN, "*:**", "*:**", "ipn:*.1.1");
    BSLP_PolicyRule_t rule_17;
    BSLP_PolicyRule_InitFrom(&rule_17, "VERIFY BCB OVER PAYLOAD AT APPIN FILTER(DEST=ipn:1.1)", 1, BSL_SECROLE_VERIFIER,
                             BSL_SECBLOCKTYPE_BIB, BSL_BLOCK_TYPE_PAYLOAD, BSL_POLICYACTION_DROP_BLOCK);
    BSLP_PolicyRule_CopyParam(&rule_17, &ctx.param_sha_variant_512);
    BSLP_PolicyRule_CopyParam(&rule_17, &ctx.param_scope_flag);
    BSLP_PolicyRule_CopyParam(&rule_17, &ctx.param_test_bib_key_correct);
    BSLP_PolicyRule_CopyParam(&rule_17, &ctx.param_dont_use_wrap_key);
    BSLP_PolicyProvider_AddRule(policy, &rule_17, &predicate_17);

    // APPIN, DEST=ipn:1.2, VERIF, BIB, PAYLOAD, DROP BUNDLE, bad key
    BSLP_PolicyPredicate_t predicate_18;
    BSLP_PolicyPredicate_InitFrom(&predicate_18, BSL_POLICYLOCATION_APPIN, "*:**", "*:**", "ipn:*.1.2");
    BSLP_PolicyRule_t rule_18;
    BSLP_PolicyRule_InitFrom(&rule_18, "VERIFY BCB OVER PAYLOAD AT APPIN FILTER(DEST=ipn:1.2)", 1, BSL_SECROLE_VERIFIER,
                             BSL_SECBLOCKTYPE_BIB, BSL_BLOCK_TYPE_PAYLOAD, BSL_POLICYACTION_DROP_BUNDLE);
    BSLP_PolicyRule_CopyParam(&rule_18, &ctx.param_sha_variant_512);
    BSLP_PolicyRule_CopyParam(&rule_18, &ctx.param_scope_flag);
    BSLP_PolicyRule_CopyParam(&rule_18, &ctx.param_test_bib_key_bad);
    BSLP_PolicyRule_CopyParam(&rule_18, &ctx.param_dont_use_wrap_key);
    BSLP_PolicyProvider_AddRule(policy, &rule_18, &predicate_18);

    // APPIN, DEST=ipn:1.3, VERIF, BIB, PAYLOAD, DROP BLOCK, bad key
    BSLP_PolicyPredicate_t predicate_19;
    BSLP_PolicyPredicate_InitFrom(&predicate_19, BSL_POLICYLOCATION_APPIN, "*:**", "*:**", "ipn:*.1.3");
    BSLP_PolicyRule_t rule_19;
    BSLP_PolicyRule_InitFrom(&rule_19, "VERIFY BCB OVER PAYLOAD AT APPIN FILTER(DEST=ipn:1.3)", 1, BSL_SECROLE_VERIFIER,
                             BSL_SECBLOCKTYPE_BIB, BSL_BLOCK_TYPE_PAYLOAD, BSL_POLICYACTION_DROP_BLOCK);
    BSLP_PolicyRule_CopyParam(&rule_19, &ctx.param_sha_variant_512);
    BSLP_PolicyRule_CopyParam(&rule_19, &ctx.param_scope_flag);
    BSLP_PolicyRule_CopyParam(&rule_19, &ctx.param_test_bib_key_bad);
    BSLP_PolicyRule_CopyParam(&rule_19, &ctx.param_dont_use_wrap_key);
    BSLP_PolicyProvider_AddRule(policy, &rule_19, &predicate_19);

    // APPIN, DEST=ipn:1.4, VERIF, BIB, PAYLOAD, NOTHING, bad key
    BSLP_PolicyPredicate_t predicate_20;
    BSLP_PolicyPredicate_InitFrom(&predicate_20, BSL_POLICYLOCATION_APPIN, "*:**", "*:**", "ipn:*.1.4");
    BSLP_PolicyRule_t rule_20;
    BSLP_PolicyRule_InitFrom(&rule_20, "VERIFY BCB OVER PAYLOAD AT APPIN FILTER(DEST=ipn:1.4)", 1, BSL_SECROLE_VERIFIER,
                             BSL_SECBLOCKTYPE_BIB, BSL_BLOCK_TYPE_PAYLOAD, BSL_POLICYACTION_NOTHING);
    BSLP_PolicyRule_CopyParam(&rule_20, &ctx.param_sha_variant_512);
    BSLP_PolicyRule_CopyParam(&rule_20, &ctx.param_scope_flag);
    BSLP_PolicyRule_CopyParam(&rule_20, &ctx.param_test_bib_key_bad);
    BSLP_PolicyRule_CopyParam(&rule_20, &ctx.param_dont_use_wrap_key);
    BSLP_PolicyProvider_AddRule(policy, &rule_20, &predicate_20);

    // test bcb verif with good key, bad key (drop bundle), bad key (drop block), bad key (nothing)
    // APPIN, DEST=ipn:1.5, VERIF, BCB, PAYLOAD, DROP BLOCK, good key
    BSLP_PolicyPredicate_t predicate_21;
    BSLP_PolicyPredicate_InitFrom(&predicate_21, BSL_POLICYLOCATION_APPIN, "*:**", "*:**", "ipn:*.1.5");
    BSLP_PolicyRule_t rule_21;
    BSLP_PolicyRule_InitFrom(&rule_21, "VERIFY BCB OVER PAYLOAD AT APPIN FILTER(DEST=ipn:1.5)", 2, BSL_SECROLE_VERIFIER,
                             BSL_SECBLOCKTYPE_BCB, BSL_BLOCK_TYPE_PAYLOAD, BSL_POLICYACTION_DROP_BLOCK);
    BSLP_PolicyRule_CopyParam(&rule_21, &ctx.param_test_bcb_key_correct);
    BSLP_PolicyRule_CopyParam(&rule_21, &ctx.param_iv);
    BSLP_PolicyRule_CopyParam(&rule_21, &ctx.param_wrapped_key);
    BSLP_PolicyRule_CopyParam(&rule_21, &ctx.param_auth_tag);
    BSLP_PolicyRule_CopyParam(&rule_21, &ctx.param_aes_variant_128);
    BSLP_PolicyRule_CopyParam(&rule_21, &ctx.param_use_wrap_key);
    BSLP_PolicyProvider_AddRule(policy, &rule_21, &predicate_21);

    // APPIN, DEST=ipn:1.6, VERIF, BCB, PAYLOAD, DROP BUNDLE, bad key
    BSLP_PolicyPredicate_t predicate_22;
    BSLP_PolicyPredicate_InitFrom(&predicate_22, BSL_POLICYLOCATION_APPIN, "*:**", "*:**", "ipn:*.1.6");
    BSLP_PolicyRule_t rule_22;
    BSLP_PolicyRule_InitFrom(&rule_22, "VERIFY BCB OVER PAYLOAD AT APPIN FILTER(DEST=ipn:1.6)", 2, BSL_SECROLE_VERIFIER,
                             BSL_SECBLOCKTYPE_BCB, BSL_BLOCK_TYPE_PAYLOAD, BSL_POLICYACTION_DROP_BUNDLE);
    BSLP_PolicyRule_CopyParam(&rule_22, &ctx.param_test_bcb_key_bad);
    BSLP_PolicyRule_CopyParam(&rule_22, &ctx.param_iv);
    BSLP_PolicyRule_CopyParam(&rule_22, &ctx.param_wrapped_key);
    BSLP_PolicyRule_CopyParam(&rule_22, &ctx.param_auth_tag);
    BSLP_PolicyRule_CopyParam(&rule_22, &ctx.param_aes_variant_128);
    BSLP_PolicyRule_CopyParam(&rule_22, &ctx.param_use_wrap_key);
    BSLP_PolicyProvider_AddRule(policy, &rule_22, &predicate_22);

    // APPIN, DEST=ipn:1.7, VERIF, BCB, PAYLOAD, DROP BLOCK, bad key
    BSLP_PolicyPredicate_t predicate_23;
    BSLP_PolicyPredicate_InitFrom(&predicate_23, BSL_POLICYLOCATION_APPIN, "*:**", "*:**", "ipn:*.1.7");
    BSLP_PolicyRule_t rule_23;
    BSLP_PolicyRule_InitFrom(&rule_23, "VERIFY BCB OVER PAYLOAD AT APPIN FILTER(DEST=ipn:1.7)", 2, BSL_SECROLE_VERIFIER,
                             BSL_SECBLOCKTYPE_BCB, BSL_BLOCK_TYPE_PAYLOAD, BSL_POLICYACTION_DROP_BLOCK);
    BSLP_PolicyRule_CopyParam(&rule_23, &ctx.param_test_bcb_key_bad);
    BSLP_PolicyRule_CopyParam(&rule_23, &ctx.param_iv);
    BSLP_PolicyRule_CopyParam(&rule_23, &ctx.param_wrapped_key);
    BSLP_PolicyRule_CopyParam(&rule_23, &ctx.param_auth_tag);
    BSLP_PolicyRule_CopyParam(&rule_23, &ctx.param_aes_variant_128);
    BSLP_PolicyRule_CopyParam(&rule_23, &ctx.param_use_wrap_key);
    BSLP_PolicyProvider_AddRule(policy, &rule_23, &predicate_23);

    // APPIN, DEST=ipn:1.8, VERIF, BCB, PAYLOAD, NOTHING, bad key
    BSLP_PolicyPredicate_t predicate_24;
    BSLP_PolicyPredicate_InitFrom(&predicate_24, BSL_POLICYLOCATION_APPIN, "*:**", "*:**", "ipn:*.1.8");
    BSLP_PolicyRule_t rule_24;
    BSLP_PolicyRule_InitFrom(&rule_24, "VERIFY BCB OVER PAYLOAD AT APPIN FILTER(DEST=ipn:1.8)", 2, BSL_SECROLE_VERIFIER,
                             BSL_SECBLOCKTYPE_BCB, BSL_BLOCK_TYPE_PAYLOAD, BSL_POLICYACTION_NOTHING);
    BSLP_PolicyRule_CopyParam(&rule_24, &ctx.param_test_bcb_key_bad);
    BSLP_PolicyRule_CopyParam(&rule_24, &ctx.param_iv);
    BSLP_PolicyRule_CopyParam(&rule_24, &ctx.param_wrapped_key);
    BSLP_PolicyRule_CopyParam(&rule_24, &ctx.param_auth_tag);
    BSLP_PolicyRule_CopyParam(&rule_24, &ctx.param_aes_variant_128);
    BSLP_PolicyRule_CopyParam(&rule_24, &ctx.param_use_wrap_key);
    BSLP_PolicyProvider_AddRule(policy, &rule_24, &predicate_24);

    // test bib & bcb verif with good key, bad key (drop bundle), bad key (drop block), bad key (nothing)
    // APPIN, DEST=ipn:1.9, VERIF, BIB, PAYLOAD, DROP BLOCK, good key
    // APPIN, DEST=ipn:1.9, VERIF, BCB, PAYLOAD, DROP BLOCK, good key
    BSLP_PolicyPredicate_t predicate_25a;
    BSLP_PolicyPredicate_InitFrom(&predicate_25a, BSL_POLICYLOCATION_APPIN, "*:**", "*:**", "ipn:*.1.9");
    BSLP_PolicyRule_t rule_25a;
    BSLP_PolicyRule_InitFrom(&rule_25a, "VERIFY BCB OVER PAYLOAD AT APPIN FILTER(DEST=ipn:1.9)", 1,
                             BSL_SECROLE_VERIFIER, BSL_SECBLOCKTYPE_BIB, BSL_BLOCK_TYPE_PAYLOAD,
                             BSL_POLICYACTION_DROP_BLOCK);
    BSLP_PolicyRule_CopyParam(&rule_25a, &ctx.param_sha_variant_512);
    BSLP_PolicyRule_CopyParam(&rule_25a, &ctx.param_scope_flag);
    BSLP_PolicyRule_CopyParam(&rule_25a, &ctx.param_test_bib_key_correct);
    BSLP_PolicyRule_CopyParam(&rule_25a, &ctx.param_dont_use_wrap_key);
    BSLP_PolicyProvider_AddRule(policy, &rule_25a, &predicate_25a);

    BSLP_PolicyPredicate_t predicate_25b;
    BSLP_PolicyPredicate_InitFrom(&predicate_25b, BSL_POLICYLOCATION_APPIN, "*:**", "*:**", "ipn:*.1.9");
    BSLP_PolicyRule_t rule_25b;
    BSLP_PolicyRule_InitFrom(&rule_25b, "VERIFY BCB OVER PAYLOAD AT APPIN FILTER(DEST=ipn:1.9)", 2,
                             BSL_SECROLE_VERIFIER, BSL_SECBLOCKTYPE_BCB, BSL_BLOCK_TYPE_PAYLOAD,
                             BSL_POLICYACTION_DROP_BLOCK);
    BSLP_PolicyRule_CopyParam(&rule_25b, &ctx.param_test_bcb_key_correct);
    BSLP_PolicyRule_CopyParam(&rule_25b, &ctx.param_iv);
    BSLP_PolicyRule_CopyParam(&rule_25b, &ctx.param_wrapped_key);
    BSLP_PolicyRule_CopyParam(&rule_25b, &ctx.param_auth_tag);
    BSLP_PolicyRule_CopyParam(&rule_25b, &ctx.param_aes_variant_128);
    BSLP_PolicyProvider_AddRule(policy, &rule_25b, &predicate_25b);

    // BSL 6
    BSLP_PolicyPredicate_t predicate_bsl_6;
    BSLP_PolicyPredicate_InitFrom(&predicate_bsl_6, BSL_POLICYLOCATION_CLOUT, "*:**", "*:**", "ipn:*.0.6");
    BSLP_PolicyRule_t rule_bsl_6;
    BSLP_PolicyRule_InitFrom(
        &rule_bsl_6, "SOURCE BIB OVER PAYLOAD AT CLOUT FILTER(DEST=ipn:0.6) WITH POLICY DROP BLOCK", 1,
        BSL_SECROLE_SOURCE, BSL_SECBLOCKTYPE_BIB, BSL_BLOCK_TYPE_PAYLOAD, BSL_POLICYACTION_DROP_BLOCK);
    BSLP_PolicyRule_CopyParam(&rule_bsl_6, &ctx.param_sha_variant_512);
    BSLP_PolicyRule_CopyParam(&rule_bsl_6, &ctx.param_scope_flag);
    BSLP_PolicyRule_CopyParam(&rule_bsl_6, &ctx.param_test_bib_key_correct);
    BSLP_PolicyRule_CopyParam(&rule_bsl_6, &ctx.param_dont_use_wrap_key);
    BSLP_PolicyProvider_AddRule(policy, &rule_bsl_6, &predicate_bsl_6);

    // BSL_32
    BSLP_PolicyPredicate_t predicate_bsl_32a;
    BSLP_PolicyPredicate_InitFrom(&predicate_bsl_32a, BSL_POLICYLOCATION_CLOUT, "*:**", "*:**", "ipn:*.3.2");
    BSLP_PolicyRule_t rule_bsl_32a;
    BSLP_PolicyRule_InitFrom(&rule_bsl_32a, "SOURCE BCB OVER PAYLOAD AT CLOUT FILTER(DEST=ipn:3.2)", 2,
                             BSL_SECROLE_SOURCE, BSL_SECBLOCKTYPE_BCB, BSL_BLOCK_TYPE_PAYLOAD,
                             BSL_POLICYACTION_DROP_BLOCK);
    BSLP_PolicyRule_CopyParam(&rule_bsl_32a, &ctx.param_test_bcb_key_correct);
    BSLP_PolicyRule_CopyParam(&rule_bsl_32a, &ctx.param_aes_variant_128);
    BSLP_PolicyRule_CopyParam(&rule_bsl_32a, &ctx.param_use_wrap_key);
    BSLP_PolicyProvider_AddRule(policy, &rule_bsl_32a, &predicate_bsl_32a);

    BSLP_PolicyPredicate_t predicate_bsl_32b;
    BSLP_PolicyPredicate_InitFrom(&predicate_bsl_32b, BSL_POLICYLOCATION_CLOUT, "*:**", "*:**", "ipn:*.3.2");
    BSLP_PolicyRule_t rule_bsl_32b;
    BSLP_PolicyRule_InitFrom(&rule_bsl_32b, "SOURCE BCB OVER BIB AT CLOUT FILTER(DEST=ipn:3.2)", 2, BSL_SECROLE_SOURCE,
                             BSL_SECBLOCKTYPE_BCB, BSL_BLOCK_TYPE_BIB, BSL_POLICYACTION_DROP_BLOCK);
    BSLP_PolicyRule_CopyParam(&rule_bsl_32b, &ctx.param_test_bcb_key_correct);
    BSLP_PolicyRule_CopyParam(&rule_bsl_32b, &ctx.param_aes_variant_128);
    BSLP_PolicyRule_CopyParam(&rule_bsl_32b, &ctx.param_use_wrap_key);
    BSLP_PolicyProvider_AddRule(policy, &rule_bsl_32b, &predicate_bsl_32b);
}

void tearDown(void)
{
    BSL_SecurityActionSet_Deinit(&action_set);
    BSLP_PolicyProvider_Deinit(policy_provider);
    BSL_CryptoDeinit();
    TEST_ASSERT_EQUAL(0, BSL_TestContext_Deinit(&LocalTestCtx));
    PublicInterfaceTestCtx_deinit(&ctx);
}

#define TEST_BOTH_BIB_BCB 99

TEST_CASE(BSL_POLICYLOCATION_CLIN, "ipn:1.1", NULL, NULL, BSL_SECROLE_ACCEPTOR, BSL_SECBLOCKTYPE_BIB,
          BSL_BLOCK_TYPE_PAYLOAD, BSL_POLICYACTION_DROP_BLOCK, true, 1, 1) // PASS
TEST_CASE(BSL_POLICYLOCATION_CLIN, "ipn:1.2", NULL, NULL, BSL_SECROLE_ACCEPTOR, BSL_SECBLOCKTYPE_BIB,
          BSL_BLOCK_TYPE_PAYLOAD, BSL_POLICYACTION_DROP_BUNDLE, false, 1, 1) // PASS
// TEST_CASE(BSL_POLICYLOCATION_CLIN, "ipn:1.3", NULL, NULL, BSL_SECROLE_ACCEPTOR, BSL_SECBLOCKTYPE_BIB,
// BSL_BLOCK_TYPE_PAYLOAD, BSL_POLICYACTION_DROP_BLOCK, false, 1, 1) // FAIL pending #13
// TEST_CASE(BSL_POLICYLOCATION_CLIN, "ipn:1.4", NULL, NULL, BSL_SECROLE_ACCEPTOR, BSL_SECBLOCKTYPE_BIB,
// BSL_BLOCK_TYPE_PAYLOAD, BSL_POLICYACTION_NOTHING, false, 1, 1) // FAIL pending #13
TEST_CASE(BSL_POLICYLOCATION_CLIN, "ipn:1.5", NULL, NULL, BSL_SECROLE_ACCEPTOR, BSL_SECBLOCKTYPE_BCB,
          BSL_BLOCK_TYPE_PAYLOAD, BSL_POLICYACTION_DROP_BLOCK, true, 1, 1) // PASS
TEST_CASE(BSL_POLICYLOCATION_CLIN, "ipn:1.6", NULL, NULL, BSL_SECROLE_ACCEPTOR, BSL_SECBLOCKTYPE_BCB,
          BSL_BLOCK_TYPE_PAYLOAD, BSL_POLICYACTION_DROP_BUNDLE, false, 1, 1) // PASS
TEST_CASE(BSL_POLICYLOCATION_CLIN, "ipn:1.7", NULL, NULL, BSL_SECROLE_ACCEPTOR, BSL_SECBLOCKTYPE_BCB,
          BSL_BLOCK_TYPE_PAYLOAD, BSL_POLICYACTION_DROP_BLOCK, false, 1, 1) // PASS
TEST_CASE(BSL_POLICYLOCATION_CLIN, "ipn:1.8", NULL, NULL, BSL_SECROLE_ACCEPTOR, BSL_SECBLOCKTYPE_BCB,
          BSL_BLOCK_TYPE_PAYLOAD, BSL_POLICYACTION_NOTHING, false, 1, 1) // PASS
TEST_CASE(BSL_POLICYLOCATION_CLIN, "ipn:1.9", NULL, NULL, BSL_SECROLE_ACCEPTOR, 99, BSL_BLOCK_TYPE_PAYLOAD,
          BSL_POLICYACTION_NOTHING, true, 2, 2) // PASS
TEST_CASE(BSL_POLICYLOCATION_CLOUT, NULL, "ipn:1.1", NULL, BSL_SECROLE_SOURCE, BSL_SECBLOCKTYPE_BIB,
          BSL_BLOCK_TYPE_PAYLOAD, BSL_POLICYACTION_DROP_BLOCK, true, 1, 1) // PASS
TEST_CASE(BSL_POLICYLOCATION_CLOUT, NULL, "ipn:1.5", NULL, BSL_SECROLE_SOURCE, BSL_SECBLOCKTYPE_BCB,
          BSL_BLOCK_TYPE_PAYLOAD, BSL_POLICYACTION_DROP_BLOCK, true, 1, 1) // PASS
TEST_CASE(BSL_POLICYLOCATION_CLOUT, NULL, "ipn:1.9", NULL, BSL_SECROLE_SOURCE, 99, BSL_BLOCK_TYPE_PAYLOAD,
          BSL_POLICYACTION_DROP_BLOCK, true, 2, 2) // PASS
TEST_CASE(BSL_POLICYLOCATION_APPIN, NULL, "ipn:1.1", NULL, BSL_SECROLE_VERIFIER, BSL_SECBLOCKTYPE_BIB,
          BSL_BLOCK_TYPE_PAYLOAD, BSL_POLICYACTION_DROP_BLOCK, true, 1, 1) // PASS
TEST_CASE(BSL_POLICYLOCATION_APPIN, NULL, "ipn:1.2", NULL, BSL_SECROLE_VERIFIER, BSL_SECBLOCKTYPE_BIB,
          BSL_BLOCK_TYPE_PAYLOAD, BSL_POLICYACTION_DROP_BUNDLE, false, 1, 1) // PASS
TEST_CASE(BSL_POLICYLOCATION_APPIN, NULL, "ipn:1.3", NULL, BSL_SECROLE_VERIFIER, BSL_SECBLOCKTYPE_BIB,
          BSL_BLOCK_TYPE_PAYLOAD, BSL_POLICYACTION_DROP_BLOCK, false, 1, 1) // PASS
TEST_CASE(BSL_POLICYLOCATION_APPIN, NULL, "ipn:1.4", NULL, BSL_SECROLE_VERIFIER, BSL_SECBLOCKTYPE_BIB,
          BSL_BLOCK_TYPE_PAYLOAD, BSL_POLICYACTION_NOTHING, false, 1, 1) // PASS
TEST_CASE(BSL_POLICYLOCATION_APPIN, NULL, "ipn:1.5", NULL, BSL_SECROLE_VERIFIER, BSL_SECBLOCKTYPE_BCB,
          BSL_BLOCK_TYPE_PAYLOAD, BSL_POLICYACTION_DROP_BLOCK, true, 1, 1) // PASS
TEST_CASE(BSL_POLICYLOCATION_APPIN, NULL, "ipn:1.6", NULL, BSL_SECROLE_VERIFIER, BSL_SECBLOCKTYPE_BCB,
          BSL_BLOCK_TYPE_PAYLOAD, BSL_POLICYACTION_DROP_BUNDLE, false, 1, 1) // PASS
TEST_CASE(BSL_POLICYLOCATION_APPIN, NULL, "ipn:1.7", NULL, BSL_SECROLE_VERIFIER, BSL_SECBLOCKTYPE_BCB,
          BSL_BLOCK_TYPE_PAYLOAD, BSL_POLICYACTION_DROP_BLOCK, false, 1, 1) // PASS
TEST_CASE(BSL_POLICYLOCATION_APPIN, NULL, "ipn:1.8", NULL, BSL_SECROLE_VERIFIER, BSL_SECBLOCKTYPE_BCB,
          BSL_BLOCK_TYPE_PAYLOAD, BSL_POLICYACTION_NOTHING, false, 1, 1) // PASS
// TEST_CASE(BSL_POLICYLOCATION_APPIN, NULL, "ipn:1.9", NULL, BSL_SECROLE_VERIFIER, 99, BSL_BLOCK_TYPE_PAYLOAD,
// BSL_POLICYACTION_DROP_BLOCK, true, 2, 2) // FAIL
void test_comprehensive(BSL_PolicyLocation_e policy_loc, const char *src_eid, const char *dest_eid,
                        const char *secsrc_eid, BSL_SecRole_e sec_role, int sec_block_type, uint8_t target_block,
                        BSL_PolicyAction_e policy_act, bool good_key, int sec_blks_ct, int expected_act_ct)
{
    BSL_PrimaryBlock_t        primary_block;
    BSL_SecurityResponseSet_t response_set = { 0 };
    BSL_TlmCounters_t         tlm          = BSL_TLM_COUNTERS_ZERO;

    int query_result = -1;
    int apply_result = -1;

    if (sec_block_type == BSL_SECBLOCKTYPE_BIB)
    {
        if (sec_role == BSL_SECROLE_SOURCE)
        {
            TEST_ASSERT_EQUAL(0, BSL_TestUtils_LoadBundleFromCBOR(&LocalTestCtx,
                                                                  RFC9173_TestVectors_AppendixA1.cbor_bundle_original));
        }
        else
        {
            TEST_ASSERT_EQUAL(
                0, BSL_TestUtils_LoadBundleFromCBOR(&LocalTestCtx, RFC9173_TestVectors_AppendixA1.cbor_bundle_bib));
        }
    }
    else if (sec_block_type == BSL_SECBLOCKTYPE_BCB)
    {
        if (sec_role == BSL_SECROLE_SOURCE)
        {
            TEST_ASSERT_EQUAL(0, BSL_TestUtils_LoadBundleFromCBOR(&LocalTestCtx,
                                                                  RFC9173_TestVectors_AppendixA2.cbor_bundle_original));
        }
        else
        {
            TEST_ASSERT_EQUAL(
                0, BSL_TestUtils_LoadBundleFromCBOR(&LocalTestCtx, RFC9173_TestVectors_AppendixA2.cbor_bundle_bcb));
        }
    }
    else if (sec_block_type == TEST_BOTH_BIB_BCB)
    {
        if (sec_role == BSL_SECROLE_SOURCE)
        {
            TEST_ASSERT_EQUAL(0, BSL_TestUtils_LoadBundleFromCBOR(&LocalTestCtx,
                                                                  RFC9173_TestVectors_AppendixA4.cbor_bundle_original));
        }
        else
        {
            TEST_ASSERT_EQUAL(
                0, BSL_TestUtils_LoadBundleFromCBOR(&LocalTestCtx, RFC9173_TestVectors_AppendixA4.cbor_bundle_final));
        }
    }

    // Modify EIDs to match policy rule filters
    int res = BSL_TestUtils_ModifyEIDs(&LocalTestCtx.mock_bpa_ctr.bundle_ref, src_eid, dest_eid, secsrc_eid);
    BSL_LOG_INFO("EID MODIFICATION RESULT: %d", res);

    switch (sec_role)
    {
        case BSL_SECROLE_ACCEPTOR:
        {
            BSL_BundleCtx_GetBundleMetadata(&LocalTestCtx.mock_bpa_ctr.bundle_ref, &primary_block);
            TEST_ASSERT_EQUAL(1 + sec_blks_ct, primary_block.block_count);

            query_result = BSL_API_QuerySecurity(&LocalTestCtx.bsl, &action_set, &LocalTestCtx.mock_bpa_ctr.bundle_ref,
                                                 policy_loc);
            TEST_ASSERT_EQUAL(0, query_result);
            TEST_ASSERT_EQUAL(expected_act_ct, BSL_SecurityActionSet_CountOperations(&action_set));

            apply_result = BSL_API_ApplySecurity(&LocalTestCtx.bsl, &response_set,
                                                 &LocalTestCtx.mock_bpa_ctr.bundle_ref, &action_set);
            TEST_ASSERT_EQUAL(0, apply_result);
            BSL_PrimaryBlock_deinit(&primary_block);

            BSL_BundleCtx_GetBundleMetadata(&LocalTestCtx.mock_bpa_ctr.bundle_ref, &primary_block);
            if (good_key)
            {
                // accepted sec blocks
                TEST_ASSERT_EQUAL(1, primary_block.block_count);
                for (size_t i = 0; i < BSL_SecurityActionSet_CountActions(&action_set); i++)
                {
                    const BSL_SecurityAction_t *act = BSL_SecurityActionSet_GetActionAtIndex(&action_set, i);
                    TEST_ASSERT_EQUAL(BSL_SAMPLE_PP_ID, act->pp_id);
                    for (size_t j = 0; j < BSL_SecurityAction_CountSecOpers(act); j++)
                    {
                        TEST_ASSERT_EQUAL(BSL_SECOP_CONCLUSION_SUCCESS,
                                          BSL_SecOper_GetConclusion(BSL_SecurityAction_GetSecOperAtIndex(act, j)));
                    }
                }
            }
            else
            {
                size_t fail_ct = 0;
                for (size_t i = 0; i < BSL_SecurityActionSet_CountActions(&action_set); i++)
                {
                    const BSL_SecurityAction_t *act = BSL_SecurityActionSet_GetActionAtIndex(&action_set, i);
                    TEST_ASSERT_EQUAL(BSL_SAMPLE_PP_ID, act->pp_id);
                    for (size_t j = 0; j < BSL_SecurityAction_CountSecOpers(act); j++)
                    {
                        if (BSL_SECOP_CONCLUSION_FAILURE
                            == BSL_SecOper_GetConclusion(BSL_SecurityAction_GetSecOperAtIndex(act, j)))
                        {
                            fail_ct++;
                        }
                    }
                }

                TEST_ASSERT(fail_ct > 0);

                if (policy_act == BSL_POLICYACTION_DROP_BLOCK)
                {
                    TEST_ASSERT_EQUAL(sec_blks_ct, primary_block.block_count);
                }
                else if (policy_act == BSL_POLICYACTION_NOTHING)
                {
                    TEST_ASSERT_EQUAL(1 + sec_blks_ct, primary_block.block_count);
                }
                else if (policy_act == BSL_POLICYACTION_DROP_BUNDLE)
                {
                    TEST_ASSERT_EQUAL(false, ((MockBPA_Bundle_t *)LocalTestCtx.mock_bpa_ctr.bundle_ref.data)->retain);
                }
            }
            BSL_PrimaryBlock_deinit(&primary_block);

            break;
        }
        case BSL_SECROLE_VERIFIER:
        {
            BSL_BundleCtx_GetBundleMetadata(&LocalTestCtx.mock_bpa_ctr.bundle_ref, &primary_block);
            TEST_ASSERT_EQUAL(1 + sec_blks_ct, primary_block.block_count);

            BSL_CanonicalBlock_t blk_before;
            TEST_ASSERT_EQUAL(
                0, BSL_BundleCtx_GetBlockMetadata(&LocalTestCtx.mock_bpa_ctr.bundle_ref, target_block, &blk_before));
            size_t  buf_sz_before = blk_before.btsd_len;
            uint8_t btsd_buf_before[buf_sz_before];

            BSL_SeqReader_t *reader_before =
                BSL_BundleCtx_ReadBTSD(&LocalTestCtx.mock_bpa_ctr.bundle_ref, target_block);
            BSL_SeqReader_Get(reader_before, btsd_buf_before, &buf_sz_before);

            query_result = BSL_API_QuerySecurity(&LocalTestCtx.bsl, &action_set, &LocalTestCtx.mock_bpa_ctr.bundle_ref,
                                                 policy_loc);
            TEST_ASSERT_EQUAL(0, query_result);
            TEST_ASSERT_EQUAL(expected_act_ct, BSL_SecurityActionSet_CountOperations(&action_set));

            apply_result = BSL_API_ApplySecurity(&LocalTestCtx.bsl, &response_set,
                                                 &LocalTestCtx.mock_bpa_ctr.bundle_ref, &action_set);
            TEST_ASSERT_EQUAL(0, apply_result);
            BSL_PrimaryBlock_deinit(&primary_block);

            BSL_BundleCtx_GetBundleMetadata(&LocalTestCtx.mock_bpa_ctr.bundle_ref, &primary_block);
            if (good_key)
            {
                // verified sec blocks
                TEST_ASSERT_EQUAL(1 + sec_blks_ct, primary_block.block_count);
                for (size_t i = 0; i < BSL_SecurityActionSet_CountActions(&action_set); i++)
                {
                    const BSL_SecurityAction_t *act = BSL_SecurityActionSet_GetActionAtIndex(&action_set, i);
                    TEST_ASSERT_EQUAL(BSL_SAMPLE_PP_ID, act->pp_id);
                    for (size_t j = 0; j < BSL_SecurityAction_CountSecOpers(act); j++)
                    {
                        TEST_ASSERT_EQUAL(BSL_SECOP_CONCLUSION_SUCCESS,
                                          BSL_SecOper_GetConclusion(BSL_SecurityAction_GetSecOperAtIndex(act, j)));
                    }
                }

                // Verify BCB verification did not modify target BTSD
                if (sec_block_type == BSL_SECBLOCKTYPE_BCB)
                {
                    BSL_CanonicalBlock_t blk_after;
                    TEST_ASSERT_EQUAL(0, BSL_BundleCtx_GetBlockMetadata(&LocalTestCtx.mock_bpa_ctr.bundle_ref,
                                                                        target_block, &blk_after));
                    size_t  buf_sz_after = blk_after.btsd_len;
                    uint8_t btsd_buf_after[buf_sz_after];

                    BSL_SeqReader_t *reader_after =
                        BSL_BundleCtx_ReadBTSD(&LocalTestCtx.mock_bpa_ctr.bundle_ref, target_block);
                    BSL_SeqReader_Get(reader_after, btsd_buf_after, &buf_sz_after);

                    TEST_ASSERT_EQUAL(buf_sz_after, buf_sz_before);
                    TEST_ASSERT_EQUAL_HEX8_ARRAY(btsd_buf_after, btsd_buf_before, buf_sz_after);

                    TEST_ASSERT_EQUAL(0, BSL_LibCtx_AccumulateTlmCounters(&LocalTestCtx.bsl, &tlm));
                    TEST_ASSERT_NOT_EQUAL(0, tlm.counters[BSL_TLM_SECOP_VERIFIER_COUNT]);

                    BSL_SeqReader_Destroy(reader_after);
                }
            }
            else
            {
                size_t fail_ct = 0;
                for (size_t i = 0; i < BSL_SecurityActionSet_CountActions(&action_set); i++)
                {
                    const BSL_SecurityAction_t *act = BSL_SecurityActionSet_GetActionAtIndex(&action_set, i);
                    TEST_ASSERT_EQUAL(BSL_SAMPLE_PP_ID, act->pp_id);
                    for (size_t j = 0; j < BSL_SecurityAction_CountSecOpers(act); j++)
                    {
                        if (BSL_SECOP_CONCLUSION_FAILURE
                            == BSL_SecOper_GetConclusion(BSL_SecurityAction_GetSecOperAtIndex(act, j)))
                        {
                            fail_ct++;
                        }
                    }
                }

                TEST_ASSERT(fail_ct > 0);

                if (policy_act == BSL_POLICYACTION_DROP_BLOCK)
                {
                    BSL_CanonicalBlock_t res;
                    TEST_ASSERT_EQUAL(0,
                                      BSL_BundleCtx_GetBlockMetadata(&LocalTestCtx.mock_bpa_ctr.bundle_ref, 2, &res));

                    // dropped target
                    TEST_ASSERT_EQUAL(sec_blks_ct, primary_block.block_count);
                }
                else if (policy_act == BSL_POLICYACTION_NOTHING)
                {
                    TEST_ASSERT_EQUAL(1 + sec_blks_ct, primary_block.block_count);
                }
                else if (policy_act == BSL_POLICYACTION_DROP_BUNDLE)
                {
                    TEST_ASSERT_EQUAL(false, ((MockBPA_Bundle_t *)LocalTestCtx.mock_bpa_ctr.bundle_ref.data)->retain);
                }
            }

            BSL_SeqReader_Destroy(reader_before);
            BSL_PrimaryBlock_deinit(&primary_block);

            break;
        }
        case BSL_SECROLE_SOURCE:
        {
            BSL_BundleCtx_GetBundleMetadata(&LocalTestCtx.mock_bpa_ctr.bundle_ref, &primary_block);
            TEST_ASSERT_EQUAL(1, primary_block.block_count);

            query_result = BSL_API_QuerySecurity(&LocalTestCtx.bsl, &action_set, &LocalTestCtx.mock_bpa_ctr.bundle_ref,
                                                 policy_loc);
            TEST_ASSERT_EQUAL(0, query_result);
            TEST_ASSERT_EQUAL(expected_act_ct, BSL_SecurityActionSet_CountOperations(&action_set));

            apply_result = BSL_API_ApplySecurity(&LocalTestCtx.bsl, &response_set,
                                                 &LocalTestCtx.mock_bpa_ctr.bundle_ref, &action_set);
            TEST_ASSERT_EQUAL(0, apply_result);
            BSL_PrimaryBlock_deinit(&primary_block);

            BSL_BundleCtx_GetBundleMetadata(&LocalTestCtx.mock_bpa_ctr.bundle_ref, &primary_block);

            // sourced sec blocks
            TEST_ASSERT_EQUAL(1 + sec_blks_ct, primary_block.block_count);
            BSL_PrimaryBlock_deinit(&primary_block);

            for (size_t i = 0; i < BSL_SecurityActionSet_CountActions(&action_set); i++)
            {
                const BSL_SecurityAction_t *act = BSL_SecurityActionSet_GetActionAtIndex(&action_set, i);
                TEST_ASSERT_EQUAL(BSL_SAMPLE_PP_ID, act->pp_id);
                for (size_t j = 0; j < BSL_SecurityAction_CountSecOpers(act); j++)
                {
                    TEST_ASSERT_EQUAL(BSL_SECOP_CONCLUSION_SUCCESS,
                                      BSL_SecOper_GetConclusion(BSL_SecurityAction_GetSecOperAtIndex(act, j)));
                }
            }

            BSL_CanonicalBlock_t res;
            if (sec_block_type == TEST_BOTH_BIB_BCB)
            {
                TEST_ASSERT_EQUAL(0, BSL_BundleCtx_GetBlockMetadata(&LocalTestCtx.mock_bpa_ctr.bundle_ref, 2, &res));
                TEST_ASSERT_EQUAL(11, res.type_code);
                TEST_ASSERT_EQUAL(0, BSL_BundleCtx_GetBlockMetadata(&LocalTestCtx.mock_bpa_ctr.bundle_ref, 3, &res));
                TEST_ASSERT_EQUAL(12, res.type_code);
            }
            else
            {
                TEST_ASSERT_EQUAL(0, BSL_BundleCtx_GetBlockMetadata(&LocalTestCtx.mock_bpa_ctr.bundle_ref, 2, &res));
                TEST_ASSERT_EQUAL(sec_block_type, res.type_code);
            }
            break;
        }
    }
}

// Recommended BSL_6 be removed
// But, here's the fixture anyways, can be used for a future PP enhancement ticket (like #68)
void n_test_BSL_6(void)
{
    BSL_PrimaryBlock_t        primary_block;
    BSL_SecurityResponseSet_t response_set = { 0 };
    BSL_CanonicalBlock_t      res_blk;
    int                       query_result = -1;
    int                       apply_result = -1;

    TEST_ASSERT_EQUAL(0,
                      BSL_TestUtils_LoadBundleFromCBOR(&LocalTestCtx, RFC9173_TestVectors_AppendixA1.cbor_bundle_bib));

    int res = BSL_TestUtils_ModifyEIDs(&LocalTestCtx.mock_bpa_ctr.bundle_ref, NULL, "ipn:0.6", NULL);
    BSL_LOG_INFO("EID MODIFICATION RESULT: %d", res);

    BSL_BundleCtx_GetBundleMetadata(&LocalTestCtx.mock_bpa_ctr.bundle_ref, &primary_block);
    TEST_ASSERT_EQUAL(2, primary_block.block_count);

    TEST_ASSERT_EQUAL(0, BSL_BundleCtx_GetBlockMetadata(&LocalTestCtx.mock_bpa_ctr.bundle_ref, 2, &res_blk));
    TEST_ASSERT_EQUAL(11, res_blk.type_code); // should be a bib already

    // Arguably, it should fail here.
    query_result = BSL_API_QuerySecurity(&LocalTestCtx.bsl, &action_set, &LocalTestCtx.mock_bpa_ctr.bundle_ref,
                                         BSL_POLICYLOCATION_CLOUT);
    TEST_ASSERT_EQUAL(0, query_result);
    TEST_ASSERT_EQUAL(1, action_set.action_count);
    TEST_ASSERT_EQUAL(1, BSL_SecurityAction_CountSecOpers(BSL_SecurityActionSet_GetActionAtIndex(&action_set, 0)));

    apply_result =
        BSL_API_ApplySecurity(&LocalTestCtx.bsl, &response_set, &LocalTestCtx.mock_bpa_ctr.bundle_ref, &action_set);
    TEST_ASSERT_EQUAL(0, apply_result);
    TEST_ASSERT_EQUAL(
        BSL_SECOP_CONCLUSION_FAILURE,
        BSL_SecurityAction_GetSecOperAtIndex(BSL_SecurityActionSet_GetActionAtIndex(&action_set, 0), 0)->conclusion);

    BSL_BundleCtx_GetBundleMetadata(&LocalTestCtx.mock_bpa_ctr.bundle_ref, &primary_block);
    TEST_ASSERT_EQUAL(2, primary_block.block_count);

    BSL_PrimaryBlock_deinit(&primary_block);
}

// Recreate MockBPA test BSL_43
void test_BSL_32(void)
{
    BSL_PrimaryBlock_t        primary_block;
    BSL_SecurityResponseSet_t response_set = { 0 };
    BSL_CanonicalBlock_t      res_blk;
    int                       query_result = -1;
    int                       apply_result = -1;

    TEST_ASSERT_EQUAL(0,
                      BSL_TestUtils_LoadBundleFromCBOR(&LocalTestCtx, RFC9173_TestVectors_AppendixA1.cbor_bundle_bib));

    int res = BSL_TestUtils_ModifyEIDs(&LocalTestCtx.mock_bpa_ctr.bundle_ref, NULL, "ipn:3.2", NULL);
    BSL_LOG_INFO("EID MODIFICATION RESULT: %d", res);

    BSL_BundleCtx_GetBundleMetadata(&LocalTestCtx.mock_bpa_ctr.bundle_ref, &primary_block);
    TEST_ASSERT_EQUAL(2, primary_block.block_count);

    TEST_ASSERT_EQUAL(0, BSL_BundleCtx_GetBlockMetadata(&LocalTestCtx.mock_bpa_ctr.bundle_ref, 2, &res_blk));
    TEST_ASSERT_EQUAL(11, res_blk.type_code); // should be a bib already

    query_result = BSL_API_QuerySecurity(&LocalTestCtx.bsl, &action_set, &LocalTestCtx.mock_bpa_ctr.bundle_ref,
                                         BSL_POLICYLOCATION_CLOUT);
    TEST_ASSERT_EQUAL(0, query_result);
    TEST_ASSERT_EQUAL(2, BSL_SecurityActionSet_CountOperations(&action_set));

    apply_result =
        BSL_API_ApplySecurity(&LocalTestCtx.bsl, &response_set, &LocalTestCtx.mock_bpa_ctr.bundle_ref, &action_set);
    TEST_ASSERT_EQUAL(0, apply_result);

    for (size_t i = 0; i < BSL_SecurityActionSet_CountActions(&action_set); i++)
    {
        const BSL_SecurityAction_t *act = BSL_SecurityActionSet_GetActionAtIndex(&action_set, i);
        for (size_t j = 0; j < BSL_SecurityAction_CountSecOpers(act); j++)
        {
            TEST_ASSERT_EQUAL(BSL_SECOP_CONCLUSION_SUCCESS,
                              BSL_SecOper_GetConclusion(BSL_SecurityAction_GetSecOperAtIndex(act, j)));
        }
    }
    BSL_PrimaryBlock_deinit(&primary_block);

    BSL_BundleCtx_GetBundleMetadata(&LocalTestCtx.mock_bpa_ctr.bundle_ref, &primary_block);

    // sourced sec blocks
    TEST_ASSERT_EQUAL(4, primary_block.block_count);

    TEST_ASSERT_EQUAL(0, BSL_BundleCtx_GetBlockMetadata(&LocalTestCtx.mock_bpa_ctr.bundle_ref, 2, &res_blk));
    TEST_ASSERT_EQUAL(11, res_blk.type_code);
    TEST_ASSERT_EQUAL(0, BSL_BundleCtx_GetBlockMetadata(&LocalTestCtx.mock_bpa_ctr.bundle_ref, 3, &res_blk));
    TEST_ASSERT_EQUAL(12, res_blk.type_code);
    TEST_ASSERT_EQUAL(0, BSL_BundleCtx_GetBlockMetadata(&LocalTestCtx.mock_bpa_ctr.bundle_ref, 4, &res_blk));
    TEST_ASSERT_EQUAL(12, res_blk.type_code);

    BSL_PrimaryBlock_deinit(&primary_block);
}
