Add DSLogic capture, signal conversion and DSView decoders
This commit is contained in:
116
tools/dsview/tests/test_install_decoders.py
Normal file
116
tools/dsview/tests/test_install_decoders.py
Normal file
@@ -0,0 +1,116 @@
|
||||
"""Exercise the standalone PowerShell installer without modifying installed DSView."""
|
||||
import os
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
SHELL = shutil.which('powershell.exe') or shutil.which('pwsh')
|
||||
|
||||
|
||||
@unittest.skipUnless(os.name == 'nt' and SHELL, 'Windows PowerShell required')
|
||||
class InstallerTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.temp = tempfile.TemporaryDirectory(prefix='dsview installer ')
|
||||
self.addCleanup(self.temp.cleanup)
|
||||
self.app = Path(self.temp.name)/'DSView test'
|
||||
self.app.mkdir()
|
||||
(self.app/'DSView.exe').write_bytes(b'fixture, not executable')
|
||||
(self.app/'decoders/common').mkdir(parents=True)
|
||||
(self.app/'decoders/common/__init__.py').write_text('# existing common package\n')
|
||||
(self.app/'decoders/common/keep.txt').write_text('unrelated')
|
||||
|
||||
def run_installer(self, *extra, script=None):
|
||||
return subprocess.run([SHELL, '-NoProfile', '-ExecutionPolicy', 'Bypass', '-File',
|
||||
str(script or ROOT/'install_decoders.ps1'),
|
||||
'-DsViewPath', str(self.app), *extra], capture_output=True, text=True)
|
||||
|
||||
def test_install_import_and_update_backup(self):
|
||||
result = self.run_installer()
|
||||
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
|
||||
code = '''
|
||||
import importlib, pathlib, sys, types
|
||||
root = pathlib.Path(sys.argv[1])
|
||||
sys.path.insert(0, str(root))
|
||||
stub = types.ModuleType('sigrokdecode')
|
||||
stub.Decoder = type('Decoder', (), {})
|
||||
sys.modules['sigrokdecode'] = stub
|
||||
for name in ('gate_driver_timing', 'transistor_pair', 'set_uart', 'set_can', 'pm35_uart'):
|
||||
module = importlib.import_module(name + '.pd')
|
||||
assert module.Decoder.api_version == 3
|
||||
core = importlib.import_module('common.setgui_decoders.gate_timing')
|
||||
pathlib.Path(core.__file__).resolve().relative_to(root)
|
||||
assert '1SP0635' in core.PROFILES
|
||||
'''
|
||||
check = subprocess.run([sys.executable, '-I', '-c', code, str(self.app/'decoders')],
|
||||
cwd=self.app, capture_output=True, text=True)
|
||||
self.assertEqual(check.returncode, 0, check.stderr)
|
||||
target = self.app/'decoders/set_uart/pd.py'
|
||||
target.write_text('# old decoder\n')
|
||||
result = self.run_installer()
|
||||
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
|
||||
backups = list((self.app/'set-decoder-backups').glob('*/set_uart/pd.py'))
|
||||
self.assertEqual(len(backups), 1)
|
||||
self.assertEqual(backups[0].read_text(), '# old decoder\n')
|
||||
self.assertEqual(target.read_bytes(), (ROOT/'decoders/set_uart/pd.py').read_bytes())
|
||||
self.assertEqual((self.app/'decoders/common/keep.txt').read_text(), 'unrelated')
|
||||
self.assertEqual((self.app/'decoders/common/__init__.py').read_text(), '# existing common package\n')
|
||||
for name in ('gate_timing', 'transistor_pair', 'set_uart', 'set_can', 'pm35_uart'):
|
||||
self.assertEqual((self.app/('decoders/common/setgui_decoders/'+name+'.py')).read_bytes(),
|
||||
(ROOT.parents[1]/('python/logic_analyzer/decoders/'+name+'.py')).read_bytes())
|
||||
|
||||
def test_check_only_does_not_install(self):
|
||||
result = self.run_installer('-CheckOnly')
|
||||
self.assertEqual(result.returncode, 0, result.stderr)
|
||||
self.assertFalse((self.app/'decoders/set_uart').exists())
|
||||
self.assertFalse((self.app/'set-decoder-backups').exists())
|
||||
|
||||
def test_copy_failure_restores_previous_decoders(self):
|
||||
old = self.app/'decoders/gate_driver_timing/pd.py'
|
||||
old.parent.mkdir()
|
||||
old.write_text('# original\n')
|
||||
runner = Path(self.temp.name)/'inject-failure.ps1'
|
||||
runner.write_text('''
|
||||
param([string]$Installer, [string]$Target)
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$global:installerTestFailed = $false
|
||||
function Copy-Item {
|
||||
param([string]$LiteralPath, [string]$Destination, [switch]$Force)
|
||||
if (-not $global:installerTestFailed -and $Destination.Replace('\\', '/').EndsWith('/decoders/set_uart/pd.py')) {
|
||||
$global:installerTestFailed = $true
|
||||
throw 'Injected copy failure'
|
||||
}
|
||||
Microsoft.PowerShell.Management\\Copy-Item -LiteralPath $LiteralPath -Destination $Destination -Force:$Force
|
||||
}
|
||||
& $Installer -DsViewPath $Target
|
||||
''', encoding='utf-8')
|
||||
result = subprocess.run([SHELL, '-NoProfile', '-ExecutionPolicy', 'Bypass', '-File',
|
||||
str(runner), '-Installer', str(ROOT/'install_decoders.ps1'),
|
||||
'-Target', str(self.app)], capture_output=True)
|
||||
self.assertNotEqual(result.returncode, 0)
|
||||
self.assertEqual(old.read_text(), '# original\n')
|
||||
self.assertFalse((old.parent/'__init__.py').exists())
|
||||
self.assertFalse((self.app/'decoders/set_uart/__init__.py').exists())
|
||||
self.assertEqual(len(list((self.app/'set-decoder-backups').glob('*/gate_driver_timing/pd.py'))), 1, result.stderr)
|
||||
|
||||
def test_incomplete_target_is_untouched(self):
|
||||
(self.app/'DSView.exe').unlink()
|
||||
result = self.run_installer()
|
||||
self.assertNotEqual(result.returncode, 0)
|
||||
self.assertFalse((self.app/'decoders/set_uart').exists())
|
||||
|
||||
def test_missing_source_is_detected_before_changes(self):
|
||||
source = Path(self.temp.name)/'empty-template/tools/dsview'
|
||||
source.mkdir(parents=True)
|
||||
shutil.copy2(ROOT/'install_decoders.ps1', source/'install_decoders.ps1')
|
||||
result = self.run_installer(script=source/'install_decoders.ps1')
|
||||
self.assertNotEqual(result.returncode, 0)
|
||||
self.assertFalse((self.app/'decoders/gate_driver_timing').exists())
|
||||
self.assertFalse((self.app/'set-decoder-backups').exists())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user