How the vt_resolver Plugin Selects Which Tests to Run Based on Configuration Filters

The vt_resolver plugin constructs a Cartesian configuration parser, applies cascading default and user-defined filters (including only_filter and no_filter), optionally restricts results by test reference, and converts surviving parameter combinations into Avocado Runnable objects for execution.

The vt_resolver plugin serves as the critical bridge between Avocado-VT's cartesian configuration system and Avocado's test resolution engine. When you execute a test command, this plugin determines exactly which tests to run by filtering the full Cartesian product of test parameters according to your configuration settings and command-line options.

Entry Point and Resolution Flow

The resolution process begins in avocado_vt/plugins/vt_resolver.py within the VTResolver.resolve() method:

class VTResolver(VTResolverUtils, Resolver):
    name = "vt"
    description = "Test resolver for Avocado-VT tests"

    def resolve(self, reference):
        """Resolve vt test references into resolutions."""
        return self._get_reference_resolution(reference)

The resolve() method receives a test reference string (which may be empty) and delegates to _get_reference_resolution(). This internal method orchestrates the entire filtering pipeline before returning a ReferenceResolution object indicating success or failure.

Building the Cartesian Parser with VirtTestOptionsProcess

Before applying filters, the resolver must construct a Cartesian parser populated with base configuration values. This occurs in avocado_vt/discovery.py through the DiscoveryMixIn class:

class DiscoveryMixIn:
    def _get_parser(self):
        options_processor = VirtTestOptionsProcess(self.config)
        return options_processor.get_parser()

The VirtTestOptionsProcess class (defined in avocado_vt/options.py) serves as the configuration engine. Its get_parser() method returns a fully configured cartesian_config.Parser instance that has already processed all default and user-specified options.

Applying Configuration Filters in Three Stages

The filtering logic operates in distinct phases within VirtTestOptionsProcess._process_options() (lines 48-80 of avocado_vt/options.py). Each phase narrows the test set further.

Default Filters and Exclusions

When no explicit vt.config file is provided, the system loads tests-shared.cfg and applies built-in default filters. Lines 53-68 check the vt.filter.default_filters configuration and automatically exclude specific test variants unless explicitly overridden:

for arg in ("no_9p_export", "no_virtio_rng", ...):
    if arg not in get_opt(self.config, "vt.filter.default_filters"):
        self.cartesian_parser.only_filter(arg)

These hardcoded exclusions prevent running tests that require unsupported features (such as 9p exports or virtio RNG devices) unless the user explicitly opts into them via the default_filters setting.

User-Defined Only and No Filters

The resolver processes explicit user filters through dedicated methods that parse space-separated values from the configuration. For vt.only_filter:

def _process_only_filter(self):
    if get_opt(self.config, "vt.only_filter"):
        for item in get_opt(self.config, "vt.only_filter").split(" "):
            self.cartesian_parser.only_filter(item)

An identical pattern exists for vt.no_filter in _process_no_filter(), which calls self.cartesian_parser.no_filter(item) for each token. These methods allow precise inclusion or exclusion of test variants based on tags, architectures, or custom labels.

Reference-Based Filtering

After the general configuration filters are applied, the resolver performs a final narrowing step in avocado_vt/plugins/vt_resolver.py if the user provided a specific test reference:

if reference != "":
    cartesian_parser.only_filter(reference)

This step ensures that when you run avocado vt run mysuite/virtio_net, the resolver restricts results to variants matching that specific reference while still respecting all previously applied configuration filters.

Converting Filtered Parameters to Avocado Runnables

Once filtering is complete, the resolver retrieves the surviving parameter combinations via cartesian_parser.get_dicts() and converts each into an Avocado nrunner Runnable. The conversion occurs in _parameters_to_runnable():

def _parameters_to_runnable(self, params):
    params = self.convert_parameters(params)
    uri = params.get("name")
    vt_params = params.get("vt_params")
    for key in ("_name_map_file", "_short_name_map_file", "dep"):
        if key in vt_params:
            del vt_params[key]
    return Runnable("avocado-vt", uri, **vt_params)

The convert_parameters() method (lines 41-64 of avocado_vt/discovery.py) extracts the test name and packages remaining cartesian variables into vt_params. The resulting Runnable objects carry all necessary configuration to execute the specific test variants.

Practical Usage Examples

To run tests while applying specific configuration filters:


# Apply custom only-filters while respecting default exclusions

avocado vt run --vt-only-filter "up smp2" --vt-no-filter "no_9p_export"

# Request a specific test reference with additional filtering

avocado vt run mysuite/virtio_net --vt-only-filter "nic_custom"

In the first command, the resolver applies default filters (excluding no_9p_export unless overridden), then adds the user-specified only_filter tokens ("up", "smp2") and no_filter exclusions. In the second command, the resolver additionally restricts results to variants matching the mysuite/virtio_net reference.

Summary

  • The vt_resolver plugin coordinates test selection through a multi-stage filtering pipeline implemented across avocado_vt/plugins/vt_resolver.py, avocado_vt/discovery.py, and avocado_vt/options.py.
  • Default filters automatically exclude unsupported test variants (such as no_9p_export) unless explicitly included via vt.filter.default_filters.
  • User-defined filters (vt.only_filter and vt.no_filter) parse space-separated tokens to narrow the test set according to specific requirements.
  • Reference filtering provides a final narrowing step when users specify explicit test paths, ensuring only matching variants are returned.
  • Surviving parameter sets are converted into Avocado Runnables via _parameters_to_runnable(), enabling execution through Avocado's nrunner architecture.

Frequently Asked Questions

How do default filters interact with user-specified only_filter options?

Default filters apply first during VirtTestOptionsProcess._process_options() in avocado_vt/options.py (lines 53-68), excluding variants like no_9p_export unless listed in vt.filter.default_filters. User-specified vt.only_filter values are applied afterward through _process_only_filter(), further narrowing the set. The final test list represents the intersection of all applied filters.

Can I override the default exclusion of specific test variants?

Yes. The default filters check vt.filter.default_filters before applying hardcoded exclusions such as no_9p_export or no_virtio_rng. If you include these specific tokens in your vt.filter.default_filters configuration, the VirtTestOptionsProcess class skips the automatic only_filter() call for those arguments, effectively including them in the test set.

What happens when I provide a specific test reference to the resolver?

When VTResolver.resolve() receives a non-empty reference string, the _get_reference_resolution() method in avocado_vt/plugins/vt_resolver.py applies an additional only_filter(reference) call to the Cartesian parser (line 37). This ensures the final parameter set includes only variants matching your specific reference, such as mysuite/virtio_net, while still respecting all previously applied configuration filters.

How are the filtered parameters converted into executable tests?

After filtering, cartesian_parser.get_dicts() yields the surviving parameter dictionaries. The _parameters_to_runnable() method in avocado_vt/plugins/vt_resolver.py processes these through convert_parameters() (defined in avocado_vt/discovery.py, lines 41-64) to extract the test URI and vt_params. It then instantiates an Runnable("avocado-vt", uri, **vt_params) object that Avocado's nrunner architecture executes.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →