[tests] support testing commissioning (#3441)

Add support for testing commissioning process, including:

1. Add DTLS, Thread Discovery and commissioning messages(JOIN_FIN.req etc) parsing;
2. Support parsing log from UART response, and construct decrypted messages;
3. Common commands for commissioning related verification;
This commit is contained in:
wgtdkp
2019-02-26 15:49:57 -08:00
committed by Jonathan Hui
parent cc37bd1dfb
commit dc947f0152
13 changed files with 1420 additions and 47 deletions
+64 -12
View File
@@ -45,6 +45,8 @@ class otCli:
self.verbose = int(float(os.getenv('VERBOSE', 0)))
self.node_type = os.getenv('NODE_TYPE', 'sim')
self.simulator = simulator
if self.simulator:
self.simulator.add_node(self)
mode = os.environ.get('USE_MTD') is '1' and is_mtd and 'mtd' or 'ftd'
@@ -152,6 +154,56 @@ class otCli:
self.pexpect.expect(pexpect.EOF)
self.pexpect = None
def read_cert_messages_in_commissioning_log(self, timeout=-1):
"""Get the log of the traffic after DTLS handshake.
"""
format_str = br"=+?\[\[THCI\].*?type=%s.*?\].*?=+?[\s\S]+?-{40,}"
join_fin_req = format_str % br"JOIN_FIN\.req"
join_fin_rsp = format_str % br"JOIN_FIN\.rsp"
dummy_format_str = br"\[THCI\].*?type=%s.*?"
join_ent_ntf = dummy_format_str % br"JOIN_ENT\.ntf"
join_ent_rsp = dummy_format_str % br"JOIN_ENT\.rsp"
pattern = (b"(" + join_fin_req + b")|(" + join_fin_rsp + b")|("+ join_ent_ntf + b")|(" + join_ent_rsp + b")")
messages = []
# There are at most 4 cert messages both for joiner and commissioner
for _ in range(0, 4):
try:
self._expect(pattern, timeout=timeout)
log = self.pexpect.match.group(0)
messages.append(self._extract_cert_message(log))
except:
break
return messages
def _extract_cert_message(self, log):
res = re.search(br"direction=\w+", log)
assert res
direction = res.group(0).split(b'=')[1].strip()
res = re.search(br"type=\S+", log)
assert res
type = res.group(0).split(b'=')[1].strip()
payload = bytearray([])
payload_len = 0
if type in [b"JOIN_FIN.req", b"JOIN_FIN.rsp"]:
res = re.search(br"len=\d+", log)
assert res
payload_len = int(res.group(0).split(b'=')[1].strip())
hex_pattern = br"\|(\s([0-9a-fA-F]{2}|\.\.))+?\s+?\|"
while True:
res = re.search(hex_pattern, log)
if not res:
break
data = [int(hex, 16) for hex in res.group(0)[1:-1].split(b' ') if hex and hex != b'..']
payload += bytearray(data)
log = log[res.end()-1:]
assert len(payload) == payload_len
return (direction, type, payload)
def send_command(self, cmd, go=True):
print("%d: %s" % (self.nodeid, cmd))
self.pexpect.send(cmd + '\n')
@@ -164,7 +216,7 @@ class otCli:
self._expect('Commands:')
commands = []
while True:
i = self._expect(['Done', '(\S+)'])
i = self._expect(['Done', r'(\S+)'])
if i != 0:
commands.append(self.pexpect.match.groups()[0])
else:
@@ -280,7 +332,7 @@ class otCli:
def get_channel(self):
self.send_command('channel')
i = self._expect('(\d+)\r?\n')
i = self._expect(r'(\d+)\r?\n')
if i == 0:
channel = int(self.pexpect.match.groups()[0])
self._expect('Done')
@@ -306,7 +358,7 @@ class otCli:
def get_key_sequence_counter(self):
self.send_command('keysequence counter')
i = self._expect('(\d+)\r?\n')
i = self._expect(r'(\d+)\r?\n')
if i == 0:
key_sequence_counter = int(self.pexpect.match.groups()[0])
self._expect('Done')
@@ -330,7 +382,7 @@ class otCli:
def get_network_name(self):
self.send_command('networkname')
while True:
i = self._expect(['Done', '(\S+)'])
i = self._expect(['Done', r'(\S+)'])
if i != 0:
network_name = self.pexpect.match.groups()[0].decode('utf-8')
else:
@@ -357,7 +409,7 @@ class otCli:
def get_partition_id(self):
self.send_command('leaderpartitionid')
i = self._expect('(\d+)\r?\n')
i = self._expect(r'(\d+)\r?\n')
if i == 0:
weight = self.pexpect.match.groups()[0]
self._expect('Done')
@@ -397,7 +449,7 @@ class otCli:
def get_timeout(self):
self.send_command('childtimeout')
i = self._expect('(\d+)\r?\n')
i = self._expect(r'(\d+)\r?\n')
if i == 0:
timeout = self.pexpect.match.groups()[0]
self._expect('Done')
@@ -415,7 +467,7 @@ class otCli:
def get_weight(self):
self.send_command('leaderweight')
i = self._expect('(\d+)\r?\n')
i = self._expect(r'(\d+)\r?\n')
if i == 0:
weight = self.pexpect.match.groups()[0]
self._expect('Done')
@@ -436,7 +488,7 @@ class otCli:
self.send_command('ipaddr')
while True:
i = self._expect(['(\S+(:\S*)+)\r?\n', 'Done'])
i = self._expect([r'(\S+(:\S*)+)\r?\n', 'Done'])
if i == 0:
addrs.append(self.pexpect.match.groups()[0].decode("utf-8"))
elif i == 1:
@@ -464,7 +516,7 @@ class otCli:
self.send_command('eidcache')
while True:
i = self._expect(['([a-fA-F0-9\:]+) ([a-fA-F0-9]+)\r?\n', 'Done'])
i = self._expect([r'([a-fA-F0-9\:]+) ([a-fA-F0-9]+)\r?\n', 'Done'])
if i == 0:
eid = self.pexpect.match.groups()[0].decode("utf-8")
rloc = self.pexpect.match.groups()[1].decode("utf-8")
@@ -553,7 +605,7 @@ class otCli:
def get_context_reuse_delay(self):
self.send_command('contextreusedelay')
i = self._expect('(\d+)\r?\n')
i = self._expect(r'(\d+)\r?\n')
if i == 0:
timeout = self.pexpect.match.groups()[0]
self._expect('Done')
@@ -617,7 +669,7 @@ class otCli:
results = []
while True:
i = self._expect(['\|\s(\S+)\s+\|\s(\S+)\s+\|\s([0-9a-fA-F]{4})\s\|\s([0-9a-fA-F]{16})\s\|\s(\d+)\r?\n',
i = self._expect([r'\|\s(\S+)\s+\|\s(\S+)\s+\|\s([0-9a-fA-F]{4})\s\|\s([0-9a-fA-F]{16})\s\|\s(\d+)\r?\n',
'Done'])
if i == 0:
results.append(self.pexpect.match.groups())
@@ -640,7 +692,7 @@ class otCli:
try:
responders = {}
while len(responders) < num_responses:
i = self._expect(['from (\S+):'])
i = self._expect([r'from (\S+):'])
if i == 0:
responders[self.pexpect.match.groups()[0]] = 1
self._expect('\n')