Added tests for run_e/drc fails (mocked)

This commit is contained in:
Salvador E. Tropea 2021-02-03 15:16:42 -03:00
parent 9a703186de
commit afaecfe570
2 changed files with 102 additions and 81 deletions

View File

@ -3,7 +3,7 @@ import sys
import pytest import pytest
import coverage import coverage
import logging import logging
from subprocess import CalledProcessError import subprocess
# Look for the 'utils' module from where the script is running # Look for the 'utils' module from where the script is running
prev_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) prev_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
if prev_dir not in sys.path: if prev_dir not in sys.path:
@ -18,7 +18,7 @@ from kibot.pre_base import BasePreFlight
from kibot.gs import GS from kibot.gs import GS
from kibot.kiplot import load_actions, _import from kibot.kiplot import load_actions, _import
from kibot.registrable import RegOutput, RegFilter from kibot.registrable import RegOutput, RegFilter
from kibot.misc import (MISSING_TOOL, WRONG_INSTALL, BOM_ERROR) from kibot.misc import (MISSING_TOOL, WRONG_INSTALL, BOM_ERROR, DRC_ERROR, ERC_ERROR)
from kibot.bom.columnlist import ColumnList from kibot.bom.columnlist import ColumnList
@ -30,6 +30,7 @@ mocked_check_output_retOK = ''
# Important note: # Important note:
# - We can't load the plug-ins twice, the import fails. # - We can't load the plug-ins twice, the import fails.
# - Once we patched them using monkey patch the patch isn't reverted unless we load them again. # - Once we patched them using monkey patch the patch isn't reverted unless we load them again.
# I don't know the real reason, may be related to the way we load plug-ins.
# For this reason this patch is used for more than one case. # For this reason this patch is used for more than one case.
def mocked_check_output(cmd, stderr=None): def mocked_check_output(cmd, stderr=None):
logging.debug('mocked_check_output called') logging.debug('mocked_check_output called')
@ -38,32 +39,37 @@ def mocked_check_output(cmd, stderr=None):
else: else:
if mocked_check_output_retOK: if mocked_check_output_retOK:
return mocked_check_output_retOK return mocked_check_output_retOK
e = CalledProcessError(10, 'rar') e = subprocess.CalledProcessError(10, 'rar')
e.output = b'THE_ERROR' e.output = b'THE_ERROR'
raise e raise e
def mocked_call(cmd):
logging.debug('Forcing fail on '+str(cmd))
return 5
def patch_functions(m):
m.setattr("subprocess.check_output", mocked_check_output)
m.setattr('kibot.kiplot.exec_with_retry', mocked_call)
def run_compress(ctx, test_import_fail=False): def run_compress(ctx, test_import_fail=False):
# Start coverage with context.cover_it(cov):
cov.load() # Load the plug-ins
cov.start() load_actions()
# Load the plug-ins # Create a compress object with the dummy file as source
load_actions() out = RegOutput.get_class_for('compress')()
# Create a compress object with the dummy file as source out.set_tree({'options': {'format': 'RAR', 'files': [{'source': ctx.get_out_path('*')}]}})
out = RegOutput.get_class_for('compress')() out.config()
out.set_tree({'options': {'format': 'RAR', 'files': [{'source': ctx.get_out_path('*')}]}}) # Setup the GS output dir, needed for the output path
out.config() GS.out_dir = '.'
# Setup the GS output dir, needed for the output path # Run the compression and catch the error
GS.out_dir = '.' with pytest.raises(SystemExit) as pytest_wrapped_e:
# Run the compression and catch the error if test_import_fail:
with pytest.raises(SystemExit) as pytest_wrapped_e: _import('out_bogus', os.path.abspath(os.path.join(os.path.dirname(__file__), 'fake_plugin/out_bogus.py')))
if test_import_fail: else:
_import('out_bogus', os.path.abspath(os.path.join(os.path.dirname(__file__), 'fake_plugin/out_bogus.py'))) out.run('')
else:
out.run('')
# Stop coverage
cov.stop()
cov.save()
return pytest_wrapped_e return pytest_wrapped_e
@ -76,7 +82,7 @@ def test_no_rar(test_dir, caplog, monkeypatch):
ctx.create_dummy_out_file('Test.txt') ctx.create_dummy_out_file('Test.txt')
# We will patch subprocess.check_output to make rar fail # We will patch subprocess.check_output to make rar fail
with monkeypatch.context() as m: with monkeypatch.context() as m:
m.setattr("subprocess.check_output", mocked_check_output) patch_functions(m)
pytest_wrapped_e = run_compress(ctx) pytest_wrapped_e = run_compress(ctx)
# Check we exited because rar isn't installed # Check we exited because rar isn't installed
assert pytest_wrapped_e.type == SystemExit assert pytest_wrapped_e.type == SystemExit
@ -93,7 +99,7 @@ def test_rar_fail(test_dir, caplog, monkeypatch):
ctx.create_dummy_out_file('Test.txt') ctx.create_dummy_out_file('Test.txt')
# We will patch subprocess.check_output to make rar fail # We will patch subprocess.check_output to make rar fail
with monkeypatch.context() as m: with monkeypatch.context() as m:
m.setattr("subprocess.check_output", mocked_check_output) patch_functions(m)
pytest_wrapped_e = run_compress(ctx) pytest_wrapped_e = run_compress(ctx)
pytest_wrapped_e2 = run_compress(ctx, test_import_fail=True) pytest_wrapped_e2 = run_compress(ctx, test_import_fail=True)
# Check we exited because rar isn't installed # Check we exited because rar isn't installed
@ -129,15 +135,10 @@ def test_no_get_targets(caplog):
# Also check the dependencies fallback # Also check the dependencies fallback
GS.sch = None GS.sch = None
GS.sch_file = 'fake' GS.sch_file = 'fake'
# Start coverage with context.cover_it(cov):
cov.load() test.get_targets('')
cov.start() files = test.get_dependencies()
test.get_targets('') files_pre = test_pre.get_dependencies()
files = test.get_dependencies()
files_pre = test_pre.get_dependencies()
# Stop coverage
cov.stop()
cov.save()
assert "Output 'Fake' (dummy) [none] doesn't implement get_targets(), plese report it" in caplog.text assert "Output 'Fake' (dummy) [none] doesn't implement get_targets(), plese report it" in caplog.text
assert files == [GS.sch_file] assert files == [GS.sch_file]
assert files_pre == [GS.sch_file] assert files_pre == [GS.sch_file]
@ -150,23 +151,18 @@ def test_ibom_parse_fail(test_dir, caplog, monkeypatch):
mocked_check_output_retOK = b'ERROR Parsing failed' mocked_check_output_retOK = b'ERROR Parsing failed'
# We will patch subprocess.check_output to make ibom fail # We will patch subprocess.check_output to make ibom fail
with monkeypatch.context() as m: with monkeypatch.context() as m:
m.setattr("subprocess.check_output", mocked_check_output) patch_functions(m)
# Start coverage with context.cover_it(cov):
cov.load() # Load the plug-ins
cov.start() load_actions()
# Load the plug-ins # Create an ibom object
load_actions() out = RegOutput.get_class_for('ibom')()
# Create an ibom object out.set_tree({})
out = RegOutput.get_class_for('ibom')() out.config()
out.set_tree({}) # Setup the GS output dir, needed for the output path
out.config() #GS.out_dir = '.'
# Setup the GS output dir, needed for the output path with pytest.raises(SystemExit) as pytest_wrapped_e:
#GS.out_dir = '.' out.run('')
with pytest.raises(SystemExit) as pytest_wrapped_e:
out.run('')
# Stop coverage
cov.stop()
cov.save()
assert pytest_wrapped_e.type == SystemExit assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.value.code == BOM_ERROR assert pytest_wrapped_e.value.code == BOM_ERROR
# logging.debug(caplog.text) # logging.debug(caplog.text)
@ -175,36 +171,49 @@ def test_ibom_parse_fail(test_dir, caplog, monkeypatch):
def test_var_rename_no_variant(): def test_var_rename_no_variant():
# Start coverage with context.cover_it(cov):
cov.load() # Load the plug-ins
cov.start() load_actions()
# Load the plug-ins # Create an ibom object
load_actions() filter = RegFilter.get_class_for('var_rename')()
# Create an ibom object GS.variant = None
filter = RegFilter.get_class_for('var_rename')() # Should just return
GS.variant = None filter.filter(None)
# Should just return
filter.filter(None)
# Stop coverage
cov.stop()
cov.save()
def test_bom_no_sch(): def test_bom_no_sch():
# Start coverage with context.cover_it(cov):
cov.load() # Load the plug-ins
cov.start() load_actions()
# Load the plug-ins # Create an ibom object
load_actions() GS.sch = None
# Create an ibom object out = RegOutput.get_class_for('bom')()
GS.sch = None columns = out.options._get_columns()
out = RegOutput.get_class_for('bom')() assert columns == ColumnList.COLUMNS_DEFAULT
columns = out.options._get_columns() out = RegOutput.get_class_for('kibom')()
assert columns == ColumnList.COLUMNS_DEFAULT options = out.options()
out = RegOutput.get_class_for('kibom')() columns = options.conf._get_columns()
options = out.options() assert columns == ColumnList.COLUMNS_DEFAULT
columns = options.conf._get_columns()
assert columns == ColumnList.COLUMNS_DEFAULT
# Stop coverage def test_pre_xrc_fail(test_dir, caplog, monkeypatch):
cov.stop() ctx = context.TestContext(test_dir, 'test_pre_xrc_fail', 'test_v5', 'empty_zip', '')
cov.save() with monkeypatch.context() as m:
patch_functions(m)
with context.cover_it(cov):
load_actions()
GS.set_pcb(ctx.board_file)
sch = ctx.board_file
GS.set_sch(sch.replace('.kicad_pcb', '.sch'))
GS.out_dir = test_dir
pre_drc = BasePreFlight.get_class_for('run_drc')('run_drc', True)
pre_erc = BasePreFlight.get_class_for('run_erc')('run_erc', True)
with pytest.raises(SystemExit) as e1:
pre_drc.run()
with pytest.raises(SystemExit) as e2:
pre_erc.run()
assert e1.type == SystemExit
assert e1.value.code == DRC_ERROR
assert e2.type == SystemExit
assert e2.value.code == ERC_ERROR
ctx.clean_up()

View File

@ -6,6 +6,7 @@ import logging
import subprocess import subprocess
import re import re
import csv import csv
from contextlib import contextmanager
from glob import glob from glob import glob
from pty import openpty from pty import openpty
import xml.etree.ElementTree as ET import xml.etree.ElementTree as ET
@ -71,6 +72,17 @@ def usable_cmd(cmd):
return ' '.join(cmd) return ' '.join(cmd)
@contextmanager
def cover_it(cov):
# Start coverage
cov.load()
cov.start()
yield
# Stop coverage
cov.stop()
cov.save()
class TestContext(object): class TestContext(object):
def __init__(self, test_dir, test_name, board_name, yaml_name, sub_dir, yaml_compressed=False, add_cfg_kmajor=False): def __init__(self, test_dir, test_name, board_name, yaml_name, sub_dir, yaml_compressed=False, add_cfg_kmajor=False):