1
+ #
2
+ # Copyright (c) 2024 Project CHIP Authors
3
+ # All rights reserved.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ # See https://github.com/project-chip/connectedhomeip/blob/master/docs/testing/python.md#defining-the-ci-test-arguments
19
+ # for details about the block below.
20
+ #
21
+ # TODO: Skip CI for now, we don't have any way to run this. Needs setup. See test_TC_CCTRL.py
22
+
23
+ import ipaddress
24
+ import logging
25
+ import os
26
+ import signal
27
+ import subprocess
28
+ import uuid
29
+ import random
30
+ import pathlib
31
+ import time
32
+
33
+ import chip .clusters as Clusters
34
+ import chip .exceptions
35
+ from matter_testing_support import MatterBaseTest , default_matter_test_main , per_endpoint_test , has_cluster , async_test_body
36
+ from mobly import asserts
37
+ from chip .interaction_model import InteractionModelError , Status
38
+
39
+ # isort: off
40
+
41
+ from chip import ChipDeviceCtrl # Needed before chip.FabricAdmin
42
+ import chip .CertificateAuthority
43
+ from chip .ChipDeviceCtrl import CommissioningParameters
44
+
45
+ # isort: on
46
+
47
+
48
+ class TC_CCTRL (MatterBaseTest ):
49
+
50
+ @async_test_body
51
+ async def setup_class (self ):
52
+ super ().setup_class ()
53
+ # TODO: This needs to come from an arg and needs to be something available on the TH
54
+ # TODO: confirm whether we can open processes like this on the TH
55
+ app = os .path .join (pathlib .Path (__file__ ).resolve ().parent , '..' ,'..' ,'out' , 'linux-x64-all-clusters-no-ble' , 'chip-all-clusters-app' )
56
+
57
+ self .kvs = f'kvs_{ str (uuid .uuid4 ())} '
58
+ self .port = 5543
59
+ discriminator = random .randint (0 , 4095 )
60
+ discriminator = 3840
61
+ passcode = 20202021
62
+ app_args = f'--secured-device-port { self .port } --discriminator { discriminator } --passcode { passcode } --KVS { self .kvs } '
63
+ cmd = f'{ app } { app_args } '
64
+ # TODO: Determine if we want these logs cooked or pushed to somewhere else
65
+ logging .info ("Starting TH_SERVER" )
66
+ self .app_process = subprocess .Popen (cmd , bufsize = 0 , shell = True )
67
+ logging .info ("TH_SERVER started" )
68
+ time .sleep (3 )
69
+
70
+ logging .info ("Commissioning from separate fabric" )
71
+
72
+
73
+ # Create a second controller on a new fabric to communicate to the server
74
+ new_certificate_authority = self .certificate_authority_manager .NewCertificateAuthority ()
75
+ new_fabric_admin = new_certificate_authority .NewFabricAdmin (vendorId = 0xFFF1 , fabricId = 2 )
76
+ paa_path = str (self .matter_test_config .paa_trust_store_path )
77
+ print (f"paa_path = { paa_path } ------------------------------------------------" )
78
+ self .TH_server_controller = new_fabric_admin .NewController (nodeId = 112233 , paaTrustStorePath = paa_path )
79
+ self .server_nodeid = 1111
80
+ await self .TH_server_controller .CommissionOnNetwork (nodeId = self .server_nodeid , setupPinCode = passcode , filterType = ChipDeviceCtrl .DiscoveryFilterType .LONG_DISCRIMINATOR , filter = discriminator )
81
+ logging .info ("Commissioning TH_SERVER complete" )
82
+
83
+ def teardown_class (self ):
84
+ logging .warning ("Stopping app with SIGTERM" )
85
+ self .app_process .send_signal (signal .SIGTERM .value )
86
+ test_app_exit_code = self .app_process .wait ()
87
+ # TODO: Use timeout, if term doesn't work, try SIGINT
88
+
89
+ os .remove (self .kvs )
90
+ super ().teardown_class ()
91
+
92
+
93
+ #@per_endpoint_test(has_cluster(Clusters.CommissionerControl))
94
+ @async_test_body
95
+ async def test_TC_CCTRL_3_1 (self ):
96
+ th_server_fabrics = await self .read_single_attribute_check_success (cluster = Clusters .OperationalCredentials , attribute = Clusters .OperationalCredentials .Attributes .Fabrics , dev_ctrl = self .TH_server_controller , node_id = self .server_nodeid , endpoint = 0 )
97
+ th_server_vid = await self .read_single_attribute_check_success (cluster = Clusters .BasicInformation , attribute = Clusters .BasicInformation .Attributes .VendorID , dev_ctrl = self .TH_server_controller , node_id = self .server_nodeid , endpoint = 0 )
98
+ th_server_pid = await self .read_single_attribute_check_success (cluster = Clusters .BasicInformation , attribute = Clusters .BasicInformation .Attributes .ProductID , dev_ctrl = self .TH_server_controller , node_id = self .server_nodeid , endpoint = 0 )
99
+
100
+ # TODO: Read event, not yet implemented in mock
101
+
102
+ ipaddr = ipaddress .IPv6Address ('::1' )
103
+ cmd = Clusters .CommissionerControl .Commands .CommissionNode (requestId = 1 , responseTimeoutSeconds = 30 , ipAddress = ipaddr .packed , port = self .port )
104
+ try :
105
+ await self .send_single_cmd (cmd )
106
+ asserts .fail ("Unexpected success on CommissionNode" )
107
+ except InteractionModelError as e :
108
+ asserts .assert_equal (e .status , Status .Failure , "Incorrect error returned" )
109
+
110
+ params = await self .openCommissioningWindow (dev_ctrl = self .default_controller , node_id = self .dut_node_id )
111
+
112
+ pase_nodeid = self .dut_node_id + 1
113
+ await self .default_controller .FindOrEstablishPASESession (setupCode = params .commissioningParameters .setupQRCode , nodeid = pase_nodeid )
114
+ try :
115
+ await self .send_single_cmd (cmd = cmd , node_id = pase_nodeid )
116
+ asserts .fail ("Unexpected success on CommissionNode" )
117
+ except InteractionModelError as e :
118
+ asserts .assert_equal (e .status , Status .UnsupportedAccess , "Incorrect error returned" )
119
+
120
+ good_request_id = 0x1234567887654321
121
+ cmd = Clusters .CommissionerControl .Commands .RequestCommissioningApproval (requestId = good_request_id , vendorId = th_server_vid , productId = th_server_pid )
122
+ try :
123
+ await self .send_single_cmd (cmd = cmd , node_id = pase_nodeid )
124
+ asserts .fail ("Unexpected success on CommissionNode" )
125
+ except InteractionModelError as e :
126
+ asserts .assert_equal (e .status , Status .UnsupportedAccess , "Incorrect error returned" )
127
+
128
+
129
+ # TODO: read event - need to implement in the mock
130
+
131
+ # If no exception is raised, this is success
132
+ await self .send_single_cmd (cmd )
133
+
134
+ if __name__ == "__main__" :
135
+ default_matter_test_main ()
0 commit comments