Skip to content

Commit d377679

Browse files
TCP: Make HandleConnCloseTest[46] work reliably on Darwin and related fixes (project-chip#42136)
* TestTCP: Retry with different ports on EADDRINUSE * TestTCP: Make HandleConnCloseTest[46] work reliably on Darwin Wait until after HandleConnectionReceived() is called before closing the client connection, otherwise we can't be sure the connection actually gets accepted at the application level (as opposed to in the kernel) on the server side. Also add some logging to the callbacks, and check that the callbacks are actually being called with the expected handles. Remove some unused test code. * TCPConnect base implementation should not return CHIP_NO_ERROR * Darwin: Detect saLen == 0 from accept() and ignore the connection * TCPTest: Add test for "late" failure (in TCP.DoHandleIncomingConnection) * TCP: Remove the fallback for GetPeerAddress The updated tests show this is no longer needed. I encountered no test failures in 1000 repetitions on either Linux or Darwin. Certain test scenarios have a chance of logging a "Failure accepting incoming connection" error, but these are cases where the client-side socket is being closed as soon as it's connected. Particularly on Darwin this may then cause the GetPeerAddress call to fail (Linux doesn't seem to exhibit this behavior.) * From review: make test macro docs less verbose
1 parent 013e1bb commit d377679

File tree

6 files changed

+195
-141
lines changed

6 files changed

+195
-141
lines changed

src/inet/TCPEndPointImplSockets.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1010,6 +1010,12 @@ CHIP_ERROR TCPEndPointImplSockets::HandleIncomingConnection()
10101010
return CHIP_ERROR_POSIX(errno);
10111011
}
10121012

1013+
#ifdef __APPLE__
1014+
// On Darwin, if the client closes the connection just as it is being accepted, it is
1015+
// possible for accept() to return a socket but saLen is 0. Ignore the connection.
1016+
VerifyOrReturnError(saLen != 0, CHIP_NO_ERROR);
1017+
#endif
1018+
10131019
// If there's no callback available, fail with an error.
10141020
VerifyOrReturnError(OnConnectionReceived != nullptr, CHIP_ERROR_NO_CONNECTION_HANDLER);
10151021

src/lib/support/tests/ExtraPwTestMacros.h

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
* See the License for the specific language governing permissions and
1616
* limitations under the License.
1717
*/
18+
1819
#pragma once
1920

2021
/**
@@ -61,7 +62,6 @@
6162
*
6263
* This macro does not define the body of the test function. It can be used to
6364
* run a single test case which needs to be run against different fixtures.
64-
*
6565
*/
6666
#define TEST_F_FROM_FIXTURE_NO_BODY(test_fixture, test_name) \
6767
TEST_F(test_fixture, test_name) \
@@ -70,33 +70,11 @@
7070
}
7171

7272
/**
73-
* @def EXPECT_SUCCESS(expr)
74-
*
75-
* @brief
76-
* Shorthand for EXPECT_EQ(expr, CHIP_NO_ERROR)
77-
*
78-
* Example usage:
79-
*
80-
* @code
81-
* EXPECT_SUCCESS(channel->SendMsg(msg));
82-
* @endcode
83-
*
84-
* @param[in] expr A scalar expression to be evaluated against CHIP_NO_ERROR.
73+
* Shorthand for EXPECT_EQ(expr, CHIP_NO_ERROR)
8574
*/
8675
#define EXPECT_SUCCESS(expr) EXPECT_EQ((expr), CHIP_NO_ERROR)
8776

8877
/**
89-
* @def EXPECT_SUCCESS(expr)
90-
*
91-
* @brief
92-
* Shorthand for EXPECT_EQ(expr, CHIP_NO_ERROR)
93-
*
94-
* Example usage:
95-
*
96-
* @code
97-
* EXPECT_SUCCESS(channel->SendMsg(msg));
98-
* @endcode
99-
*
100-
* @param[in] expr A scalar expression to be evaluated against CHIP_NO_ERROR.
78+
* Shorthand for ASSERT_EQ(expr, CHIP_NO_ERROR)
10179
*/
102-
#define EXPECT_SUCCESS(expr) EXPECT_EQ((expr), CHIP_NO_ERROR)
80+
#define ASSERT_SUCCESS(expr) ASSERT_EQ((expr), CHIP_NO_ERROR)

