예제 #1
0
	size_t ut_WiflyControl_FwSetFade_2(void)
	{
		led_cmd expectedOutgoingFrame;
		expectedOutgoingFrame.cmd = SET_FADE;
		expectedOutgoingFrame.data.set_fade.addr[0] = 0x44;
		expectedOutgoingFrame.data.set_fade.addr[1] = 0x33;
		expectedOutgoingFrame.data.set_fade.addr[2] = 0x22;
		expectedOutgoingFrame.data.set_fade.addr[3] = 0x11;
		expectedOutgoingFrame.data.set_fade.red = 0x11;
		expectedOutgoingFrame.data.set_fade.green = 0x22;
		expectedOutgoingFrame.data.set_fade.blue = 0x33;
		expectedOutgoingFrame.data.set_fade.parallelFade = 0x01;
		//TODO why do we use fadeTmms == 1 for SetColor?
		expectedOutgoingFrame.data.set_fade.fadeTmms = htons(1000);

		TestCaseBegin();
		Control testee(0, 0);

		// set color
		testee << FwCmdSetFade {0xff112233, 1000, 0x11223344, true};
		TraceBuffer(ZONE_INFO, &g_SendFrame,           sizeof(cmd_set_fade) + 1, "%02x ", "IS  :");
		TraceBuffer(ZONE_INFO, &expectedOutgoingFrame, sizeof(cmd_set_fade) + 1, "%02x ", "SOLL:");
		CHECK(0 == memcmp(&g_SendFrame, &expectedOutgoingFrame, sizeof(cmd_set_fade) + 1));


		TestCaseEnd();
	}
예제 #2
0
	size_t ut_WiflyControl_FwSetGradient(void)
	{
		led_cmd expectedOutgoingFrame;
		expectedOutgoingFrame.cmd = SET_GRADIENT;
		expectedOutgoingFrame.data.set_gradient.red_1 = 0x11;
		expectedOutgoingFrame.data.set_gradient.green_1 = 0x22;
		expectedOutgoingFrame.data.set_gradient.blue_1 = 0x33;
		expectedOutgoingFrame.data.set_gradient.red_2 = 0x33;
		expectedOutgoingFrame.data.set_gradient.green_2 = 0x22;
		expectedOutgoingFrame.data.set_gradient.blue_2 = 0x11;
		expectedOutgoingFrame.data.set_gradient.parallelAndOffset = 0xff;
		expectedOutgoingFrame.data.set_gradient.numberOfLeds = 10;
		expectedOutgoingFrame.data.set_gradient.fadeTmms = htons(1000);

		TestCaseBegin();
		Control testee(0, 0);

		testee << FwCmdSetGradient {0xff112233,0xff332211, 1000, true, 10, 127};
		TraceBuffer(ZONE_INFO, &g_SendFrame,           sizeof(cmd_set_gradient) + 1, "%02x ", "IS  :");
		TraceBuffer(ZONE_INFO, &expectedOutgoingFrame, sizeof(cmd_set_gradient) + 1, "%02x ", "SOLL:");
		CHECK(0 == memcmp(&g_SendFrame, &expectedOutgoingFrame, sizeof(cmd_set_gradient) + 1));


		TestCaseEnd();
	}
예제 #3
0
	size_t ut_WiflyControl_FwSetColorDirectThreeLeds_2(void)
	{
		TestCaseBegin();
		Control testee(0, 0);

		// three leds only, all set to yellow
		const uint32_t argb = 0xffffff00;
		const uint32_t addr = 0x00000007;
		uint8_t shortBuffer[3 * 3];
		memset(shortBuffer, 0, sizeof(shortBuffer));
		shortBuffer[0 * 3 + 0] = 0xff; //first led red
		shortBuffer[1 * 3 + 1] = 0xff; //second led green
		shortBuffer[2 * 3 + 2] = 0xff; //third led blue
		led_cmd expectedOutgoingFrame;
		expectedOutgoingFrame.cmd = SET_COLOR_DIRECT;
		memset(expectedOutgoingFrame.data.set_color_direct.ptr_led_array, 0, 3 * NUM_OF_LED);
		expectedOutgoingFrame.data.set_color_direct.ptr_led_array[0] = 0xff;
		expectedOutgoingFrame.data.set_color_direct.ptr_led_array[1] = 0xff;
		expectedOutgoingFrame.data.set_color_direct.ptr_led_array[2] = 0x00;
		expectedOutgoingFrame.data.set_color_direct.ptr_led_array[3] = 0xff;
		expectedOutgoingFrame.data.set_color_direct.ptr_led_array[4] = 0xff;
		expectedOutgoingFrame.data.set_color_direct.ptr_led_array[5] = 0x00;
		expectedOutgoingFrame.data.set_color_direct.ptr_led_array[6] = 0xff;
		expectedOutgoingFrame.data.set_color_direct.ptr_led_array[7] = 0xff;
		expectedOutgoingFrame.data.set_color_direct.ptr_led_array[8] = 0x00;

		testee << FwCmdSetColorDirect {argb, addr};


		TraceBuffer(ZONE_INFO, &g_SendFrame,           sizeof(led_cmd) + 1, "%02x ", "IS  :");
		TraceBuffer(ZONE_INFO, &expectedOutgoingFrame, sizeof(led_cmd) + 1, "%02x ", "SOLL:");

		CHECK(0 == memcmp(&g_SendFrame, &expectedOutgoingFrame, sizeof(led_cmd)));
		TestCaseEnd();
	}
