2018-03-26 17:48:24 +02:00
|
|
|
#!/usr/bin/env python
|
|
|
|
#
|
|
|
|
# Perform Security Manager Test Cases using two BTstack instances
|
|
|
|
#
|
|
|
|
# Copyright 2018 BlueKitchen GmbH
|
|
|
|
#
|
|
|
|
|
|
|
|
import os
|
|
|
|
import subprocess
|
|
|
|
import sys
|
|
|
|
import time
|
|
|
|
import signal
|
|
|
|
import select
|
|
|
|
import fcntl
|
2018-03-26 18:27:26 +02:00
|
|
|
import csv
|
|
|
|
import shutil
|
2018-03-26 17:48:24 +02:00
|
|
|
|
|
|
|
usb_paths = ['3', '5']
|
|
|
|
|
|
|
|
class Node:
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
self.name = 'node'
|
|
|
|
self._got_line = False
|
|
|
|
self.peer_addr = None
|
|
|
|
|
|
|
|
def get_name(self):
|
|
|
|
return self.name
|
|
|
|
|
|
|
|
def set_name(self, name):
|
|
|
|
self.name = name
|
|
|
|
|
|
|
|
def set_usb_path(self, path):
|
|
|
|
self.usb_path = path
|
|
|
|
|
|
|
|
def get_stdout_fd(self):
|
|
|
|
return self.stdout.fileno()
|
|
|
|
|
|
|
|
def read_stdout(self):
|
|
|
|
c = os.read(self.stdout.fileno(), 1)
|
|
|
|
if len(c) == 0:
|
|
|
|
return
|
|
|
|
if c in '\n\r':
|
|
|
|
if len(self.linebuffer) > 0:
|
|
|
|
self._got_line = True
|
|
|
|
else:
|
|
|
|
self.linebuffer += c
|
|
|
|
|
|
|
|
def got_line(self):
|
|
|
|
return self._got_line
|
|
|
|
|
|
|
|
def fetch_line(self):
|
|
|
|
line = self.linebuffer
|
|
|
|
self.linebuffer = ''
|
|
|
|
self._got_line = False
|
|
|
|
return line
|
|
|
|
|
|
|
|
def start_process(self):
|
|
|
|
args = ['./sm_test', '-u', self.usb_path]
|
|
|
|
if self.peer_addr != None:
|
|
|
|
args.append('-a')
|
|
|
|
args.append(self.peer_addr)
|
|
|
|
print('%s - "%s"' % (self.name, ' '.join(args)))
|
|
|
|
self.p = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
|
|
|
(self.stdin, self.stdout) = (self.p.stdin, self.p.stdout)
|
|
|
|
self.linebuffer = ''
|
|
|
|
|
|
|
|
def set_packet_log(self, path):
|
|
|
|
self.packet_log = path
|
|
|
|
|
|
|
|
def get_packet_log(self):
|
|
|
|
return self.packet_log
|
|
|
|
|
|
|
|
def set_bd_addr(self, addr):
|
|
|
|
self.bd_addr = addr
|
|
|
|
|
|
|
|
def get_bd_addr(self, addr):
|
|
|
|
return self.bd_addr
|
|
|
|
|
|
|
|
def set_peer_addr(self, addr):
|
|
|
|
self.peer_addr = addr
|
|
|
|
|
|
|
|
def write(self, string):
|
|
|
|
self.stdin.write(string)
|
|
|
|
|
|
|
|
def terminate(self):
|
|
|
|
self.write('x')
|
|
|
|
self.p.terminate()
|
|
|
|
|
|
|
|
def run(nodes):
|
|
|
|
state = 'W4_SLAVE_BD_ADDR'
|
|
|
|
|
|
|
|
while True:
|
|
|
|
# create map fd -> node
|
|
|
|
nodes_by_fd = { node.get_stdout_fd():node for node in nodes}
|
|
|
|
read_fds = nodes_by_fd.keys()
|
|
|
|
(read_ready, write_ready, exception_ready) = select.select(read_fds,[],[])
|
|
|
|
for fd in read_ready:
|
|
|
|
node = nodes_by_fd[fd]
|
|
|
|
node.read_stdout()
|
|
|
|
if node.got_line():
|
|
|
|
line = node.fetch_line()
|
|
|
|
# print('%s: %s' % (node.get_name(), line))
|
|
|
|
if line.startswith('Packet Log: '):
|
|
|
|
path = line.split(': ')[1]
|
|
|
|
node.set_packet_log(path)
|
|
|
|
print('%s log %s' % (node.get_name(), path))
|
|
|
|
if line.startswith('BD_ADDR: '):
|
|
|
|
addr = line.split(': ')[1]
|
|
|
|
node.set_bd_addr(addr)
|
|
|
|
print('%s started' % node.get_name())
|
|
|
|
if state == 'W4_SLAVE_BD_ADDR':
|
|
|
|
# peripheral started, start central
|
|
|
|
state = 'W4_CONNECTED'
|
|
|
|
node = Node()
|
|
|
|
node.set_name('Master')
|
|
|
|
node.usb_path = usb_paths[1]
|
|
|
|
node.set_peer_addr(addr)
|
|
|
|
node.start_process()
|
|
|
|
nodes.append(node)
|
|
|
|
if line.startswith('CONNECTED:'):
|
|
|
|
print('%s connected' % node.get_name())
|
|
|
|
if state == 'W4_CONNECTED':
|
|
|
|
state = 'W4_PAIRING'
|
|
|
|
if line.startswith('JUST_WORKS_REQUEST'):
|
|
|
|
print('%s just works requested' % node.get_name())
|
|
|
|
node.write('a')
|
|
|
|
if line.startswith('PAIRING_COMPLETE'):
|
|
|
|
print('%s pairing complete' % node.get_name())
|
|
|
|
return
|
|
|
|
|
2018-03-26 18:27:26 +02:00
|
|
|
def run_test(test_descriptor):
|
|
|
|
# shutdown previous sm_test instances
|
|
|
|
try:
|
|
|
|
subprocess.call("killall sm_test", shell = True)
|
|
|
|
except:
|
|
|
|
pass
|
|
|
|
|
|
|
|
test_name = test_descriptor['name']
|
|
|
|
print('Test: %s' % test_name)
|
|
|
|
|
|
|
|
# start up slave process
|
|
|
|
slave = Node()
|
|
|
|
slave.set_name('Slave')
|
|
|
|
slave.usb_path = usb_paths[0]
|
|
|
|
slave.start_process()
|
|
|
|
|
|
|
|
nodes = [slave]
|
|
|
|
|
|
|
|
# run test
|
|
|
|
try:
|
|
|
|
run(nodes)
|
|
|
|
except KeyboardInterrupt:
|
|
|
|
pass
|
|
|
|
|
|
|
|
# identify iut and tester
|
|
|
|
if '/SLA/' in test_descriptor['name']:
|
|
|
|
iut = nodes[0]
|
|
|
|
tester = nodes[1]
|
|
|
|
else:
|
|
|
|
iut = nodes[1]
|
|
|
|
tester = nodes[0]
|
|
|
|
|
|
|
|
# move hci logs into result folder
|
|
|
|
test_folder = test_descriptor['test_folder']
|
|
|
|
os.makedirs(test_folder)
|
|
|
|
shutil.move(iut.get_packet_log(), test_folder + '/iut.pklg')
|
|
|
|
shutil.move(tester.get_packet_log(), test_folder + '/tester.pklg')
|
|
|
|
|
|
|
|
# shutdown
|
|
|
|
for node in nodes:
|
|
|
|
node.terminate()
|
|
|
|
print("Done\n")
|
|
|
|
|
|
|
|
# read tests
|
|
|
|
with open('sm_test.csv') as csvfile:
|
|
|
|
reader = csv.DictReader(csvfile)
|
|
|
|
for test_descriptor in reader:
|
|
|
|
test_name = test_descriptor['name']
|
|
|
|
test_folder = test_name.replace('/', '_')
|
|
|
|
test_descriptor['test_folder'] = test_folder
|
|
|
|
|
|
|
|
# check if result folder exists
|
|
|
|
if os.path.exists(test_folder):
|
|
|
|
print('Test: %s (completed)' % test_name)
|
|
|
|
continue
|
|
|
|
|
|
|
|
# run test
|
|
|
|
run_test(test_descriptor)
|
|
|
|
|