Files
templates/python/tests/test_logic_csv_import.py

97 lines
4.5 KiB
Python

from decimal import Decimal
from pathlib import Path
import tempfile
import unittest
import zipfile
from logic_analyzer.csv_import import convert_csv
from logic_analyzer.files import ImportCancelled, read_capture
class CsvImportTests(unittest.TestCase):
def setUp(self):
self.temp = tempfile.TemporaryDirectory()
self.addCleanup(self.temp.cleanup)
self.source = Path(self.temp.name) / 'сигналы.csv'
self.output = Path(self.temp.name) / 'сигналы.dsl'
def write(self, value):
self.source.write_text(value, encoding='utf-8-sig')
def test_regular_samples_preserve_levels_and_names(self):
self.write('Time [ns],Vin,Vstat\n0,0,1\n10,1,0\n20,0,1\n')
original = self.source.read_bytes()
info = convert_csv(self.source, self.output)
result = read_capture(self.output)
self.assertEqual(info['samplerate'], 100_000_000)
self.assertEqual([c.name for c in result.channels], ['Vin', 'Vstat'])
self.assertEqual(list(result.channels[0].edges), [1e-8, 2e-8])
self.assertEqual([result.channels[1].level_at(t) for t in [0, 1e-8, 2e-8, 5e-7]], [1, 0, 1, 1])
self.assertEqual(self.source.read_bytes(), original)
def test_sparse_transitions_preserve_short_pulses_across_blocks(self):
self.write('Time [ns],A\n0,0\n10,1\n650,0\n680,1\n710,0\n')
convert_csv(self.source, self.output, block_samples=64)
capture = read_capture(self.output)
self.assertEqual(list(capture.channels[0].edges), [1e-8, 6.5e-7, 6.8e-7, 7.1e-7])
with zipfile.ZipFile(self.output) as archive:
self.assertIn('L-0/1', archive.namelist())
self.assertEqual(len(archive.read('L-0/0')), 8)
def test_initial_snapshot_need_not_be_on_edge_clock(self):
self.write('Time [s];A\n127,632374014;0\n127,632482000;1\n127,632482400;0\n127,632483000;1\n')
info = convert_csv(self.source, self.output)
self.assertEqual(info['samplerate'], 5_000_000)
self.assertEqual(Decimal(info['origin_seconds']), Decimal('127.632374'))
capture = read_capture(self.output)
edges = capture.channels[0].edges
self.assertAlmostEqual(edges[1] - edges[0], 400e-9, places=14)
self.assertAlmostEqual(edges[2] - edges[1], 600e-9, places=14)
def test_comments_tab_delimiter_and_negative_origin(self):
self.write('; DSView export\n# data\nTime(us)\tКанал\n-1\t1\n0\t0\n1\t1\n')
info = convert_csv(self.source, self.output)
self.assertEqual(info['origin_seconds'], '-0.000001')
self.assertEqual(read_capture(self.output).channels[0].name, 'Канал')
def test_bad_csv_leaves_no_output(self):
for rows in ('0,0\n1,3.3', '0,0\n0,1', 'nan,0\n1,1', '0,0', '0,0,1\n1,1,0'):
with self.subTest(rows=rows):
self.write('Time [s],A\n' + rows + '\n')
with self.assertRaises(ValueError):
convert_csv(self.source, self.output)
self.assertFalse(self.output.exists())
def test_output_is_not_overwritten_and_size_limit_precedes_expansion(self):
self.write('Time [ns],A\n0,0\n10,1\n100000,0\n')
with self.assertRaises(ValueError):
convert_csv(self.source, self.output, max_packed_bytes=64)
self.output.write_bytes(b'old recording')
with self.assertRaises(ValueError):
convert_csv(self.source, self.output)
self.assertEqual(self.output.read_bytes(), b'old recording')
def test_cancel_during_packing_cleans_temporary_output(self):
self.write('Time [ns],A\n0,0\n10,1\n100000,0\n')
cancelled = False
def progress(value):
nonlocal cancelled
if value > 40:
cancelled = True
with self.assertRaises(ImportCancelled):
convert_csv(self.source, self.output, progress, lambda: cancelled, block_samples=64)
self.assertFalse(self.output.exists())
self.assertEqual([p.name for p in Path(self.temp.name).iterdir()], [self.source.name])
def test_changed_source_rejected_before_publication(self):
self.write('Time [ns],A\n0,0\n10,1\n20,0\n')
changed = False
def progress(value):
nonlocal changed
if value == 99 and not changed:
changed = True
self.source.write_text('changed', encoding='utf-8')
with self.assertRaisesRegex(ValueError, 'изменился'):
convert_csv(self.source, self.output, progress)
self.assertFalse(self.output.exists())