예제 #4
0
	size_t ut_WiflyControl_BlEraseFlash(void)
	{
		TestCaseBegin();

		srand(time_t(NULL));

		/* fill gloabal random data pool */
		for(unsigned int i = 0; i < sizeof(g_FlashRndDataPool); i++)
			g_FlashRndDataPool[i] = (uint8_t) rand() % 255;

		BlInfo blInfo;
		Control testctrl(0,0);
		try {
			testctrl.BlReadInfo(blInfo);
			testctrl.BlEraseFlash();
		} catch(FatalError& e) {
			CHECK(false);
		}

		for(unsigned int i = 0; i < blInfo.GetAddress(); i++) {
			CHECK(0 == g_FlashRndDataPool[i]);
		}

		TestCaseEnd();
	}
예제 #5
0
	size_t ut_WiflyControl_BlFlashRead(void)
	{
		TestCaseBegin();
		srand(time_t(NULL));

		/* fill gloabal random data pool */
		for(unsigned int i = 0; i < sizeof(g_FlashRndDataPool); i++)
			g_FlashRndDataPool[i] = (uint8_t) rand() % 255;

		Control testctrl(0,0);

		std::stringstream mStream;

		testctrl.BlReadFlash(mStream, 0, FLASH_SIZE);

		size_t counter = 0;
		do
		{
			uint8_t byte = 0;
			mStream >> byte;
			if(mStream.eof()) break;
			CHECK(g_FlashRndDataPool[counter++] == byte);
		}
		while(!mStream.eof());
			CHECK(counter == FLASH_SIZE);
		TestCaseEnd();

	}
예제 #6
0
	size_t ut_WiflyControl_FwSetRtc(void)
	{
		tm timeinfo;
		time_t rawtime;
		rawtime = time(NULL);
		localtime_r(&rawtime, &timeinfo);

		led_cmd expectedOutgoingFrame = {0xff};
		expectedOutgoingFrame.cmd = SET_RTC;
		expectedOutgoingFrame.data.set_rtc.tm_sec = (uns8) timeinfo.tm_sec;
		expectedOutgoingFrame.data.set_rtc.tm_min = (uns8) timeinfo.tm_min;
		expectedOutgoingFrame.data.set_rtc.tm_hour = (uns8) timeinfo.tm_hour;
		expectedOutgoingFrame.data.set_rtc.tm_mday = (uns8) timeinfo.tm_mday;
		expectedOutgoingFrame.data.set_rtc.tm_mon = (uns8) timeinfo.tm_mon;
		expectedOutgoingFrame.data.set_rtc.tm_year = (uns8) timeinfo.tm_year;
		expectedOutgoingFrame.data.set_rtc.tm_wday = (uns8) timeinfo.tm_wday;


		TestCaseBegin();
		Control testee(0, 0);

		testee << FwCmdSetRtc {timeinfo};
		TraceBuffer(ZONE_INFO, &g_SendFrame,           sizeof(rtc_time) + 1, "%02x ", "IS  :");
		TraceBuffer(ZONE_INFO, &expectedOutgoingFrame, sizeof(rtc_time) + 1, "%02x ", "SOLL:");
		CHECK(0 == memcmp(&g_SendFrame, &expectedOutgoingFrame, sizeof(rtc_time) + 1));

		TestCaseEnd();
	}
예제 #7
0
	size_t ut_WiflyControl_ConfSetWlan(void)
	{
		TestCaseBegin();
		static const std::string phraseBase("12345678911234567892123456789312345678941234567895123456789612");
		static const std::string phraseContainsNonAlNum(phraseBase + "\x1f");
		static const std::string phrase(phraseBase + "3");
		static const std::string phraseToLong(phrase + " ");
		static const std::string ssid      ("12345678911234567892123456789312");
		static const std::string ssidToLong(ssid + " ");
		Control testee(0, 0);

		// passphrase to short
		CHECK(!testee.ConfSetWlan("", ssid));
		// passphrase to long
		CHECK(!testee.ConfSetWlan(phraseToLong, ssid));

		// passphrase contains not only alphanumeric characters
		CHECK(!testee.ConfSetWlan(phraseContainsNonAlNum, ssid));

		// ssid to short
		CHECK(!testee.ConfSetWlan(phrase, ""));

		// ssid to long
		CHECK(!testee.ConfSetWlan(phrase, ssidToLong));

		// valid passphrase and ssid
		CHECK(testee.ConfSetWlan(phrase, ssid));

		TestCaseEnd();
	}
예제 #8
0
	size_t ut_WiflyControl_FwClearScript(void)
	{
		led_cmd expectedOutgoingFrame = {0xff};
		expectedOutgoingFrame.cmd = CLEAR_SCRIPT;

		TestCaseBegin();
		Control testee(0, 0);

		testee << FwCmdClearScript {};
		TraceBuffer(ZONE_INFO, &g_SendFrame,           1, "%02x ", "IS  :");
		TraceBuffer(ZONE_INFO, &expectedOutgoingFrame, 1, "%02x ", "SOLL:");
		CHECK(0 == memcmp(&g_SendFrame, &expectedOutgoingFrame, 1));

		TestCaseEnd();
	}
