Extract reusable device protocols, ports and logic analyzers from SETGUI
This commit is contained in:
91
python/tests/test_logic_analyzer_saleae.py
Normal file
91
python/tests/test_logic_analyzer_saleae.py
Normal file
@@ -0,0 +1,91 @@
|
||||
from dataclasses import replace
|
||||
from pathlib import Path
|
||||
import struct
|
||||
import tempfile
|
||||
import unittest
|
||||
from unittest.mock import MagicMock, patch
|
||||
from logic_analyzer import saleae
|
||||
from logic_analyzer.files import ImportCancelled
|
||||
|
||||
|
||||
def binary(path, edges=(), initial=0, start=0., end=1., version=0):
|
||||
Path(path).write_bytes(struct.pack('<8siiIddQ', b'<SALEAE>', version, 0,
|
||||
initial, start, end, len(edges)) +
|
||||
struct.pack('<%dd' % len(edges), *edges))
|
||||
|
||||
|
||||
class SaleaeCoreTests(unittest.TestCase):
|
||||
def test_constant_channel_tail_and_sparse_channel_numbers(self):
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
binary(Path(directory) / 'digital_2.bin', [.2, .3])
|
||||
binary(Path(directory) / 'digital_7.bin', initial=1)
|
||||
capture = saleae.read_binary(directory, (2, 7))
|
||||
self.assertEqual([c.name for c in capture.channels], ['D2', 'D7'])
|
||||
self.assertEqual(capture.end, 1.)
|
||||
self.assertEqual(capture.channels[0].level_at(.25), 1)
|
||||
self.assertEqual(capture.channels[0].level_at(.9), 0)
|
||||
self.assertEqual(capture.channels[1].level_at(.9), 1)
|
||||
|
||||
def test_reject_bad_binary_and_cancel(self):
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
path = Path(directory) / 'digital_0.bin'
|
||||
for kwargs in ({'version': 1}, {'edges': [.4, .3]}, {'edges': [float('nan')]},
|
||||
{'end': -1}, {'initial': 2}):
|
||||
binary(path, **kwargs)
|
||||
with self.assertRaises(ValueError):
|
||||
saleae.read_binary(directory, (0,))
|
||||
binary(path, [.2])
|
||||
with self.assertRaises(ImportCancelled):
|
||||
saleae.read_binary(directory, (0,), lambda: True)
|
||||
|
||||
def test_settings_validation(self):
|
||||
good = saleae.SaleaeSettings('id')
|
||||
good.validate()
|
||||
for kwargs in ({'channels': ()}, {'channels': (1, 1)}, {'channels': (16,)},
|
||||
{'sample_rate': 0}, {'duration': float('nan')}, {'port': 0},
|
||||
{'buffer_mb': 1}, {'threshold': 5}, {'device_id': ''}):
|
||||
with self.assertRaises(ValueError):
|
||||
replace(good, **kwargs).validate()
|
||||
|
||||
def fake_api(self):
|
||||
api = MagicMock()
|
||||
manager = api.Manager.connect.return_value.__enter__.return_value
|
||||
capture = manager.start_capture.return_value
|
||||
|
||||
def export(directory, **kwargs):
|
||||
for channel in kwargs['digital_channels']:
|
||||
binary(Path(directory) / ('digital_%d.bin' % channel), [.25])
|
||||
capture.export_raw_data_binary.side_effect = export
|
||||
return api, manager, capture
|
||||
|
||||
def test_stop_exports_and_closes_exactly_once(self):
|
||||
api, manager, capture = self.fake_api()
|
||||
settings = saleae.SaleaeSettings('abc', channels=(3, 5), threshold=1.8)
|
||||
with patch.object(saleae, 'automation_api', return_value=api):
|
||||
result = saleae.acquire(settings, lambda: True, lambda: False)
|
||||
self.assertEqual(result.sample_rate, 24000000)
|
||||
self.assertIn('abc', result.source)
|
||||
self.assertEqual([c.name for c in result.channels], ['D3', 'D5'])
|
||||
capture.stop.assert_called_once()
|
||||
capture.wait.assert_not_called()
|
||||
capture.close.assert_called_once()
|
||||
api.LogicDeviceConfiguration.assert_called_once_with(
|
||||
enabled_digital_channels=[3, 5], digital_sample_rate=24000000, digital_threshold_volts=1.8)
|
||||
self.assertFalse(Path(capture.export_raw_data_binary.call_args[0][0]).exists())
|
||||
|
||||
def test_cancel_stops_without_export_and_failure_closes(self):
|
||||
api, manager, capture = self.fake_api()
|
||||
with patch.object(saleae, 'automation_api', return_value=api):
|
||||
calls = iter((False, True, True))
|
||||
with self.assertRaises(ImportCancelled):
|
||||
saleae.acquire(saleae.SaleaeSettings('id'), lambda: False, lambda: next(calls))
|
||||
capture.stop.assert_called_once()
|
||||
capture.close.assert_called_once()
|
||||
capture.export_raw_data_binary.assert_not_called()
|
||||
capture.reset_mock()
|
||||
capture.stop.side_effect = RuntimeError('USB disconnected')
|
||||
with patch.object(saleae, 'automation_api', return_value=api):
|
||||
with self.assertRaisesRegex(RuntimeError, 'USB'):
|
||||
saleae.acquire(saleae.SaleaeSettings('id'), lambda: True, lambda: False)
|
||||
capture.stop.assert_called_once()
|
||||
capture.close.assert_called_once()
|
||||
Reference in New Issue
Block a user