#include <gtest/gtest.h>

#include "packet_helper.h"

/*
 * User Datagram Protocol, Src Port: 2123, Dst Port: 12491
 * GPRS Tunneling Protocol V2
 *     Flags: 0x48
 *         010. .... = Version: 2
 *         ...0 .... = Piggybacking flag (P): 0
 *         .... 1... = TEID flag (T): 1
 *         .... .0.. = Message Priority(MP): 0
 *     Message Type: Delete Session Response (37)
 *     Message Length: 19
 *     Tunnel Endpoint Identifier: 0x0e05cd4d (235261261)
 *     Sequence Number: 0x000ce7 (3303)
 *     Spare: 0
 *     Cause : Request accepted (16)
 *         IE Type: Cause (2)
 *         IE Length: 2
 *         0000 .... = CR flag: 0
 *         .... 0000 = Instance: 0
 *         Cause: Request accepted (16)
 *         0000 0... = Spare bit(s): 0
 *         .... .0.. = PCE (PDN Connection IE Error): False
 *         .... ..0. = BCE (Bearer Context IE Error): False
 *         .... ...0 = CS (Cause Source): Originated by node sending the message
 *     Recovery (Restart Counter) : 13
 *         IE Type: Recovery (Restart Counter) (3)
 *         IE Length: 1
 *         0000 .... = CR flag: 0
 *         .... 0000 = Instance: 0
 *         Restart Counter: 13
 */

unsigned char gtp2_c_pkt1[] = {
    0x48, 0x25, 0x00, 0x13, 0x0e, 0x05, 0xcd, 0x4d, 0x00, 0x0c, 0xe7, 0x00, 0x02, 0x00, 0x02, 0x00, 0x10, 0x00, 0x03, 0x00, 0x01, 0x00, 0x0d};

// have teid

TEST(GTP2_UTILS, C_GET1)
{
    const struct gtp2_hdr *hdr = (struct gtp2_hdr *)gtp2_c_pkt1;

    EXPECT_TRUE(calc_gtp2_hdr_len((const char *)gtp2_c_pkt1, sizeof(gtp2_c_pkt1)) == 12);
    EXPECT_TRUE(gtp2_hdr_get_flags(hdr) == 0x48);
    EXPECT_TRUE(gtp2_hdr_get_version(hdr) == 2);
    EXPECT_TRUE(gtp2_hdr_get_piggyback_flag(hdr) == 0);
    EXPECT_TRUE(gtp2_hdr_get_teid_flag(hdr) == 1);
    EXPECT_TRUE(gtp2_hdr_get_spare_flag(hdr) == 0);
    EXPECT_TRUE(gtp2_hdr_get_msg_type(hdr) == 37);
    EXPECT_TRUE(gtp2_hdr_get_msg_len(hdr) == 19);
    EXPECT_TRUE(gtp2_hdr_get_teid(hdr) == 0x0e05cd4d);
    EXPECT_TRUE(gtp2_hdr_get_seq(hdr) == 0x000ce7);
    EXPECT_TRUE(gtp2_hdr_get_spare(hdr) == 0);

    char buff[1024] = {0};
    gtp2_hdr_to_str(hdr, buff, sizeof(buff));
    printf("%s\n", buff);
}

TEST(GTP2_UTILS, C_SET1)
{
    char buff[12] = {0};

    struct gtp2_hdr *hdr = (struct gtp2_hdr *)buff;
    gtp2_hdr_set_flags(hdr, 0x48);
    gtp2_hdr_set_version(hdr, 2);
    gtp2_hdr_set_piggyback_flag(hdr, 0);
    gtp2_hdr_set_teid_flag(hdr, 1);
    gtp2_hdr_set_spare_flag(hdr, 0);
    gtp2_hdr_set_msg_type(hdr, 37);
    gtp2_hdr_set_msg_len(hdr, 19);
    gtp2_hdr_set_teid(hdr, 0x0e05cd4d);
    gtp2_hdr_set_seq(hdr, 0x000ce7);
    gtp2_hdr_set_spare(hdr, 0);

    EXPECT_TRUE(memcmp(buff, gtp2_c_pkt1, 12) == 0);
}

/*
 * User Datagram Protocol, Src Port: 2123, Dst Port: 2123
 * GPRS Tunneling Protocol V2
 *     Flags: 0x40
 *         010. .... = Version: 2
 *         ...0 .... = Piggybacking flag (P): 0
 *         .... 0... = TEID flag (T): 0
 *         .... .0.. = Message Priority(MP): 0
 *     Message Type: Echo Request (1)
 *     Message Length: 9
 *     Sequence Number: 0x0041d4 (16852)
 *     Spare: 0
 *     Recovery (Restart Counter) : 5
 *         IE Type: Recovery (Restart Counter) (3)
 *         IE Length: 1
 *         0000 .... = CR flag: 0
 *         .... 0000 = Instance: 0
 *         Restart Counter: 5
 */

unsigned char gtp2_c_pkt2[] = {
    0x40, 0x01, 0x00, 0x09, 0x00, 0x41, 0xd4, 0x00, 0x03, 0x00, 0x01, 0x00, 0x05};

// no teid

TEST(GTP2_UTILS, C_GET2)
{
    const struct gtp2_hdr *hdr = (struct gtp2_hdr *)gtp2_c_pkt2;

    EXPECT_TRUE(calc_gtp2_hdr_len((const char *)gtp2_c_pkt2, sizeof(gtp2_c_pkt2)) == 8);
    EXPECT_TRUE(gtp2_hdr_get_flags(hdr) == 0x40);
    EXPECT_TRUE(gtp2_hdr_get_version(hdr) == 2);
    EXPECT_TRUE(gtp2_hdr_get_piggyback_flag(hdr) == 0);
    EXPECT_TRUE(gtp2_hdr_get_teid_flag(hdr) == 0);
    EXPECT_TRUE(gtp2_hdr_get_spare_flag(hdr) == 0);
    EXPECT_TRUE(gtp2_hdr_get_msg_type(hdr) == 1);
    EXPECT_TRUE(gtp2_hdr_get_msg_len(hdr) == 9);
    EXPECT_TRUE(gtp2_hdr_get_teid(hdr) == 0);
    EXPECT_TRUE(gtp2_hdr_get_seq(hdr) == 0x0041d4);
    EXPECT_TRUE(gtp2_hdr_get_spare(hdr) == 0);

    char buff[1024] = {0};
    gtp2_hdr_to_str(hdr, buff, sizeof(buff));
    printf("%s\n", buff);
}

TEST(GTP2_UTILS, C_SET2)
{
    char buff[8] = {0};

    struct gtp2_hdr *hdr = (struct gtp2_hdr *)buff;
    gtp2_hdr_set_flags(hdr, 0x40);
    gtp2_hdr_set_version(hdr, 2);
    gtp2_hdr_set_piggyback_flag(hdr, 0);
    gtp2_hdr_set_teid_flag(hdr, 0);
    gtp2_hdr_set_spare_flag(hdr, 0);
    gtp2_hdr_set_msg_type(hdr, 1);
    gtp2_hdr_set_msg_len(hdr, 9);
    gtp2_hdr_set_teid(hdr, 0);
    gtp2_hdr_set_seq(hdr, 0x0041d4);
    gtp2_hdr_set_spare(hdr, 0);

    EXPECT_TRUE(memcmp(buff, gtp2_c_pkt2, 8) == 0);
}

int main(int argc, char **argv)
{
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