예제 #9
0
	size_t ut_WiflyControl_FwLoopOn(void)
	{
		led_cmd expectedOutgoingFrame = {0xff};
		expectedOutgoingFrame.cmd = LOOP_ON;

		TestCaseBegin();
		Control testee(0, 0);

		testee << FwCmdLoopOn {};

		TraceBuffer(ZONE_INFO, &g_SendFrame,           1, "%02x ", "IS  :");
		TraceBuffer(ZONE_INFO, &expectedOutgoingFrame, 1, "%02x ", "SOLL:");
		CHECK(0 == memcmp(&g_SendFrame, &expectedOutgoingFrame, 1));

		TestCaseEnd();
	}
예제 #10
0
	size_t ut_WiflyControl_FwSetWait(void)
	{
		led_cmd expectedOutgoingFrame = {0xff};
		expectedOutgoingFrame.cmd = WAIT;
		expectedOutgoingFrame.data.wait.waitTmms = htons(1000);

		TestCaseBegin();
		Control testee(0, 0);

		testee << FwCmdWait {1000};
		TraceBuffer(ZONE_INFO, &g_SendFrame,           sizeof(cmd_wait) + 1, "%02x ", "IS  :");
		TraceBuffer(ZONE_INFO, &expectedOutgoingFrame, sizeof(cmd_wait) + 1, "%02x ", "SOLL:");
		CHECK(0 == memcmp(&g_SendFrame, &expectedOutgoingFrame, sizeof(cmd_wait) + 1));

		TestCaseEnd();
	}
예제 #11
0
	size_t ut_WiflyControl_FwSetColorDirectRedOnly(void)
	{
		TestCaseBegin();
		Control testee(0, 0);

		// one leds only, first red
		uint8_t shortBuffer[1] {0xff};
		led_cmd expectedOutgoingFrame;
		expectedOutgoingFrame.cmd = SET_COLOR_DIRECT;
		memcpy(expectedOutgoingFrame.data.set_color_direct.ptr_led_array, shortBuffer, sizeof(shortBuffer));
		memset(expectedOutgoingFrame.data.set_color_direct.ptr_led_array + sizeof(shortBuffer), 0x00, sizeof(cmd_set_color_direct) - sizeof(shortBuffer));

		testee << FwCmdSetColorDirect {shortBuffer, sizeof(shortBuffer)};

		CHECK(0 == memcmp(&g_SendFrame, &expectedOutgoingFrame, sizeof(led_cmd)));
		TestCaseEnd();
	}
예제 #12
0
	size_t ut_WiflyControl_FwSetColorDirectToMany(void)
	{
		TestCaseBegin();
		Control testee(0, 0);

		// three leds only, first red, second green last blue
		uint8_t shortBuffer[2 * NUM_OF_LED * 3];
		memset(shortBuffer, 0xff, sizeof(shortBuffer));
		led_cmd expectedOutgoingFrame;
		expectedOutgoingFrame.cmd = SET_COLOR_DIRECT;
		memcpy(expectedOutgoingFrame.data.set_color_direct.ptr_led_array, shortBuffer, NUM_OF_LED * 3);

		testee << FwCmdSetColorDirect(shortBuffer, sizeof(shortBuffer));

		CHECK(0 == memcmp(&g_SendFrame, &expectedOutgoingFrame, sizeof(led_cmd)));
		TestCaseEnd();
	}
예제 #13
0
	size_t ut_WiflyControl_ConfSetDefaults(void)
	{
		TestCaseBegin();
		static const std::string commands[] = {
			"set broadcast interval 0x1\r\n",    // to support fast broadcast recognition
			"set comm close 0\r\n",            // Disable *CLOS* string
			"set comm open 0\r\n",             // Disable *OPEN* string
			"set comm remote 0\r\n",           // Disable *Hello* string
			"set comm time 5\r\n", 			// Set flush timer to 5 ms
			"set comm idle 240\r\n",			// Set idle timer to 240 s, to close tcp connections after 240s if there's no traffic
			"set dns name rn.microchip.com\r\n",    // set dns of updateserver
			"set ip flags 0x6\r\n",                    // if the module loses the accesspoint connection, the connection is closed
			"set ip dhcp 1\r\n",               // enable DHCP client
			//		"set ftp address 169.254.7.57\r\n",// configure localhost as ftp server in ad-hoc connection
			"set ftp pass Pass123\r\n",        // configure ftp password
			"set ftp user roving\r\n",         // configure ftp username
			"set opt deviceid Wifly_Light\r\n", // Set deviceid which appears in broadcastmsg to "Wifly_Light"
			"set uart baud 115200\r\n",        // PIC uart parameter
			"set uart flow 0\r\n",             // PIC uart parameter
			"set uart mode 0\r\n",             // PIC uart parameter
			"set wlan channel 0\r\n",                  // Set the wlan channel to 0 to perform an automatic scan for a free channel
			"set wlan auth 4\r\n",             // use WPA2 protection
			"set wlan join 1\r\n",             // scan for ap and auto join
			"set wlan rate 0\r\n",             // slowest datarate but highest range
			"set wlan tx 12\r\n",              // Set the Wi-Fi transmit power to maximum
			"set sys printlvl 0\r\n",				// Disables Debug Messages to UART
			"set ip p 11\r\n",                                 // Enable UDP, TCP_CLIENT and TCP Protocol
			//"set sys launch_string wps_app"	   // Choose Wps mode
		};
		static const size_t numCommands = sizeof(commands) / sizeof(commands[0]);

		Control testee(0, 0);

		g_TestBuffer.clear();
			CHECK(testee.ConfSetDefaults());
			CHECK(!g_ProxyConnected);
			CHECK(g_ProxySaved);
			CHECK(numCommands == g_TestBuffer.size());
		for(size_t i = 0; i < numCommands; i++) {
			CHECK(0 == commands[i].compare(g_TestBuffer.front()));
			g_TestBuffer.pop_front();

		}
		TestCaseEnd();
	}