src/transport/raw/Base.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,12 @@ class Base
9797

9898
#if INET_CONFIG_ENABLE_TCP_ENDPOINT
9999
/**
100-
* Connect to the specified peer.
100+
* Connect to the specified peer. On success, outPeerConnHandle will be populated with a handle to the connection.
101101
*/
102102
virtual CHIP_ERROR TCPConnect(const PeerAddress & address, Transport::AppTCPConnectionCallbackCtxt * appState,
103-
ActiveTCPConnectionHandle & peerConnState)
103+
ActiveTCPConnectionHandle & outPeerConnHandle)
104104
{
105-
return CHIP_NO_ERROR;
105+
return CHIP_ERROR_INTERNAL;
106106
}
107107
#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT
108108

src/transport/raw/TCP.cpp

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -632,21 +632,19 @@ CHIP_ERROR TCPBase::DoHandleIncomingConnection(const Inet::TCPEndPointHandle & l
632632
const Inet::TCPEndPointHandle & endPoint, const Inet::IPAddress & peerAddress,
633633
uint16_t peerPort)
634634
{
635-
PeerAddress addr;
636-
CHIP_ERROR getPeerError = GetPeerAddress(*endPoint, addr);
637-
// See https://github.com/project-chip/connectedhomeip/issues/41746
638-
// Failures here must be handled carefully so that broken connections
639-
// continue to propagate to failure callbacks to avoid flaky tests
640-
if (getPeerError != CHIP_NO_ERROR)
635+
#if INET_CONFIG_TEST
636+
if (sForceFailureInDoHandleIncomingConnection)
641637
{
642-
ChipLogFailure(getPeerError, Inet, "Failure getting peer info, using fallback");
643-
addr = PeerAddress::TCP(peerAddress, peerPort, Inet::InterfaceId::Null());
638+
return CHIP_ERROR_INTERNAL;
644639
}
640+
#endif
641+
642+
// GetPeerAddress may fail if the client has already closed the connection, just drop it.
643+
PeerAddress addr;
644+
ReturnErrorOnFailure(GetPeerAddress(*endPoint, addr));
645+
645646
ActiveTCPConnectionState * activeConnection = AllocateConnection(endPoint, addr);
646-
if (activeConnection == nullptr)
647-
{
648-
return CHIP_ERROR_TOO_MANY_CONNECTIONS;
649-
}
647+
VerifyOrReturnError(activeConnection != nullptr, CHIP_ERROR_TOO_MANY_CONNECTIONS);
650648

651649
auto connectionCleanup = ScopeExit([&]() { activeConnection->Free(); });
652650

@@ -741,5 +739,9 @@ void TCPBase::InitEndpoint(const Inet::TCPEndPointHandle & endpoint)
741739
endpoint->SetConnectTimeout(mConnectTimeout);
742740
}
743741

742+
#if INET_CONFIG_TEST
743+
bool TCPBase::sForceFailureInDoHandleIncomingConnection = false;
744+
#endif
745+
744746
} // namespace Transport
745747
} // namespace chip

src/transport/raw/TCP.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,10 @@ class DLL_EXPORT TCPBase : public Base
202202
*/
203203
void CloseActiveConnections();
204204

205+
#if INET_CONFIG_TEST
206+
static bool sForceFailureInDoHandleIncomingConnection;
207+
#endif
208+
205209
private:
206210
// Allow tests to access private members.
207211
template <size_t kActiveConnectionsSize, size_t kPendingPacketSize>

0 commit comments

Comments
 (0)