/* Include Unity header */ #include "unity.h" /* Include standard libraries */ #include #include #include #include "mock_FreeRTOS_IP.h" #include "mock_FreeRTOS_IP_Timers.h" #include "mock_FreeRTOS_Sockets.h" #include "mock_FreeRTOS_IP_Private.h" #include "mock_FreeRTOS_UDP_IP.h" #include "mock_FreeRTOS_ARP.h" #include "mock_task.h" #include "mock_NetworkBufferManagement.h" #include "mock_FreeRTOS_DHCP_mock.h" #include "FreeRTOS_DHCP.h" #include "FreeRTOS_DHCP_stubs.c" #include "catch_assert.h" #include "FreeRTOSIPConfig.h" extern Socket_t xDHCPSocket; extern DHCPData_t xDHCPData; static const char * pcHostName = "Unit-Test"; static NetworkBufferDescriptor_t * pxGlobalNetworkBuffer[ 10 ]; static uint8_t GlobalBufferCounter = 0; static NetworkBufferDescriptor_t * GetNetworkBuffer( size_t SizeOfEthBuf, long unsigned int xTimeToBlock, int callbacks ) { NetworkBufferDescriptor_t * pxNetworkBuffer = malloc( sizeof( NetworkBufferDescriptor_t ) ); pxNetworkBuffer->pucEthernetBuffer = malloc( SizeOfEthBuf ); /* Ignore the callback count. */ ( void ) callbacks; /* Ignore the timeout. */ ( void ) xTimeToBlock; /* Set the global network buffer so that memory can be freed later on. */ pxGlobalNetworkBuffer[ GlobalBufferCounter++ ] = pxNetworkBuffer; return pxNetworkBuffer; } static void ReleaseNetworkBuffer( void ) { /* Free the ethernet buffer. */ free( pxGlobalNetworkBuffer[ --GlobalBufferCounter ]->pucEthernetBuffer ); /* Free the network buffer. */ free( pxGlobalNetworkBuffer[ GlobalBufferCounter ] ); } static void ReleaseUDPBuffer( const void * temp, int callbacks ) { /* Should just call network buffer. */ ReleaseNetworkBuffer(); } #define xSizeofUDPBuffer 300 static uint8_t pucUDPBuffer[ xSizeofUDPBuffer ]; static int32_t RecvFromStub( Socket_t xSocket, void * pvBuffer, size_t uxBufferLength, BaseType_t xFlags, struct freertos_sockaddr * pxSourceAddress, socklen_t * pxSourceAddressLength, int callbacks ) { switch( callbacks ) { case 0: memset( pucUDPBuffer, 0, xSizeofUDPBuffer ); break; case 1: /* Put in correct DHCP cookie. */ ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ulDHCPCookie = dhcpCOOKIE; /* Put incorrect DHCP opcode. */ ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ucOpcode = dhcpREPLY_OPCODE + 10; break; } if( xFlags == FREERTOS_ZERO_COPY ) { *( ( uint8_t ** ) pvBuffer ) = pucUDPBuffer; } return xSizeofUDPBuffer; } static uint8_t DHCP_header[] = { dhcpREPLY_OPCODE, /**< Operation Code: Specifies the general type of message. */ 0x01, /**< Hardware type used on the local network. */ 0x06, /**< Hardware Address Length: Specifies how long hardware * addresses are in this message. */ 0x02, /**< Hops. */ 0x01, 0xAB, 0xCD, 0xEF, /**< A 32-bit identification field generated by the client, * to allow it to match up the request with replies received * from DHCP servers. */ 0x01, /**< Number of seconds elapsed since a client began an attempt to acquire or renew a lease. */ 0x00, /**< Just one bit used to indicate broadcast. */ 0xC0, 0xA8, 0x00, 0x0A, /**< Client's IP address if it has one or 0 is put in this field. */ 0x00, 0xAA, 0xAA, 0xAA, /**< The IP address that the server is assigning to the client. */ 0x00, 0xAA, 0xAA, 0xAA, /**< The DHCP server address that the client should use. */ 0x00, 0xAA, 0xAA, 0xAA /**< Gateway IP address in case the server client are on different subnets. */ }; static uint8_t * ucGenericPtr; static int32_t ulGenericLength; static int32_t FreeRTOS_recvfrom_Generic( Socket_t xSocket, void * pvBuffer, size_t uxBufferLength, BaseType_t xFlags, struct freertos_sockaddr * pxSourceAddress, socklen_t * pxSourceAddressLength, int callbacks ) { if( xFlags == FREERTOS_ZERO_COPY ) { *( ( uint8_t ** ) pvBuffer ) = ucGenericPtr; } return ulGenericLength; } static int32_t FreeRTOS_recvfrom_eWaitingOfferRecvfromLessBytesNoTimeout( Socket_t xSocket, void * pvBuffer, size_t uxBufferLength, BaseType_t xFlags, struct freertos_sockaddr * pxSourceAddress, socklen_t * pxSourceAddressLength, int callbacks ) { if( xFlags == FREERTOS_ZERO_COPY ) { *( ( uint8_t ** ) pvBuffer ) = pucUDPBuffer; } memset( pucUDPBuffer, 0, xSizeofUDPBuffer ); return sizeof( DHCPMessage_IPv4_t ) - 1; } static int32_t FreeRTOS_recvfrom_eWaitingOfferRecvfromSucceedsFalseCookieNoTimeout( Socket_t xSocket, void * pvBuffer, size_t uxBufferLength, BaseType_t xFlags, struct freertos_sockaddr * pxSourceAddress, socklen_t * pxSourceAddressLength, int callbacks ) { if( xFlags == FREERTOS_ZERO_COPY ) { *( ( uint8_t ** ) pvBuffer ) = pucUDPBuffer; } memset( pucUDPBuffer, 0, xSizeofUDPBuffer ); return xSizeofUDPBuffer; } static int32_t FreeRTOS_recvfrom_eWaitingOfferRecvfromSucceedsFalseOpcodeNoTimeout( Socket_t xSocket, void * pvBuffer, size_t uxBufferLength, BaseType_t xFlags, struct freertos_sockaddr * pxSourceAddress, socklen_t * pxSourceAddressLength, int callbacks ) { if( xFlags == FREERTOS_ZERO_COPY ) { *( ( uint8_t ** ) pvBuffer ) = pucUDPBuffer; } memset( pucUDPBuffer, 0, xSizeofUDPBuffer ); /* Put in correct DHCP cookie. */ ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ulDHCPCookie = dhcpCOOKIE; return xSizeofUDPBuffer; } static int32_t FreeRTOS_recvfrom_eWaitingOfferRecvfromSucceedsCorrectCookieAndOpcodeNoTimeout( Socket_t xSocket, void * pvBuffer, size_t uxBufferLength, BaseType_t xFlags, struct freertos_sockaddr * pxSourceAddress, socklen_t * pxSourceAddressLength, int callbacks ) { if( xFlags == FREERTOS_ZERO_COPY ) { *( ( uint8_t ** ) pvBuffer ) = pucUDPBuffer; } memset( pucUDPBuffer, 0, xSizeofUDPBuffer ); /* Put in correct DHCP cookie. */ ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ulDHCPCookie = dhcpCOOKIE; /* Put incorrect DHCP opcode. */ ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ucOpcode = dhcpREPLY_OPCODE; return xSizeofUDPBuffer; } static int32_t FreeRTOS_recvfrom_eWaitingOfferRecvfromSuccessCorrectTxID( Socket_t xSocket, void * pvBuffer, size_t uxBufferLength, BaseType_t xFlags, struct freertos_sockaddr * pxSourceAddress, socklen_t * pxSourceAddressLength, int callbacks ) { if( xFlags == FREERTOS_ZERO_COPY ) { *( ( uint8_t ** ) pvBuffer ) = pucUDPBuffer; } memset( pucUDPBuffer, 0, xSizeofUDPBuffer ); /* Put in correct DHCP cookie. */ ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ulDHCPCookie = dhcpCOOKIE; /* Put in correct DHCP opcode. */ ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ucOpcode = dhcpREPLY_OPCODE; /* Put in correct DHCP Tx ID. */ ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ulTransactionID = FreeRTOS_htonl( EP_DHCPData.ulTransactionId ); return xSizeofUDPBuffer; } static int32_t FreeRTOS_recvfrom_eWaitingOfferRecvfromSuccess_CorrectAddrType( Socket_t xSocket, void * pvBuffer, size_t uxBufferLength, BaseType_t xFlags, struct freertos_sockaddr * pxSourceAddress, socklen_t * pxSourceAddressLength, int callbacks ) { if( xFlags == FREERTOS_ZERO_COPY ) { *( ( uint8_t ** ) pvBuffer ) = pucUDPBuffer; } memset( pucUDPBuffer, 0, xSizeofUDPBuffer ); /* Put in correct DHCP cookie. */ ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ulDHCPCookie = dhcpCOOKIE; /* Put in correct DHCP opcode. */ ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ucOpcode = dhcpREPLY_OPCODE; /* Put in correct DHCP Tx ID. */ ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ulTransactionID = FreeRTOS_htonl( EP_DHCPData.ulTransactionId ); /* Put in address type as ethernet. */ ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ucAddressType = ( uint8_t ) dhcpADDRESS_TYPE_ETHERNET; return xSizeofUDPBuffer; } static int32_t FreeRTOS_recvfrom_eWaitingOfferRecvfromSuccess_CorrectAddrLen( Socket_t xSocket, void * pvBuffer, size_t uxBufferLength, BaseType_t xFlags, struct freertos_sockaddr * pxSourceAddress, socklen_t * pxSourceAddressLength, int callbacks ) { if( xFlags == FREERTOS_ZERO_COPY ) { *( ( uint8_t ** ) pvBuffer ) = pucUDPBuffer; } memset( pucUDPBuffer, 0, xSizeofUDPBuffer ); /* Put in correct DHCP cookie. */ ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ulDHCPCookie = dhcpCOOKIE; /* Put in correct DHCP opcode. */ ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ucOpcode = dhcpREPLY_OPCODE; /* Put in correct DHCP Tx ID. */ ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ulTransactionID = FreeRTOS_htonl( EP_DHCPData.ulTransactionId ); /* Put in address type as ethernet. */ ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ucAddressType = ( uint8_t ) dhcpADDRESS_TYPE_ETHERNET; /* Put in correct address length. */ ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ucAddressLength = ( uint8_t ) dhcpETHERNET_ADDRESS_LENGTH; ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ulYourIPAddress_yiaddr = 0xFFFFFFFF; return xSizeofUDPBuffer; } static int32_t FreeRTOS_recvfrom_eWaitingOfferRecvfromSuccess_LocalHostAddr( Socket_t xSocket, void * pvBuffer, size_t uxBufferLength, BaseType_t xFlags, struct freertos_sockaddr * pxSourceAddress, socklen_t * pxSourceAddressLength, int callbacks ) { if( xFlags == FREERTOS_ZERO_COPY ) { *( ( uint8_t ** ) pvBuffer ) = pucUDPBuffer; } memset( pucUDPBuffer, 0, xSizeofUDPBuffer ); /* Put in correct DHCP cookie. */ ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ulDHCPCookie = dhcpCOOKIE; /* Put in correct DHCP opcode. */ ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ucOpcode = dhcpREPLY_OPCODE; /* Put in correct DHCP Tx ID. */ ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ulTransactionID = FreeRTOS_htonl( EP_DHCPData.ulTransactionId ); /* Put in address type as ethernet. */ ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ucAddressType = ( uint8_t ) dhcpADDRESS_TYPE_ETHERNET; /* Put in correct address length. */ ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ucAddressLength = ( uint8_t ) dhcpETHERNET_ADDRESS_LENGTH; /* Non local host address. */ ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ulYourIPAddress_yiaddr = 0x01FFFF7F; return xSizeofUDPBuffer; } static int32_t FreeRTOS_recvfrom_eWaitingOfferRecvfromSuccess_NonLocalHostAddr( Socket_t xSocket, void * pvBuffer, size_t uxBufferLength, BaseType_t xFlags, struct freertos_sockaddr * pxSourceAddress, socklen_t * pxSourceAddressLength, int callbacks ) { if( xFlags == FREERTOS_ZERO_COPY ) { *( ( uint8_t ** ) pvBuffer ) = pucUDPBuffer; } memset( pucUDPBuffer, 0, xSizeofUDPBuffer ); /* Put in correct DHCP cookie. */ ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ulDHCPCookie = dhcpCOOKIE; /* Put in correct DHCP opcode. */ ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ucOpcode = dhcpREPLY_OPCODE; /* Put in correct DHCP Tx ID. */ ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ulTransactionID = FreeRTOS_htonl( EP_DHCPData.ulTransactionId + 1 ); /* Put in address type as ethernet. */ ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ucAddressType = ( uint8_t ) dhcpADDRESS_TYPE_ETHERNET; /* Put in correct address length. */ ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ucAddressLength = ( uint8_t ) dhcpETHERNET_ADDRESS_LENGTH; /* Non local host address. */ ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ulYourIPAddress_yiaddr = 0x01FFFF3F; return xSizeofUDPBuffer; } static int32_t FreeRTOS_recvfrom_eWaitingOfferRecvfromSuccess_LocalMACAddrNotMatching( Socket_t xSocket, void * pvBuffer, size_t uxBufferLength, BaseType_t xFlags, struct freertos_sockaddr * pxSourceAddress, socklen_t * pxSourceAddressLength, int callbacks ) { if( xFlags == FREERTOS_ZERO_COPY ) { *( ( uint8_t ** ) pvBuffer ) = pucUDPBuffer; } memset( pucUDPBuffer, 0, xSizeofUDPBuffer ); /* Put in correct DHCP cookie. */ ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ulDHCPCookie = dhcpCOOKIE; /* Put in correct DHCP opcode. */ ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ucOpcode = dhcpREPLY_OPCODE; /* Put in correct DHCP Tx ID. */ ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ulTransactionID = FreeRTOS_htonl( EP_DHCPData.ulTransactionId ); /* Put in address type as ethernet. */ ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ucAddressType = ( uint8_t ) dhcpADDRESS_TYPE_ETHERNET; /* Put in correct address length. */ ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ucAddressLength = ( uint8_t ) dhcpETHERNET_ADDRESS_LENGTH; /* Non local host address. */ ( ( struct xDHCPMessage_IPv4 * ) pucUDPBuffer )->ulYourIPAddress_yiaddr = 0x01FFFF3F; return xSizeofUDPBuffer; } void test_xIsDHCPSocket( void ) { BaseType_t xReturn; struct xSOCKET xTestSocket; xDHCPSocket = &xTestSocket; /************************************/ /* Test by NOT giving DHCP socket. */ xReturn = xIsDHCPSocket( NULL ); TEST_ASSERT_EQUAL( pdFALSE, xReturn ); /************************************/ /* Test by giving DHCP socket. */ xReturn = xIsDHCPSocket( xDHCPSocket ); TEST_ASSERT_EQUAL( pdTRUE, xReturn ); } void test_vDHCPSetPreferredIPAddress( void ) { uint32_t ulReturn; uint32_t ulIPAddress = 0xABCDEFAB; uint32_t ulSecondIP = 0xAABBCCDD; xDHCPData.ulPreferredIPAddress = ulSecondIP; ulReturn = vDHCPSetPreferredIPAddress( ulIPAddress ); TEST_ASSERT_EQUAL( ulSecondIP, ulReturn ); ulReturn = vDHCPSetPreferredIPAddress( ulSecondIP ); TEST_ASSERT_EQUAL( ulIPAddress, ulReturn ); } void test_eGetDHCPState( void ) { DHCPData_t xTestData; eDHCPState_t eReturn; int i; for( i = 0; i < sizeof( xTestData.eDHCPState ); i++ ) { /* Modify the global state. */ xDHCPData.eDHCPState = i; eReturn = eGetDHCPState(); TEST_ASSERT_EQUAL( i, eReturn ); } } void test_vDHCPProcess_NotResetAndIncorrectState( void ) { xDHCPData.eDHCPState = eSendDHCPRequest; vDHCPProcess( pdFALSE, eWaitingSendFirstDiscover ); /* Since the expected state is incorrect, the state * should remain the same. */ TEST_ASSERT_EQUAL( eSendDHCPRequest, xDHCPData.eDHCPState ); } void test_vDHCPProcess_ResetAndIncorrectStateWithRNGFail( void ) { xDHCPData.eDHCPState = eSendDHCPRequest; /* Make random number generation fail. */ xApplicationGetRandomNumber_ExpectAndReturn( &( xDHCPData.ulTransactionId ), pdFALSE ); vDHCPProcess( pdTRUE, eWaitingSendFirstDiscover ); /* Expected state is incorrect, but we are trying to reset * the DHCP the state machine. */ TEST_ASSERT_EQUAL( eWaitingSendFirstDiscover, xDHCPData.eDHCPState ); } void test_vDHCPProcess_ResetAndIncorrectStateWithRNGSuccessSocketCreationFail( void ) { /* Test all the valid and invalid entries. */ for( int i = 0; i < ( eNotUsingLeasedAddress * 2 ); i++ ) { /* This should get assigned to a given value. */ xDHCPSocket = NULL; /* Put any state. */ xDHCPData.eDHCPState = eSendDHCPRequest; /* This should be reset to 0. */ xDHCPData.xUseBroadcast = 1; /* This should be reset as well */ xDHCPData.ulOfferedIPAddress = 0xAAAAAAAA; /* And this too. */ xDHCPData.ulDHCPServerAddress = 0xABABABAB; /* Make random number generation pass. */ xApplicationGetRandomNumber_ExpectAndReturn( &( xDHCPData.ulTransactionId ), pdTRUE ); /* return an invalid socket. */ FreeRTOS_socket_ExpectAndReturn( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP, FREERTOS_INVALID_SOCKET ); /* See if the timer is reloaded. */ vDHCPTimerReload_Expect( dhcpINITIAL_TIMER_PERIOD ); /* Try all kinds of states. */ vDHCPProcess( pdTRUE, i ); /* Expected state is incorrect, but we are trying to reset * the DHCP the state machine. */ TEST_ASSERT_EQUAL( eWaitingSendFirstDiscover, xDHCPData.eDHCPState ); TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); TEST_ASSERT_EQUAL( 0, xDHCPData.xUseBroadcast ); /* This should be reset as well */ TEST_ASSERT_EQUAL( 0, xDHCPData.ulOfferedIPAddress ); /* And this too. */ TEST_ASSERT_EQUAL( 0, xDHCPData.ulDHCPServerAddress ); } } void test_vDHCPProcess_ResetAndIncorrectStateWithRNGSuccessSocketBindFail( void ) { struct xSOCKET xTestSocket; /* Test all the valid and invalid entries. */ for( int i = 0; i < ( eNotUsingLeasedAddress * 2 ); i++ ) { /* This should get assigned to a given value. */ xDHCPSocket = NULL; /* Put any state. */ xDHCPData.eDHCPState = eSendDHCPRequest; /* This should be reset to 0. */ xDHCPData.xUseBroadcast = 1; /* This should be reset as well */ xDHCPData.ulOfferedIPAddress = 0xAAAAAAAA; /* And this too. */ xDHCPData.ulDHCPServerAddress = 0xABABABAB; /* Make random number generation pass. */ xApplicationGetRandomNumber_ExpectAndReturn( &( xDHCPData.ulTransactionId ), pdTRUE ); /* Return a valid socket. */ FreeRTOS_socket_ExpectAndReturn( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP, &xTestSocket ); /* Ignore the inputs to setting the socket options. */ FreeRTOS_setsockopt_ExpectAnyArgsAndReturn( pdPASS ); FreeRTOS_setsockopt_ExpectAnyArgsAndReturn( pdPASS ); /* Make sure that binding fails. Return anything except zero. */ vSocketBind_ExpectAnyArgsAndReturn( pdTRUE ); /* Then expect the socket to be closed. */ vSocketClose_ExpectAndReturn( &xTestSocket, NULL ); /* See if the timer is reloaded. */ vDHCPTimerReload_Expect( dhcpINITIAL_TIMER_PERIOD ); /* Try all kinds of states. */ vDHCPProcess( pdTRUE, i ); /* Expected state is incorrect, but we are trying to reset * the DHCP the state machine. */ TEST_ASSERT_EQUAL( eWaitingSendFirstDiscover, xDHCPData.eDHCPState ); TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); TEST_ASSERT_EQUAL( 0, xDHCPData.xUseBroadcast ); /* This should be reset as well */ TEST_ASSERT_EQUAL( 0, xDHCPData.ulOfferedIPAddress ); /* And this too. */ TEST_ASSERT_EQUAL( 0, xDHCPData.ulDHCPServerAddress ); } } void test_vDHCPProcess_ResetAndIncorrectStateWithRNGSuccessSocketSuccess( void ) { struct xSOCKET xTestSocket; /* Test all the valid and invalid entries. */ for( int i = 0; i < ( eNotUsingLeasedAddress * 2 ); i++ ) { /* This should get assigned to a given value. */ xDHCPSocket = NULL; /* Put any state. */ xDHCPData.eDHCPState = eSendDHCPRequest; /* This should be reset to 0. */ xDHCPData.xUseBroadcast = 1; /* This should be reset as well */ xDHCPData.ulOfferedIPAddress = 0xAAAAAAAA; /* And this too. */ xDHCPData.ulDHCPServerAddress = 0xABABABAB; /* Make random number generation pass. */ xApplicationGetRandomNumber_ExpectAndReturn( &( xDHCPData.ulTransactionId ), pdTRUE ); /* Return a valid socket. */ FreeRTOS_socket_ExpectAndReturn( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP, &xTestSocket ); /* Ignore the inputs to setting the socket options. */ FreeRTOS_setsockopt_ExpectAnyArgsAndReturn( pdPASS ); FreeRTOS_setsockopt_ExpectAnyArgsAndReturn( pdPASS ); /* Make sure that binding fails. Return anything except zero. */ vSocketBind_ExpectAnyArgsAndReturn( 0 ); /* See if the timer is reloaded. */ vDHCPTimerReload_Expect( dhcpINITIAL_TIMER_PERIOD ); /* Try all kinds of states. */ vDHCPProcess( pdTRUE, i ); /* Expected state is incorrect, but we are trying to reset * the DHCP the state machine. */ TEST_ASSERT_EQUAL( eWaitingSendFirstDiscover, xDHCPData.eDHCPState ); TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); TEST_ASSERT_EQUAL( 0, xDHCPData.xUseBroadcast ); /* This should be reset as well */ TEST_ASSERT_EQUAL( 0, xDHCPData.ulOfferedIPAddress ); /* And this too. */ TEST_ASSERT_EQUAL( 0, xDHCPData.ulDHCPServerAddress ); } } void test_vDHCPProcess_ResetAndIncorrectStateWithSocketAlreadyCreated( void ) { struct xSOCKET xTestSocket; /* Test all the valid and invalid entries. */ for( int i = 0; i < ( eNotUsingLeasedAddress * 2 ); i++ ) { /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put any state. */ xDHCPData.eDHCPState = eSendDHCPRequest; /* This should be reset to 0. */ xDHCPData.xUseBroadcast = 1; /* This should be reset as well */ xDHCPData.ulOfferedIPAddress = 0xAAAAAAAA; /* And this too. */ xDHCPData.ulDHCPServerAddress = 0xABABABAB; /* And this should be updated. */ xDHCPData.xDHCPTxPeriod = 0; /* Make random number generation pass. */ xApplicationGetRandomNumber_ExpectAndReturn( &( xDHCPData.ulTransactionId ), pdTRUE ); /* See if the timer is reloaded. */ vDHCPTimerReload_Expect( dhcpINITIAL_TIMER_PERIOD ); /* Try all kinds of states. */ vDHCPProcess( pdTRUE, i ); /* Expected state is incorrect, but we are trying to reset * the DHCP the state machine. */ TEST_ASSERT_EQUAL( eWaitingSendFirstDiscover, xDHCPData.eDHCPState ); TEST_ASSERT_EQUAL( xDHCPSocket, &xTestSocket ); TEST_ASSERT_EQUAL( 0, xDHCPData.xUseBroadcast ); /* This should be reset as well */ TEST_ASSERT_EQUAL( 0, xDHCPData.ulOfferedIPAddress ); /* And this too. */ TEST_ASSERT_EQUAL( 0, xDHCPData.ulDHCPServerAddress ); /* This should be updated. */ TEST_ASSERT_EQUAL( dhcpINITIAL_DHCP_TX_PERIOD, xDHCPData.xDHCPTxPeriod ); } } void test_vDHCPProcess_CorrectStateDHCPHookFailsDHCPSocketNULL( void ) { /* The DHCP socket is NULL. */ xDHCPSocket = NULL; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingSendFirstDiscover; /* Make sure that the local IP address is uninitialised. */ *ipLOCAL_IP_ADDRESS_POINTER = 0; /* Put a verifiable value. */ xNetworkAddressing.ulDefaultIPAddress = 0x12345678; /* Make sure that the user indicates anything else than the desired options. */ xApplicationDHCPHook_ExpectAndReturn( eDHCPPhasePreDiscover, xNetworkAddressing.ulDefaultIPAddress, ( eDHCPContinue + eDHCPUseDefaults ) << 2 ); /* Expect the timer to be disabled. */ vIPSetDHCPTimerEnableState_Expect( pdFALSE ); vIPNetworkUpCalls_Ignore(); vDHCPProcess( pdFALSE, eWaitingSendFirstDiscover ); /* DHCP socket should be NULL */ TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); /* The state should indicate that we are not using leased address. */ TEST_ASSERT_EQUAL( eNotUsingLeasedAddress, xDHCPData.eDHCPState ); /* Make sure that the local IP address pointer indicates that. */ TEST_ASSERT_EQUAL( xNetworkAddressing.ulDefaultIPAddress, *ipLOCAL_IP_ADDRESS_POINTER ); } void test_vDHCPProcess_CorrectStateDHCPHookFailsDHCPSocketNonNULL( void ) { struct xSOCKET xTestSocket; /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingSendFirstDiscover; /* Make sure that the local IP address is uninitialised. */ *ipLOCAL_IP_ADDRESS_POINTER = 0; /* Put a verifiable value. */ xNetworkAddressing.ulDefaultIPAddress = 0x12345678; /* Make sure that the user indicates anything else than the desired options. */ xApplicationDHCPHook_ExpectAndReturn( eDHCPPhasePreDiscover, xNetworkAddressing.ulDefaultIPAddress, ( eDHCPContinue + eDHCPUseDefaults ) << 2 ); /* Expect the timer to be disabled. */ vIPSetDHCPTimerEnableState_Expect( pdFALSE ); /* Ignore the call. */ vIPNetworkUpCalls_Ignore(); /* Expect the socket to be closed. */ vSocketClose_ExpectAndReturn( xDHCPSocket, NULL ); vDHCPProcess( pdFALSE, eWaitingSendFirstDiscover ); /* DHCP socket should be NULL */ TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); /* The state should indicate that we are not using leased address. */ TEST_ASSERT_EQUAL( eNotUsingLeasedAddress, xDHCPData.eDHCPState ); /* Make sure that the local IP address pointer indicates that. */ TEST_ASSERT_EQUAL( xNetworkAddressing.ulDefaultIPAddress, *ipLOCAL_IP_ADDRESS_POINTER ); } void test_vDHCPProcess_CorrectStateDHCPHookDefaultReturn( void ) { struct xSOCKET xTestSocket; /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingSendFirstDiscover; /* Make sure that the local IP address is uninitialised. */ *ipLOCAL_IP_ADDRESS_POINTER = 0; /* Put a verifiable value. */ memset( &xNetworkAddressing, 0xAA, sizeof( xNetworkAddressing ) ); /* Put a verifiable value. */ memset( &xDefaultAddressing, 0xBB, sizeof( xDefaultAddressing ) ); /* Make sure that the user indicates anything else than the desired options. */ xApplicationDHCPHook_ExpectAndReturn( eDHCPPhasePreDiscover, xNetworkAddressing.ulDefaultIPAddress, eDHCPUseDefaults ); /* Expect the timer to be disabled. */ vIPSetDHCPTimerEnableState_Expect( pdFALSE ); /* Ignore the call. */ vIPNetworkUpCalls_Ignore(); /* Expect the socket to be closed. */ vSocketClose_ExpectAndReturn( xDHCPSocket, NULL ); vDHCPProcess( pdFALSE, eWaitingSendFirstDiscover ); /* DHCP socket should be NULL */ TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); /* The state should indicate that we are not using leased address. */ TEST_ASSERT_EQUAL( eNotUsingLeasedAddress, xDHCPData.eDHCPState ); /* Make sure that the network addressing struct is updated to show that. */ TEST_ASSERT_EQUAL_MEMORY( &xDefaultAddressing, &xNetworkAddressing, sizeof( xDefaultAddressing ) ); /* Make sure that the local IP address pointer indicates that. */ TEST_ASSERT_EQUAL( xNetworkAddressing.ulDefaultIPAddress, *ipLOCAL_IP_ADDRESS_POINTER ); } /* GNW = getNetworkBufferWithDescriptor */ void test_vDHCPProcess_CorrectStateDHCPHookContinueReturnDHCPSocketNotNULLButGNWFails( void ) { struct xSOCKET xTestSocket; /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingSendFirstDiscover; /* Make sure that the user indicates anything else than the desired options. */ xApplicationDHCPHook_ExpectAndReturn( eDHCPPhasePreDiscover, xNetworkAddressing.ulDefaultIPAddress, eDHCPContinue ); xTaskGetTickCount_ExpectAndReturn( 100 ); pcApplicationHostnameHook_ExpectAndReturn( pcHostName ); /* Returning NULL will mean the prvSendDHCPDiscover fail. */ pxGetNetworkBufferWithDescriptor_ExpectAnyArgsAndReturn( NULL ); vDHCPProcess( pdFALSE, eWaitingSendFirstDiscover ); /* DHCP socket should be NULL */ TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); /* The state should indicate that we are not using leased address. */ TEST_ASSERT_EQUAL( eWaitingSendFirstDiscover, xDHCPData.eDHCPState ); } void test_vDHCPProcess_CorrectStateDHCPHookContinueReturnDHCPSocketNULL( void ) { /* This should remain unchanged. */ xDHCPSocket = NULL; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingSendFirstDiscover; /* Make sure that the user indicates anything else than the desired options. */ xApplicationDHCPHook_ExpectAndReturn( eDHCPPhasePreDiscover, xNetworkAddressing.ulDefaultIPAddress, eDHCPContinue ); /* Expect the timer to be disabled. */ vIPSetDHCPTimerEnableState_Expect( pdFALSE ); /* Ignore the call. */ vIPNetworkUpCalls_Ignore(); vDHCPProcess( pdFALSE, eWaitingSendFirstDiscover ); /* DHCP socket should be NULL */ TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); /* The state should indicate that we are not using leased address. */ TEST_ASSERT_EQUAL( eNotUsingLeasedAddress, xDHCPData.eDHCPState ); } void test_vDHCPProcess_CorrectStateDHCPHookContinueReturnSendFailsNoBroadcast( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingSendFirstDiscover; /* Not using broadcast. */ xDHCPData.xUseBroadcast = pdFALSE; /* Make sure that the user indicates anything else than the desired options. */ xApplicationDHCPHook_ExpectAndReturn( eDHCPPhasePreDiscover, xNetworkAddressing.ulDefaultIPAddress, eDHCPContinue ); /* Return the time value. */ xTaskGetTickCount_ExpectAndReturn( xTimeValue ); /* Get the hostname. */ pcApplicationHostnameHook_ExpectAndReturn( pcHostName ); /* Returning a proper network buffer. */ pxGetNetworkBufferWithDescriptor_Stub( GetNetworkBuffer ); /* Make the call to FreeRTOS_send fail. */ FreeRTOS_sendto_ExpectAnyArgsAndReturn( 0 ); /* Since the send failed, a call to release the buffer should be there. */ FreeRTOS_ReleaseUDPPayloadBuffer_Stub( ReleaseUDPBuffer ); vDHCPProcess( pdFALSE, eWaitingSendFirstDiscover ); /* DHCP socket should be NULL */ TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); /* The state should indicate that we still in the state from where we started. */ TEST_ASSERT_EQUAL( eWaitingSendFirstDiscover, xDHCPData.eDHCPState ); /* The time value should be as expected. */ TEST_ASSERT_EQUAL( xTimeValue, xDHCPData.xDHCPTxTime ); } void test_vDHCPProcess_CorrectStateDHCPHookContinueReturnSendFailsUseBroadCast( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingSendFirstDiscover; /* Not using broadcast. */ xDHCPData.xUseBroadcast = pdTRUE; /* Make sure that the user indicates anything else than the desired options. */ xApplicationDHCPHook_ExpectAndReturn( eDHCPPhasePreDiscover, xNetworkAddressing.ulDefaultIPAddress, eDHCPContinue ); /* Return the time value. */ xTaskGetTickCount_ExpectAndReturn( xTimeValue ); /* Get the hostname. */ pcApplicationHostnameHook_ExpectAndReturn( pcHostName ); /* Returning a proper network buffer. */ pxGetNetworkBufferWithDescriptor_Stub( GetNetworkBuffer ); /* Make the call to FreeRTOS_send fail. */ FreeRTOS_sendto_ExpectAnyArgsAndReturn( 0 ); /* Since the send failed, a call to release the buffer should be there. */ FreeRTOS_ReleaseUDPPayloadBuffer_Stub( ReleaseUDPBuffer ); vDHCPProcess( pdFALSE, eWaitingSendFirstDiscover ); /* DHCP socket should be NULL */ TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); /* The state should indicate that we still in the state from where we started. */ TEST_ASSERT_EQUAL( eWaitingSendFirstDiscover, xDHCPData.eDHCPState ); /* The time value should be as expected. */ TEST_ASSERT_EQUAL( xTimeValue, xDHCPData.xDHCPTxTime ); } void test_vDHCPProcess_CorrectStateDHCPHookContinueReturnSendSucceedsUseBroadCast( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingSendFirstDiscover; /* Using broadcast. */ xDHCPData.xUseBroadcast = pdTRUE; xDHCPData.ulPreferredIPAddress = 0x00; /* Make sure that the user indicates anything else than the desired options. */ xApplicationDHCPHook_ExpectAndReturn( eDHCPPhasePreDiscover, xNetworkAddressing.ulDefaultIPAddress, eDHCPContinue ); /* Return the time value. */ xTaskGetTickCount_ExpectAndReturn( xTimeValue ); /* Get the hostname. */ pcApplicationHostnameHook_ExpectAndReturn( pcHostName ); /* Returning a proper network buffer. */ pxGetNetworkBufferWithDescriptor_Stub( GetNetworkBuffer ); /* Make the call to FreeRTOS_send succeed. */ FreeRTOS_sendto_ExpectAnyArgsAndReturn( 1 ); vDHCPProcess( pdFALSE, eWaitingSendFirstDiscover ); /* DHCP socket should be NULL */ TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); /* The state should indicate that we still in the state from where we started. */ TEST_ASSERT_EQUAL( eWaitingOffer, xDHCPData.eDHCPState ); /* The time value should be as expected. */ TEST_ASSERT_EQUAL( xTimeValue, xDHCPData.xDHCPTxTime ); /* Free the allocated memory. */ ReleaseNetworkBuffer(); } void test_vDHCPProcess_CorrectStateDHCPHookContinueReturnSendSucceedsUseBroadCast1( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingSendFirstDiscover; /* Using broadcast. */ xDHCPData.xUseBroadcast = pdTRUE; xDHCPData.ulPreferredIPAddress = 0x01; /* Make sure that the user indicates anything else than the desired options. */ xApplicationDHCPHook_ExpectAndReturn( eDHCPPhasePreDiscover, xNetworkAddressing.ulDefaultIPAddress, eDHCPContinue ); /* Return the time value. */ xTaskGetTickCount_ExpectAndReturn( xTimeValue ); /* Get the hostname. */ pcApplicationHostnameHook_ExpectAndReturn( pcHostName ); /* Returning a proper network buffer. */ pxGetNetworkBufferWithDescriptor_Stub( GetNetworkBuffer ); /* Make the call to FreeRTOS_send succeed. */ FreeRTOS_sendto_ExpectAnyArgsAndReturn( 1 ); vDHCPProcess( pdFALSE, eWaitingSendFirstDiscover ); /* DHCP socket should be NULL */ TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); /* The state should indicate that we still in the state from where we started. */ TEST_ASSERT_EQUAL( eWaitingOffer, xDHCPData.eDHCPState ); /* The time value should be as expected. */ TEST_ASSERT_EQUAL( xTimeValue, xDHCPData.xDHCPTxTime ); /* Free the allocated memory. */ ReleaseNetworkBuffer(); } void test_vDHCPProcess_eSendDHCPRequestCorrectStateGNWFails( void ) { struct xSOCKET xTestSocket; /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eSendDHCPRequest; /* Get the hostname. */ pcApplicationHostnameHook_ExpectAndReturn( pcHostName ); /* Return NULL network buffer. */ pxGetNetworkBufferWithDescriptor_ExpectAnyArgsAndReturn( NULL ); vDHCPProcess( pdFALSE, eSendDHCPRequest ); /* DHCP socket should be NULL */ TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); /* The state should indicate that we still in the state from where we started. */ TEST_ASSERT_EQUAL( eSendDHCPRequest, xDHCPData.eDHCPState ); } void test_vDHCPProcess_eSendDHCPRequestCorrectStateGNWSucceedsSendFails( void ) { struct xSOCKET xTestSocket; /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eSendDHCPRequest; /* Get the hostname. */ pcApplicationHostnameHook_ExpectAndReturn( pcHostName ); /* Returning a proper network buffer. */ pxGetNetworkBufferWithDescriptor_Stub( GetNetworkBuffer ); /* Send fails. */ FreeRTOS_sendto_ExpectAnyArgsAndReturn( 0 ); /* ReleaseUDPPayloadBuffer will be called. */ FreeRTOS_ReleaseUDPPayloadBuffer_Stub( ReleaseUDPBuffer ); vDHCPProcess( pdFALSE, eSendDHCPRequest ); /* DHCP socket should be still allocated */ TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); /* The state should indicate that we still in the state from where we started. */ TEST_ASSERT_EQUAL( eSendDHCPRequest, xDHCPData.eDHCPState ); } void test_vDHCPProcess_eSendDHCPRequestCorrectStateGNWSucceedsSendSucceeds( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eSendDHCPRequest; /* Get the hostname. */ pcApplicationHostnameHook_ExpectAndReturn( pcHostName ); /* Returning a proper network buffer. */ pxGetNetworkBufferWithDescriptor_Stub( GetNetworkBuffer ); /* Send succeeds. */ FreeRTOS_sendto_ExpectAnyArgsAndReturn( 1 ); /* Return the time value. */ xTaskGetTickCount_ExpectAndReturn( xTimeValue ); vDHCPProcess( pdFALSE, eSendDHCPRequest ); /* DHCP socket should be still allocated */ TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); /* The state should indicate that we still in the state from where we started. */ TEST_ASSERT_EQUAL( eWaitingAcknowledge, xDHCPData.eDHCPState ); TEST_ASSERT_EQUAL( xTimeValue, xDHCPData.xDHCPTxTime ); TEST_ASSERT_EQUAL( dhcpINITIAL_DHCP_TX_PERIOD, xDHCPData.xDHCPTxPeriod ); } void test_vDHCPProcess_eWaitingOfferRecvfromFailsNoTimeout( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingOffer; /* Put some time values. */ xDHCPData.xDHCPTxTime = 100; xDHCPData.xDHCPTxPeriod = 100; /* Expect these arguments. */ FreeRTOS_recvfrom_ExpectAndReturn( xDHCPSocket, NULL, 0UL, FREERTOS_ZERO_COPY, NULL, NULL, 0 ); /* Ignore the buffer argument though. */ FreeRTOS_recvfrom_IgnoreArg_pvBuffer(); /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ /* Return a value which makes the difference just equal to the period. */ xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod ); vDHCPProcess( pdFALSE, eWaitingOffer ); /* DHCP socket should be still allocated */ TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); /* The state should indicate that we still in the state from where we started. */ TEST_ASSERT_EQUAL( eWaitingOffer, xDHCPData.eDHCPState ); } void test_vDHCPProcess_eWaitingOfferRecvfromFailsTimeoutGiveUp( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingOffer; /* Put some time values. */ xDHCPData.xDHCPTxTime = 100; /* Make sure that we exceed the period - and give up. */ xDHCPData.xDHCPTxPeriod = ipconfigMAXIMUM_DISCOVER_TX_PERIOD; /* Expect these arguments. */ FreeRTOS_recvfrom_ExpectAndReturn( xDHCPSocket, NULL, 0UL, FREERTOS_ZERO_COPY, NULL, NULL, 0 ); /* Ignore the buffer argument though. */ FreeRTOS_recvfrom_IgnoreArg_pvBuffer(); /* Make sure that there is timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ /* Return a value which makes the difference greater than the period. */ xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod + 100 ); /* Time will be stored in DHCP state machine. */ xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod + 100 ); /* Make all calls to the RNG succeed. */ xApplicationGetRandomNumber_ExpectAnyArgsAndReturn( pdTRUE ); xApplicationGetRandomNumber_ExpectAnyArgsAndReturn( pdTRUE ); /* Closing the DHCP socket. */ vSocketClose_ExpectAndReturn( xDHCPSocket, 0 ); xApplicationGetRandomNumber_ExpectAnyArgsAndReturn( pdTRUE ); /* Ignore the call to this function. */ vARPSendGratuitous_Ignore(); vDHCPProcess( pdFALSE, eWaitingOffer ); /* DHCP socket should be unallocated */ TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); /* The state should indicate that we still in the state from where we started. */ TEST_ASSERT_EQUAL( eGetLinkLayerAddress, xDHCPData.eDHCPState ); } void test_vDHCPProcess_eWaitingOfferRecvfromFailsTimeoutDontGiveUpRNGFail( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingOffer; /* Put some time values. */ xDHCPData.xDHCPTxTime = 100; /* Make sure that we don't exceed the period - and thus, don't give up. */ xDHCPData.xDHCPTxPeriod = ( ipconfigMAXIMUM_DISCOVER_TX_PERIOD >> 1 ) - 1; /* Expect these arguments. Return a 0 to fail. */ FreeRTOS_recvfrom_ExpectAndReturn( xDHCPSocket, NULL, 0UL, FREERTOS_ZERO_COPY, NULL, NULL, 0 ); /* Ignore the buffer argument though. */ FreeRTOS_recvfrom_IgnoreArg_pvBuffer(); /* Make sure that there is timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ /* Return a value which makes the difference greater than the period. */ xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod + 100 ); /* Make all calls to the RNG fail. */ xApplicationGetRandomNumber_ExpectAnyArgsAndReturn( pdFALSE ); vDHCPProcess( pdFALSE, eWaitingOffer ); /* DHCP socket should be unallocated */ TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); /* The state should indicate that we still in the state from where we started. */ TEST_ASSERT_EQUAL( eWaitingOffer, xDHCPData.eDHCPState ); /* make sure that the period is increased by a factor of two. */ TEST_ASSERT_EQUAL( ( ( ipconfigMAXIMUM_DISCOVER_TX_PERIOD >> 1 ) - 1 ) << 1, xDHCPData.xDHCPTxPeriod ); } void test_vDHCPProcess_eWaitingOfferRecvfromFailsTimeoutDontGiveUpRNGPassUseBroadcast( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingOffer; /* Put some time values. */ xDHCPData.xDHCPTxTime = 100; /* Make sure that we don't exceed the period - and thus, don't give up. */ xDHCPData.xDHCPTxPeriod = ( ipconfigMAXIMUM_DISCOVER_TX_PERIOD >> 1 ) - 1; /* Using broadcast. */ xDHCPData.xUseBroadcast = pdTRUE; /* Expect these arguments. Return a 0 to fail. */ FreeRTOS_recvfrom_ExpectAndReturn( xDHCPSocket, NULL, 0UL, FREERTOS_ZERO_COPY, NULL, NULL, 0 ); /* Ignore the buffer argument though. */ FreeRTOS_recvfrom_IgnoreArg_pvBuffer(); /* Make sure that there is timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ /* Return a value which makes the difference greater than the period. */ xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod + 100 ); /* Make all calls to the RNG succeed. */ xApplicationGetRandomNumber_ExpectAnyArgsAndReturn( pdTRUE ); xTaskGetTickCount_ExpectAndReturn( xTimeValue ); /* Get the hostname. */ pcApplicationHostnameHook_ExpectAndReturn( pcHostName ); /* Returning a proper network buffer. */ pxGetNetworkBufferWithDescriptor_Stub( GetNetworkBuffer ); /* Send succeeds. */ FreeRTOS_sendto_ExpectAnyArgsAndReturn( 1 ); vDHCPProcess( pdFALSE, eWaitingOffer ); /* DHCP socket should be unallocated */ TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); /* The state should indicate that we still in the state from where we started. */ TEST_ASSERT_EQUAL( eWaitingOffer, xDHCPData.eDHCPState ); /* make sure that the period is increased by a factor of two. */ TEST_ASSERT_EQUAL( ( ( ipconfigMAXIMUM_DISCOVER_TX_PERIOD >> 1 ) - 1 ) << 1, xDHCPData.xDHCPTxPeriod ); } void test_vDHCPProcess_eWaitingOfferRecvfromFailsTimeoutDontGiveUpRNGPassNoBroadcast( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingOffer; /* Put some time values. */ xDHCPData.xDHCPTxTime = 100; /* Make sure that we don't exceed the period - and thus, don't give up. */ xDHCPData.xDHCPTxPeriod = ( ipconfigMAXIMUM_DISCOVER_TX_PERIOD >> 1 ) - 1; /* Not Using broadcast. */ xDHCPData.xUseBroadcast = pdFALSE; /* Expect these arguments. Return a 0 to fail. */ FreeRTOS_recvfrom_ExpectAndReturn( xDHCPSocket, NULL, 0UL, FREERTOS_ZERO_COPY, NULL, NULL, 0 ); /* Ignore the buffer argument though. */ FreeRTOS_recvfrom_IgnoreArg_pvBuffer(); /* Make sure that there is timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ /* Return a value which makes the difference greater than the period. */ xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod + 100 ); /* Make all calls to the RNG succeed. */ xApplicationGetRandomNumber_ExpectAnyArgsAndReturn( pdTRUE ); xTaskGetTickCount_ExpectAndReturn( xTimeValue ); /* Get the hostname. */ pcApplicationHostnameHook_ExpectAndReturn( pcHostName ); /* Returning a NULL network buffer. */ pxGetNetworkBufferWithDescriptor_ExpectAnyArgsAndReturn( NULL ); vDHCPProcess( pdFALSE, eWaitingOffer ); /* DHCP socket should be allocated */ TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); /* The state should indicate that we still in the state from where we started. */ TEST_ASSERT_EQUAL( eInitialWait, xDHCPData.eDHCPState ); /* make sure that the period is increased by a factor of two. */ TEST_ASSERT_EQUAL( ( ( ipconfigMAXIMUM_DISCOVER_TX_PERIOD >> 1 ) - 1 ) << 1, xDHCPData.xDHCPTxPeriod ); } void test_vDHCPProcess_eWaitingOfferRecvfromSucceedsFalseCookieNoTimeout( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingOffer; /* Put some time values. */ xDHCPData.xDHCPTxTime = 100; /* Make sure that we don't exceed the period - and thus, don't give up. */ xDHCPData.xDHCPTxPeriod = 100; /* Not Using broadcast. */ xDHCPData.xUseBroadcast = pdFALSE; /* Get a stub. */ FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_eWaitingOfferRecvfromSucceedsFalseCookieNoTimeout ); FreeRTOS_ReleaseUDPPayloadBuffer_Expect( pucUDPBuffer ); /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ /* Return a value which makes the difference just equal to the period. */ xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod ); vDHCPProcess( pdFALSE, eWaitingOffer ); /* DHCP socket should be allocated */ TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); /* The state should indicate that we still in the state from where we started. */ TEST_ASSERT_EQUAL( eWaitingOffer, xDHCPData.eDHCPState ); } void test_vDHCPProcess_eWaitingOfferRecvfromSucceedsFalseOpcodeNoTimeout( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingOffer; /* Put some time values. */ xDHCPData.xDHCPTxTime = 100; /* Make sure that we don't exceed the period - and thus, don't give up. */ xDHCPData.xDHCPTxPeriod = 100; /* Not Using broadcast. */ xDHCPData.xUseBroadcast = pdFALSE; /* Get a stub. */ FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_eWaitingOfferRecvfromSucceedsFalseOpcodeNoTimeout ); FreeRTOS_ReleaseUDPPayloadBuffer_Expect( pucUDPBuffer ); /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ /* Return a value which makes the difference just equal to the period. */ xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod ); vDHCPProcess( pdFALSE, eWaitingOffer ); /* DHCP socket should be allocated */ TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); /* The state should indicate that we still in the state from where we started. */ TEST_ASSERT_EQUAL( eWaitingOffer, xDHCPData.eDHCPState ); } void test_vDHCPProcess_eWaitingOfferRecvfromSucceedsCorrectCookieAndOpcodeNoTimeout( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingOffer; /* Put some time values. */ xDHCPData.xDHCPTxTime = 100; /* Make sure that we don't exceed the period - and thus, don't give up. */ xDHCPData.xDHCPTxPeriod = 100; /* Not Using broadcast. */ xDHCPData.xUseBroadcast = pdFALSE; /* Set the transaction ID which won't match. */ xDHCPData.ulTransactionId = 0x01ABCDEF; /* Get a stub. */ FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_eWaitingOfferRecvfromSucceedsCorrectCookieAndOpcodeNoTimeout ); FreeRTOS_ReleaseUDPPayloadBuffer_Expect( pucUDPBuffer ); /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ /* Return a value which makes the difference just equal to the period. */ xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod ); vDHCPProcess( pdFALSE, eWaitingOffer ); /* DHCP socket should be allocated */ TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); /* The state should indicate that we still in the state from where we started. */ TEST_ASSERT_EQUAL( eWaitingOffer, xDHCPData.eDHCPState ); } void test_vDHCPProcess_eWaitingOfferRecvfromLessBytesNoTimeout( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingOffer; /* Put some time values. */ xDHCPData.xDHCPTxTime = 100; /* Make sure that we don't exceed the period - and thus, don't give up. */ xDHCPData.xDHCPTxPeriod = 100; /* Not Using broadcast. */ xDHCPData.xUseBroadcast = pdFALSE; /* Get a stub. */ FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_eWaitingOfferRecvfromLessBytesNoTimeout ); FreeRTOS_ReleaseUDPPayloadBuffer_Expect( pucUDPBuffer ); /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ /* Return a value which makes the difference just equal to the period. */ xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod ); vDHCPProcess( pdFALSE, eWaitingOffer ); /* DHCP socket should be allocated */ TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); /* The state should indicate that we still in the state from where we started. */ TEST_ASSERT_EQUAL( eWaitingOffer, xDHCPData.eDHCPState ); } void test_vDHCPProcess_eWaitingOfferRecvfromSuccessCorrectTxID( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingOffer; /* Put some time values. */ xDHCPData.xDHCPTxTime = 100; /* Make sure that we don't exceed the period - and thus, don't give up. */ xDHCPData.xDHCPTxPeriod = 100; /* Not Using broadcast. */ xDHCPData.xUseBroadcast = pdFALSE; /* Set the transaction ID which will match. */ xDHCPData.ulTransactionId = 0x01ABCDEF; /* Get a stub. */ FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_eWaitingOfferRecvfromSuccessCorrectTxID ); FreeRTOS_ReleaseUDPPayloadBuffer_Expect( pucUDPBuffer ); /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ /* Return a value which makes the difference just equal to the period. */ xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod ); vDHCPProcess( pdFALSE, eWaitingOffer ); /* DHCP socket should be allocated */ TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); /* The state should indicate that we still in the state from where we started. */ TEST_ASSERT_EQUAL( eWaitingOffer, xDHCPData.eDHCPState ); } void test_vDHCPProcess_eWaitingOfferRecvfromSuccess_CorrectAddrType( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingOffer; /* Put some time values. */ xDHCPData.xDHCPTxTime = 100; /* Make sure that we don't exceed the period - and thus, don't give up. */ xDHCPData.xDHCPTxPeriod = 100; /* Not Using broadcast. */ xDHCPData.xUseBroadcast = pdFALSE; /* Set the transaction ID which will match. */ xDHCPData.ulTransactionId = 0x01ABCDEF; /* Get a stub. */ FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_eWaitingOfferRecvfromSuccess_CorrectAddrType ); FreeRTOS_ReleaseUDPPayloadBuffer_Expect( pucUDPBuffer ); /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ /* Return a value which makes the difference just equal to the period. */ xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod ); vDHCPProcess( pdFALSE, eWaitingOffer ); /* DHCP socket should be allocated */ TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); /* The state should indicate that we still in the state from where we started. */ TEST_ASSERT_EQUAL( eWaitingOffer, xDHCPData.eDHCPState ); } void test_vDHCPProcess_eWaitingOfferRecvfromSuccess_CorrectAddrLen_BroadcastAddress( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingOffer; /* Put some time values. */ xDHCPData.xDHCPTxTime = 100; /* Make sure that we don't exceed the period - and thus, don't give up. */ xDHCPData.xDHCPTxPeriod = 100; /* Not Using broadcast. */ xDHCPData.xUseBroadcast = pdFALSE; /* Set the transaction ID which will match. */ xDHCPData.ulTransactionId = 0x01ABCDEF; /* Get a stub. */ FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_eWaitingOfferRecvfromSuccess_CorrectAddrLen ); FreeRTOS_ReleaseUDPPayloadBuffer_Expect( pucUDPBuffer ); /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ /* Return a value which makes the difference just equal to the period. */ xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod ); vDHCPProcess( pdFALSE, eWaitingOffer ); /* DHCP socket should be allocated */ TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); /* The state should indicate that we still in the state from where we started. */ TEST_ASSERT_EQUAL( eWaitingOffer, xDHCPData.eDHCPState ); } void test_vDHCPProcess_eWaitingOfferRecvfromSuccess_CorrectAddrLen_LocalHostAddress( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingOffer; /* Put some time values. */ xDHCPData.xDHCPTxTime = 100; /* Make sure that we don't exceed the period - and thus, don't give up. */ xDHCPData.xDHCPTxPeriod = 100; /* Not Using broadcast. */ xDHCPData.xUseBroadcast = pdFALSE; /* Set the transaction ID which will match. */ xDHCPData.ulTransactionId = 0x01ABCDEF; /* Get a stub. */ FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_eWaitingOfferRecvfromSuccess_LocalHostAddr ); FreeRTOS_ReleaseUDPPayloadBuffer_Expect( pucUDPBuffer ); /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ /* Return a value which makes the difference just equal to the period. */ xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod ); vDHCPProcess( pdFALSE, eWaitingOffer ); /* DHCP socket should be allocated */ TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); /* The state should indicate that we still in the state from where we started. */ TEST_ASSERT_EQUAL( eWaitingOffer, xDHCPData.eDHCPState ); } void test_vDHCPProcess_eWaitingOfferRecvfromSuccess_CorrectAddrLen_NonLocalHostAddress( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingOffer; /* Put some time values. */ xDHCPData.xDHCPTxTime = 100; /* Make sure that we don't exceed the period - and thus, don't give up. */ xDHCPData.xDHCPTxPeriod = 100; /* Not Using broadcast. */ xDHCPData.xUseBroadcast = pdFALSE; /* Set the transaction ID which will match. */ xDHCPData.ulTransactionId = 0x01ABCDEF; /* Get a stub. */ FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_eWaitingOfferRecvfromSuccess_NonLocalHostAddr ); FreeRTOS_ReleaseUDPPayloadBuffer_Expect( pucUDPBuffer ); /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ /* Return a value which makes the difference just equal to the period. */ xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod ); vDHCPProcess( pdFALSE, eWaitingOffer ); /* DHCP socket should be allocated */ TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); /* The state should indicate that we still in the state from where we started. */ TEST_ASSERT_EQUAL( eWaitingOffer, xDHCPData.eDHCPState ); } void test_vDHCPProcess_eWaitingOfferRecvfromSuccess_CorrectAddrLen_LocalMACNotmatching( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; MACAddress_t xBackup; /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingOffer; /* Put some time values. */ xDHCPData.xDHCPTxTime = 100; /* Make sure that we don't exceed the period - and thus, don't give up. */ xDHCPData.xDHCPTxPeriod = 100; /* Not Using broadcast. */ xDHCPData.xUseBroadcast = pdFALSE; /* Set the transaction ID which will match. */ xDHCPData.ulTransactionId = 0x01ABCDEF; memcpy( &xBackup, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); memset( ipLOCAL_MAC_ADDRESS, 0xAA, sizeof( MACAddress_t ) ); /* Get a stub. */ FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_eWaitingOfferRecvfromSuccess_LocalMACAddrNotMatching ); FreeRTOS_ReleaseUDPPayloadBuffer_Expect( pucUDPBuffer ); /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ /* Return a value which makes the difference just equal to the period. */ xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod ); vDHCPProcess( pdFALSE, eWaitingOffer ); memcpy( ipLOCAL_MAC_ADDRESS, &xBackup, sizeof( MACAddress_t ) ); /* DHCP socket should be allocated */ TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); /* The state should indicate that we still in the state from where we started. */ TEST_ASSERT_EQUAL( eWaitingOffer, xDHCPData.eDHCPState ); } void test_vDHCPProcess_eWaitingOfferCorrectDHCPMessageWithoutOptionsNoTimeout( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; uint8_t DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) ]; DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; ucGenericPtr = DHCPMsg; ulGenericLength = sizeof( DHCPMsg ); /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingOffer; /* Put some time values. */ xDHCPData.xDHCPTxTime = 100; /* Make sure that we don't exceed the period - and thus, don't give up. */ xDHCPData.xDHCPTxPeriod = 100; /* Not Using broadcast. */ xDHCPData.xUseBroadcast = pdFALSE; /* Set the transaction ID which will match. */ xDHCPData.ulTransactionId = 0x01ABCDEF; /* Get a stub. */ FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ /* Return a value which makes the difference just equal to the period. */ xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod ); vDHCPProcess( pdFALSE, eWaitingOffer ); /* DHCP socket should be allocated */ TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); /* The state should indicate that we still in the state from where we started. */ TEST_ASSERT_EQUAL( eWaitingOffer, xDHCPData.eDHCPState ); } void test_vDHCPProcess_eWaitingOfferCorrectDHCPMessageIncorrectOptionsNoTimeout( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* Create a bit longer DHCP message but keep it empty. */ const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 3U; uint8_t DHCPMsg[ xTotalLength ]; DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; /* Set the header - or at least the start of DHCP message. */ memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); /* Copy the header here. */ memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); /* Make sure that the address matches. */ memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); /* Add the expected cookie. */ pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; /* Now add options which will be processed. */ /* Add a closing flag at the end. */ DHCPMsg[ xTotalLength - 1U ] = 0xFF; /* Put the information in global variables to be returned by * the FreeRTOS_recvrom. */ ucGenericPtr = DHCPMsg; ulGenericLength = sizeof( DHCPMsg ); /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingOffer; /* Put some time values. */ xDHCPData.xDHCPTxTime = 100; /* Make sure that we don't exceed the period - and thus, don't give up. */ xDHCPData.xDHCPTxPeriod = 100; /* Not Using broadcast. */ xDHCPData.xUseBroadcast = pdFALSE; /* Set the transaction ID which will match. */ xDHCPData.ulTransactionId = 0x01ABCDEF; /* Get a stub. */ FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ /* Return a value which makes the difference just equal to the period. */ xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod ); vDHCPProcess( pdFALSE, eWaitingOffer ); /* DHCP socket should be allocated */ TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); /* The state should indicate that we still in the state from where we started. */ TEST_ASSERT_EQUAL( eWaitingOffer, xDHCPData.eDHCPState ); } void test_vDHCPProcess_eWaitingOfferCorrectDHCPMessageMissingLengthByteNoTimeout( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* Create a bit longer DHCP message but keep it empty. */ const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U + 1U; uint8_t DHCPMsg[ xTotalLength ]; DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; /* Set the header - or at least the start of DHCP message. */ memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); /* Copy the header here. */ memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); /* Make sure that the address matches. */ memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); /* Add the expected cookie. */ pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; /* Leave one byte for the padding. */ uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; /* Put the information in global variables to be returned by * the FreeRTOS_recvrom. */ ucGenericPtr = DHCPMsg; ulGenericLength = sizeof( DHCPMsg ); /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingOffer; /* Put some time values. */ xDHCPData.xDHCPTxTime = 100; /* Make sure that we don't exceed the period - and thus, don't give up. */ xDHCPData.xDHCPTxPeriod = 100; /* Not Using broadcast. */ xDHCPData.xUseBroadcast = pdFALSE; /* Set the transaction ID which will match. */ xDHCPData.ulTransactionId = 0x01ABCDEF; /* Get a stub. */ FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ /* Return a value which makes the difference just equal to the period. */ xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod ); vDHCPProcess( pdFALSE, eWaitingOffer ); /* DHCP socket should be allocated */ TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); /* The state should indicate that we still in the state from where we started. */ TEST_ASSERT_EQUAL( eWaitingOffer, xDHCPData.eDHCPState ); } void test_vDHCPProcess_eWaitingOfferCorrectDHCPMessageIncorrectLengthByteNoTimeout( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* Create a bit longer DHCP message but keep it empty. */ const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U + 3U; uint8_t DHCPMsg[ xTotalLength ]; DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; /* Set the header - or at least the start of DHCP message. */ memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); /* Copy the header here. */ memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); /* Make sure that the address matches. */ memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); /* Add the expected cookie. */ pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; /* Leave one byte for the padding. */ uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; /* Add incorrect length. */ DHCPOption[ 1 ] = 100; /* Put the information in global variables to be returned by * the FreeRTOS_recvrom. */ ucGenericPtr = DHCPMsg; ulGenericLength = sizeof( DHCPMsg ); /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingOffer; /* Put some time values. */ xDHCPData.xDHCPTxTime = 100; /* Make sure that we don't exceed the period - and thus, don't give up. */ xDHCPData.xDHCPTxPeriod = 100; /* Not Using broadcast. */ xDHCPData.xUseBroadcast = pdFALSE; /* Set the transaction ID which will match. */ xDHCPData.ulTransactionId = 0x01ABCDEF; /* Get a stub. */ FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ /* Return a value which makes the difference just equal to the period. */ xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod ); vDHCPProcess( pdFALSE, eWaitingOffer ); /* DHCP socket should be allocated */ TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); /* The state should indicate that we still in the state from where we started. */ TEST_ASSERT_EQUAL( eWaitingOffer, xDHCPData.eDHCPState ); } void test_vDHCPProcess_eWaitingOfferCorrectDHCPMessageGetNACKNoTimeout( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* Create a bit longer DHCP message but keep it empty. */ const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U + 3U + 1U; uint8_t DHCPMsg[ xTotalLength ]; DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; /* Set the header - or at least the start of DHCP message. */ memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); /* Copy the header here. */ memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); /* Make sure that the address matches. */ memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); /* Add the expected cookie. */ pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; /* Leave one byte for the padding. */ uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 1; /* Add the offer byte. */ DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_NACK; /* Put the information in global variables to be returned by * the FreeRTOS_recvrom. */ ucGenericPtr = DHCPMsg; ulGenericLength = sizeof( DHCPMsg ); /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingOffer; /* Put some time values. */ xDHCPData.xDHCPTxTime = 100; /* Make sure that we don't exceed the period - and thus, don't give up. */ xDHCPData.xDHCPTxPeriod = 100; /* Not Using broadcast. */ xDHCPData.xUseBroadcast = pdFALSE; /* Set the transaction ID which will match. */ xDHCPData.ulTransactionId = 0x01ABCDEF; /* Get a stub. */ FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ /* Return a value which makes the difference just equal to the period. */ xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod ); vDHCPProcess( pdFALSE, eWaitingOffer ); /* DHCP socket should be allocated */ TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); /* The state should indicate that we still in the state from where we started. */ TEST_ASSERT_EQUAL( eWaitingOffer, xDHCPData.eDHCPState ); } void test_vDHCPProcess_eWaitingOfferCorrectDHCPMessageGetACKNoTimeout( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* Create a bit longer DHCP message but keep it empty. */ const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U + 3U + 1U; uint8_t DHCPMsg[ xTotalLength ]; DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; /* Set the header - or at least the start of DHCP message. */ memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); /* Copy the header here. */ memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); /* Make sure that the address matches. */ memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); /* Add the expected cookie. */ pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; /* Leave one byte for the padding. */ uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 1; /* Add the offer byte. */ DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_ACK; /* Put the information in global variables to be returned by * the FreeRTOS_recvrom. */ ucGenericPtr = DHCPMsg; ulGenericLength = sizeof( DHCPMsg ); /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingOffer; /* Put some time values. */ xDHCPData.xDHCPTxTime = 100; /* Make sure that we don't exceed the period - and thus, don't give up. */ xDHCPData.xDHCPTxPeriod = 100; /* Not Using broadcast. */ xDHCPData.xUseBroadcast = pdFALSE; /* Set the transaction ID which will match. */ xDHCPData.ulTransactionId = 0x01ABCDEF; /* Get a stub. */ FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ /* Return a value which makes the difference just equal to the period. */ xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod ); vDHCPProcess( pdFALSE, eWaitingOffer ); /* DHCP socket should be allocated */ TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); /* The state should indicate that we still in the state from where we started. */ TEST_ASSERT_EQUAL( eWaitingOffer, xDHCPData.eDHCPState ); } void test_vDHCPProcess_eWaitingOfferCorrectDHCPMessageOneOptionNoTimeout( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* Create a bit longer DHCP message but keep it empty. */ const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U + 3U + 1U; uint8_t DHCPMsg[ xTotalLength ]; DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; /* Set the header - or at least the start of DHCP message. */ memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); /* Copy the header here. */ memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); /* Make sure that the address matches. */ memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); /* Add the expected cookie. */ pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; /* Leave one byte for the padding. */ uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 1; /* Add the offer byte. */ DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_OFFER; /* Put the information in global variables to be returned by * the FreeRTOS_recvrom. */ ucGenericPtr = DHCPMsg; ulGenericLength = sizeof( DHCPMsg ); /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingOffer; /* Put some time values. */ xDHCPData.xDHCPTxTime = 100; /* Make sure that we don't exceed the period - and thus, don't give up. */ xDHCPData.xDHCPTxPeriod = 100; /* Not Using broadcast. */ xDHCPData.xUseBroadcast = pdFALSE; /* Set the transaction ID which will match. */ xDHCPData.ulTransactionId = 0x01ABCDEF; /* Get a stub. */ FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ /* Return a value which makes the difference just equal to the period. */ xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod ); vDHCPProcess( pdFALSE, eWaitingOffer ); /* DHCP socket should be allocated */ TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); /* The state should indicate that we still in the state from where we started. */ TEST_ASSERT_EQUAL( eWaitingOffer, xDHCPData.eDHCPState ); } void test_vDHCPProcess_eWaitingOfferCorrectDHCPMessageTwoOptionsSendFails( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* Create a bit longer DHCP message but keep it empty. */ const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U /* Padding */ + 3U /* DHCP offer */ + 6U /* Server IP address */ + 1U /* End */; uint8_t DHCPMsg[ xTotalLength ]; uint32_t DHCPServerAddress = 0xC0A80001; /* 192.168.0.1 */ uint32_t ulClientIPAddress = 0xC0A8000A; /* 192.168.0.10 */ DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; xDHCPData.ulOfferedIPAddress = DHCPServerAddress; /* Set the header - or at least the start of DHCP message. */ memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); /* Copy the header here. */ memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); /* Make sure that the address matches. */ memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); /* Add the expected cookie. */ pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; /* Set the client IP address. */ pxDHCPMessage->ulYourIPAddress_yiaddr = ulClientIPAddress; /* Leave one byte for the padding. */ uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 1; /* Add the offer byte. */ DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_OFFER; DHCPOption += 4; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 4; /* Add the offer byte. */ *( ( uint32_t * ) &DHCPOption[ 2 ] ) = DHCPServerAddress; /* Put the information in global variables to be returned by * the FreeRTOS_recvrom. */ ucGenericPtr = DHCPMsg; ulGenericLength = sizeof( DHCPMsg ); /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingOffer; /* Put some time values. */ xDHCPData.xDHCPTxTime = 100; /* Make sure that we don't exceed the period - and thus, don't give up. */ xDHCPData.xDHCPTxPeriod = 100; /* Not Using broadcast. */ xDHCPData.xUseBroadcast = pdFALSE; /* Set the transaction ID which will match. */ xDHCPData.ulTransactionId = 0x01ABCDEF; /* Get a stub. */ FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); /* Release the UDP buffer. */ FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); /* Return continue. */ xApplicationDHCPHook_ExpectAndReturn( eDHCPPhasePreRequest, ulClientIPAddress, eDHCPContinue ); /* Make the hook return correct value. */ pcApplicationHostnameHook_ExpectAndReturn( pcHostName ); /* Returning NULL will mean the prvSendDHCPRequest fails. */ pxGetNetworkBufferWithDescriptor_ExpectAnyArgsAndReturn( NULL ); vDHCPProcess( pdFALSE, eWaitingOffer ); /* DHCP socket should be allocated */ TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); /* The state should indicate that sending failed. */ TEST_ASSERT_EQUAL( eSendDHCPRequest, xDHCPData.eDHCPState ); } void test_vDHCPProcess_eWaitingOfferCorrectDHCPMessageTwoOptionsSendSucceeds( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* Create a bit longer DHCP message but keep it empty. */ const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U /* Padding */ + 3U /* DHCP offer */ + 6U /* Server IP address */ + 1U /* End */; uint8_t DHCPMsg[ xTotalLength ]; uint32_t DHCPServerAddress = 0xC0A80001; /* 192.168.0.1 */ uint32_t ulClientIPAddress = 0xC0A8000A; /* 192.168.0.10 */ DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; xDHCPData.ulOfferedIPAddress = DHCPServerAddress; /* Set the header - or at least the start of DHCP message. */ memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); /* Copy the header here. */ memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); /* Make sure that the address matches. */ memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); /* Add the expected cookie. */ pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; /* Set the client IP address. */ pxDHCPMessage->ulYourIPAddress_yiaddr = ulClientIPAddress; /* Leave one byte for the padding. */ uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 1; /* Add the offer byte. */ DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_OFFER; DHCPOption += 4; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 4; /* Add the offer byte. */ *( ( uint32_t * ) &DHCPOption[ 2 ] ) = DHCPServerAddress; /* Put the information in global variables to be returned by * the FreeRTOS_recvrom. */ ucGenericPtr = DHCPMsg; ulGenericLength = sizeof( DHCPMsg ); /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingOffer; /* Put some time values. */ xDHCPData.xDHCPTxTime = 100; /* Make sure that we don't exceed the period - and thus, don't give up. */ xDHCPData.xDHCPTxPeriod = 100; /* Not Using broadcast. */ xDHCPData.xUseBroadcast = pdFALSE; /* Set the transaction ID which will match. */ xDHCPData.ulTransactionId = 0x01ABCDEF; /* Get a stub. */ FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); /* Release the UDP buffer. */ FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); /* Return continue. */ xApplicationDHCPHook_ExpectAndReturn( eDHCPPhasePreRequest, ulClientIPAddress, eDHCPContinue ); /* Make the hook return correct value. */ pcApplicationHostnameHook_ExpectAndReturn( pcHostName ); /* Returning a proper network buffer. */ pxGetNetworkBufferWithDescriptor_Stub( GetNetworkBuffer ); /* Make the call to FreeRTOS_send succeed. */ FreeRTOS_sendto_ExpectAnyArgsAndReturn( 1 ); xTaskGetTickCount_ExpectAndReturn( xTimeValue ); vDHCPProcess( pdFALSE, eWaitingOffer ); /* DHCP socket should be allocated */ TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); /* The state should indicate that sending failed. */ TEST_ASSERT_EQUAL( eWaitingAcknowledge, xDHCPData.eDHCPState ); /* The time should be updated. */ TEST_ASSERT_EQUAL( xTimeValue, xDHCPData.xDHCPTxTime ); } void test_vDHCPProcess_eWaitingOfferCorrectDHCPMessageTwoOptionsDHCPHookReturnDefaultSendSucceeds( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* Create a bit longer DHCP message but keep it empty. */ const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U /* Padding */ + 3U /* DHCP offer */ + 6U /* Server IP address */ + 1U /* End */; uint8_t DHCPMsg[ xTotalLength ]; uint32_t DHCPServerAddress = 0xC0A80001; /* 192.168.0.1 */ uint32_t ulClientIPAddress = 0xC0A8000A; /* 192.168.0.10 */ DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; xDHCPData.ulOfferedIPAddress = DHCPServerAddress; /* Rest the network addressing values. */ memset( &( xNetworkAddressing ), 0, sizeof( xNetworkAddressing ) ); /* Set the header - or at least the start of DHCP message. */ memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); /* Copy the header here. */ memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); /* Make sure that the address matches. */ memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); /* Add the expected cookie. */ pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; /* Set the client IP address. */ pxDHCPMessage->ulYourIPAddress_yiaddr = ulClientIPAddress; /* Leave one byte for the padding. */ uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 1; /* Add the offer byte. */ DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_OFFER; DHCPOption += 4; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 4; /* Add the offer byte. */ *( ( uint32_t * ) &DHCPOption[ 2 ] ) = DHCPServerAddress; /* Put the information in global variables to be returned by * the FreeRTOS_recvrom. */ ucGenericPtr = DHCPMsg; ulGenericLength = sizeof( DHCPMsg ); /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingOffer; /* Put some time values. */ xDHCPData.xDHCPTxTime = 100; /* Make sure that we don't exceed the period - and thus, don't give up. */ xDHCPData.xDHCPTxPeriod = 100; /* Not Using broadcast. */ xDHCPData.xUseBroadcast = pdFALSE; /* Set the transaction ID which will match. */ xDHCPData.ulTransactionId = 0x01ABCDEF; /* Get a stub. */ FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); /* Release the UDP buffer. */ FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); /* Return continue. */ xApplicationDHCPHook_ExpectAndReturn( eDHCPPhasePreRequest, ulClientIPAddress, eDHCPUseDefaults ); /* Expect the timer to be disabled. */ vIPSetDHCPTimerEnableState_Expect( pdFALSE ); vIPNetworkUpCalls_Ignore(); /* Expect the socket to be closed. */ vSocketClose_ExpectAndReturn( xDHCPSocket, NULL ); vDHCPProcess( pdFALSE, eWaitingOffer ); /* DHCP socket should be unallocated */ TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); /* The state should indicate that sending failed. */ TEST_ASSERT_EQUAL( eNotUsingLeasedAddress, xDHCPData.eDHCPState ); TEST_ASSERT_EQUAL_MEMORY( &( xNetworkAddressing ), &( xDefaultAddressing ), sizeof( xNetworkAddressing ) ); } void test_vDHCPProcess_eWaitingOfferCorrectDHCPMessageTwoOptionsDHCPHookReturnErrorSendSucceeds( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* Create a bit longer DHCP message but keep it empty. */ const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U /* Padding */ + 3U /* DHCP offer */ + 6U /* Server IP address */ + 1U /* End */; uint8_t DHCPMsg[ xTotalLength ]; uint32_t DHCPServerAddress = 0xC0A80001; /* 192.168.0.1 */ uint32_t ulClientIPAddress = 0xC0A8000A; /* 192.168.0.10 */ uint8_t testMemory[ sizeof( xNetworkAddressing ) ]; DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; xDHCPData.ulOfferedIPAddress = DHCPServerAddress; /* Rest the network addressing values. */ memset( &( xNetworkAddressing ), 0, sizeof( xNetworkAddressing ) ); memset( &( testMemory ), 0, sizeof( xNetworkAddressing ) ); /* Set the header - or at least the start of DHCP message. */ memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); /* Copy the header here. */ memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); /* Make sure that the address matches. */ memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); /* Add the expected cookie. */ pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; /* Set the client IP address. */ pxDHCPMessage->ulYourIPAddress_yiaddr = ulClientIPAddress; /* Leave one byte for the padding. */ uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 1; /* Add the offer byte. */ DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_OFFER; DHCPOption += 4; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 4; /* Add the offer byte. */ *( ( uint32_t * ) &DHCPOption[ 2 ] ) = DHCPServerAddress; /* Put the information in global variables to be returned by * the FreeRTOS_recvrom. */ ucGenericPtr = DHCPMsg; ulGenericLength = sizeof( DHCPMsg ); /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingOffer; /* Put some time values. */ xDHCPData.xDHCPTxTime = 100; /* Make sure that we don't exceed the period - and thus, don't give up. */ xDHCPData.xDHCPTxPeriod = 100; /* Not Using broadcast. */ xDHCPData.xUseBroadcast = pdFALSE; /* Set the transaction ID which will match. */ xDHCPData.ulTransactionId = 0x01ABCDEF; /* Get a stub. */ FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); /* Release the UDP buffer. */ FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); /* Return continue. */ xApplicationDHCPHook_ExpectAndReturn( eDHCPPhasePreRequest, ulClientIPAddress, ( eDHCPContinue + eDHCPUseDefaults ) << 1 ); /* Expect the timer to be disabled. */ vIPSetDHCPTimerEnableState_Expect( pdFALSE ); vIPNetworkUpCalls_Ignore(); /* Expect the socket to be closed. */ vSocketClose_ExpectAndReturn( xDHCPSocket, NULL ); vDHCPProcess( pdFALSE, eWaitingOffer ); /* DHCP socket should be unallocated */ TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); /* The state should indicate that sending failed. */ TEST_ASSERT_EQUAL( eNotUsingLeasedAddress, xDHCPData.eDHCPState ); TEST_ASSERT_EQUAL_MEMORY( &( xNetworkAddressing ), &( testMemory ), sizeof( xNetworkAddressing ) ); } void test_vDHCPProcess_eWaitingAcknowledgeTwoOptionsIncorrectServerNoTimeout( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* Create a bit longer DHCP message but keep it empty. */ const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U /* Padding */ + 3U /* DHCP offer */ + 6U /* Server IP address */ + 1U /* End */; uint8_t DHCPMsg[ xTotalLength ]; uint32_t DHCPServerAddress = 0xC0A80001; /* 192.168.0.1 */ uint32_t ulClientIPAddress = 0xC0A8000A; /* 192.168.0.10 */ uint8_t testMemory[ sizeof( xNetworkAddressing ) ]; DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; /* Rest the network addressing values. */ memset( &( xNetworkAddressing ), 0, sizeof( xNetworkAddressing ) ); memset( &( testMemory ), 0, sizeof( xNetworkAddressing ) ); /* Set the header - or at least the start of DHCP message. */ memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); /* Copy the header here. */ memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); /* Make sure that the address matches. */ memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); /* Add the expected cookie. */ pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; /* Set the client IP address. */ pxDHCPMessage->ulYourIPAddress_yiaddr = ulClientIPAddress; /* Leave one byte for the padding. */ uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 1; /* Add the offer byte. */ DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_ACK; DHCPOption += 4; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 4; /* Add the offer byte. */ *( ( uint32_t * ) &DHCPOption[ 2 ] ) = DHCPServerAddress; /* Put the information in global variables to be returned by * the FreeRTOS_recvrom. */ ucGenericPtr = DHCPMsg; ulGenericLength = sizeof( DHCPMsg ); /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingAcknowledge; /* Put some time values. */ xDHCPData.xDHCPTxTime = 100; /* Make sure that we don't exceed the period - and thus, don't give up. */ xDHCPData.xDHCPTxPeriod = 100; /* Not Using broadcast. */ xDHCPData.xUseBroadcast = pdFALSE; /* Set the transaction ID which will match. */ xDHCPData.ulTransactionId = 0x01ABCDEF; /* Put incorrect address. */ xDHCPData.ulDHCPServerAddress = DHCPServerAddress + 1234; /* Get a stub. */ FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); /* Release the UDP buffer. */ FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ /* Return a value which makes the difference just equal to the period. */ xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod ); vDHCPProcess( pdFALSE, eWaitingAcknowledge ); /* DHCP socket should be allocated */ TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); /* Still waiting on acknowledge. */ TEST_ASSERT_EQUAL( eWaitingAcknowledge, xDHCPData.eDHCPState ); TEST_ASSERT_EQUAL_MEMORY( &( xNetworkAddressing ), &( testMemory ), sizeof( xNetworkAddressing ) ); } void test_vDHCPProcess_eWaitingAcknowledgeTwoOptionsIncorrectServerTimeoutGNBfails( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* Create a bit longer DHCP message but keep it empty. */ const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U /* Padding */ + 3U /* DHCP offer */ + 6U /* Server IP address */ + 1U /* End */; uint8_t DHCPMsg[ xTotalLength ]; uint32_t DHCPServerAddress = 0xC0A80001; /* 192.168.0.1 */ uint32_t ulClientIPAddress = 0xC0A8000A; /* 192.168.0.10 */ uint8_t testMemory[ sizeof( xNetworkAddressing ) ]; DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; /* Rest the network addressing values. */ memset( &( xNetworkAddressing ), 0, sizeof( xNetworkAddressing ) ); memset( &( testMemory ), 0, sizeof( xNetworkAddressing ) ); /* Set the header - or at least the start of DHCP message. */ memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); /* Copy the header here. */ memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); /* Make sure that the address matches. */ memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); /* Add the expected cookie. */ pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; /* Set the client IP address. */ pxDHCPMessage->ulYourIPAddress_yiaddr = ulClientIPAddress; /* Leave one byte for the padding. */ uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 1; /* Add the offer byte. */ DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_ACK; DHCPOption += 4; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 4; /* Add the offer byte. */ *( ( uint32_t * ) &DHCPOption[ 2 ] ) = DHCPServerAddress; /* Put the information in global variables to be returned by * the FreeRTOS_recvrom. */ ucGenericPtr = DHCPMsg; ulGenericLength = sizeof( DHCPMsg ); /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingAcknowledge; /* Put some time values. */ xDHCPData.xDHCPTxTime = 100; /* Make sure that we don't exceed the period - and thus, don't give up. */ xDHCPData.xDHCPTxPeriod = 100; /* Not Using broadcast. */ xDHCPData.xUseBroadcast = pdFALSE; /* Set the transaction ID which will match. */ xDHCPData.ulTransactionId = 0x01ABCDEF; /* Put incorrect address. */ xDHCPData.ulDHCPServerAddress = DHCPServerAddress + 1234; /* Get a stub. */ FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); /* Release the UDP buffer. */ FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ /* Return a value which makes the difference just equal to the period. */ xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod + 100 ); /* Return time second time which can be verified. */ xTaskGetTickCount_ExpectAndReturn( xTimeValue ); /* Get the hostname. */ pcApplicationHostnameHook_ExpectAndReturn( pcHostName ); /* Returning a NULL so that prvSendDHCPRequest fails. */ pxGetNetworkBufferWithDescriptor_ExpectAnyArgsAndReturn( NULL ); vDHCPProcess( pdFALSE, eWaitingAcknowledge ); /* DHCP socket should be allocated */ TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); /* Still waiting on acknowledge. */ TEST_ASSERT_EQUAL( eSendDHCPRequest, xDHCPData.eDHCPState ); /* The time value should be stored in the state machine. */ TEST_ASSERT_EQUAL( xTimeValue, xDHCPData.xDHCPTxTime ); TEST_ASSERT_EQUAL_MEMORY( &( xNetworkAddressing ), &( testMemory ), sizeof( xNetworkAddressing ) ); } void test_vDHCPProcess_eWaitingAcknowledgeTwoOptionsIncorrectServerTimeoutGNBsucceeds( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* Create a bit longer DHCP message but keep it empty. */ const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U /* Padding */ + 3U /* DHCP offer */ + 6U /* Server IP address */ + 1U /* End */; uint8_t DHCPMsg[ xTotalLength ]; uint32_t DHCPServerAddress = 0xC0A80001; /* 192.168.0.1 */ uint32_t ulClientIPAddress = 0xC0A8000A; /* 192.168.0.10 */ DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; /* Set the header - or at least the start of DHCP message. */ memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); /* Copy the header here. */ memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); /* Make sure that the address matches. */ memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); /* Add the expected cookie. */ pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; /* Set the client IP address. */ pxDHCPMessage->ulYourIPAddress_yiaddr = ulClientIPAddress; /* Leave one byte for the padding. */ uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 1; /* Add the offer byte. */ DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_ACK; DHCPOption += 4; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 4; /* Add the offer byte. */ *( ( uint32_t * ) &DHCPOption[ 2 ] ) = DHCPServerAddress; /* Put the information in global variables to be returned by * the FreeRTOS_recvrom. */ ucGenericPtr = DHCPMsg; ulGenericLength = sizeof( DHCPMsg ); /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingAcknowledge; /* Put some time values. */ xDHCPData.xDHCPTxTime = 100; /* Make sure that we don't exceed the period - and thus, don't give up. */ xDHCPData.xDHCPTxPeriod = 100; /* Not Using broadcast. */ xDHCPData.xUseBroadcast = pdFALSE; /* Set the transaction ID which will match. */ xDHCPData.ulTransactionId = 0x01ABCDEF; /* Put incorrect address. */ xDHCPData.ulDHCPServerAddress = DHCPServerAddress + 1234; /* Get a stub. */ FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); /* Release the UDP buffer. */ FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ /* Return a value which makes the difference just equal to the period. */ xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod + 100 ); /* Return time second time which can be verified. */ xTaskGetTickCount_ExpectAndReturn( xTimeValue ); /* Get the hostname. */ pcApplicationHostnameHook_ExpectAndReturn( pcHostName ); /* Returning a proper network buffer. */ pxGetNetworkBufferWithDescriptor_Stub( GetNetworkBuffer ); /* Send succeeds. */ FreeRTOS_sendto_ExpectAnyArgsAndReturn( 1 ); vDHCPProcess( pdFALSE, eWaitingAcknowledge ); /* DHCP socket should be allocated */ TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); /* Still waiting on acknowledge. */ TEST_ASSERT_EQUAL( eWaitingAcknowledge, xDHCPData.eDHCPState ); TEST_ASSERT_EQUAL( xTimeValue, xDHCPData.xDHCPTxTime ); } void test_vDHCPProcess_eWaitingAcknowledgeTwoOptionsIncorrectServerTimeoutPeriodLess( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* Create a bit longer DHCP message but keep it empty. */ const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U /* Padding */ + 3U /* DHCP offer */ + 6U /* Server IP address */ + 1U /* End */; uint8_t DHCPMsg[ xTotalLength ]; uint32_t DHCPServerAddress = 0xC0A80001; /* 192.168.0.1 */ uint32_t ulClientIPAddress = 0xC0A8000A; /* 192.168.0.10 */ DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; /* Set the header - or at least the start of DHCP message. */ memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); /* Copy the header here. */ memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); /* Make sure that the address matches. */ memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); /* Add the expected cookie. */ pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; /* Set the client IP address. */ pxDHCPMessage->ulYourIPAddress_yiaddr = ulClientIPAddress; /* Leave one byte for the padding. */ uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 1; /* Add the offer byte. */ DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_ACK; DHCPOption += 4; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 4; /* Add the offer byte. */ *( ( uint32_t * ) &DHCPOption[ 2 ] ) = DHCPServerAddress; /* Put the information in global variables to be returned by * the FreeRTOS_recvrom. */ ucGenericPtr = DHCPMsg; ulGenericLength = sizeof( DHCPMsg ); /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingAcknowledge; /* Put some time values. */ xDHCPData.xDHCPTxTime = 100; /* Make sure we exceed the period - and thus, give up. */ xDHCPData.xDHCPTxPeriod = ( ipconfigMAXIMUM_DISCOVER_TX_PERIOD >> 1 ) + 1; /* Not Using broadcast. */ xDHCPData.xUseBroadcast = pdFALSE; /* Set the transaction ID which will match. */ xDHCPData.ulTransactionId = 0x01ABCDEF; /* Put incorrect address. */ xDHCPData.ulDHCPServerAddress = DHCPServerAddress + 1234; /* Get a stub. */ FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); /* Release the UDP buffer. */ FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ /* Return a value which makes the difference just equal to the period. */ xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod + 100 ); vDHCPProcess( pdFALSE, eWaitingAcknowledge ); /* DHCP socket should be allocated */ TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); /* Period exceeded. We should now be in initial state. */ TEST_ASSERT_EQUAL( eInitialWait, xDHCPData.eDHCPState ); /* Period exceeded, should have initial value */ TEST_ASSERT_EQUAL( 100, xDHCPData.xDHCPTxTime ); } void test_vDHCPProcess_eWaitingAcknowledgeTwoOptionsCorrectServerLeaseTimeZero( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* Create a bit longer DHCP message but keep it empty. */ const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U /* Padding */ + 3U /* DHCP offer */ + 6U /* Server IP address */ + 1U /* End */; uint8_t DHCPMsg[ xTotalLength ]; uint32_t DHCPServerAddress = 0xC0A80001; /* 192.168.0.1 */ uint32_t ulClientIPAddress = 0xC0A8000A; /* 192.168.0.10 */ DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; /* Set the header - or at least the start of DHCP message. */ memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); /* Copy the header here. */ memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); /* Make sure that the address matches. */ memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); /* Add the expected cookie. */ pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; /* Set the client IP address. */ pxDHCPMessage->ulYourIPAddress_yiaddr = ulClientIPAddress; /* Leave one byte for the padding. */ uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 1; /* Add the offer byte. */ DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_ACK; DHCPOption += 4; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 4; /* Add the offer byte. */ *( ( uint32_t * ) &DHCPOption[ 2 ] ) = DHCPServerAddress; /* Put the information in global variables to be returned by * the FreeRTOS_recvrom. */ ucGenericPtr = DHCPMsg; ulGenericLength = sizeof( DHCPMsg ); /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingAcknowledge; /* Not Using broadcast. */ xDHCPData.xUseBroadcast = pdFALSE; /* Set the transaction ID which will match. */ xDHCPData.ulTransactionId = 0x01ABCDEF; /* Put correct address. */ xDHCPData.ulDHCPServerAddress = DHCPServerAddress; /* Reset the lease time so that it will be set to default * value later. */ xDHCPData.ulLeaseTime = 0; /* Reset this value so that it can be verified later. */ *ipLOCAL_IP_ADDRESS_POINTER = 0; /* Get a stub. */ FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); /* Release the UDP buffer. */ FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); /* Expect this function to be called since we now have * successfully acquired an IP address. */ vIPNetworkUpCalls_Expect(); /* Then expect the socket to be closed. */ vSocketClose_ExpectAndReturn( &xTestSocket, NULL ); /* Expect ARP to begin. */ vARPSendGratuitous_Expect(); /* Expect the timer to be reloaded. */ vDHCPTimerReload_Expect( dhcpDEFAULT_LEASE_TIME ); vDHCPProcess( pdFALSE, eWaitingAcknowledge ); /* DHCP socket should be unallocated */ TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); /* Should now be using leased address. */ TEST_ASSERT_EQUAL( eLeasedAddress, xDHCPData.eDHCPState ); } void test_vDHCPProcess_eWaitingAcknowledgeTwoOptionsCorrectServerLeaseTimeLessThanMinConfig( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* Create a bit longer DHCP message but keep it empty. */ const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U /* Padding */ + 3U /* DHCP offer */ + 6U /* Server IP address */ + 1U /* End */; uint8_t DHCPMsg[ xTotalLength ]; uint32_t DHCPServerAddress = 0xC0A80001; /* 192.168.0.1 */ uint32_t ulClientIPAddress = 0xC0A8000A; /* 192.168.0.10 */ DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; /* Set the header - or at least the start of DHCP message. */ memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); /* Copy the header here. */ memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); /* Make sure that the address matches. */ memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); /* Add the expected cookie. */ pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; /* Set the client IP address. */ pxDHCPMessage->ulYourIPAddress_yiaddr = ulClientIPAddress; /* Leave one byte for the padding. */ uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 1; /* Add the offer byte. */ DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_ACK; DHCPOption += 4; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 4; /* Add the offer byte. */ *( ( uint32_t * ) &DHCPOption[ 2 ] ) = DHCPServerAddress; /* Put the information in global variables to be returned by * the FreeRTOS_recvrom. */ ucGenericPtr = DHCPMsg; ulGenericLength = sizeof( DHCPMsg ); /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingAcknowledge; /* Not Using broadcast. */ xDHCPData.xUseBroadcast = pdFALSE; /* Set the transaction ID which will match. */ xDHCPData.ulTransactionId = 0x01ABCDEF; /* Put correct address. */ xDHCPData.ulDHCPServerAddress = DHCPServerAddress; /* Reset the lease time so that it will be set to minimum * value later. */ xDHCPData.ulLeaseTime = dhcpMINIMUM_LEASE_TIME - 10; /* Reset this value so that it can be verified later. */ *ipLOCAL_IP_ADDRESS_POINTER = 0; /* Get a stub. */ FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); /* Release the UDP buffer. */ FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); /* Expect this function to be called since we now have * successfully acquired an IP address. */ vIPNetworkUpCalls_Expect(); /* Then expect the socket to be closed. */ vSocketClose_ExpectAndReturn( &xTestSocket, NULL ); /* Expect ARP to begin. */ vARPSendGratuitous_Expect(); /* Expect the timer to be reloaded. */ vDHCPTimerReload_Expect( dhcpMINIMUM_LEASE_TIME ); vDHCPProcess( pdFALSE, eWaitingAcknowledge ); /* DHCP socket should be unallocated */ TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); /* Should now be using leased address. */ TEST_ASSERT_EQUAL( eLeasedAddress, xDHCPData.eDHCPState ); TEST_ASSERT_EQUAL( dhcpMINIMUM_LEASE_TIME, xDHCPData.ulLeaseTime ); } void test_vDHCPProcess_eWaitingAcknowledge_TwoOptions_CorrectServer_AptLeaseTime( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* Create a bit longer DHCP message but keep it empty. */ const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U /* Padding */ + 3U /* DHCP offer */ + 6U /* Server IP address */ + 1U /* End */; uint8_t DHCPMsg[ xTotalLength ]; uint32_t DHCPServerAddress = 0xC0A80001; /* 192.168.0.1 */ uint32_t ulClientIPAddress = 0xC0A8000A; /* 192.168.0.10 */ DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; /* Set the header - or at least the start of DHCP message. */ memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); /* Copy the header here. */ memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); /* Make sure that the address matches. */ memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); /* Add the expected cookie. */ pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; /* Set the client IP address. */ pxDHCPMessage->ulYourIPAddress_yiaddr = ulClientIPAddress; /* Leave one byte for the padding. */ uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 1; /* Add the offer byte. */ DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_ACK; DHCPOption += 4; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 4; /* Add the offer byte. */ *( ( uint32_t * ) &DHCPOption[ 2 ] ) = DHCPServerAddress; /* Put the information in global variables to be returned by * the FreeRTOS_recvrom. */ ucGenericPtr = DHCPMsg; ulGenericLength = sizeof( DHCPMsg ); /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingAcknowledge; /* Not Using broadcast. */ xDHCPData.xUseBroadcast = pdFALSE; /* Set the transaction ID which will match. */ xDHCPData.ulTransactionId = 0x01ABCDEF; /* Put correct address. */ xDHCPData.ulDHCPServerAddress = DHCPServerAddress; /* Reset the lease time to an appropriate value. */ xDHCPData.ulLeaseTime = dhcpMINIMUM_LEASE_TIME + 10; /* Reset this value so that it can be verified later. */ *ipLOCAL_IP_ADDRESS_POINTER = 0; /* Get a stub. */ FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); /* Release the UDP buffer. */ FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); /* Expect this function to be called since we now have * successfully acquired an IP address. */ vIPNetworkUpCalls_Expect(); /* Then expect the socket to be closed. */ vSocketClose_ExpectAndReturn( &xTestSocket, NULL ); /* Expect ARP to begin. */ vARPSendGratuitous_Expect(); /* Expect the timer to be reloaded. */ vDHCPTimerReload_Expect( dhcpMINIMUM_LEASE_TIME + 10 ); vDHCPProcess( pdFALSE, eWaitingAcknowledge ); /* DHCP socket should be unallocated */ TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); /* Should now be using leased address. */ TEST_ASSERT_EQUAL( eLeasedAddress, xDHCPData.eDHCPState ); /* Make sure that this is not changed. */ TEST_ASSERT_EQUAL( dhcpMINIMUM_LEASE_TIME + 10, xDHCPData.ulLeaseTime ); } void test_vDHCPProcess_eWaitingAcknowledge_TwoOptions_NACK( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* Create a bit longer DHCP message but keep it empty. */ const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U /* Padding */ + 3U /* DHCP offer */ + 6U /* Server IP address */ + 1U /* End */; uint8_t DHCPMsg[ xTotalLength ]; uint32_t DHCPServerAddress = 0xC0A80001; /* 192.168.0.1 */ uint32_t ulClientIPAddress = 0xC0A8000A; /* 192.168.0.10 */ DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; /* Set the header - or at least the start of DHCP message. */ memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); /* Copy the header here. */ memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); /* Make sure that the address matches. */ memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); /* Add the expected cookie. */ pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; /* Set the client IP address. */ pxDHCPMessage->ulYourIPAddress_yiaddr = ulClientIPAddress; /* Leave one byte for the padding. */ uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 1; /* Add the offer byte. */ DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_NACK; DHCPOption += 4; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 4; /* Add the offer byte. */ *( ( uint32_t * ) &DHCPOption[ 2 ] ) = DHCPServerAddress; /* Put the information in global variables to be returned by * the FreeRTOS_recvrom. */ ucGenericPtr = DHCPMsg; ulGenericLength = sizeof( DHCPMsg ); /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingAcknowledge; /* Not Using broadcast. */ xDHCPData.xUseBroadcast = pdFALSE; /* Set the transaction ID which will match. */ xDHCPData.ulTransactionId = 0x01ABCDEF; /* Put correct address. */ xDHCPData.ulDHCPServerAddress = DHCPServerAddress; /* Reset the lease time to an appropriate value. */ xDHCPData.ulLeaseTime = dhcpMINIMUM_LEASE_TIME + 10; /* Put some time values. */ xDHCPData.xDHCPTxTime = 100; /* Make sure that we don't exceed the period - and thus, don't give up. */ xDHCPData.xDHCPTxPeriod = 100; /* Reset this value so that it can be verified later. */ *ipLOCAL_IP_ADDRESS_POINTER = 0; /* Get a stub. */ FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); /* Release the UDP buffer. */ FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ /* Return a value which makes the difference just equal to the period. */ xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod ); vDHCPProcess( pdFALSE, eWaitingAcknowledge ); /* DHCP socket should be allocated */ TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); /* Should now be reset after NACK. */ TEST_ASSERT_EQUAL( eInitialWait, xDHCPData.eDHCPState ); } void test_vDHCPProcess_eWaitingAcknowledge_AllOptionsCorrectLength( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* Create a bit longer DHCP message but keep it empty. */ const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U /* Padding */ + 3U /* DHCP offer */ + 6U /* Server IP address */ + 6U /* Subnet Mask */ + 6U /* Gateway */ + 6U /* Lease time */ + 6U /* DNS server */ + 1U /* End */; uint8_t DHCPMsg[ xTotalLength ]; uint32_t DHCPServerAddress = 0xC0A80001; /* 192.168.0.1 */ uint32_t ulClientIPAddress = 0xC0A8000A; /* 192.168.0.10 */ uint32_t ulSubnetMask = 0xFFFFF100; /* 255.255.241.0 */ uint32_t ulGateway = 0xC0A80001; /* 192.168.0.1 */ uint32_t ulLeaseTime = 0x00000096; /* 150 seconds */ uint32_t ulDNSServer = 0xC0010101; /* 192.1.1.1 */ DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; DHCPMsg[ xTotalLength - 1U ] = 0xFF; /* Set the header - or at least the start of DHCP message. */ memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); /* Copy the header here. */ memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); /* Make sure that the address matches. */ memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); /* Add the expected cookie. */ pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; /* Set the client IP address. */ pxDHCPMessage->ulYourIPAddress_yiaddr = ulClientIPAddress; /* Leave one byte for the padding. */ uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 1; /* Add the offer byte. */ DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_ACK; DHCPOption += 4; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 4; /* Add the offer byte. */ *( ( uint32_t * ) &DHCPOption[ 2 ] ) = DHCPServerAddress; DHCPOption += 6; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_SUBNET_MASK_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 4; /* Add the offer byte. */ *( ( uint32_t * ) &DHCPOption[ 2 ] ) = ulSubnetMask; DHCPOption += 6; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_GATEWAY_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 4; /* Add the offer byte. */ *( ( uint32_t * ) &DHCPOption[ 2 ] ) = ulGateway; DHCPOption += 6; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_LEASE_TIME_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 4; /* Add the offer byte. */ *( ( uint32_t * ) &DHCPOption[ 2 ] ) = ulLeaseTime; DHCPOption += 6; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_DNS_SERVER_OPTIONS_CODE; /* Add length. */ DHCPOption[ 1 ] = 4; /* Add the offer byte. */ *( ( uint32_t * ) &DHCPOption[ 2 ] ) = ulDNSServer; /* Put the information in global variables to be returned by * the FreeRTOS_recvrom. */ ucGenericPtr = DHCPMsg; ulGenericLength = sizeof( DHCPMsg ); /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingAcknowledge; /* Not Using broadcast. */ xDHCPData.xUseBroadcast = pdFALSE; /* Set the transaction ID which will match. */ xDHCPData.ulTransactionId = 0x01ABCDEF; /* Put correct address. */ xDHCPData.ulDHCPServerAddress = DHCPServerAddress; /* Reset the lease time. */ xDHCPData.ulLeaseTime = 0; /* Reset this value so that it can be verified later. */ *ipLOCAL_IP_ADDRESS_POINTER = 0; /* Get a stub. */ FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); /* Release the UDP buffer. */ FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); /* Expect this function to be called since we now have * successfully acquired an IP address. */ vIPNetworkUpCalls_Expect(); /* Then expect the socket to be closed. */ vSocketClose_ExpectAndReturn( &xTestSocket, NULL ); /* Expect ARP to begin. */ vARPSendGratuitous_Expect(); /* Expect the timer to be reloaded. */ vDHCPTimerReload_Expect( configTICK_RATE_HZ * ( FreeRTOS_ntohl( ulLeaseTime ) >> 1 ) ); vDHCPProcess( pdFALSE, eWaitingAcknowledge ); /* DHCP socket should be unallocated */ TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); /* Should now be using leased address. */ TEST_ASSERT_EQUAL( eLeasedAddress, xDHCPData.eDHCPState ); /* Make sure that this is not changed. */ TEST_ASSERT_EQUAL( configTICK_RATE_HZ * ( FreeRTOS_ntohl( ulLeaseTime ) >> 1 ), xDHCPData.ulLeaseTime ); TEST_ASSERT_EQUAL( EP_IPv4_SETTINGS.ulGatewayAddress, ulGateway ); TEST_ASSERT_EQUAL( EP_IPv4_SETTINGS.ulNetMask, ulSubnetMask ); } void test_vDHCPProcess_eWaitingAcknowledge_DNSIncorrectLength( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* Create a bit longer DHCP message but keep it empty. */ const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U /* Padding */ + 3U /* DHCP offer */ + 6U /* Server IP address */ + 6U /* Subnet Mask */ + 6U /* Gateway */ + 6U /* Lease time */ + 6U /* DNS server */ + 1U /* End */; uint8_t DHCPMsg[ xTotalLength ]; uint32_t DHCPServerAddress = 0xC0A80001; /* 192.168.0.1 */ uint32_t ulClientIPAddress = 0xC0A8000A; /* 192.168.0.10 */ uint32_t ulSubnetMask = 0xFFFFF100; /* 255.255.241.0 */ uint32_t ulGateway = 0xC0A80001; /* 192.168.0.1 */ uint32_t ulLeaseTime = 0x00000096; /* 150 seconds */ uint32_t ulDNSServer = 0xC0010101; /* 192.1.1.1 */ DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; DHCPMsg[ xTotalLength - 1U ] = 0xFF; /* Set the header - or at least the start of DHCP message. */ memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); /* Copy the header here. */ memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); /* Make sure that the address matches. */ memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); /* Add the expected cookie. */ pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; /* Set the client IP address. */ pxDHCPMessage->ulYourIPAddress_yiaddr = ulClientIPAddress; /* Leave one byte for the padding. */ uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 1; /* Add the offer byte. */ DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_ACK; DHCPOption += 4; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 4; /* Add the offer byte. */ *( ( uint32_t * ) &DHCPOption[ 2 ] ) = DHCPServerAddress; DHCPOption += 6; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_SUBNET_MASK_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 4; /* Add the offer byte. */ *( ( uint32_t * ) &DHCPOption[ 2 ] ) = ulSubnetMask; DHCPOption += 6; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_GATEWAY_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 4; /* Add the offer byte. */ *( ( uint32_t * ) &DHCPOption[ 2 ] ) = ulGateway; DHCPOption += 6; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_LEASE_TIME_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 4; /* Add the offer byte. */ *( ( uint32_t * ) &DHCPOption[ 2 ] ) = ulLeaseTime; DHCPOption += 6; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_DNS_SERVER_OPTIONS_CODE; /* Add length. */ DHCPOption[ 1 ] = 3; /* Add the offer byte. */ *( ( uint32_t * ) &DHCPOption[ 2 ] ) = ulDNSServer; /* Put the information in global variables to be returned by * the FreeRTOS_recvrom. */ ucGenericPtr = DHCPMsg; ulGenericLength = sizeof( DHCPMsg ); /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingAcknowledge; /* Not Using broadcast. */ xDHCPData.xUseBroadcast = pdFALSE; /* Set the transaction ID which will match. */ xDHCPData.ulTransactionId = 0x01ABCDEF; /* Put correct address. */ xDHCPData.ulDHCPServerAddress = DHCPServerAddress; /* Reset the lease time. */ xDHCPData.ulLeaseTime = 0; /* Reset this value so that it can be verified later. */ *ipLOCAL_IP_ADDRESS_POINTER = 0; /* Get a stub. */ FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); /* Release the UDP buffer. */ FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); /* Expect this function to be called since we now have * successfully acquired an IP address. */ vIPNetworkUpCalls_Expect(); /* Then expect the socket to be closed. */ vSocketClose_ExpectAndReturn( &xTestSocket, NULL ); /* Expect ARP to begin. */ vARPSendGratuitous_Expect(); /* Expect the timer to be reloaded. */ vDHCPTimerReload_Expect( configTICK_RATE_HZ * ( FreeRTOS_ntohl( ulLeaseTime ) >> 1 ) ); vDHCPProcess( pdFALSE, eWaitingAcknowledge ); /* DHCP socket should be unallocated */ TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); /* Should now be using leased address. */ TEST_ASSERT_EQUAL( eLeasedAddress, xDHCPData.eDHCPState ); /* Make sure that this is not changed. */ TEST_ASSERT_EQUAL( configTICK_RATE_HZ * ( FreeRTOS_ntohl( ulLeaseTime ) >> 1 ), xDHCPData.ulLeaseTime ); TEST_ASSERT_EQUAL( EP_IPv4_SETTINGS.ulGatewayAddress, ulGateway ); TEST_ASSERT_EQUAL( EP_IPv4_SETTINGS.ulNetMask, ulSubnetMask ); } void test_vDHCPProcess_eWaitingAcknowledge_IPv4ServerIncorrectLength( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* Create a bit longer DHCP message but keep it empty. */ const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U /* Padding */ + 3U /* DHCP offer */ + 6U /* Server IP address */ + 6U /* Subnet Mask */ + 6U /* Gateway */ + 6U /* Lease time */ + 1U /* End */; uint8_t DHCPMsg[ xTotalLength ]; uint32_t DHCPServerAddress = 0xC0A80001; /* 192.168.0.1 */ uint32_t ulClientIPAddress = 0xC0A8000A; /* 192.168.0.10 */ uint32_t ulSubnetMask = 0xFFFFF100; /* 255.255.241.0 */ uint32_t ulGateway = 0xC0A80001; /* 192.168.0.1 */ uint32_t ulLeaseTime = 0x00000096; /* 150 seconds */ DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; DHCPMsg[ xTotalLength - 1U ] = 0xFF; /* Set the header - or at least the start of DHCP message. */ memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); /* Copy the header here. */ memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); /* Make sure that the address matches. */ memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); /* Add the expected cookie. */ pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; /* Set the client IP address. */ pxDHCPMessage->ulYourIPAddress_yiaddr = ulClientIPAddress; /* Leave one byte for the padding. */ uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 1; /* Add the offer byte. */ DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_ACK; DHCPOption += 4; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 4; /* Add the offer byte. */ *( ( uint32_t * ) &DHCPOption[ 2 ] ) = DHCPServerAddress; DHCPOption += 6; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 3; /* Add the offer byte. */ *( ( uint32_t * ) &DHCPOption[ 2 ] ) = DHCPServerAddress; /* Put the information in global variables to be returned by * the FreeRTOS_recvrom. */ ucGenericPtr = DHCPMsg; ulGenericLength = sizeof( DHCPMsg ); /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingAcknowledge; /* Not Using broadcast. */ xDHCPData.xUseBroadcast = pdFALSE; /* Set the transaction ID which will match. */ xDHCPData.ulTransactionId = 0x01ABCDEF; /* Put correct address. */ xDHCPData.ulDHCPServerAddress = DHCPServerAddress; /* Reset the lease time. */ xDHCPData.ulLeaseTime = 0; /* Reset this value so that it can be verified later. */ *ipLOCAL_IP_ADDRESS_POINTER = 0; /* Get a stub. */ FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); /* Release the UDP buffer. */ FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); /* Expect this function to be called since we now have * successfully acquired an IP address. */ vIPNetworkUpCalls_Expect(); /* Then expect the socket to be closed. */ vSocketClose_ExpectAndReturn( &xTestSocket, NULL ); /* Expect ARP to begin. */ vARPSendGratuitous_Expect(); /* Expect the timer to be reloaded. */ vDHCPTimerReload_Ignore(); vDHCPProcess( pdFALSE, eWaitingAcknowledge ); /* DHCP socket should be unallocated */ TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); /* Should now be using leased address. */ TEST_ASSERT_EQUAL( eLeasedAddress, xDHCPData.eDHCPState ); /* Make sure that this is not changed. */ TEST_ASSERT_EQUAL( dhcpDEFAULT_LEASE_TIME, xDHCPData.ulLeaseTime ); } void test_vDHCPProcess_eWaitingAcknowledge_SubnetMaskIncorrectLength( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* Create a bit longer DHCP message but keep it empty. */ const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U /* Padding */ + 3U /* DHCP offer */ + 6U /* Server IP address */ + 6U /* Subnet Mask */ + 6U /* Gateway */ + 6U /* Lease time */ + 1U /* End */; uint8_t DHCPMsg[ xTotalLength ]; uint32_t DHCPServerAddress = 0xC0A80001; /* 192.168.0.1 */ uint32_t ulClientIPAddress = 0xC0A8000A; /* 192.168.0.10 */ uint32_t ulSubnetMask = 0xFFFFF100; /* 255.255.241.0 */ uint32_t ulGateway = 0xC0A80001; /* 192.168.0.1 */ uint32_t ulLeaseTime = 0x00000096; /* 150 seconds */ DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; DHCPMsg[ xTotalLength - 1U ] = 0xFF; /* Set the header - or at least the start of DHCP message. */ memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); /* Copy the header here. */ memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); /* Make sure that the address matches. */ memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); /* Add the expected cookie. */ pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; /* Set the client IP address. */ pxDHCPMessage->ulYourIPAddress_yiaddr = ulClientIPAddress; /* Leave one byte for the padding. */ uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 1; /* Add the offer byte. */ DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_ACK; DHCPOption += 4; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 4; /* Add the offer byte. */ *( ( uint32_t * ) &DHCPOption[ 2 ] ) = DHCPServerAddress; DHCPOption += 6; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_SUBNET_MASK_OPTION_CODE; /* Add incorrect length. */ DHCPOption[ 1 ] = 3; /* Add the offer byte. */ *( ( uint32_t * ) &DHCPOption[ 2 ] ) = ulSubnetMask; /* Put the information in global variables to be returned by * the FreeRTOS_recvrom. */ ucGenericPtr = DHCPMsg; ulGenericLength = sizeof( DHCPMsg ); /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingAcknowledge; /* Not Using broadcast. */ xDHCPData.xUseBroadcast = pdFALSE; /* Set the transaction ID which will match. */ xDHCPData.ulTransactionId = 0x01ABCDEF; /* Put correct address. */ xDHCPData.ulDHCPServerAddress = DHCPServerAddress; /* Reset the lease time. */ xDHCPData.ulLeaseTime = 0; /* Reset this value so that it can be verified later. */ *ipLOCAL_IP_ADDRESS_POINTER = 0; /* Get a stub. */ FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); /* Release the UDP buffer. */ FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); /* Expect this function to be called since we now have * successfully acquired an IP address. */ vIPNetworkUpCalls_Expect(); /* Then expect the socket to be closed. */ vSocketClose_ExpectAndReturn( &xTestSocket, NULL ); /* Expect ARP to begin. */ vARPSendGratuitous_Expect(); /* Expect the timer to be reloaded. */ vDHCPTimerReload_Ignore(); vDHCPProcess( pdFALSE, eWaitingAcknowledge ); /* DHCP socket should be unallocated */ TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); /* Should now be using leased address. */ TEST_ASSERT_EQUAL( eLeasedAddress, xDHCPData.eDHCPState ); /* Make sure that this is not changed. */ TEST_ASSERT_EQUAL( dhcpDEFAULT_LEASE_TIME, xDHCPData.ulLeaseTime ); } void test_vDHCPProcess_eWaitingAcknowledge_GatewayIncorrectLength( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* Create a bit longer DHCP message but keep it empty. */ const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U /* Padding */ + 3U /* DHCP offer */ + 6U /* Server IP address */ + 6U /* Subnet Mask */ + 6U /* Gateway */ + 6U /* Lease time */ + 1U /* End */; uint8_t DHCPMsg[ xTotalLength ]; uint32_t DHCPServerAddress = 0xC0A80001; /* 192.168.0.1 */ uint32_t ulClientIPAddress = 0xC0A8000A; /* 192.168.0.10 */ uint32_t ulSubnetMask = 0xFFFFF100; /* 255.255.241.0 */ uint32_t ulGateway = 0xC0A80001; /* 192.168.0.1 */ uint32_t ulLeaseTime = 0x00000096; /* 150 seconds */ DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; DHCPMsg[ xTotalLength - 1U ] = 0xFF; /* Set the header - or at least the start of DHCP message. */ memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); /* Copy the header here. */ memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); /* Make sure that the address matches. */ memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); /* Add the expected cookie. */ pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; /* Set the client IP address. */ pxDHCPMessage->ulYourIPAddress_yiaddr = ulClientIPAddress; /* Leave one byte for the padding. */ uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 1; /* Add the offer byte. */ DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_ACK; DHCPOption += 4; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 4; /* Add the offer byte. */ *( ( uint32_t * ) &DHCPOption[ 2 ] ) = DHCPServerAddress; DHCPOption += 6; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_SUBNET_MASK_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 4; /* Add the offer byte. */ *( ( uint32_t * ) &DHCPOption[ 2 ] ) = ulSubnetMask; DHCPOption += 6; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_GATEWAY_OPTION_CODE; /* Add incorrect length. */ DHCPOption[ 1 ] = 2; /* Add the offer byte. */ *( ( uint32_t * ) &DHCPOption[ 2 ] ) = ulGateway; /* Put the information in global variables to be returned by * the FreeRTOS_recvrom. */ ucGenericPtr = DHCPMsg; ulGenericLength = sizeof( DHCPMsg ); /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingAcknowledge; /* Not Using broadcast. */ xDHCPData.xUseBroadcast = pdFALSE; /* Set the transaction ID which will match. */ xDHCPData.ulTransactionId = 0x01ABCDEF; /* Put correct address. */ xDHCPData.ulDHCPServerAddress = DHCPServerAddress; /* Reset the lease time. */ xDHCPData.ulLeaseTime = 0; /* Reset this value so that it can be verified later. */ *ipLOCAL_IP_ADDRESS_POINTER = 0; /* Get a stub. */ FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); /* Release the UDP buffer. */ FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); /* Expect this function to be called since we now have * successfully acquired an IP address. */ vIPNetworkUpCalls_Expect(); /* Then expect the socket to be closed. */ vSocketClose_ExpectAndReturn( &xTestSocket, NULL ); /* Expect ARP to begin. */ vARPSendGratuitous_Expect(); /* Expect the timer to be reloaded. */ vDHCPTimerReload_Ignore(); vDHCPProcess( pdFALSE, eWaitingAcknowledge ); /* DHCP socket should be unallocated */ TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); /* Should now be using leased address. */ TEST_ASSERT_EQUAL( eLeasedAddress, xDHCPData.eDHCPState ); /* Make sure that this is not changed. */ TEST_ASSERT_EQUAL( dhcpDEFAULT_LEASE_TIME, xDHCPData.ulLeaseTime ); } void test_vDHCPProcess_eWaitingAcknowledge_LeaseTimeIncorrectLength( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* Create a bit longer DHCP message but keep it empty. */ const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 1U /* Padding */ + 3U /* DHCP offer */ + 6U /* Server IP address */ + 6U /* Subnet Mask */ + 6U /* Gateway */ + 6U /* Lease time */ + 1U /* End */; uint8_t DHCPMsg[ xTotalLength ]; uint32_t DHCPServerAddress = 0xC0A80001; /* 192.168.0.1 */ uint32_t ulClientIPAddress = 0xC0A8000A; /* 192.168.0.10 */ uint32_t ulSubnetMask = 0xFFFFF100; /* 255.255.241.0 */ uint32_t ulGateway = 0xC0A80001; /* 192.168.0.1 */ uint32_t ulLeaseTime = 0x00000096; /* 150 seconds */ DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; DHCPMsg[ xTotalLength - 1U ] = 0xFF; /* Set the header - or at least the start of DHCP message. */ memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); /* Copy the header here. */ memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); /* Make sure that the address matches. */ memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); /* Add the expected cookie. */ pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; /* Set the client IP address. */ pxDHCPMessage->ulYourIPAddress_yiaddr = ulClientIPAddress; /* Leave one byte for the padding. */ uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) + 1 ]; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 1; /* Add the offer byte. */ DHCPOption[ 2 ] = dhcpMESSAGE_TYPE_ACK; DHCPOption += 4; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_SERVER_IP_ADDRESS_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 4; /* Add the offer byte. */ *( ( uint32_t * ) &DHCPOption[ 2 ] ) = DHCPServerAddress; DHCPOption += 6; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_SUBNET_MASK_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 4; /* Add the offer byte. */ *( ( uint32_t * ) &DHCPOption[ 2 ] ) = ulSubnetMask; DHCPOption += 6; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_GATEWAY_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 4; /* Add the offer byte. */ *( ( uint32_t * ) &DHCPOption[ 2 ] ) = ulGateway; DHCPOption += 6; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_LEASE_TIME_OPTION_CODE; /* Add incorrect length. */ DHCPOption[ 1 ] = 3; /* Add the offer byte. */ *( ( uint32_t * ) &DHCPOption[ 2 ] ) = ulLeaseTime; /* Put the information in global variables to be returned by * the FreeRTOS_recvrom. */ ucGenericPtr = DHCPMsg; ulGenericLength = sizeof( DHCPMsg ); /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingAcknowledge; /* Not Using broadcast. */ xDHCPData.xUseBroadcast = pdFALSE; /* Set the transaction ID which will match. */ xDHCPData.ulTransactionId = 0x01ABCDEF; /* Put correct address. */ xDHCPData.ulDHCPServerAddress = DHCPServerAddress; /* Reset the lease time. */ xDHCPData.ulLeaseTime = 0; /* Reset this value so that it can be verified later. */ *ipLOCAL_IP_ADDRESS_POINTER = 0; /* Get a stub. */ FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); /* Release the UDP buffer. */ FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); /* Expect this function to be called since we now have * successfully acquired an IP address. */ vIPNetworkUpCalls_Expect(); /* Then expect the socket to be closed. */ vSocketClose_ExpectAndReturn( &xTestSocket, NULL ); /* Expect ARP to begin. */ vARPSendGratuitous_Expect(); /* Expect the timer to be reloaded. */ vDHCPTimerReload_Ignore(); vDHCPProcess( pdFALSE, eWaitingAcknowledge ); /* DHCP socket should be unallocated */ TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); /* Should now be using leased address. */ TEST_ASSERT_EQUAL( eLeasedAddress, xDHCPData.eDHCPState ); /* Make sure that this is not changed. */ TEST_ASSERT_EQUAL( dhcpDEFAULT_LEASE_TIME, xDHCPData.ulLeaseTime ); } void test_vDHCPProcess_eWaitingAcknowledge_IncorrectLengthofpacket( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; /* Create a bit longer DHCP message but keep it empty. */ const BaseType_t xTotalLength = sizeof( struct xDHCPMessage_IPv4 ) + 2U; uint8_t DHCPMsg[ xTotalLength ]; uint32_t DHCPServerAddress = 0xC0A80001; /* 192.168.0.1 */ uint32_t ulClientIPAddress = 0xC0A8000A; /* 192.168.0.10 */ uint32_t ulSubnetMask = 0xFFFFF100; /* 255.255.241.0 */ uint32_t ulGateway = 0xC0A80001; /* 192.168.0.1 */ uint32_t ulLeaseTime = 0x00000096; /* 150 seconds */ DHCPMessage_IPv4_t * pxDHCPMessage = ( DHCPMessage_IPv4_t * ) DHCPMsg; DHCPMsg[ xTotalLength - 1U ] = 0xFF; /* Set the header - or at least the start of DHCP message. */ memset( DHCPMsg, 0, sizeof( DHCPMsg ) ); /* Copy the header here. */ memcpy( DHCPMsg, DHCP_header, sizeof( DHCP_header ) ); /* Make sure that the address matches. */ memcpy( pxDHCPMessage->ucClientHardwareAddress, ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) ); /* Add the expected cookie. */ pxDHCPMessage->ulDHCPCookie = dhcpCOOKIE; /* Set the client IP address. */ pxDHCPMessage->ulYourIPAddress_yiaddr = ulClientIPAddress; /* Get pointer to the end. */ uint8_t * DHCPOption = &DHCPMsg[ sizeof( struct xDHCPMessage_IPv4 ) ]; /* Add Message type code. */ DHCPOption[ 0 ] = dhcpIPv4_MESSAGE_TYPE_OPTION_CODE; /* Add length. */ DHCPOption[ 1 ] = 0; /* Put the information in global variables to be returned by * the FreeRTOS_recvrom. */ ucGenericPtr = DHCPMsg; ulGenericLength = sizeof( DHCPMsg ); /* This should remain unchanged. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eWaitingAcknowledge; /* Not Using broadcast. */ xDHCPData.xUseBroadcast = pdFALSE; /* Set the transaction ID which will match. */ xDHCPData.ulTransactionId = 0x01ABCDEF; /* Put correct address. */ xDHCPData.ulDHCPServerAddress = DHCPServerAddress; /* Reset the lease time. */ xDHCPData.ulLeaseTime = 0; /* Put some time values. */ xDHCPData.xDHCPTxTime = 100; /* Make sure that we don't exceed the period - and thus, don't give up. */ xDHCPData.xDHCPTxPeriod = 100; /* Reset this value so that it can be verified later. */ *ipLOCAL_IP_ADDRESS_POINTER = 0; /* Get a stub. */ FreeRTOS_recvfrom_Stub( FreeRTOS_recvfrom_Generic ); /* Release the UDP buffer. */ FreeRTOS_ReleaseUDPPayloadBuffer_Expect( DHCPMsg ); /* Make sure that there is no timeout. The expression is: xTaskGetTickCount() - EP_DHCPData.xDHCPTxTime ) > EP_DHCPData.xDHCPTxPeriod */ /* Return a value which makes the difference just equal to the period. */ xTaskGetTickCount_ExpectAndReturn( xDHCPData.xDHCPTxTime + xDHCPData.xDHCPTxPeriod + 100 ); /* Return time second time which can be verified. */ xTaskGetTickCount_ExpectAndReturn( xTimeValue ); /* Get the hostname. */ pcApplicationHostnameHook_ExpectAndReturn( pcHostName ); /* Returning a proper network buffer. */ pxGetNetworkBufferWithDescriptor_Stub( GetNetworkBuffer ); /* Send succeeds. */ FreeRTOS_sendto_ExpectAnyArgsAndReturn( 1 ); vDHCPProcess( pdFALSE, eWaitingAcknowledge ); /* DHCP socket should be allocated */ TEST_ASSERT_EQUAL( &xTestSocket, xDHCPSocket ); /* Should still be stuck in waiting for ack state. */ TEST_ASSERT_EQUAL( eWaitingAcknowledge, xDHCPData.eDHCPState ); } void test_vDHCPProcess_eGetLinkLayerAddress_Timeout_NoARPIPClash( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; EP_DHCPData.xDHCPTxTime = 100; EP_DHCPData.xDHCPTxPeriod = 100; /* Put the required state. */ xDHCPData.eDHCPState = eGetLinkLayerAddress; xARPHadIPClash = pdFALSE; xTaskGetTickCount_ExpectAndReturn( EP_DHCPData.xDHCPTxPeriod + EP_DHCPData.xDHCPTxTime + 100 ); vIPNetworkUpCalls_Expect(); vDHCPProcess( pdFALSE, eGetLinkLayerAddress ); TEST_ASSERT_EQUAL( eNotUsingLeasedAddress, EP_DHCPData.eDHCPState ); } void test_vDHCPProcess_eGetLinkLayerAddress_Timeout_ARPIPClash( void ) { struct xSOCKET xTestSocket; TickType_t xTimeValue = 1234; EP_DHCPData.xDHCPTxTime = 100; EP_DHCPData.xDHCPTxPeriod = 100; /* Put the required state. */ xDHCPData.eDHCPState = eGetLinkLayerAddress; /* This should be nullified. */ xDHCPSocket = &xTestSocket; xARPHadIPClash = pdTRUE; xTaskGetTickCount_ExpectAndReturn( EP_DHCPData.xDHCPTxPeriod + EP_DHCPData.xDHCPTxTime + 100 ); xTaskGetTickCount_ExpectAndReturn( xTimeValue ); xApplicationGetRandomNumber_ExpectAnyArgsAndReturn( pdTRUE ); xApplicationGetRandomNumber_ExpectAnyArgsAndReturn( pdTRUE ); /* Then expect the socket to be closed. */ vSocketClose_ExpectAndReturn( &xTestSocket, NULL ); xApplicationGetRandomNumber_ExpectAnyArgsAndReturn( pdTRUE ); vARPSendGratuitous_Expect(); vDHCPProcess( pdFALSE, eGetLinkLayerAddress ); TEST_ASSERT_EQUAL( eGetLinkLayerAddress, EP_DHCPData.eDHCPState ); TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); } void test_vDHCPProcess_eGetLinkLayerAddress_NoTimeout( void ) { EP_DHCPData.xDHCPTxTime = 100; EP_DHCPData.xDHCPTxPeriod = 100; /* Put the required state. */ xDHCPData.eDHCPState = eGetLinkLayerAddress; xARPHadIPClash = pdTRUE; /* Make it so that there is no timeout. */ xTaskGetTickCount_ExpectAndReturn( EP_DHCPData.xDHCPTxPeriod + EP_DHCPData.xDHCPTxTime ); vDHCPProcess( pdFALSE, eGetLinkLayerAddress ); TEST_ASSERT_EQUAL( eGetLinkLayerAddress, EP_DHCPData.eDHCPState ); } void test_vDHCPProcess_eLeasedAddress_NetworkDown( void ) { /* Put the required state. */ xDHCPData.eDHCPState = eLeasedAddress; /* The network is not up. */ FreeRTOS_IsNetworkUp_ExpectAndReturn( 0 ); /* Expect the DHCP timer to be reloaded. */ vDHCPTimerReload_Expect( pdMS_TO_TICKS( 5000U ) ); vDHCPProcess( pdFALSE, eLeasedAddress ); /* Still in this phase. */ TEST_ASSERT_EQUAL( eLeasedAddress, EP_DHCPData.eDHCPState ); } void test_vDHCPProcess_eLeasedAddress_NetworkUp_SokcetCreated_RNGPass_GNBfail( void ) { struct xSOCKET xTestSocket; BaseType_t xTimeValue = 300; /* Socket is already created. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eLeasedAddress; /* The network is up. */ FreeRTOS_IsNetworkUp_ExpectAndReturn( 1 ); xApplicationGetRandomNumber_ExpectAnyArgsAndReturn( pdTRUE ); xTaskGetTickCount_ExpectAndReturn( xTimeValue ); /* Return the hostname. */ pcApplicationHostnameHook_ExpectAndReturn( pcHostName ); /* Returning NULL will mean the prvSendDHCPDiscover fail. */ pxGetNetworkBufferWithDescriptor_ExpectAnyArgsAndReturn( NULL ); /* Expect the timer to be set. */ vDHCPTimerReload_Expect( dhcpINITIAL_TIMER_PERIOD ); vDHCPProcess( pdFALSE, eLeasedAddress ); /* Need to send DHCP request. */ TEST_ASSERT_EQUAL( eSendDHCPRequest, EP_DHCPData.eDHCPState ); TEST_ASSERT_EQUAL( xTimeValue, EP_DHCPData.xDHCPTxTime ); TEST_ASSERT_EQUAL( dhcpINITIAL_DHCP_TX_PERIOD, EP_DHCPData.xDHCPTxPeriod ); } void test_vDHCPProcess_eLeasedAddress_NetworkUp_SokcetCreated_RNGFail( void ) { struct xSOCKET xTestSocket; BaseType_t xTimeValue = 300; /* Socket is already created. */ xDHCPSocket = &xTestSocket; /* Put the required state. */ xDHCPData.eDHCPState = eLeasedAddress; /* The network is up. */ FreeRTOS_IsNetworkUp_ExpectAndReturn( 1 ); /* Make RNG fail. */ xApplicationGetRandomNumber_ExpectAnyArgsAndReturn( pdFALSE ); xTaskGetTickCount_ExpectAndReturn( xTimeValue ); /* Return the hostname. */ pcApplicationHostnameHook_ExpectAndReturn( pcHostName ); /* Returning a proper network buffer. */ pxGetNetworkBufferWithDescriptor_Stub( GetNetworkBuffer ); /* Make the call to FreeRTOS_send succeed. */ FreeRTOS_sendto_ExpectAnyArgsAndReturn( 1 ); /* Expect the timer to be set. */ vDHCPTimerReload_Expect( dhcpINITIAL_TIMER_PERIOD ); vDHCPProcess( pdFALSE, eLeasedAddress ); /* Sent DHCP request - waiting ACK. */ TEST_ASSERT_EQUAL( eWaitingAcknowledge, EP_DHCPData.eDHCPState ); TEST_ASSERT_EQUAL( xTimeValue, EP_DHCPData.xDHCPTxTime ); TEST_ASSERT_EQUAL( dhcpINITIAL_DHCP_TX_PERIOD, EP_DHCPData.xDHCPTxPeriod ); } void test_vDHCPProcess_eLeasedAddress_NetworkUp_SocketNotCreated_RNGPass_GNBfail( void ) { /* Socket not created. */ xDHCPSocket = NULL; /* Put the required state. */ xDHCPData.eDHCPState = eLeasedAddress; /* The network is up. */ FreeRTOS_IsNetworkUp_ExpectAndReturn( 1 ); /* Return invalid socket. */ FreeRTOS_socket_ExpectAnyArgsAndReturn( FREERTOS_INVALID_SOCKET ); vDHCPProcess( pdFALSE, eLeasedAddress ); /* Still here. */ TEST_ASSERT_EQUAL( eLeasedAddress, EP_DHCPData.eDHCPState ); TEST_ASSERT_EQUAL( NULL, xDHCPSocket ); } void test_vDHCPProcess_eNotUsingLeasedAddress( void ) { /* Put the required state. */ xDHCPData.eDHCPState = eNotUsingLeasedAddress; /* Expect the timer to be disabled. */ vIPSetDHCPTimerEnableState_Expect( pdFALSE ); vDHCPProcess( pdFALSE, eNotUsingLeasedAddress ); /* Continue not using DHCP. */ TEST_ASSERT_EQUAL( eNotUsingLeasedAddress, EP_DHCPData.eDHCPState ); } void test_vDHCPProcess_IncorrectState( void ) { /* Put a non-existent state. */ xDHCPData.eDHCPState = ( eNotUsingLeasedAddress << 1 ); vDHCPProcess( pdFALSE, ( eNotUsingLeasedAddress << 1 ) ); /* Continue not using DHCP. */ TEST_ASSERT_EQUAL( ( eNotUsingLeasedAddress << 1 ), EP_DHCPData.eDHCPState ); }