예제 #14
0
	size_t ut_WiflyControl_FwGetVersion(void)
	{
		led_cmd expectedOutgoingFrame = {0xff};
		expectedOutgoingFrame.cmd = GET_FW_VERSION;

		TestCaseBegin();
		Control testee(0, 0);

		try {
			testee.FwGetVersion();
		} catch(std::exception) { }

		TraceBuffer(ZONE_INFO, &g_SendFrame,           1, "%02x ", "IS  :");
		TraceBuffer(ZONE_INFO, &expectedOutgoingFrame, 1, "%02x ", "SOLL:");
		CHECK(0 == memcmp(&g_SendFrame, &expectedOutgoingFrame, 1));

		TestCaseEnd();
	}
예제 #15
0
	size_t ut_WiflyControl_BlReadInfo(void)
	{
		TestCaseBegin();
		Control testctrl(0,0);
		BlInfo mInfo;
		testctrl.BlReadInfo(mInfo);
		CHECK(mInfo.familyId == 4);
		CHECK(mInfo.versionMajor == 1);
		CHECK(mInfo.versionMinor == 5);
		CHECK(mInfo.zero == 0);
		CHECK(mInfo.sizeHigh == 3);
		CHECK(mInfo.sizeLow == 0);
		CHECK(mInfo.startU == 0);
		CHECK(mInfo.startHigh == 253);
		CHECK(mInfo.startLow == 0);
		CHECK(mInfo.cmdmaskHigh == 255);
		//CHECK(mInfo.cmdmaskLow == 0x84);
		TestCaseEnd();
	}
예제 #16
0
	size_t ut_WiflyControl_FwLoopOff(void)
	{
		led_cmd expectedOutgoingFrame = {0xff};
		expectedOutgoingFrame.cmd = LOOP_OFF;
		expectedOutgoingFrame.data.loopEnd.numLoops = 100;
		expectedOutgoingFrame.data.loopEnd.counter = 0;
		expectedOutgoingFrame.data.loopEnd.depth = 0;
		expectedOutgoingFrame.data.loopEnd.startIndex = 0;

		TestCaseBegin();
		Control testee(0, 0);

		testee << FwCmdLoopOff {100};

		TraceBuffer(ZONE_INFO, &g_SendFrame,           1, "%02x ", "IS  :");
		TraceBuffer(ZONE_INFO, &expectedOutgoingFrame, 1, "%02x ", "SOLL:");
		CHECK(0 == memcmp(&g_SendFrame, &expectedOutgoingFrame, 1));

		TestCaseEnd();
	}
예제 #17
0
	size_t ut_WiflyControl_FwSetColorDirectThreeLeds(void)
	{
		TestCaseBegin();
		Control testee(0, 0);

		// three leds only, first red, second green last blue
		uint8_t shortBuffer[3 * 3];
		memset(shortBuffer, 0, sizeof(shortBuffer));
		shortBuffer[0 * 3 + 0] = 0xff; //first led red
		shortBuffer[1 * 3 + 1] = 0xff; //second led green
		shortBuffer[2 * 3 + 2] = 0xff; //third led blue
		led_cmd expectedOutgoingFrame;
		expectedOutgoingFrame.cmd = SET_COLOR_DIRECT;
		memcpy(expectedOutgoingFrame.data.set_color_direct.ptr_led_array, shortBuffer, sizeof(shortBuffer));
		memset(expectedOutgoingFrame.data.set_color_direct.ptr_led_array + sizeof(shortBuffer), 0x00, sizeof(cmd_set_color_direct) - sizeof(shortBuffer));

		testee << FwCmdSetColorDirect {shortBuffer, sizeof(shortBuffer)};

		CHECK(0 == memcmp(&g_SendFrame, &expectedOutgoingFrame, sizeof(led_cmd)));
		TestCaseEnd();
	}
