/*
 * 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 <inttypes.h>
#include <unity.h>
#include "bsl_test_utils.h"
#include <mock_bpa/ctr.h>
#include <mock_bpa/agent.h>
#include <mock_bpa/log.h>

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;
}

TEST_CASE("9f88070000820282030482028201028202820000821903e81903e900850101000043010203ff")
// private extension with non-contiguous number
TEST_CASE("9f88070000820282030482028201028202820000821903e81903e9008518c00a000043010203850101000043010203ff")
// random large payload
TEST_CASE(
    "9F88070000820282030482028201028202820000821903E81903E90085010100005903E8E059257BAE6D2D4AB0FB90EEF5FA695D8B07A466"
    "51CC45E5DE4E66F26EE329751A85D9C357DBEBF6D5EF38BA18629E7C17DF2D511ECE2FB2C99B3BD6C12E5746C530888F105D4835C3952DF922"
    "1EE17E51E9663FADC00194FBF0332BAF8025C6313B5922C39FB9A5C68EC20FA1717D0B224219417BD930CE1C6356F0044DF3989C47971E30A2"
    "94232A6E31CE6B05125A49CEB0AD606A0361658001AEA5A2D715F1D17CB2203E347D64DDF8CF8B9864B90541DB790EF1E9E97A6E042C7A4D48"
    "906AA7AA9A0A1414F03D4C73458A1029775730C451ABB12D2F1604566A87D0F0140054D74AA1FE99D2E1FAC62F1C27AE0C6B74847E17D49D25"
    "97FFD8ADC635A9D94C5618FF30C9FE609B92E7218226DD99EC0FB5E1EF5F14C9C95173733FC9F11263D0CC5913D71922AED65AA5D0BABE0F7B"
    "FB4D01CD5471675E94112F8201B633E29CF82F7E2429C4F46F17776768C4AC715ED05BFD85EA3B3D04F45CCCAE262EF0B9B882294A59540E4E"
    "4E0973397A6CD0048C2A62F8609DEB4D6A9BB762C86C212E79B4A4F273C40036E43B9DB6DA279C9FAF8BE12A6A6A6913C65333490C89EB5E0A"
    "4C0549B91B85A92AD05B599153388BB885819D05BF8C4C3DD152231D1EAD22FFEC6AFBE654C2FB6A4758214E96D2A7ED42666C498711DF3402"
    "4BED8DF3946B49660063BA9250BCB4D4315EA75B68F31D93CFB124BBFFCECC3643864DA8350C3C0F48AE12D9C50ECA11987F2E7B3B6D9C012D"
    "EDCB62D6F07D08FA267129D533DB423CC09AE072316247E72EF9C6577622B3D82A53F73C09A2ABD748984D957B337612FCCB2AF37B5EB6C3BA"
    "DA1349E79FA33CFB088769A6D2FB788DF1D79112075A5F735AD000F94D5D8A1D4F3CB262FEB0D7988EAF9CA1C5F983E898446568365154CBBC"
    "2C9AEB62305491490C106647A001C8971287B057C8F86DFBC7BB606FA25C6920BD52EB26A0804389F5DE84A6002C5BE2495B7268C890F4441F"
    "0D4D0CBEC41EC27093DCA8D5831F4A7D388A9C227CFC1C9FE97A91183D623A47D63388C76809AEBF15D6CF48E1A150C543490C38AC5AB38251"
    "F82EDC170A02DFD9F24FC0A8BD24EE4C78B2307105B620970E71B949530C275051B7A3DC41AEEC3339617773A548AA99B0A8D050B0D65A9082"
    "7627A88874B9F9CFDB8A10F52393AF5139E023D6CC304B8FDADDE74F4D2635E614FEBE6E65F1EE0925AE00098D3FF10D5BB3EE90C9BD32AF20"
    "2864E141AEBE8C6D3B36B01E59D6956EF58EF2EDFCAC2A026E000A31FAAD22D93BA30E8338349C11ABE2DF0C3E16E87247DBC975C69872CC30"
    "AC5D1B6D4C9A5B9BB548FB50C0CD47A961DCD58636F1165467D8C09260C0E12ACA3F790703907997CC9C6BDE1F63939310B66364E1B29617FE"
    "5757A814E7264B7EB063AFFF")
void test_mock_bpa_ctr_loopback_decode_encode(const char *hexdata)
{
    BSL_Data_t in_data;
    BSL_Data_Init(&in_data);
    {
        string_t in_text;
        string_init_set_str(in_text, hexdata);
        TEST_ASSERT_EQUAL_INT_MESSAGE(0, BSL_TestUtils_DecodeBase16(&in_data, in_text),
                                      "BSL_TestUtils_DecodeBase16() failed");
        string_clear(in_text);
    }

    mock_bpa_ctr_t ctr;
    mock_bpa_ctr_init(&ctr);
    TEST_ASSERT_EQUAL_INT(0, BSL_Data_CopyFrom(&ctr.encoded, in_data.len, in_data.ptr));

    int res = mock_bpa_ctr_decode(&ctr);
    TEST_ASSERT_EQUAL_INT_MESSAGE(0, res, "mock_bpa_decode() failed");

    // no reordering of blocks
    res = mock_bpa_ctr_encode(&ctr);
    TEST_ASSERT_EQUAL_INT_MESSAGE(0, res, "mock_bpa_encode() failed");

    TEST_ASSERT_EQUAL_INT(in_data.len, ctr.encoded.len);
    TEST_ASSERT_EQUAL_MEMORY(in_data.ptr, ctr.encoded.ptr, in_data.len);

    mock_bpa_ctr_deinit(&ctr);
    BSL_Data_Deinit(&in_data);
}

// no primary
TEST_CASE("9fff")
// only primary
TEST_CASE("9f88070000820282030482028201028202820000821903e81903e900ff")
// no payload block type 1
TEST_CASE("9f88070000820282030482028201028202820000821903e81903e9008518c001000043010203ff")
// no payload block number 1
TEST_CASE("9f88070000820282030482028201028202820000821903e81903e900850102000043010203ff")
// payload is not last block
TEST_CASE("9f88070000820282030482028201028202820000821903e81903e9008501010000430102038518c002000043010203ff")
// duplicate block number
TEST_CASE("9f88070000820282030482028201028202820000821903e81903e9008501010000430102038518c001000043010203ff")
// invalid block type
TEST_CASE("9f88070000820282030482028201028202820000821903e81903e900850001000043010203850101000043010203ff")
// invalid block number
TEST_CASE("9f88070000820282030482028201028202820000821903e81903e9008518c000000043010203850101000043010203ff")
void test_mock_bpa_ctr_decode_invalid(const char *hexdata)
{
    BSL_Data_t in_data;
    BSL_Data_Init(&in_data);
    {
        string_t in_text;
        string_init_set_str(in_text, hexdata);
        TEST_ASSERT_EQUAL_INT_MESSAGE(0, BSL_TestUtils_DecodeBase16(&in_data, in_text),
                                      "BSL_TestUtils_DecodeBase16() failed");
        string_clear(in_text);
    }

    mock_bpa_ctr_t ctr;
    mock_bpa_ctr_init(&ctr);
    TEST_ASSERT_EQUAL_INT(0, BSL_Data_CopyFrom(&ctr.encoded, in_data.len, in_data.ptr));

    int res = mock_bpa_ctr_decode(&ctr);
    TEST_ASSERT_NOT_EQUAL_INT_MESSAGE(0, res, "mock_bpa_decode() succeded");

    mock_bpa_ctr_deinit(&ctr);
    BSL_Data_Deinit(&in_data);
}
