Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions python/gvtest/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ def __init__(
self.default_target: Target = Target('default')
else:
self.default_target = Target(self.target_names[0])
# Mark the default target as a fallback — it was
# not resolved from a gvtest.yaml targets section.
self.default_target._is_fallback = True
self.cpu_poll_interval: float = 0.1
self.report_all: bool = report_all
self.progress: bool = progress
Expand Down Expand Up @@ -406,6 +409,11 @@ def stop(self) -> None:
signal.signal(signal.SIGINT, self._orig_sigint)
self._orig_sigint = None

@property
def _cli_targets_specified(self) -> bool:
"""True when the user explicitly passed --target."""
return self.target_names != ['default']

def add_testset(self, file: str) -> None:
if not os.path.isabs(file):
file = os.path.join(os.getcwd(), file)
Expand All @@ -420,6 +428,11 @@ def add_testset(self, file: str) -> None:
self.import_testset(file, target, None)
)
else:
# No YAML targets at this level — load with
# default target. The testset may import
# sub-testsets that DO define targets.
# Filtering of untargeted tests happens at
# enqueue time (see TestCommon.enqueue).
self.testsets.append(
self.import_testset(
file, self.default_target, None
Expand Down
13 changes: 13 additions & 0 deletions python/gvtest/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,19 @@ def enqueue(self) -> None:
self.target.name if self.target is not None
else self.runner.get_config()
)

# When --target is specified, skip tests whose target
# is just the fallback (not from a gvtest.yaml
# targets section). This ensures only tests
# belonging to a real target are executed.
if (self.runner._cli_targets_specified
and self.target is not None
and getattr(
self.target, '_is_fallback', False
)):
# Don't count or show — silently excluded
return

self.runner.count_test()
if self.runner.tui is not None:
self.runner.tui.count_target(config)
Expand Down
5 changes: 4 additions & 1 deletion python/gvtest/testset_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,10 @@ def import_testset(self, file: str) -> None:
)
# else: parent's target not in sub's list → skip
else:
# Inherit parent's target
# Inherit parent's target. If parent is
# "default" and --target was specified,
# the tests created inside will be filtered
# at enqueue time.
self.testsets.append(
self.runner.import_testset(
filepath, self.target, self
Expand Down
146 changes: 146 additions & 0 deletions tests/test_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,152 @@ def testset_build(testset):
assert r.stats.stats['passed'] == 1


def test_cli_target_skips_untargeted_tests(self, tmp_path):
"""When --target X is specified, tests without any
target definition should be skipped entirely."""
# No gvtest.yaml → no targets defined
testset_file = tmp_path / 'testset.cfg'
testset_file.write_text('''
from gvtest.testsuite import *

def testset_build(testset):
testset.set_name('no_target')
test = testset.new_test('should_not_run')
test.add_command(Shell('run', 'echo bad'))
''')
r = Runner(
properties=[], flags=[], nb_threads=1,
targets=['some_target']
)
r.add_testset(str(testset_file))
r.start()
r.run()
r.stop()
# No tests should have run
assert r.stats.stats['passed'] == 0
assert r.stats.stats['failed'] == 0

def test_no_cli_target_runs_all(self, tmp_path):
"""When no --target is specified, tests without
targets should run normally."""
testset_file = tmp_path / 'testset.cfg'
testset_file.write_text('''
from gvtest.testsuite import *

def testset_build(testset):
testset.set_name('default_run')
test = testset.new_test('should_run')
test.add_command(Shell('run', 'echo ok'))
''')
r = Runner(properties=[], flags=[], nb_threads=1)
r.add_testset(str(testset_file))
r.start()
r.run()
r.stop()
assert r.stats.stats['passed'] == 1

def test_cli_target_runs_only_matching(self, tmp_path):
"""When --target X is specified, only tests with
target X should run, not untargeted tests."""
config = tmp_path / 'gvtest.yaml'
config.write_text(
'targets:\n target_a: {}\n target_b: {}\n'
)

testset_file = tmp_path / 'testset.cfg'
testset_file.write_text('''
from gvtest.testsuite import *

def testset_build(testset):
testset.set_name('multi')
test = testset.new_test('targeted_test')
test.add_command(Shell('run', 'echo ok'))
''')
# Request only target_a
r = Runner(
properties=[], flags=[], nb_threads=1,
targets=['target_a']
)
r.add_testset(str(testset_file))
r.start()
r.run()
r.stop()
# Should run once (target_a only, not target_b)
assert r.stats.stats['passed'] == 1

def test_cli_target_with_sub_testset_targets(
self, tmp_path
):
"""When --target X is specified, root has no targets
but a sub-testset defines X, the sub's tests should
run and root's direct tests should be skipped."""
# Sub-testset with targets
sub_dir = tmp_path / 'sub'
sub_dir.mkdir()
sub_config = sub_dir / 'gvtest.yaml'
sub_config.write_text(
'targets:\n spatz_v2: {}\n rv64: {}\n'
)
sub_testset = sub_dir / 'testset.cfg'
sub_testset.write_text('''
from gvtest.testsuite import *

def testset_build(testset):
testset.set_name('sub')
test = testset.new_test('targeted_test')
test.add_command(Shell('run', 'echo targeted'))
''')
# Root testset imports sub, also has its own test
root_testset = tmp_path / 'testset.cfg'
root_testset.write_text('''
from gvtest.testsuite import *

def testset_build(testset):
testset.set_name('root')
test = testset.new_test('untargeted_test')
test.add_command(Shell('run', 'echo untargeted'))
testset.import_testset('sub/testset.cfg')
''')
r = Runner(
properties=[], flags=[], nb_threads=1,
targets=['spatz_v2']
)
r.add_testset(str(root_testset))
r.start()
r.run()
r.stop()
# Only the sub's test for spatz_v2 should run,
# not the root's untargeted test
assert r.stats.stats['passed'] == 1

def test_no_cli_target_runs_all_yaml_targets(
self, tmp_path
):
"""When no --target is specified and YAML defines
targets, all targets should run."""
config = tmp_path / 'gvtest.yaml'
config.write_text(
'targets:\n target_a: {}\n target_b: {}\n'
)

testset_file = tmp_path / 'testset.cfg'
testset_file.write_text('''
from gvtest.testsuite import *

def testset_build(testset):
testset.set_name('all_targets')
test = testset.new_test('run_both')
test.add_command(Shell('run', 'echo ok'))
''')
r = Runner(properties=[], flags=[], nb_threads=1)
r.add_testset(str(testset_file))
r.start()
r.run()
r.stop()
# Should run twice (once per target)
assert r.stats.stats['passed'] == 2


# ---------------------------------------------------------------------------
# Config integration (gvtest.yaml + testset loading)
# ---------------------------------------------------------------------------
Expand Down
Loading