HackRF-Treasure-Chest/Software/Universal Radio Hacker/tests/test_simulator_tab_gui.py
2022-09-22 13:46:47 -07:00

418 lines
19 KiB
Python

import os
import tempfile
import time
from array import array
import numpy as np
from PyQt5.QtCore import Qt, QTimer, QPoint
from PyQt5.QtGui import QContextMenuEvent
from PyQt5.QtTest import QTest
from PyQt5.QtWidgets import QApplication, QMenu, QCompleter
from tests.QtTestCase import QtTestCase
from urh import settings
from urh.controller.MainController import MainController
from urh.controller.SimulatorTabController import SimulatorTabController
from urh.plugins.NetworkSDRInterface.NetworkSDRInterfacePlugin import NetworkSDRInterfacePlugin
from urh.signalprocessing.IQArray import IQArray
from urh.signalprocessing.Modulator import Modulator
from urh.signalprocessing.Participant import Participant
from urh.simulator.MessageItem import MessageItem
from urh.simulator.RuleItem import RuleItem
from urh.simulator.SimulatorMessage import SimulatorMessage
from urh.simulator.SimulatorRule import ConditionType
from urh.ui.ExpressionLineEdit import ExpressionLineEdit
from urh.ui.RuleExpressionValidator import RuleExpressionValidator
from urh.util import util
from urh.util.Logger import logger
class TestSimulatorTabGUI(QtTestCase):
def setUp(self):
super().setUp()
settings.OVERWRITE_RECEIVE_BUFFER_SIZE = 50000
self.carl = Participant("Carl", "C")
self.dennis = Participant("Dennis", "D")
self.participants = [self.carl, self.dennis]
self.project_folder = os.path.join(tempfile.gettempdir(), "simulator_project")
self.menus_to_ignore = []
def test_save_and_load(self):
assert isinstance(self.form, MainController)
stc = self.form.simulator_tab_controller # type: SimulatorTabController
self.__setup_project()
self.assertEqual(len(stc.simulator_config.get_all_items()), 0)
self.add_all_signals_to_simulator()
self.assertGreater(len(stc.simulator_config.get_all_items()), 0)
self.assertEqual(stc.simulator_message_table_model.rowCount(), 3)
rule = stc.simulator_scene.add_rule(ref_item=None, position=0)
stc.simulator_scene.add_rule_condition(rule, ConditionType.ELSE_IF)
stc.simulator_scene.add_goto_action(None, 0)
stc.simulator_scene.add_trigger_command_action(None, 0)
messages = stc.simulator_config.get_all_messages()
self.assertEqual(len(messages), 3)
for i, msg in enumerate(messages):
self.assertEqual(msg.source, self.carl, msg=str(i))
# select items
self.assertEqual(stc.simulator_message_field_model.rowCount(), 0)
stc.simulator_scene.select_all_items()
self.assertEqual(stc.simulator_message_field_model.rowCount(), 1)
self.form.close_project()
self.assertEqual(len(stc.simulator_config.get_all_items()), 0)
stc.simulator_scene.select_all_items()
self.assertEqual(stc.simulator_message_field_model.rowCount(), 0)
self.form.project_manager.set_project_folder(self.project_folder)
self.assertEqual(stc.simulator_message_table_model.rowCount(), 3)
self.assertGreater(len(stc.simulator_config.get_all_items()), 0)
stc.simulator_scene.select_all_items()
self.assertEqual(stc.simulator_message_field_model.rowCount(), 1)
def test_save_and_load_standalone(self):
assert isinstance(self.form, MainController)
self.__setup_project()
stc = self.form.simulator_tab_controller
self.assertEqual(len(stc.simulator_config.get_all_items()), 0)
self.add_all_signals_to_simulator()
self.assertGreater(len(stc.simulator_config.get_all_items()), 0)
self.assertEqual(stc.simulator_message_table_model.rowCount(), 3)
self.assertEqual(stc.participant_table_model.rowCount(), 2)
filename = os.path.join(tempfile.gettempdir(), "test.sim.xml")
if os.path.isfile(filename):
os.remove(filename)
self.form.simulator_tab_controller.save_simulator_file(filename)
self.form.close_all_files()
self.form.project_manager.participants.clear()
self.form.project_manager.project_updated.emit()
self.assertEqual(len(stc.simulator_config.get_all_items()), 0)
self.assertEqual(stc.simulator_message_table_model.rowCount(), 0)
self.assertEqual(stc.participant_table_model.rowCount(), 0)
self.form.add_files([filename])
self.assertGreater(len(stc.simulator_config.get_all_items()), 0)
self.assertEqual(stc.simulator_message_table_model.rowCount(), 3)
self.assertEqual(stc.participant_table_model.rowCount(), 2)
def test_edit_simulator_label_table(self):
self.__setup_project()
self.add_all_signals_to_simulator()
stc = self.form.simulator_tab_controller # type: SimulatorTabController
stc.simulator_scene.select_all_items()
model = stc.simulator_message_field_model
self.assertEqual(model.rowCount(), 1)
self.assertEqual(model.data(model.index(0, 3)), "1" * 8)
# constant value
model.setData(model.index(0, 2), 0, role=Qt.EditRole)
model.setData(model.index(0, 1), 0, role=Qt.EditRole)
model.setData(model.index(0, 3), "11110000", role=Qt.EditRole)
self.assertEqual(model.data(model.index(0, 3)), "11110000")
model.setData(model.index(0, 1), 1, role=Qt.EditRole)
model.setData(model.index(0, 3), "ab", role=Qt.EditRole)
self.assertEqual(model.data(model.index(0, 3)), "ab")
model.setData(model.index(0, 1), 2, role=Qt.EditRole)
model.setData(model.index(0, 3), "=", role=Qt.EditRole)
self.assertEqual(model.data(model.index(0, 3)), "=")
model.setData(model.index(0, 1), 3, role=Qt.EditRole)
model.setData(model.index(0, 3), "240", role=Qt.EditRole)
self.assertEqual(model.data(model.index(0, 3)), "240")
model.setData(model.index(0, 1), 4, role=Qt.EditRole)
model.setData(model.index(0, 3), "55", role=Qt.EditRole)
self.assertEqual(model.data(model.index(0, 3)), "55")
# get live during simulation
model.setData(model.index(0, 2), 1, role=Qt.EditRole)
self.assertEqual(model.data(model.index(0, 3)), "-")
stc.ui.tblViewFieldValues.openPersistentEditor(model.index(0, 3))
# formula
model.setData(model.index(0, 2), 2, role=Qt.EditRole)
self.assertEqual(model.data(model.index(0, 3)), "")
stc.ui.tblViewFieldValues.openPersistentEditor(model.index(0, 3))
model.setData(model.index(0, 3), "4+5", role=Qt.EditRole)
self.assertNotEqual(model.data(model.index(0, 3), role=Qt.BackgroundColorRole), settings.ERROR_BG_COLOR)
model.setData(model.index(0, 3), "item1.preamble + 42", role=Qt.EditRole)
self.assertNotEqual(model.data(model.index(0, 3), role=Qt.BackgroundColorRole), settings.ERROR_BG_COLOR)
model.setData(model.index(0, 3), "item1.preamble + 42/", role=Qt.EditRole)
self.assertEqual(model.data(model.index(0, 3), role=Qt.BackgroundColorRole), settings.ERROR_BG_COLOR)
# external program
model.setData(model.index(0, 2), 3, role=Qt.EditRole)
stc.ui.tblViewFieldValues.openPersistentEditor(model.index(0, 3))
self.assertEqual(model.data(model.index(0, 3)), "")
# random value
model.setData(model.index(0, 2), 4, role=Qt.EditRole)
stc.ui.tblViewFieldValues.openPersistentEditor(model.index(0, 3))
self.assertTrue(model.data(model.index(0, 3)).startswith("Range (Decimal):"))
model.setData(model.index(0, 3), (42, 1337), role=Qt.EditRole)
self.assertEqual(model.data(model.index(0, 3)), "Range (Decimal): 42 - 1337")
def test_insert_column(self):
self.__setup_project()
self.add_all_signals_to_simulator()
stc = self.form.simulator_tab_controller # type: SimulatorTabController
stc.ui.cbViewType.setCurrentText("Hex")
lens = [len(msg) for msg in stc.simulator_message_table_model.protocol.messages]
stc.ui.tblViewMessage.selectAll()
stc.ui.tblViewMessage._insert_column(2)
for i, l in enumerate(lens):
self.assertEqual(lens[i] + 4, len(stc.simulator_message_table_model.protocol.messages[i]))
stc.ui.cbViewType.setCurrentText("Bit")
stc.ui.tblViewMessage.selectAll()
stc.ui.tblViewMessage._insert_column(6)
for i, l in enumerate(lens):
self.assertEqual(lens[i] + 5, len(stc.simulator_message_table_model.protocol.messages[i]))
def test_simulator_graphics_view(self):
self.__setup_project()
self.add_all_signals_to_simulator()
stc = self.form.simulator_tab_controller # type: SimulatorTabController
self.assertGreater(len(stc.simulator_config.get_all_items()), 0)
self.assertEqual(len(stc.simulator_scene.selectedItems()), 0)
# select first message
messages = stc.simulator_scene.get_all_message_items()
pos = stc.ui.gvSimulator.mapFromScene(messages[0].scenePos())
QTest.mouseClick(stc.ui.gvSimulator.viewport(), Qt.LeftButton, Qt.NoModifier, pos)
self.assertEqual(len(stc.simulator_scene.selectedItems()), 1)
self.assertIsInstance(stc.simulator_scene.selectedItems()[0], MessageItem)
rules = [item for item in stc.simulator_scene.items() if isinstance(item, RuleItem)]
self.assertEqual(len(rules), 0)
self.menus_to_ignore = [w for w in QApplication.topLevelWidgets() if isinstance(w, QMenu)]
timer = QTimer(self.form)
timer.setInterval(1)
timer.setSingleShot(True)
timer.timeout.connect(self.__on_context_menu_simulator_graphics_view_timer_timeout)
timer.start()
stc.ui.gvSimulator.contextMenuEvent(QContextMenuEvent(QContextMenuEvent.Mouse, pos))
rules = [item for item in stc.simulator_scene.items() if isinstance(item, RuleItem)]
self.assertEqual(len(rules), 1)
def test_simulator_message_table_context_menu(self):
self.__setup_project()
self.add_all_signals_to_simulator()
stc = self.form.simulator_tab_controller # type: SimulatorTabController
stc.ui.tabWidget.setCurrentIndex(1)
stc.simulator_scene.get_all_message_items()[0].setSelected(True)
self.assertEqual(stc.simulator_message_field_model.rowCount(), 1)
stc.ui.tblViewMessage.selectColumn(4)
x, y = stc.ui.tblViewMessage.columnViewportPosition(4), stc.ui.tblViewMessage.rowViewportPosition(0)
pos = QPoint(x, y)
stc.ui.tblViewMessage.context_menu_pos = pos
menu = stc.ui.tblViewMessage.create_context_menu()
names = [action.text() for action in menu.actions()]
self.assertIn("Enforce encoding", names)
add_label_action = next(action for action in menu.actions() if action.text() == "Create label...")
add_label_action.trigger()
menu.close()
stc.ui.tblViewMessage.selectRow(0)
self.assertEqual(stc.simulator_message_field_model.rowCount(), 2)
def test_expression_line_edit(self):
e = ExpressionLineEdit()
e.setCompleter(QCompleter(self.form.simulator_tab_controller.completer_model, e))
e.setValidator(RuleExpressionValidator(self.form.simulator_tab_controller.sim_expression_parser))
self.assertEqual(e.text(), "")
QTest.keyClick(e, Qt.Key_R, Qt.NoModifier)
self.assertEqual(e.text(), "r")
def test_participant_table(self):
stc = self.form.simulator_tab_controller # type: SimulatorTabController
stc.ui.tabWidget.setCurrentIndex(2)
self.assertEqual(stc.participant_table_model.rowCount(), 0)
for i in range(3):
stc.ui.btnAddParticipant.click()
QApplication.processEvents()
self.assertEqual(stc.participant_table_model.rowCount(), 3)
participants = stc.project_manager.participants
self.assertEqual(participants[0].name, "Alice")
self.assertEqual(participants[1].name, "Bob")
self.assertEqual(participants[2].name, "Carl")
stc.ui.tableViewParticipants.selectRow(1)
stc.ui.btnUp.click()
self.assertEqual(participants[0].name, "Bob")
self.assertEqual(participants[1].name, "Alice")
self.assertEqual(participants[2].name, "Carl")
stc.ui.btnDown.click()
self.assertEqual(participants[0].name, "Alice")
self.assertEqual(participants[1].name, "Bob")
self.assertEqual(participants[2].name, "Carl")
stc.ui.btnDown.click()
self.assertEqual(participants[0].name, "Alice")
self.assertEqual(participants[1].name, "Carl")
self.assertEqual(participants[2].name, "Bob")
def test_participants_list(self):
alice = Participant("Alice", "A")
bob = Participant("Bob", "B")
self.form.project_manager.participants.append(alice)
self.form.project_manager.participants.append(bob)
self.form.project_manager.project_updated.emit()
mt = self.form.compare_frame_controller.proto_analyzer.default_message_type
msg1 = SimulatorMessage(destination=alice, plain_bits=array("B", [1, 0, 1, 1]), pause=100, message_type=mt)
msg2 = SimulatorMessage(destination=bob, plain_bits=array("B", [1, 0, 1, 1]), pause=100, message_type=mt)
simulator_manager = self.form.simulator_tab_controller.simulator_config
simulator_manager.add_items([msg1, msg2], 0, simulator_manager.rootItem)
simulator_manager.add_label(5, 15, "test", parent_item=simulator_manager.rootItem.children[0])
stc = self.form.simulator_tab_controller # type: SimulatorTabController
model = stc.ui.listViewSimulate.model()
self.assertEqual(model.rowCount(), 2)
self.assertEqual(model.data(model.index(0, 0)), "Alice (A)")
self.assertEqual(model.data(model.index(1, 0)), "Bob (B)")
self.assertFalse(self.form.project_manager.participants[0].simulate)
self.assertEqual(model.data(model.index(0, 0), role=Qt.CheckStateRole), Qt.Unchecked)
self.assertFalse(self.form.project_manager.participants[1].simulate)
self.assertEqual(model.data(model.index(1, 0), role=Qt.CheckStateRole), Qt.Unchecked)
model.setData(model.index(0, 0), Qt.Checked, role=Qt.CheckStateRole)
self.assertTrue(self.form.project_manager.participants[0].simulate)
def test_valid_goto_targets(self):
stc = self.form.simulator_tab_controller
assert isinstance(stc, SimulatorTabController)
self.__setup_project()
self.add_all_signals_to_simulator()
self.assertEqual(len(stc.simulator_config.get_all_messages()), 3)
stc.ui.gvSimulator.on_add_goto_action_triggered()
self.assertEqual(stc.ui.detail_view_widget.currentWidget(), stc.ui.page_goto_action)
self.assertEqual(stc.ui.goto_combobox.count(), 3 + 1) # select item... also in combobox
stc.ui.gvSimulator.on_add_counter_action_triggered()
stc.ui.gvSimulator.on_add_sleep_action_triggered()
stc.ui.gvSimulator.on_add_goto_action_triggered()
self.assertEqual(stc.ui.goto_combobox.count(), 5 + 1) # select item... also in combobox
def test_open_simulator_dialog_and_send_message(self):
def __wait_for_simulator_log_message(dialog, log_message):
n = 0
while not any(log_message in msg for msg in dialog.simulator.log_messages):
if n < 50:
time.sleep(0.5)
else:
self.fail("Did not receive log message \"{}\"".format(log_message))
n += 1
stc = self.form.simulator_tab_controller
assert isinstance(stc, SimulatorTabController)
self.__setup_project()
self.add_all_signals_to_simulator()
stc.simulator_scene.select_all_items()
for msg in stc.simulator_scene.get_selected_messages():
msg.destination = self.dennis
stc.ui.gvSimulator.message_updated.emit(msg)
list_model = stc.ui.listViewSimulate.model()
self.assertEqual(list_model.rowCount(), 2)
list_model.setData(list_model.createIndex(1, 0), Qt.Checked, role=Qt.CheckStateRole)
dialog = stc.get_simulator_dialog()
network_sdr_name = NetworkSDRInterfacePlugin.NETWORK_SDR_NAME
dialog.device_settings_rx_widget.ui.cbDevice.setCurrentText(network_sdr_name)
rcv_port = util.get_free_port()
dialog.simulator.sniffer.rcv_device.set_server_port(rcv_port)
dialog.simulator.sniffer.adaptive_noise = False
dialog.simulator.sniffer.automatic_center = False
dialog.ui.btnStartStop.click()
__wait_for_simulator_log_message(dialog, "Waiting for message 1")
modulator = dialog.project_manager.modulators[0] # type: Modulator
sender = NetworkSDRInterfacePlugin(raw_mode=True, sending=True)
sender.client_port = rcv_port
sender.send_raw_data(modulator.modulate("1" * 352), 1)
time.sleep(0.5)
sender.send_raw_data(IQArray(None, np.float32, 2000), 1)
time.sleep(0.5)
dialog.on_timer_timeout() # enforce writing to text view
simulator_log = dialog.ui.textEditSimulation.toPlainText()
self.assertIn("Received message 1", simulator_log)
self.assertIn("preamble: 11111111", simulator_log)
dialog.close()
def __on_context_menu_simulator_graphics_view_timer_timeout(self):
menu = next(w for w in QApplication.topLevelWidgets() if isinstance(w, QMenu)
and w.parent() is None and w not in self.menus_to_ignore)
names = [action.text() for action in menu.actions()]
self.assertIn("Source", names)
add_rule_action = next(action for action in menu.actions() if action.text() == "Add rule")
add_rule_action.trigger()
menu.close()
def __setup_project(self):
assert isinstance(self.form, MainController)
directory = self.project_folder
if not os.path.isdir(directory):
os.mkdir(directory)
if os.path.isfile(os.path.join(directory, "URHProject.xml")):
os.remove(os.path.join(directory, "URHProject.xml"))
self.form.project_manager.set_project_folder(directory, ask_for_new_project=False)
self.form.project_manager.participants[:] = self.participants
self.form.project_manager.project_updated.emit()
self.add_signal_to_form("esaver.complex16s")
self.assertEqual(self.form.signal_tab_controller.num_frames, 1)
self.assertEqual(self.form.compare_frame_controller.participant_list_model.rowCount(), 3)
for i in range(3):
self.form.compare_frame_controller.proto_analyzer.messages[i].participant = self.carl
self.form.compare_frame_controller.add_protocol_label(8, 15, 0, 0, False)
self.assertEqual(self.form.compare_frame_controller.label_value_model.rowCount(), 1)