예제 #18
0
	// Testcases
	size_t ut_WiflyControl_BlEraseEeprom(void)
	{
		TestCaseBegin();

		srand(time_t(NULL));

		/* fill gloabal random data pool */
		for(unsigned int i = 0; i < sizeof(g_EepromRndDataPool); i++) {
			g_EepromRndDataPool[i] = (uint8_t) rand() % 255;
		}

		Control testctrl(0,0);

		testctrl.BlEraseEeprom();

		for(unsigned int i = 0; i < EEPROM_SIZE; i++) {
			CHECK(0xff == g_EepromRndDataPool[i]);
		}

		TestCaseEnd();
	}
예제 #19
0
	size_t ut_WiflyControl_BlFlashWrite(void)
	{
		TestCaseBegin();

		srand(time_t(NULL));

		uint8_t m_FlashRndDataPool[FLASH_SIZE];

		/* fill gloabal random data pool */
		for(unsigned int i = 0; i < sizeof(g_FlashRndDataPool); i++) {
			g_FlashRndDataPool[i] = (uint8_t) rand() % 255;
			m_FlashRndDataPool[i] = (uint8_t) rand() % 255;
		}

		Control testctrl(0,0);

		testctrl.BlWriteFlash(0, m_FlashRndDataPool, sizeof(m_FlashRndDataPool));

		for(unsigned int i = 0; i < FLASH_SIZE; i++) {
			CHECK(m_FlashRndDataPool[i] == g_FlashRndDataPool[i]);
		}

		TestCaseEnd();
	}
