int main ()
{
    std::cout << "--- Testing the encode and decode functions of Eurobalise Telegram consecutively with conditional packets." << std::endl;
    // declare a telegram
    Eurobalise_Telegram telegram;

    // declare and initialize a telegram header
    // telegram.header = create_Telegram_Header_TrainToTrack();
    telegram.header = create_Telegram_Header_TrackToTrain();

    // create a pointer to a data packet including core data packet 1
    // and push this pointer into the telegam packet vector
    // telegram.add(std::make_shared<Train_running_number>(create_Train_running_number()));
    // telegram.add(std::make_shared<Error_Reporting>(create_Error_Reporting()));

    telegram.add(std::make_shared<Temporary_Speed_Restriction>(create_Temporary_Speed_Restriction()));
    telegram.add(std::make_shared<Adhesion_Factor>(create_Adhesion_Factor()));
    telegram.add(std::make_shared<Infill_location_reference>(create_Infill_location_reference(1)));
    telegram.add(std::make_shared<Infill_location_reference>(create_Infill_location_reference(0)));

    // add end of information package to packet sequence
    telegram.add(std::make_shared<End_of_Information>());

    std::cout << " Encoder Input: " << telegram << std::endl;

    // declare and initialize the stream
    std::vector<uint8_t> raw_stream(1000);
    Bitstream stream;
    Bitstream_Init(&stream, &(raw_stream[0]), raw_stream.size(), 73);

    // save the old bitpos
    uint32_t init_pos = stream.bitpos;

    // *** encode the telegram to the stream ***
    std::cout << " Encoding Eurobalise Telegram." << std::endl;
    telegram.encode(stream);

    // reset to the old bitpos
    stream.bitpos = init_pos;

    // declare a new telegram
    Eurobalise_Telegram telegram_new;

    // *** decode from the stream to the new telegram ***
    std::cout << " Decoding Eurobalise Telegram." << std::endl;
    telegram_new.decode(stream);

    std::cout << " Decoder Ouput: " << telegram_new << std::endl;
    assert(telegram_new == telegram);

    std::cout << " Test successfull.\n" << std::endl;

    return EXIT_SUCCESS;
}
int main ()
{
    std::cout << "\n--- Testing the en-/decode bit functions of Eurobalise Telegram with conditional packets" << std::endl;

    // construct telegram from header
    // telegram.header = create_TelegramHeader_TrainToTrack();
    EurobaliseTelegram telegram(create_TelegramHeader_TrackToTrain());

    telegram.add(std::make_shared<Temporary_Speed_Restriction>(create_Temporary_Speed_Restriction()));
    telegram.add(std::make_shared<Adhesion_Factor>(create_Adhesion_Factor()));
    telegram.add(std::make_shared<Infill_location_reference>(create_Infill_location_reference(1)));
    telegram.add(std::make_shared<Infill_location_reference>(create_Infill_location_reference(0)));

    // add end of information package to packet sequence
    telegram.add(std::make_shared<End_of_Information>());

    //std::cout << " Encoder Input: " << telegram << std::endl;

    // declare and initialize the stream
    std::vector<uint8_t> raw_stream(1000);
    Bitstream stream;
    Bitstream_Init(&stream, &(raw_stream[0]), raw_stream.size(), 73);

    // save the old bitpos
    uint32_t init_pos = stream.bitpos;

    //std::cout << " Encoding Eurobalise Telegram." << std::endl;
    telegram.encode(stream);

    // reset to the old bitpos
    stream.bitpos = init_pos;

    // declare a new telegram
    EurobaliseTelegram telegram_new;
    //std::cout << " Decoding Eurobalise Telegram." << std::endl;
    telegram_new.decode(stream);

    //std::cout << " Decoder Ouput: " << telegram_new << std::endl;
    assert(telegram_new == telegram);

    std::cout << " Test successfull." << std::endl;

    return EXIT_SUCCESS;
}
int main ()
{
    std::cout << "\n--- Testing the decode function of Eurobalise Telegram with N_ITER packets." << std::endl;
    std::vector<uint8_t> raw_stream(1000);
    Bitstream stream;
    Bitstream_Init(&stream, &(raw_stream[0]), raw_stream.size(), 73);

    uint32_t init_pos = stream.bitpos;

    // TelegramHeader header = create_TelegramHeader_TrainToTrack();
    std::cout << " Encoding Telegram Header: " << header << std::endl;
    TelegramHeader header = create_TelegramHeader_TrackToTrain();
    encode(stream, header);

    Temporary_Speed_Restriction a = create_Temporary_Speed_Restriction();
    {
        std::cout << "    Encoding packet " << a << std::endl;
        encode(stream, a.header);
        encode(stream, a.core);
    }

    Adhesion_Factor b = create_Adhesion_Factor();
    {
        std::cout << "    Encoding packet " << b << std::endl;
        encode(stream, b.header);
        encode(stream, b.core);
    }

    Infill_location_reference c = create_Infill_location_reference(1);
    {
        std::cout << "    Encoding packet " << c << std::endl;
        encode(stream, c.header);
        encode(stream, c.core);
    }

    Infill_location_reference d = create_Infill_location_reference(0);
    {
        std::cout << "    Encoding packet " << d << std::endl;
        encode(stream, d.header);
        encode(stream, d.core);
    }

    Gradient_Profile e = create_Gradient_Profile();
    {
        std::cout << "    Encoding packet " << e << std::endl;
        encode(stream, e.header);
        encode(stream, e.core);
    }

    End_of_Information f;
    {
        std::cout << "    Encoding packet " << f << std::endl;
        encode(stream, f.header);
        encode(stream, f.core);
    }

    stream.bitpos = init_pos;

    EurobaliseTelegram telegram;

    std::cout << " Decoding Eurobalise Telegram." << std::endl;
    telegram.decode(stream);

    std::cout << " Decoder Output: " << telegram << std::endl;

    assert(telegram.header == header);

    assert_equal(a, telegram.packets[0]);
    assert_equal(b, telegram.packets[1]);
    assert_equal(c, telegram.packets[2]);

    std::cout << " Test successful." << std::endl;

    return EXIT_SUCCESS;
}