Skip to content

Commit 0e7795e

Browse files
committed
Fixed edge case and added unit tests
1 parent 400474a commit 0e7795e

File tree

5 files changed

+153
-5
lines changed

5 files changed

+153
-5
lines changed

src/controller/SetUpCodePairer.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -901,12 +901,13 @@ void SetUpCodePairer::OnDeviceDiscoveredTimeoutCallback(System::Layer * layer, v
901901
ChipLogError(Controller, "Discovery timed out");
902902
auto * pairer = static_cast<SetUpCodePairer *>(context);
903903

904-
// If a PASE attempt is in progress, do not stop any discovery — give every
905-
// transport that has started (DNS-SD, BLE, Wi-Fi PAF, NFC) a chance to
906-
// complete, fail, or time out naturally. DNS-SD will be stopped in
907-
// OnPairingComplete once the PASE attempt it triggered completes.
904+
// If a PASE attempt is in progress, do not stop physical-proximity
905+
// transports (BLE, Wi-Fi PAF, NFC) — they have their own completion/timeout
906+
// mechanisms. DNS-SD, however, runs indefinitely, so stop it now to
907+
// prevent DiscoveryInProgress() from being true forever.
908908
if (pairer->mWaitingForPASE)
909909
{
910+
LogErrorOnFailure(pairer->StopDiscoveryOverDNSSD());
910911
return;
911912
}
912913

src/controller/SetUpCodePairer.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,13 @@
5050
#include <vector>
5151

5252
namespace chip {
53+
54+
namespace Testing {
55+
56+
class SetUpCodePairerTestAccess;
57+
58+
} // namespace Testing
59+
5360
namespace Controller {
5461

5562
class DeviceCommissioner;
@@ -98,6 +105,8 @@ class DLL_EXPORT SetUpCodePairer : public DevicePairingDelegate
98105
public Nfc::NFCReaderTransportDelegate
99106
#endif
100107
{
108+
friend class chip::Testing::SetUpCodePairerTestAccess;
109+
101110
public:
102111
SetUpCodePairer(DeviceCommissioner * commissioner) : mCommissioner(commissioner) {}
103112
virtual ~SetUpCodePairer() {}

src/controller/tests/BUILD.gn

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ chip_test_suite("tests") {
5252
test_sources += [
5353
"TestCommissioningWindowOpener.cpp",
5454
"TestExampleOperationalCredentialsIssuer.cpp",
55+
"TestSetUpCodePairer.cpp",
5556
]
5657
}
5758
}
@@ -64,7 +65,10 @@ chip_test_suite("tests") {
6465

6566
cflags = [ "-Wconversion" ]
6667

67-
sources = [ "AutoCommissionerTestAccess.h" ]
68+
sources = [
69+
"AutoCommissionerTestAccess.h",
70+
"SetUpCodePairerTestAccess.h",
71+
]
6872

6973
public_deps = [
7074
"${chip_root}/src/app/common:cluster-objects",
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
*
3+
* Copyright (c) 2025 Project CHIP Authors
4+
* All rights reserved.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
#pragma once
19+
20+
#include <controller/SetUpCodePairer.h>
21+
22+
namespace chip {
23+
namespace Testing {
24+
25+
// Provides access to private members of SetUpCodePairer for testing.
26+
class SetUpCodePairerTestAccess
27+
{
28+
public:
29+
SetUpCodePairerTestAccess() = delete;
30+
explicit SetUpCodePairerTestAccess(Controller::SetUpCodePairer * pairer) : mPairer(pairer) {}
31+
32+
// Re-export private transport type indices for use in tests.
33+
static constexpr int kBLETransport = Controller::SetUpCodePairer::kBLETransport;
34+
static constexpr int kIPTransport = Controller::SetUpCodePairer::kIPTransport;
35+
static constexpr int kWiFiPAFTransport = Controller::SetUpCodePairer::kWiFiPAFTransport;
36+
37+
bool GetWaitingForDiscovery(int transport) const { return mPairer->mWaitingForDiscovery[transport]; }
38+
void SetWaitingForDiscovery(int transport, bool val) { mPairer->mWaitingForDiscovery[transport] = val; }
39+
40+
bool GetWaitingForPASE() const { return mPairer->mWaitingForPASE; }
41+
void SetWaitingForPASE(bool val) { mPairer->mWaitingForPASE = val; }
42+
43+
NodeId GetRemoteId() const { return mPairer->mRemoteId; }
44+
void SetRemoteId(NodeId id) { mPairer->mRemoteId = id; }
45+
46+
void FireTimeoutCallback() { Controller::SetUpCodePairer::OnDeviceDiscoveredTimeoutCallback(nullptr, mPairer); }
47+
48+
private:
49+
Controller::SetUpCodePairer * mPairer = nullptr;
50+
};
51+
52+
} // namespace Testing
53+
} // namespace chip
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*
2+
*
3+
* Copyright (c) 2025 Project CHIP Authors
4+
* All rights reserved.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
#include <gtest/gtest.h>
20+
21+
#include <controller/CHIPDeviceController.h>
22+
#include <controller/SetUpCodePairer.h>
23+
#include <controller/tests/SetUpCodePairerTestAccess.h>
24+
#include <lib/core/CHIPError.h>
25+
26+
using namespace chip;
27+
using namespace chip::Controller;
28+
using PairerAccess = chip::Testing::SetUpCodePairerTestAccess;
29+
30+
namespace {
31+
32+
class TestSetUpCodePairer : public ::testing::Test
33+
{
34+
public:
35+
static void SetUpTestSuite() { ASSERT_EQ(Platform::MemoryInit(), CHIP_NO_ERROR); }
36+
static void TearDownTestSuite() { Platform::MemoryShutdown(); }
37+
38+
protected:
39+
DeviceCommissioner commissioner;
40+
SetUpCodePairer pairer{ &commissioner };
41+
PairerAccess access{ &pairer };
42+
};
43+
44+
// When the discovery timeout fires while a PASE attempt is in progress,
45+
// DNS-SD should be stopped (it runs indefinitely) but other transports
46+
// (BLE, Wi-Fi PAF, NFC) should be left alone since they self-terminate.
47+
TEST_F(TestSetUpCodePairer, TimeoutDuringPASE_StopsDNSSD_PreservesOtherTransports)
48+
{
49+
access.SetRemoteId(1);
50+
access.SetWaitingForPASE(true);
51+
access.SetWaitingForDiscovery(PairerAccess::kIPTransport, true);
52+
access.SetWaitingForDiscovery(PairerAccess::kBLETransport, true);
53+
54+
access.FireTimeoutCallback();
55+
56+
// DNS-SD must be stopped to prevent DiscoveryInProgress() from being stuck true.
57+
EXPECT_FALSE(access.GetWaitingForDiscovery(PairerAccess::kIPTransport));
58+
// BLE must be preserved — it may still discover a commissionee.
59+
EXPECT_TRUE(access.GetWaitingForDiscovery(PairerAccess::kBLETransport));
60+
// PASE state must not be disturbed.
61+
EXPECT_TRUE(access.GetWaitingForPASE());
62+
}
63+
64+
// When the discovery timeout fires with no PASE in progress,
65+
// all transports should be stopped and failure reported.
66+
TEST_F(TestSetUpCodePairer, TimeoutNoPASE_StopsAllTransports)
67+
{
68+
access.SetRemoteId(1);
69+
access.SetWaitingForPASE(false);
70+
access.SetWaitingForDiscovery(PairerAccess::kIPTransport, true);
71+
access.SetWaitingForDiscovery(PairerAccess::kBLETransport, true);
72+
73+
access.FireTimeoutCallback();
74+
75+
EXPECT_FALSE(access.GetWaitingForDiscovery(PairerAccess::kIPTransport));
76+
EXPECT_FALSE(access.GetWaitingForDiscovery(PairerAccess::kBLETransport));
77+
// StopPairingIfTransportsExhausted should have reported failure and cleared mRemoteId.
78+
EXPECT_EQ(access.GetRemoteId(), kUndefinedNodeId);
79+
}
80+
81+
} // namespace

0 commit comments

Comments
 (0)