예제 #20
0
파일: tcp_test.c 프로젝트: FFalcon/osdev
// ------------------------------------------------------------------------------------------------
int main(int argc, const char **argv)
{
    // Common variables
    NetBuf *inPkt;
    TcpHeader *inHdr;
    Packet *outPkt;
    TcpHeader *outHdr;
    TcpConn *conn;

    TestSetup();

    // --------------------------------------------------------------------------------------------
    TestCaseBegin(TCP_CLOSED, "RST", "segment dropped");

    inPkt = NetAllocBuf();
    inHdr = (TcpHeader *)inPkt->start;
    inHdr->srcPort = 100;
    inHdr->dstPort = 101;
    inHdr->seq = 1;
    inHdr->ack = 2;
    inHdr->off = 5 << 4;
    inHdr->flags = TCP_RST;
    inHdr->windowSize = TCP_WINDOW_SIZE;
    inHdr->checksum = 0;
    inHdr->urgent = 0;
    TcpInput(inPkt);

    TestCaseEnd();

    // --------------------------------------------------------------------------------------------
    TestCaseBegin(TCP_CLOSED, "ACK", "RST sent");

    inPkt = NetAllocBuf();
    inHdr = (TcpHeader *)inPkt->start;
    inHdr->srcPort = 100;
    inHdr->dstPort = 101;
    inHdr->seq = 1;
    inHdr->ack = 2;
    inHdr->off = 5 << 4;
    inHdr->flags = TCP_ACK;
    inHdr->windowSize = TCP_WINDOW_SIZE;
    inHdr->checksum = 0;
    inHdr->urgent = 0;
    TcpInput(inPkt);

    outPkt = PopPacket();
    outHdr = (TcpHeader *)outPkt->data;
    TcpSwap(outHdr);
    ASSERT_EQ_UINT(outHdr->srcPort, 101);
    ASSERT_EQ_UINT(outHdr->dstPort, 100);
    ASSERT_EQ_UINT(outHdr->seq, 2);
    ASSERT_EQ_UINT(outHdr->ack, 0);
    ASSERT_EQ_HEX8(outHdr->flags, TCP_RST);
    free(outPkt);

    TestCaseEnd();

    // --------------------------------------------------------------------------------------------
    TestCaseBegin(TCP_CLOSED, "no ACK", "RST/ACK sent");

    inPkt = NetAllocBuf();
    inHdr = (TcpHeader *)inPkt->start;
    inHdr->srcPort = 100;
    inHdr->dstPort = 101;
    inHdr->seq = 1;
    inHdr->ack = 2;
    inHdr->off = 5 << 4;
    inHdr->flags = 0;
    inHdr->windowSize = TCP_WINDOW_SIZE;
    inHdr->checksum = 0;
    inHdr->urgent = 0;
    TcpInput(inPkt);

    outPkt = PopPacket();
    outHdr = (TcpHeader *)outPkt->data;
    TcpSwap(outHdr);
    ASSERT_EQ_UINT(outHdr->srcPort, 101);
    ASSERT_EQ_UINT(outHdr->dstPort, 100);
    ASSERT_EQ_UINT(outHdr->seq, 0);
    ASSERT_EQ_UINT(outHdr->ack, 1);
    ASSERT_EQ_HEX8(outHdr->flags, TCP_RST | TCP_ACK);
    free(outPkt);

    TestCaseEnd();

    // --------------------------------------------------------------------------------------------
    TestCaseBegin(TCP_CLOSED, "connect", "goto SYN_SENT");

    conn = CreateConn();

    ASSERT_TRUE(TcpConnect(conn, &s_ipAddr, 80));

    outPkt = PopPacket();
    outHdr = (TcpHeader *)outPkt->data;
    TcpSwap(outHdr);
    ASSERT_TRUE(outHdr->srcPort >= 49152);
    ASSERT_EQ_UINT(outHdr->dstPort, 80);
    ASSERT_EQ_UINT(outHdr->seq, conn->iss);
    ASSERT_EQ_UINT(outHdr->ack, 0);
    ASSERT_EQ_HEX8(outHdr->flags, TCP_SYN);
    ASSERT_EQ_UINT(outHdr->windowSize, TCP_WINDOW_SIZE);
    ASSERT_EQ_UINT(outHdr->urgent, 0);
    free(outPkt);

    ExitState(conn, TCP_SYN_SENT);

    TestCaseEnd();

    // --------------------------------------------------------------------------------------------
    TestCaseBegin(TCP_SYN_SENT, "Bad ACK, no RST", "RST sent");

    conn = CreateConn();
    EnterState(conn, TCP_SYN_SENT);

    inPkt = NetAllocBuf();
    inHdr = PrepareInPkt(conn, inPkt, 1000, conn->iss, TCP_ACK);
    TcpInput(inPkt);

    outPkt = PopPacket();
    outHdr = (TcpHeader *)outPkt->data;
    TcpSwap(outHdr);
    ASSERT_EQ_UINT(outHdr->srcPort, conn->localPort);
    ASSERT_EQ_UINT(outHdr->dstPort, conn->remotePort);
    ASSERT_EQ_UINT(outHdr->seq, inHdr->ack);
    ASSERT_EQ_UINT(outHdr->ack, 0);
    ASSERT_EQ_HEX8(outHdr->flags, TCP_RST);
    free(outPkt);

    ExitState(conn, TCP_SYN_SENT);

    TestCaseEnd();

    // --------------------------------------------------------------------------------------------
    TestCaseBegin(TCP_SYN_SENT, "Bad ACK, RST", "segment dropped");

    conn = CreateConn();
    EnterState(conn, TCP_SYN_SENT);

    inPkt = NetAllocBuf();
    inHdr = PrepareInPkt(conn, inPkt, 1000, conn->iss, TCP_RST | TCP_ACK);
    TcpInput(inPkt);

    ExitState(conn, TCP_SYN_SENT);

    TestCaseEnd();

    // --------------------------------------------------------------------------------------------
    TestCaseBegin(TCP_SYN_SENT, "ACK, RST", "conn locally reset");

    conn = CreateConn();
    EnterState(conn, TCP_SYN_SENT);

    inPkt = NetAllocBuf();
    inHdr = PrepareInPkt(conn, inPkt, 1000, conn->iss + 1, TCP_RST | TCP_ACK);
    TcpInput(inPkt);

    ExpectError(TCP_CONN_RESET);
    ExitState(conn, TCP_CLOSED);

    TestCaseEnd();

    // --------------------------------------------------------------------------------------------
    TestCaseBegin(TCP_SYN_SENT, "no ACK, RST", "segment dropped");

    conn = CreateConn();
    EnterState(conn, TCP_SYN_SENT);

    inPkt = NetAllocBuf();
    inHdr = PrepareInPkt(conn, inPkt, 1000, conn->iss + 1, TCP_RST);
    TcpInput(inPkt);

    ExitState(conn, TCP_SYN_SENT);

    TestCaseEnd();

    // --------------------------------------------------------------------------------------------
    TestCaseBegin(TCP_SYN_SENT, "SYN, ACK", "goto ESTABLISHED");

    conn = CreateConn();
    EnterState(conn, TCP_SYN_SENT);

    inPkt = NetAllocBuf();
    inHdr = PrepareInPkt(conn, inPkt, 1000, conn->iss + 1, TCP_SYN | TCP_ACK);
    TcpInput(inPkt);

    ASSERT_EQ_UINT(conn->irs, 1000);
    ASSERT_EQ_UINT(conn->rcvNxt, 1001);

    outPkt = PopPacket();
    outHdr = (TcpHeader *)outPkt->data;
    TcpSwap(outHdr);
    ASSERT_EQ_UINT(outHdr->srcPort, conn->localPort);
    ASSERT_EQ_UINT(outHdr->dstPort, conn->remotePort);
    ASSERT_EQ_UINT(outHdr->seq, conn->iss + 1);
    ASSERT_EQ_UINT(outHdr->ack, 1001);
    ASSERT_EQ_HEX8(outHdr->flags, TCP_ACK);
    free(outPkt);

    ExitState(conn, TCP_ESTABLISHED);

    TestCaseEnd();

    // --------------------------------------------------------------------------------------------
    TestCaseBegin(TCP_SYN_SENT, "SYN, no ACK", "goto SYN_RECEIVED, resend SYN,ACK");

    conn = CreateConn();
    EnterState(conn, TCP_SYN_SENT);

    inPkt = NetAllocBuf();
    inHdr = PrepareInPkt(conn, inPkt, 1000, 0, TCP_SYN);
    TcpInput(inPkt);

    ASSERT_EQ_UINT(conn->irs, 1000);
    ASSERT_EQ_UINT(conn->rcvNxt, 1001);

    outPkt = PopPacket();
    outHdr = (TcpHeader *)outPkt->data;
    TcpSwap(outHdr);
    ASSERT_EQ_UINT(outHdr->srcPort, conn->localPort);
    ASSERT_EQ_UINT(outHdr->dstPort, conn->remotePort);
    ASSERT_EQ_UINT(outHdr->seq, conn->iss);
    ASSERT_EQ_UINT(outHdr->ack, 1001);
    ASSERT_EQ_HEX8(outHdr->flags, TCP_SYN | TCP_ACK);
    free(outPkt);

    ExitState(conn, TCP_SYN_RECEIVED);

    TestCaseEnd();

    // --------------------------------------------------------------------------------------------
    uint generalStates[] =
    {
        TCP_SYN_RECEIVED,
        TCP_ESTABLISHED,
        TCP_FIN_WAIT_1,
        TCP_FIN_WAIT_2,
        TCP_CLOSE_WAIT,
        TCP_CLOSING,
        TCP_LAST_ACK,
        TCP_TIME_WAIT,
        0,
    };

    for (uint *pState = generalStates; *pState; ++pState)
    {
        uint state = *pState;

        TestCaseBegin(state, "Bad seq, no RST", "resend ACK");

        conn = CreateConn();
        EnterState(conn, state);

        inPkt = NetAllocBuf();
        inHdr = PrepareInPkt(conn, inPkt, conn->rcvNxt - 1, conn->sndNxt, TCP_ACK);
        TcpInput(inPkt);

        outPkt = PopPacket();
        outHdr = (TcpHeader *)outPkt->data;
        TcpSwap(outHdr);
        ASSERT_EQ_UINT(outHdr->srcPort, conn->localPort);
        ASSERT_EQ_UINT(outHdr->dstPort, conn->remotePort);
        ASSERT_EQ_UINT(outHdr->seq, conn->sndNxt);
        ASSERT_EQ_UINT(outHdr->ack, conn->rcvNxt);
        ASSERT_EQ_HEX8(outHdr->flags, TCP_ACK);
        free(outPkt);

        ExitState(conn, state);

        TestCaseEnd();
    }

    // --------------------------------------------------------------------------------------------
    for (uint *pState = generalStates; *pState; ++pState)
    {
        uint state = *pState;

        TestCaseBegin(state, "Bad seq, RST", "segment dropped");

        conn = CreateConn();
        EnterState(conn, state);

        inPkt = NetAllocBuf();
        inHdr = PrepareInPkt(conn, inPkt, conn->rcvNxt - 1, conn->sndNxt, TCP_RST | TCP_ACK);
        TcpInput(inPkt);

        ExitState(conn, state);

        TestCaseEnd();
    }

    // --------------------------------------------------------------------------------------------
    TestCaseBegin(TCP_SYN_RECEIVED, "RST, active", "conn refused");

    conn = CreateConn();
    EnterState(conn, TCP_SYN_RECEIVED);

    inPkt = NetAllocBuf();
    inHdr = PrepareInPkt(conn, inPkt, conn->rcvNxt, 0, TCP_RST);
    TcpInput(inPkt);

    ExpectError(TCP_CONN_REFUSED);

    TestCaseEnd();

    // --------------------------------------------------------------------------------------------
    uint rstStates1[] =
    {
        TCP_ESTABLISHED,
        TCP_FIN_WAIT_1,
        TCP_FIN_WAIT_2,
        TCP_CLOSE_WAIT,
        0,
    };

    for (uint *pState = rstStates1; *pState; ++pState)
    {
        uint state = *pState;

        TestCaseBegin(state, "RST", "conn reset");

        conn = CreateConn();
        EnterState(conn, state);

        inPkt = NetAllocBuf();
        inHdr = PrepareInPkt(conn, inPkt, conn->rcvNxt, 0, TCP_RST);
        TcpInput(inPkt);

        ExpectError(TCP_CONN_RESET);

        TestCaseEnd();
    }

    // --------------------------------------------------------------------------------------------
    uint rstStates2[] =
    {
        TCP_CLOSING,
        TCP_LAST_ACK,
        TCP_TIME_WAIT,
        0,
    };

    for (uint *pState = rstStates2; *pState; ++pState)
    {
        uint state = *pState;

        TestCaseBegin(state, "RST", "conn closed");

        conn = CreateConn();
        EnterState(conn, state);

        inPkt = NetAllocBuf();
        inHdr = PrepareInPkt(conn, inPkt, conn->rcvNxt, 0, TCP_RST);
        TcpInput(inPkt);

        TestCaseEnd();
    }

    // --------------------------------------------------------------------------------------------
    for (uint *pState = generalStates; *pState; ++pState)
    {
        uint state = *pState;

        TestCaseBegin(state, "SYN", "conn reset, RST sent");

        conn = CreateConn();
        EnterState(conn, state);

        u16 localPort = conn->localPort;
        u16 remotePort = conn->remotePort;
        u32 rcvNxt = conn->rcvNxt;

        inPkt = NetAllocBuf();
        inHdr = PrepareInPkt(conn, inPkt, conn->rcvNxt, conn->sndNxt, TCP_SYN);
        TcpInput(inPkt);

        outPkt = PopPacket();
        outHdr = (TcpHeader *)outPkt->data;
        TcpSwap(outHdr);
        ASSERT_EQ_UINT(outHdr->srcPort, localPort);
        ASSERT_EQ_UINT(outHdr->dstPort, remotePort);
        ASSERT_EQ_UINT(outHdr->seq, 0);
        ASSERT_EQ_UINT(outHdr->ack, rcvNxt);
        ASSERT_EQ_HEX8(outHdr->flags, TCP_RST | TCP_ACK);
        free(outPkt);

        ExpectError(TCP_CONN_RESET);

        TestCaseEnd();
    }

    // --------------------------------------------------------------------------------------------
    TestCaseBegin(TCP_SYN_RECEIVED, "bad ACK", "RST sent");

    TestCaseEnd();

    // --------------------------------------------------------------------------------------------
    TestCaseBegin(TCP_SYN_RECEIVED, "ACK", "goto ESTABLISHED");

    TestCaseEnd();

    // --------------------------------------------------------------------------------------------
    uint ackStates[] =
    {
        TCP_ESTABLISHED,
        TCP_FIN_WAIT_1,
        TCP_FIN_WAIT_2,
        TCP_CLOSE_WAIT,
        TCP_CLOSING,
        0
    };

    for (uint *pState = ackStates; *pState; ++pState)
    {
        uint state = *pState;
        TestCaseBegin(state, "ACK", "update pointers");

        TestCaseEnd();
    }

    // --------------------------------------------------------------------------------------------
    for (uint *pState = ackStates; *pState; ++pState)
    {
        uint state = *pState;
        TestCaseBegin(state, "dup ACK", "ignore");

        TestCaseEnd();
    }

    // --------------------------------------------------------------------------------------------
    for (uint *pState = ackStates; *pState; ++pState)
    {
        uint state = *pState;
        TestCaseBegin(state, "unsent ACK", "resend ACK");

        TestCaseEnd();
    }

    // --------------------------------------------------------------------------------------------
    TestCaseBegin(TCP_FIN_WAIT_1, "ACK, FIN not ACK'd", "ignore");

    TestCaseEnd();

    // --------------------------------------------------------------------------------------------
    TestCaseBegin(TCP_CLOSING, "ACK, FIN not ACK'd", "ignore");

    TestCaseEnd();

    // --------------------------------------------------------------------------------------------
    TestCaseBegin(TCP_FIN_WAIT_1, "ACK, FIN ACK'd", "goto FIN-WAIT-2");

    TestCaseEnd();

    // --------------------------------------------------------------------------------------------
    TestCaseBegin(TCP_CLOSING, "ACK, FIN ACK'd", "goto TIME-WAIT");

    TestCaseEnd();

    // --------------------------------------------------------------------------------------------
    TestCaseBegin(TCP_LAST_ACK, "ACK, FIN not ACK'd", "ignore");

    conn = CreateConn();
    EnterState(conn, TCP_LAST_ACK);

    inPkt = NetAllocBuf();
    inHdr = PrepareInPkt(conn, inPkt, conn->rcvNxt, conn->sndNxt - 1, TCP_ACK);
    TcpInput(inPkt);

    ExitState(conn, TCP_LAST_ACK);

    TestCaseEnd();

    // --------------------------------------------------------------------------------------------
    TestCaseBegin(TCP_LAST_ACK, "ACK, FIN ACK'd", "goto CLOSED");

    conn = CreateConn();
    EnterState(conn, TCP_LAST_ACK);

    inPkt = NetAllocBuf();
    inHdr = PrepareInPkt(conn, inPkt, conn->rcvNxt, conn->sndNxt, TCP_ACK);
    TcpInput(inPkt);

    TestCaseEnd();

    // --------------------------------------------------------------------------------------------
    TestCaseBegin(TCP_TIME_WAIT, "ACK, no FIN", "ignore");

    conn = CreateConn();
    EnterState(conn, TCP_TIME_WAIT);

    inPkt = NetAllocBuf();
    inHdr = PrepareInPkt(conn, inPkt, conn->rcvNxt, conn->sndNxt, TCP_ACK);
    TcpInput(inPkt);

    ExitState(conn, TCP_TIME_WAIT);

    TestCaseEnd();

    // --------------------------------------------------------------------------------------------
    TestCaseBegin(TCP_TIME_WAIT, "FIN", "reset 2MSL timer");

    conn = CreateConn();
    EnterState(conn, TCP_TIME_WAIT);

    g_pitTicks += 1000;
    inPkt = NetAllocBuf();
    inHdr = PrepareInPkt(conn, inPkt, conn->rcvNxt, conn->sndNxt, TCP_FIN | TCP_ACK);
    TcpInput(inPkt);

    outPkt = PopPacket();
    outHdr = (TcpHeader *)outPkt->data;
    TcpSwap(outHdr);
    ASSERT_EQ_UINT(outHdr->srcPort, conn->localPort);
    ASSERT_EQ_UINT(outHdr->dstPort, conn->remotePort);
    ASSERT_EQ_UINT(outHdr->seq, conn->sndNxt);
    ASSERT_EQ_UINT(outHdr->ack, conn->rcvNxt);
    ASSERT_EQ_HEX8(outHdr->flags, TCP_ACK);
    free(outPkt);

    ASSERT_EQ_UINT(conn->mslWait, g_pitTicks + 2 * TCP_MSL);

    ExitState(conn, TCP_TIME_WAIT);

    TestCaseEnd();

    return EXIT_SUCCESS;
}