#include <gtest/gtest.h>
#include <arpa/inet.h>

#include "packet_private.h"
#include "packet_parser.h"
#include "packet_dump.h"

/******************************************************************************
 * [Protocols in frame: eth:ethertype:ip:ipv6:tcp]
 ******************************************************************************
 *
 * Frame 1: 106 bytes on wire (848 bits), 106 bytes captured (848 bits)
 * Ethernet II, Src: JuniperN_45:88:29 (2c:6b:f5:45:88:29), Dst: JuniperN_2a:a2:00 (5c:5e:ab:2a:a2:00)
 * 	Destination: JuniperN_2a:a2:00 (5c:5e:ab:2a:a2:00)
 * 	Source: JuniperN_45:88:29 (2c:6b:f5:45:88:29)
 * 	Type: IPv4 (0x0800)
 * Internet Protocol Version 4, Src: 210.77.88.163, Dst: 59.66.4.50
 * 	0100 .... = Version: 4
 * 	.... 0101 = Header Length: 20 bytes (5)
 * 	Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT)
 * 	Total Length: 92
 * 	Identification: 0x0b4d (2893)
 * 	000. .... = Flags: 0x0
 * 	...0 0000 0000 0000 = Fragment Offset: 0
 * 	Time to Live: 59
 * 	Protocol: IPv6 (41)
 * 	Header Checksum: 0x09c8 [validation disabled]
 * 	[Header checksum status: Unverified]
 * 	Source Address: 210.77.88.163
 * 	Destination Address: 59.66.4.50
 * Internet Protocol Version 6, Src: 2001:da8:200:900e:200:5efe:d24d:58a3, Dst: 2600:140e:6::1702:1058
 * 	0110 .... = Version: 6
 * 	.... 0000 0000 .... .... .... .... .... = Traffic Class: 0x00 (DSCP: CS0, ECN: Not-ECT)
 * 	.... 0000 0000 0000 0000 0000 = Flow Label: 0x00000
 * 	Payload Length: 32
 * 	Next Header: TCP (6)
 * 	Hop Limit: 64
 * 	Source Address: 2001:da8:200:900e:200:5efe:d24d:58a3
 * 	Destination Address: 2600:140e:6::1702:1058
 * 	[Source ISATAP IPv4: 210.77.88.163]
 * Transmission Control Protocol, Src Port: 52556, Dst Port: 80, Seq: 0, Len: 0
 * 	Source Port: 52556
 * 	Destination Port: 80
 * 	[Stream index: 0]
 * 	[Conversation completeness: Complete, WITH_DATA (31)]
 * 	[TCP Segment Len: 0]
 * 	Sequence Number: 0    (relative sequence number)
 * 	Sequence Number (raw): 2172673142
 * 	[Next Sequence Number: 1    (relative sequence number)]
 * 	Acknowledgment Number: 0
 * 	Acknowledgment number (raw): 0
 * 	1000 .... = Header Length: 32 bytes (8)
 * 	Flags: 0x002 (SYN)
 * 	Window: 8192
 * 	[Calculated window size: 8192]
 * 	Checksum: 0xf757 [unverified]
 * 	[Checksum Status: Unverified]
 * 	Urgent Pointer: 0
 * 	Options: (12 bytes), Maximum segment size, No-Operation (NOP), Window scale, No-Operation (NOP), No-Operation (NOP), SACK permitted
 * 	[Timestamps]
 */

unsigned char data[] = {
	0x5c, 0x5e, 0xab, 0x2a, 0xa2, 0x00, 0x2c, 0x6b, 0xf5, 0x45, 0x88, 0x29, 0x08, 0x00, 0x45, 0x00, 0x00, 0x5c, 0x0b, 0x4d, 0x00, 0x00, 0x3b, 0x29, 0x09, 0xc8,
	0xd2, 0x4d, 0x58, 0xa3, 0x3b, 0x42, 0x04, 0x32, 0x60, 0x00, 0x00, 0x00, 0x00, 0x20, 0x06, 0x40, 0x20, 0x01, 0x0d, 0xa8, 0x02, 0x00, 0x90, 0x0e, 0x02, 0x00,
	0x5e, 0xfe, 0xd2, 0x4d, 0x58, 0xa3, 0x26, 0x00, 0x14, 0x0e, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x02, 0x10, 0x58, 0xcd, 0x4c, 0x00, 0x50,
	0x81, 0x80, 0x5c, 0x76, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20, 0x00, 0xf7, 0x57, 0x00, 0x00, 0x02, 0x04, 0x04, 0xc4, 0x01, 0x03, 0x03, 0x08, 0x01, 0x01,
	0x04, 0x02};

#if 1
TEST(PACKET_LDBC, HASH_VALUE)
{
	struct packet handler;

	memset(&handler, 0, sizeof(handler));
	const char *payload = packet_parse(&handler, (const char *)data, sizeof(data));
	EXPECT_TRUE(payload != nullptr);
	EXPECT_TRUE((char *)payload - (char *)&data == 106);
	packet_print(&handler);

	// buffer: "2001:da8:200:900e:200:5efe:d24d:58a3 0 2600:140e:6::1702:1058 0"
	// buffer: "210.77.88.163 0 59.66.4.50 0"

	EXPECT_TRUE(packet_ldbc_hash(&handler, PKT_LDBC_METH_OUTERMOST_INT_IP, PACKET_DIRECTION_INCOMING) == packet_ldbc_hash(&handler, PKT_LDBC_METH_OUTERMOST_EXT_IP, PACKET_DIRECTION_OUTGOING));
	EXPECT_TRUE(packet_ldbc_hash(&handler, PKT_LDBC_METH_OUTERMOST_EXT_IP, PACKET_DIRECTION_INCOMING) == packet_ldbc_hash(&handler, PKT_LDBC_METH_OUTERMOST_INT_IP, PACKET_DIRECTION_OUTGOING));

	EXPECT_TRUE(packet_ldbc_hash(&handler, PKT_LDBC_METH_OUTERMOST_INT_EXT_IP, PACKET_DIRECTION_INCOMING) == packet_ldbc_hash(&handler, PKT_LDBC_METH_OUTERMOST_INT_EXT_IP, PACKET_DIRECTION_OUTGOING));
	EXPECT_TRUE(packet_ldbc_hash(&handler, PKT_LDBC_METH_INNERMOST_INT_IP, PACKET_DIRECTION_INCOMING) == packet_ldbc_hash(&handler, PKT_LDBC_METH_INNERMOST_EXT_IP, PACKET_DIRECTION_OUTGOING));
}
#endif

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