Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding test to do AddNOC, UpdateNOC, RemoveFabric tests #20327

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 114 additions & 0 deletions src/controller/python/test/test_scripts/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ def FailIfNot(cond, message):
_enabled_tests = []
_disabled_tests = []

_UINT16_MAX = 65535


def SetTestSet(enabled_tests, disabled_tests):
global _enabled_tests, _disabled_tests
Expand Down Expand Up @@ -179,6 +181,10 @@ def __init__(self, nodeid: int, paaTrustStorePath: str, testCommissioner: bool =
self.paaTrustStorePath = paaTrustStorePath
logging.getLogger().setLevel(logging.DEBUG)

async def _GetCommissonedFabricCount(self, nodeid: int):
data = await self.devCtrl.ReadAttribute(nodeid, [(Clusters.OperationalCredentials.Attributes.CommissionedFabrics)])
return data[0][Clusters.OperationalCredentials][Clusters.OperationalCredentials.Attributes.CommissionedFabrics]

def _WaitForOneDiscoveredDevice(self, timeoutSeconds: int = 2):
print("Waiting for device responses...")
strlen = 100
Expand Down Expand Up @@ -357,6 +363,114 @@ def TestFailsafe(self, nodeid: int):
return True
return False

async def TestAddUpdateRemoveFabric(self, nodeid: int):
logger.info("Testing AddNOC, UpdateNOC and RemoveFabric")

self.logger.info("Waiting for attribute read for CommissionedFabrics")
startOfTestFabricCount = await self._GetCommissonedFabricCount(nodeid)

tempFabric = chip.FabricAdmin.FabricAdmin(fabricId=3, fabricIndex=3)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should omit specifying a fabricId and index, and let FabricAdmin automatically pick one.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in #20430

tempDevCtrl = tempFabric.NewController(self.controllerNodeId, self.paaTrustStorePath)

self.logger.info("Setting failsafe on CASE connection")
resp = await self.devCtrl.SendCommand(nodeid, 0, Clusters.GeneralCommissioning.Commands.ArmFailSafe(60), timedRequestTimeoutMs=1000)
if resp.errorCode is not Clusters.GeneralCommissioning.Enums.CommissioningError.kOk:
self.logger.error(
"Incorrect response received from arm failsafe - wanted OK, received {}".format(resp))
return False

csrForAddNOC = await self.devCtrl.SendCommand(nodeid, 0, Clusters.OperationalCredentials.Commands.CSRRequest(CSRNonce=b'1' * 32))

chainForAddNOC = tempDevCtrl.IssueNOCChain(csrForAddNOC, nodeid)
if chainForAddNOC.rcacBytes is None or chainForAddNOC.icacBytes is None or chainForAddNOC.nocBytes is None or chainForAddNOC.ipkBytes is None:
self.logger.error("IssueNOCChain failed to generate valid cert chain for AddNOC")
return False

self.logger.info("Starting AddNOC portion of test")
# TODO error check on the commands below
await self.devCtrl.SendCommand(nodeid, 0, Clusters.OperationalCredentials.Commands.AddTrustedRootCertificate(chainForAddNOC.rcacBytes))
await self.devCtrl.SendCommand(nodeid, 0, Clusters.OperationalCredentials.Commands.AddNOC(chainForAddNOC.nocBytes, chainForAddNOC.icacBytes, chainForAddNOC.ipkBytes, tempDevCtrl.GetNodeId(), 0xFFF1))
await tempDevCtrl.SendCommand(nodeid, 0, Clusters.GeneralCommissioning.Commands.CommissioningComplete())

afterAddNocFabricCount = await self._GetCommissonedFabricCount(nodeid)
if startOfTestFabricCount == afterAddNocFabricCount:
self.logger.error("Expected commissioned fabric count to change after AddNOC")
return False

resp = await tempDevCtrl.ReadAttribute(nodeid, [(Clusters.Basic.Attributes.ClusterRevision)])
clusterRevision = resp[0][Clusters.Basic][Clusters.Basic.Attributes.ClusterRevision]
if not isinstance(clusterRevision, chip.tlv.uint) or clusterRevision < 1 or clusterRevision > _UINT16_MAX:
self.logger.error(
"Failed to read valid cluster revision on newly added fabric {}".format(resp))
return False

self.logger.info("Starting UpdateNOC using same node ID")
resp = await tempDevCtrl.SendCommand(nodeid, 0, Clusters.GeneralCommissioning.Commands.ArmFailSafe(600), timedRequestTimeoutMs=1000)
if resp.errorCode is not Clusters.GeneralCommissioning.Enums.CommissioningError.kOk:
self.logger.error(
"Incorrect response received from arm failsafe - wanted OK, received {}".format(resp))
return False
csrForUpdateNOC = await tempDevCtrl.SendCommand(
nodeid, 0, Clusters.OperationalCredentials.Commands.CSRRequest(CSRNonce=b'1' * 32, isForUpdateNOC=True))
chainForUpdateNOC = tempDevCtrl.IssueNOCChain(csrForUpdateNOC, nodeid)
if chainForUpdateNOC.rcacBytes is None or chainForUpdateNOC.icacBytes is None or chainForUpdateNOC.nocBytes is None or chainForUpdateNOC.ipkBytes is None:
self.logger.error("IssueNOCChain failed to generate valid cert chain for UpdateNOC")
return False

await tempDevCtrl.SendCommand(nodeid, 0, Clusters.OperationalCredentials.Commands.UpdateNOC(chainForUpdateNOC.nocBytes, chainForUpdateNOC.icacBytes))
await tempDevCtrl.SendCommand(nodeid, 0, Clusters.GeneralCommissioning.Commands.CommissioningComplete())
afterUpdateNocFabricCount = await self._GetCommissonedFabricCount(nodeid)
if afterUpdateNocFabricCount != afterAddNocFabricCount:
self.logger.error("Expected commissioned fabric count to remain unchanged after UpdateNOC")
return False

resp = await tempDevCtrl.ReadAttribute(nodeid, [(Clusters.Basic.Attributes.ClusterRevision)])
clusterRevision = resp[0][Clusters.Basic][Clusters.Basic.Attributes.ClusterRevision]
if not isinstance(clusterRevision, chip.tlv.uint) or clusterRevision < 1 or clusterRevision > _UINT16_MAX:
self.logger.error(
"Failed to read valid cluster revision on after UpdateNOC {}".format(resp))
return False

self.logger.info("Starting UpdateNOC using different node ID")
resp = await tempDevCtrl.SendCommand(nodeid, 0, Clusters.GeneralCommissioning.Commands.ArmFailSafe(600), timedRequestTimeoutMs=1000)
if resp.errorCode is not Clusters.GeneralCommissioning.Enums.CommissioningError.kOk:
self.logger.error(
"Incorrect response received from arm failsafe - wanted OK, received {}".format(resp))
return False
csrForUpdateNOC = await tempDevCtrl.SendCommand(
nodeid, 0, Clusters.OperationalCredentials.Commands.CSRRequest(CSRNonce=b'1' * 32, isForUpdateNOC=True))

newNodeIdForUpdateNoc = nodeid + 1
chainForSecondUpdateNOC = tempDevCtrl.IssueNOCChain(csrForUpdateNOC, newNodeIdForUpdateNoc)
if chainForSecondUpdateNOC.rcacBytes is None or chainForSecondUpdateNOC.icacBytes is None or chainForSecondUpdateNOC.nocBytes is None or chainForSecondUpdateNOC.ipkBytes is None:
self.logger.error("IssueNOCChain failed to generate valid cert chain for UpdateNOC with new node ID")
return False
updateNocResponse = await tempDevCtrl.SendCommand(nodeid, 0, Clusters.OperationalCredentials.Commands.UpdateNOC(chainForSecondUpdateNOC.nocBytes, chainForSecondUpdateNOC.icacBytes))
await tempDevCtrl.SendCommand(newNodeIdForUpdateNoc, 0, Clusters.GeneralCommissioning.Commands.CommissioningComplete())
afterUpdateNocWithNewNodeIdFabricCount = await self._GetCommissonedFabricCount(nodeid)
if afterUpdateNocFabricCount != afterUpdateNocWithNewNodeIdFabricCount:
self.logger.error("Expected commissioned fabric count to remain unchanged after UpdateNOC with new node ID")
return False

# TODO Read using old node ID and expect that it fails.
resp = await tempDevCtrl.ReadAttribute(newNodeIdForUpdateNoc, [(Clusters.Basic.Attributes.ClusterRevision)])
clusterRevision = resp[0][Clusters.Basic][Clusters.Basic.Attributes.ClusterRevision]
if not isinstance(clusterRevision, chip.tlv.uint) or clusterRevision < 1 or clusterRevision > _UINT16_MAX:
self.logger.error(
"Failed to read valid cluster revision on after UpdateNOC with new node ID {}".format(resp))
return False

removeFabricResponse = await tempDevCtrl.SendCommand(newNodeIdForUpdateNoc, 0, Clusters.OperationalCredentials.Commands.RemoveFabric(updateNocResponse.fabricIndex))

endOfTestFabricCount = await self._GetCommissonedFabricCount(nodeid)
if endOfTestFabricCount != startOfTestFabricCount:
self.logger.error("Expected fabric count to be the same at the end of test as when it started")
return False

tempDevCtrl.Shutdown()
tempFabric.Shutdown()
return True

async def TestCaseEviction(self, nodeid: int):
self.logger.info("Testing CASE eviction")

Expand Down
3 changes: 3 additions & 0 deletions src/controller/python/test/test_scripts/mobile-device-test.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ def ethernet_commissioning(test: BaseTestHelper, discriminator: int, setup_pin:
nodeid=1))
FailIfNot(ok, "Failed to commission multi-fabric")

FailIfNot(asyncio.run(test.TestAddUpdateRemoveFabric(nodeid=device_nodeid)),
"Failed AddUpdateRemoveFabric test")

logger.info("Testing CASE Eviction")
FailIfNot(asyncio.run(test.TestCaseEviction(device_nodeid)), "Failed TestCaseEviction")

Expand Down