├── README ├── VERSION ├── selftests ├── __init__.py ├── unit │ ├── __init__.py │ ├── plugin │ │ └── __init__.py │ ├── utils │ │ ├── __init__.py │ │ ├── cpu.py.data │ │ │ ├── risc_v │ │ │ ├── armv8 │ │ │ ├── power9 │ │ │ ├── power8 │ │ │ ├── armv7 │ │ │ └── i386 │ │ ├── pmem.py │ │ ├── linux_modules.py.data │ │ │ └── lsmod │ │ └── aurl.py │ ├── task.py │ ├── status_utils.py │ ├── safeloader_caveats.py │ ├── references.py │ ├── output.py │ ├── parser.py │ └── dependencies_resolver.py ├── functional │ ├── __init__.py │ ├── utils │ │ ├── __init__.py │ │ └── gdb.py.data │ │ │ ├── segfault.c │ │ │ └── return99.c │ ├── plugin │ │ ├── __init__.py │ │ ├── spawners │ │ │ └── __init__.py │ │ ├── runner_nrunner.py │ │ ├── podman_image.py │ │ └── bystatus.py │ ├── nrunner_interface.py.data │ │ ├── recipe_task.json │ │ ├── recipe_runnable.json │ │ ├── recipe_runnable_noop.json │ │ ├── recipe_runnable_dry_run.json │ │ ├── recipe_task_noop.json │ │ ├── recipe_task_dry_run.json │ │ ├── recipe_runnable_tap.json │ │ ├── recipe_runnable_exec_test.json │ │ ├── recipe_task_tap.json │ │ ├── recipe_runnable_robot.json │ │ ├── recipe_runnable_avocado_instrumented.json │ │ ├── recipe_task_exec_test.json │ │ ├── recipe_runnable_python_unittest.json │ │ ├── recipe_task_robot.json │ │ ├── recipe_task_avocado_instrumented.json │ │ └── recipe_task_python_unittest.json │ ├── coroutine.py │ └── settings.py ├── .data │ ├── safeloader │ │ ├── data │ │ │ ├── __init__.py │ │ │ ├── path │ │ │ │ ├── __init__.py │ │ │ │ ├── parent10.py │ │ │ │ ├── parent2.py │ │ │ │ ├── parent3.py │ │ │ │ ├── parent5.py │ │ │ │ ├── parent6.py │ │ │ │ └── parent8.py │ │ │ ├── parent1.py │ │ │ ├── parent4.py │ │ │ ├── parent7.py │ │ │ ├── parent9.py │ │ │ ├── infinite_recurse.py │ │ │ ├── double_import.py │ │ │ └── dont_detect_non_avocado.py │ │ └── caveat_multilevel │ │ │ ├── l1 │ │ │ ├── __init__.py │ │ │ └── l2 │ │ │ │ ├── __init__.py │ │ │ │ └── l3 │ │ │ │ └── __init__.py │ │ │ ├── failure.py │ │ │ └── success.py │ ├── get_data.py.data │ │ ├── file_data │ │ ├── GetData.test_a │ │ │ ├── test_data │ │ │ ├── long-cbbd │ │ │ │ └── variant_data │ │ │ ├── short-475e │ │ │ │ └── variant_data │ │ │ └── medium-1a7a │ │ │ │ └── variant_data │ │ ├── GetData.test_b │ │ │ └── test_data │ │ ├── get_data.yaml │ │ └── get_data.json │ ├── archive.py.data │ │ ├── test_file.txt │ │ ├── xzfile │ │ ├── bzip2file │ │ ├── gzipfile │ │ ├── zipfile │ │ ├── zstdfile │ │ ├── archive.zip │ │ ├── avocado.gz │ │ ├── avocado.xz │ │ ├── avocado.zst │ │ ├── empty.tar.bz2 │ │ ├── test_file.bz2 │ │ ├── test_file.gz │ │ ├── test_file.xz │ │ ├── test_file.zst │ │ ├── avocado.gz.metadata │ │ ├── avocado.xz.metadata │ │ ├── avocado.zst.metadata │ │ ├── bzip2file.metadata │ │ ├── gzipfile.metadata │ │ ├── xzfile.metadata │ │ ├── tarfile.metadata │ │ ├── test_file.bz2.metadata │ │ ├── test_file.gz.metadata │ │ ├── test_file.xz.metadata │ │ ├── zipfile.metadata │ │ ├── zstdfile.metadata │ │ ├── archive.tar.metadata │ │ ├── archive.zip.metadata │ │ ├── test_file.zst.metadata │ │ ├── test_archive__symlinks.zip │ │ └── test_archive__symlinks.zip.metadata │ ├── hello.deb │ ├── hello.rpm │ ├── sample.iso │ ├── guaca.a │ ├── exec_test_std │ │ ├── exec_test_1mib.py │ │ └── exec_test_64kib.py │ └── unittests.py ├── deployment │ ├── roles │ │ ├── avocado │ │ │ └── tasks │ │ │ │ ├── copr │ │ │ │ ├── official │ │ │ │ ├── pip │ │ │ │ ├── examples.yml │ │ │ │ └── avocado.yml │ │ │ │ ├── rpm │ │ │ │ ├── avocado.yml │ │ │ │ ├── examples.yml │ │ │ │ └── plugins.yml │ │ │ │ └── main.yml │ │ ├── common │ │ │ └── tasks │ │ │ │ ├── main.yml │ │ │ │ ├── aexpect.yml │ │ │ │ └── dependencies.yml │ │ └── virtualenv │ │ │ └── tasks │ │ │ └── main.yml │ ├── inventory │ ├── group_vars │ │ └── all │ ├── ansible.cfg │ ├── deployment.yml │ └── vars.yml ├── jobs │ ├── tests │ │ ├── pass │ │ └── passtest.py │ ├── passjob_html.py │ ├── passjob_cit_varianter.py │ ├── sleepjob_dict_varianter.py │ ├── sleepjob_json_varianter.py │ ├── passjob.py │ ├── pass │ ├── status_server_auto │ └── unix_status_server.py ├── spell.sh ├── signedoff-check.sh ├── check_tmp_dirs ├── run_coverage ├── safeloader.sh └── pre_release │ └── tests │ └── check-copr-rpm-version.sh ├── avocado ├── core │ ├── nrunner │ │ ├── __init__.py │ │ └── config.py │ ├── spawners │ │ ├── __init__.py │ │ └── exceptions.py │ ├── status │ │ ├── __init__.py │ │ └── utils.py │ ├── task │ │ └── __init__.py │ ├── utils │ │ ├── __init__.py │ │ ├── version.py │ │ └── eggenv.py │ ├── dependencies │ │ ├── __init__.py │ │ └── requirements │ │ │ ├── __init__.py │ │ │ └── cache │ │ │ ├── backends │ │ │ └── __init__.py │ │ │ └── __init__.py │ ├── streams.py │ ├── safeloader │ │ ├── utils.py │ │ └── __init__.py │ ├── version.py │ └── job_id.py ├── utils │ ├── network │ │ ├── __init__.py │ │ └── exceptions.py │ ├── software_manager │ │ ├── __init__.py │ │ └── backends │ │ │ ├── __init__.py │ │ │ └── dnf.py │ ├── external │ │ └── __init__.py │ ├── __init__.py │ └── exit_codes.py ├── plugins │ ├── runners │ │ ├── __init__.py │ │ ├── noop.py │ │ └── dry_run.py │ ├── spawners │ │ └── __init__.py │ └── __init__.py ├── etc │ └── avocado │ │ ├── sysinfo │ │ ├── profilers │ │ ├── commands │ │ └── files │ │ └── scripts │ │ └── job │ │ ├── pre.d │ │ └── README │ │ └── post.d │ │ └── README ├── libexec │ ├── avocado_debug │ ├── avocado_error │ ├── avocado_info │ ├── avocado_warn │ └── avocado-bash-utils └── __main__.py ├── docs ├── source │ ├── _static │ │ └── .gitignore │ ├── _templates │ │ └── .gitignore │ ├── guides │ │ ├── contributor │ │ │ ├── api │ │ │ │ ├── .gitignore │ │ │ │ ├── core │ │ │ │ │ └── .gitignore │ │ │ │ ├── test │ │ │ │ │ └── .gitignore │ │ │ │ ├── utils │ │ │ │ │ └── .gitignore │ │ │ │ └── api_utils_heading │ │ │ ├── chapters │ │ │ │ ├── contact.rst │ │ │ │ ├── introduction.rst │ │ │ │ ├── rfc.rst │ │ │ │ └── results.rst │ │ │ └── index.rst │ │ ├── writer │ │ │ └── index.rst │ │ ├── reference │ │ │ └── index.rst │ │ └── user │ │ │ ├── chapters │ │ │ └── whatsnext.rst │ │ │ └── index.rst │ ├── plugins │ │ ├── optional │ │ │ ├── robot.rst │ │ │ ├── golang.rst │ │ │ ├── results │ │ │ │ ├── html.rst │ │ │ │ ├── mail.rst │ │ │ │ ├── resultsdb.rst │ │ │ │ ├── result_upload.rst │ │ │ │ └── index.rst │ │ │ ├── spawner_remote.rst │ │ │ └── varianters │ │ │ │ ├── cit.rst │ │ │ │ ├── pict.rst │ │ │ │ ├── yaml_to_mux.rst │ │ │ │ └── index.rst │ │ └── index.rst │ ├── api │ │ └── headers │ │ │ ├── plugins │ │ │ ├── optional │ │ │ ├── core │ │ │ ├── test │ │ │ └── utils │ ├── blueprints │ │ └── images │ │ │ ├── BP003 │ │ │ ├── Resolution.png │ │ │ ├── Resolution-to-task.png │ │ │ └── Task-scheduler-flow.png │ │ │ ├── BP004 │ │ │ ├── dependency_graph.png │ │ │ ├── dot_representation.png │ │ │ └── current_requirements_resolver.png │ │ │ └── requirements-resolver.png │ ├── releases │ │ ├── 88_1.rst │ │ ├── next.rst │ │ └── lts │ │ │ └── next.rst │ └── config │ │ └── index.rst └── README.rst ├── contrib ├── packages │ └── debian │ │ ├── compat │ │ ├── source │ │ ├── format │ │ └── options │ │ ├── watch │ │ ├── rules │ │ ├── README │ │ ├── control │ │ ├── Makefile │ │ └── copyright ├── scripts │ ├── docs-change-home.sh │ ├── vmimage-populate-cache.py │ └── avocado-get-job-results-dir.py ├── containers │ ├── ci │ │ └── selftests │ │ │ ├── check-copr-rpm-version.docker │ │ │ ├── fedora-40.docker │ │ │ └── magic.docker │ └── fedora-40-latest-copr.docker ├── job-scripts │ └── coredump-handling │ │ └── post.d │ │ └── 001-restore-core-pattern └── docker │ └── Dockerfile.fedora ├── examples ├── tests │ ├── use_data.sh.data │ │ └── data │ ├── output_check.sh.data │ │ ├── stderr.expected │ │ └── stdout.expected │ ├── failtest.sh │ ├── passtest.sh │ ├── cabort.py.data │ │ └── abort.c │ ├── datadir.py.data │ │ └── datadir.c │ ├── use_data.sh │ ├── sleeptest.sh │ ├── sleeptest.py.data │ │ ├── sleeptest.yaml │ │ └── sleeptest.json │ ├── sleeptest.sh.data │ │ └── sleeptest.yaml │ ├── linuxbuild.py.data │ │ └── linuxbuild.yaml │ ├── modify_variable.py.data │ │ └── print_variable.c │ ├── custom_env_variable.sh │ ├── custom_env_variable.sh.data │ │ └── variants.yaml │ ├── env_variables.sh.data │ │ └── env_variables.yaml │ ├── true │ ├── false │ ├── canceltest.py │ ├── passtest.py │ ├── dependency_pip.py │ ├── warntest.py │ ├── abort.py │ ├── params.py │ ├── errortest.py │ ├── failtest.py │ ├── passtest_with_dependency.py │ ├── logging_custom_level.py │ ├── simplewarning.sh │ ├── uncaught_exception.py │ ├── raise.py.data │ │ ├── raise.yaml │ │ └── raise.c │ ├── failtest_ugly.py │ ├── phases.py │ ├── failtest_with_warning.py │ ├── cancelonsetup.py │ ├── assert.py │ ├── cit_parameters.py │ ├── whiteboard.py │ ├── sleeptest.py │ ├── sleeptenmin.py.data │ │ └── sleeptenmin.yaml │ ├── doublefail.py │ ├── gendata.py │ ├── sleeptest_async.py │ ├── property.py │ ├── timeouttest.py │ ├── errortest_nasty.py │ ├── errortest_nasty3.py │ ├── errortest_nasty2.py │ ├── external_logging_stream.py │ ├── cancel_on_exception.py │ ├── env_variables.sh │ ├── fail_on_exception.py │ ├── dependency_ansible.py │ ├── multiple_tests.py │ ├── cancel_test.py │ ├── sleeptenmin.py │ ├── datadir.py │ ├── cabort.py │ └── logging_streams.py ├── plugins │ ├── tests │ │ ├── magic │ │ │ ├── avocado_magic │ │ │ │ └── __init__.py │ │ │ └── setup.py │ │ ├── rogue │ │ │ ├── avocado_rogue │ │ │ │ └── __init__.py │ │ │ └── setup.py │ │ └── README.rst │ ├── cli-cmd │ │ ├── hello │ │ │ ├── hello.py │ │ │ └── setup.py │ │ ├── hello_priority │ │ │ ├── setup.py │ │ │ └── hello_priority.py │ │ ├── hello_option │ │ │ ├── setup.py │ │ │ └── hello_option.py │ │ └── hello_parser │ │ │ ├── setup.py │ │ │ └── hello_parser.py │ ├── README.rst │ ├── test-pre-post │ │ └── hello │ │ │ ├── setup.py │ │ │ └── hello.py │ └── job-pre-post │ │ └── sleep │ │ ├── setup.py │ │ └── avocado_job_sleep.py ├── nrunner │ ├── recipes │ │ ├── runnable │ │ │ ├── noop.json │ │ │ ├── identifier.json │ │ │ ├── package_check_foo.json │ │ │ ├── pip_coverage.json │ │ │ ├── exec_test_echo_no_newline.json │ │ │ ├── noop_config.json │ │ │ ├── exec_test_sleep_3.json │ │ │ ├── vmimage_fedora.json │ │ │ ├── python_unittest.json │ │ │ ├── asset.json │ │ │ ├── exec_test_sh_echo_env_var.json │ │ │ └── sysinfo.json │ │ ├── tasks │ │ │ ├── exec-test │ │ │ │ ├── 1-uname.json │ │ │ │ ├── 3-sleep.json │ │ │ │ └── 2-echo.json │ │ │ ├── exec-status │ │ │ │ ├── 1-uname-result.json │ │ │ │ ├── 3-sleep-result.json │ │ │ │ ├── 4-sleep-long-result.json │ │ │ │ └── 2-dd-result.json │ │ │ └── unittest-result │ │ │ │ └── 1-unittest-testcase-localhost.json │ │ └── runnables │ │ │ └── true_false.json │ └── resolvers │ │ ├── exec_runnables_recipe.sh │ │ └── exec_runnables_recipe_kind.sh ├── gdb-prerun-scripts │ ├── pass-sigusr1 │ └── README ├── yaml_to_mux │ ├── simple.yaml │ ├── os │ │ ├── windows.yaml │ │ └── linux.yaml │ ├── simple_vars.yaml │ ├── complex.yaml │ ├── hw │ │ └── hw.yaml │ └── types.yaml ├── hint-files │ ├── .avocado.hint.example │ └── README.rst ├── varianter_pict │ └── params.pict ├── jobs │ ├── failjob.py │ ├── README.rst │ ├── passjob_html.py │ ├── passjob_cit_varianter.py │ ├── sleepjob_yaml_to_mux.py │ ├── sleepjob_dict_varianter.py │ ├── sleepjob_json_varianter.py │ ├── passjob_html_browser.py │ ├── passjob.py │ ├── multiple_spawners.py │ ├── sleepjob_parameters.py │ ├── passjob_with_test.py │ ├── passjob_custom.py │ ├── multiple_suites_from_config.py │ └── unix_status_server.py ├── varianter_cit │ ├── test_params.cit │ └── params.cit └── apis │ └── utils │ ├── ssh_timeout.py │ └── ssh.py ├── optional_plugins ├── html │ ├── README │ ├── VERSION │ ├── tests │ │ └── __init__.py │ └── MANIFEST.in ├── mail │ ├── README │ ├── VERSION │ ├── avocado_result_mail │ │ └── __init__.py │ └── MANIFEST.in ├── ansible │ ├── VERSION │ └── MANIFEST.in ├── golang │ ├── README │ ├── VERSION │ ├── MANIFEST.in │ └── tests │ │ └── src │ │ └── countavocados │ │ ├── countavocados.go │ │ └── countavocados_test.go ├── resultsdb │ ├── README │ ├── VERSION │ └── MANIFEST.in ├── robot │ ├── README │ ├── VERSION │ ├── MANIFEST.in │ └── tests │ │ └── avocado.robot ├── result_upload │ ├── README │ ├── VERSION │ └── MANIFEST.in ├── varianter_cit │ ├── README │ ├── VERSION │ └── MANIFEST.in ├── varianter_pict │ ├── README │ ├── VERSION │ └── MANIFEST.in ├── spawner_remote │ ├── VERSION │ └── MANIFEST.in ├── varianter_yaml_to_mux │ ├── README │ ├── VERSION │ ├── tests │ │ └── .data │ │ │ ├── empty_file │ │ │ ├── mux-selftest-using.yaml │ │ │ ├── mux-šelftest-distro.yaml │ │ │ ├── mux-environment.yaml │ │ │ └── mux-selftest-params.yaml │ └── MANIFEST.in └── README.rst ├── README.rst ├── requirements-doc.txt ├── CONTRIBUTING.rst ├── .gitattributes ├── .coveragerc ├── .gitmodules ├── avocado-static-checks.conf ├── MANIFEST.in ├── codecov.yml ├── .github ├── actions │ ├── version │ │ └── action.yml │ └── egg │ │ └── action.yml ├── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md └── workflows │ └── ansible.yml ├── .packit.yml ├── Makefile.include ├── .gitignore ├── requirements-dev.txt ├── .readthedocs.yaml └── .copr └── Makefile /README: -------------------------------------------------------------------------------- 1 | README.rst -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 112.0 2 | -------------------------------------------------------------------------------- /selftests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /selftests/unit/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /avocado/core/nrunner/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /avocado/core/spawners/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /avocado/core/status/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /avocado/core/task/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /avocado/core/utils/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /avocado/utils/network/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/source/_static/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/source/_templates/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /selftests/functional/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /selftests/unit/plugin/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /selftests/unit/utils/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /avocado/core/dependencies/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /avocado/plugins/runners/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /avocado/plugins/spawners/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /contrib/packages/debian/compat: -------------------------------------------------------------------------------- 1 | 10 2 | -------------------------------------------------------------------------------- /examples/tests/use_data.sh.data/data: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /optional_plugins/html/README: -------------------------------------------------------------------------------- 1 | README.rst -------------------------------------------------------------------------------- /optional_plugins/mail/README: -------------------------------------------------------------------------------- 1 | README.rst -------------------------------------------------------------------------------- /selftests/functional/utils/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | docs/source/quickstart/index.rst -------------------------------------------------------------------------------- /avocado/utils/software_manager/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /optional_plugins/ansible/VERSION: -------------------------------------------------------------------------------- 1 | 112.0 2 | -------------------------------------------------------------------------------- /optional_plugins/golang/README: -------------------------------------------------------------------------------- 1 | README.rst -------------------------------------------------------------------------------- /optional_plugins/golang/VERSION: -------------------------------------------------------------------------------- 1 | 112.0 2 | -------------------------------------------------------------------------------- /optional_plugins/html/VERSION: -------------------------------------------------------------------------------- 1 | 112.0 2 | -------------------------------------------------------------------------------- /optional_plugins/html/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /optional_plugins/mail/VERSION: -------------------------------------------------------------------------------- 1 | 112.0 2 | -------------------------------------------------------------------------------- /optional_plugins/resultsdb/README: -------------------------------------------------------------------------------- 1 | README.rst -------------------------------------------------------------------------------- /optional_plugins/robot/README: -------------------------------------------------------------------------------- 1 | README.rst -------------------------------------------------------------------------------- /optional_plugins/robot/VERSION: -------------------------------------------------------------------------------- 1 | 112.0 2 | -------------------------------------------------------------------------------- /selftests/.data/safeloader/data/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /selftests/functional/plugin/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /optional_plugins/result_upload/README: -------------------------------------------------------------------------------- 1 | README.rst -------------------------------------------------------------------------------- /optional_plugins/result_upload/VERSION: -------------------------------------------------------------------------------- 1 | 112.0 2 | -------------------------------------------------------------------------------- /optional_plugins/resultsdb/VERSION: -------------------------------------------------------------------------------- 1 | 112.0 2 | -------------------------------------------------------------------------------- /optional_plugins/varianter_cit/README: -------------------------------------------------------------------------------- 1 | README.rst -------------------------------------------------------------------------------- /optional_plugins/varianter_cit/VERSION: -------------------------------------------------------------------------------- 1 | 112.0 2 | -------------------------------------------------------------------------------- /optional_plugins/varianter_pict/README: -------------------------------------------------------------------------------- 1 | README.rst -------------------------------------------------------------------------------- /requirements-doc.txt: -------------------------------------------------------------------------------- 1 | sphinx-rtd-theme==2.0.0 2 | -------------------------------------------------------------------------------- /selftests/.data/safeloader/data/path/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /selftests/functional/plugin/spawners/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /avocado/core/dependencies/requirements/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /avocado/utils/software_manager/backends/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/tests/output_check.sh.data/stderr.expected: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /optional_plugins/mail/avocado_result_mail/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /optional_plugins/spawner_remote/VERSION: -------------------------------------------------------------------------------- 1 | 112.0 2 | -------------------------------------------------------------------------------- /optional_plugins/varianter_pict/VERSION: -------------------------------------------------------------------------------- 1 | 112.0 2 | -------------------------------------------------------------------------------- /selftests/.data/get_data.py.data/file_data: -------------------------------------------------------------------------------- 1 | get_data.py -------------------------------------------------------------------------------- /selftests/deployment/roles/avocado/tasks/copr: -------------------------------------------------------------------------------- 1 | rpm/ -------------------------------------------------------------------------------- /selftests/deployment/roles/avocado/tasks/official: -------------------------------------------------------------------------------- 1 | rpm -------------------------------------------------------------------------------- /selftests/jobs/tests/pass: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exit 0 3 | -------------------------------------------------------------------------------- /CONTRIBUTING.rst: -------------------------------------------------------------------------------- 1 | docs/source/guides/contributor/index.rst -------------------------------------------------------------------------------- /contrib/packages/debian/source/format: -------------------------------------------------------------------------------- 1 | 3.0 (native) 2 | -------------------------------------------------------------------------------- /docs/source/guides/contributor/api/.gitignore: -------------------------------------------------------------------------------- 1 | *.rst 2 | -------------------------------------------------------------------------------- /examples/plugins/tests/magic/avocado_magic/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/tests/failtest.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | false 3 | 4 | -------------------------------------------------------------------------------- /examples/tests/passtest.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | true 3 | 4 | -------------------------------------------------------------------------------- /optional_plugins/ansible/MANIFEST.in: -------------------------------------------------------------------------------- 1 | include VERSION 2 | -------------------------------------------------------------------------------- /optional_plugins/varianter_yaml_to_mux/README: -------------------------------------------------------------------------------- 1 | README.rst -------------------------------------------------------------------------------- /optional_plugins/varianter_yaml_to_mux/VERSION: -------------------------------------------------------------------------------- 1 | 112.0 2 | -------------------------------------------------------------------------------- /selftests/.data/get_data.py.data/GetData.test_a/test_data: -------------------------------------------------------------------------------- 1 | a -------------------------------------------------------------------------------- /selftests/.data/get_data.py.data/GetData.test_b/test_data: -------------------------------------------------------------------------------- 1 | b -------------------------------------------------------------------------------- /selftests/deployment/inventory: -------------------------------------------------------------------------------- 1 | [local] 2 | localhost 3 | -------------------------------------------------------------------------------- /docs/source/guides/contributor/api/core/.gitignore: -------------------------------------------------------------------------------- 1 | *.rst 2 | -------------------------------------------------------------------------------- /docs/source/guides/contributor/api/test/.gitignore: -------------------------------------------------------------------------------- 1 | *.rst 2 | -------------------------------------------------------------------------------- /docs/source/guides/contributor/api/utils/.gitignore: -------------------------------------------------------------------------------- 1 | *.rst 2 | -------------------------------------------------------------------------------- /optional_plugins/spawner_remote/MANIFEST.in: -------------------------------------------------------------------------------- 1 | include VERSION 2 | -------------------------------------------------------------------------------- /optional_plugins/varianter_yaml_to_mux/tests/.data/empty_file: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /selftests/.data/safeloader/caveat_multilevel/l1/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /selftests/.data/safeloader/caveat_multilevel/l1/l2/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /avocado/core/dependencies/requirements/cache/backends/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /avocado/etc/avocado/sysinfo/profilers: -------------------------------------------------------------------------------- 1 | vmstat 1 2 | journalctl -f 3 | -------------------------------------------------------------------------------- /contrib/packages/debian/source/options: -------------------------------------------------------------------------------- 1 | tar-ignore = ".git/*" 2 | -------------------------------------------------------------------------------- /examples/nrunner/recipes/runnable/noop.json: -------------------------------------------------------------------------------- 1 | {"kind": "noop"} 2 | -------------------------------------------------------------------------------- /optional_plugins/golang/MANIFEST.in: -------------------------------------------------------------------------------- 1 | include VERSION README.rst 2 | -------------------------------------------------------------------------------- /optional_plugins/mail/MANIFEST.in: -------------------------------------------------------------------------------- 1 | include VERSION README.rst 2 | -------------------------------------------------------------------------------- /optional_plugins/robot/MANIFEST.in: -------------------------------------------------------------------------------- 1 | include VERSION README.rst 2 | -------------------------------------------------------------------------------- /selftests/jobs/tests/passtest.py: -------------------------------------------------------------------------------- 1 | ../../../examples/tests/passtest.py -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.min.css binary 2 | *.min.js binary 3 | *.svg binary 4 | -------------------------------------------------------------------------------- /examples/tests/output_check.sh.data/stdout.expected: -------------------------------------------------------------------------------- 1 | Hello, world! 2 | -------------------------------------------------------------------------------- /optional_plugins/result_upload/MANIFEST.in: -------------------------------------------------------------------------------- 1 | include VERSION README.rst 2 | -------------------------------------------------------------------------------- /optional_plugins/resultsdb/MANIFEST.in: -------------------------------------------------------------------------------- 1 | include VERSION README.rst 2 | -------------------------------------------------------------------------------- /optional_plugins/varianter_cit/MANIFEST.in: -------------------------------------------------------------------------------- 1 | include VERSION README.rst 2 | -------------------------------------------------------------------------------- /optional_plugins/varianter_pict/MANIFEST.in: -------------------------------------------------------------------------------- 1 | include VERSION README.rst 2 | -------------------------------------------------------------------------------- /docs/source/plugins/optional/robot.rst: -------------------------------------------------------------------------------- 1 | ../../../../optional_plugins/robot/README.rst -------------------------------------------------------------------------------- /optional_plugins/varianter_yaml_to_mux/MANIFEST.in: -------------------------------------------------------------------------------- 1 | include VERSION README.rst 2 | -------------------------------------------------------------------------------- /selftests/.data/get_data.py.data/GetData.test_a/long-cbbd/variant_data: -------------------------------------------------------------------------------- 1 | variant_data -------------------------------------------------------------------------------- /selftests/.data/get_data.py.data/GetData.test_a/short-475e/variant_data: -------------------------------------------------------------------------------- 1 | variant_data -------------------------------------------------------------------------------- /avocado/core/spawners/exceptions.py: -------------------------------------------------------------------------------- 1 | class SpawnerException(Exception): 2 | pass 3 | -------------------------------------------------------------------------------- /docs/source/plugins/optional/golang.rst: -------------------------------------------------------------------------------- 1 | ../../../../optional_plugins/golang/README.rst -------------------------------------------------------------------------------- /selftests/.data/get_data.py.data/GetData.test_a/medium-1a7a/variant_data: -------------------------------------------------------------------------------- 1 | variant_data -------------------------------------------------------------------------------- /selftests/deployment/group_vars/all: -------------------------------------------------------------------------------- 1 | ansible_python_interpreter: /usr/bin/python3 2 | -------------------------------------------------------------------------------- /selftests/functional/nrunner_interface.py.data/recipe_task.json: -------------------------------------------------------------------------------- 1 | recipe_task_noop.json -------------------------------------------------------------------------------- /docs/source/api/headers/plugins: -------------------------------------------------------------------------------- 1 | Extension APIs that may be of interest to plugin writers. 2 | -------------------------------------------------------------------------------- /docs/source/plugins/optional/results/html.rst: -------------------------------------------------------------------------------- 1 | ../../../../../optional_plugins/html/README.rst -------------------------------------------------------------------------------- /docs/source/plugins/optional/results/mail.rst: -------------------------------------------------------------------------------- 1 | ../../../../../optional_plugins/mail/README.rst -------------------------------------------------------------------------------- /examples/gdb-prerun-scripts/pass-sigusr1: -------------------------------------------------------------------------------- 1 | signal SIGUSR1 pass 2 | signal SIGUSR1 nostop 3 | -------------------------------------------------------------------------------- /selftests/.data/archive.py.data/test_file.txt: -------------------------------------------------------------------------------- 1 | This is a test file for archive testing. 2 | -------------------------------------------------------------------------------- /selftests/functional/nrunner_interface.py.data/recipe_runnable.json: -------------------------------------------------------------------------------- 1 | recipe_runnable_noop.json -------------------------------------------------------------------------------- /selftests/functional/nrunner_interface.py.data/recipe_runnable_noop.json: -------------------------------------------------------------------------------- 1 | {"kind": "noop"} 2 | -------------------------------------------------------------------------------- /avocado/libexec/avocado_debug: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . avocado-bash-utils 3 | 4 | avocado_log DEBUG $* 5 | -------------------------------------------------------------------------------- /avocado/libexec/avocado_error: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . avocado-bash-utils 3 | 4 | avocado_log ERROR $* 5 | -------------------------------------------------------------------------------- /avocado/libexec/avocado_info: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . avocado-bash-utils 3 | 4 | avocado_log INFO $* 5 | -------------------------------------------------------------------------------- /avocado/libexec/avocado_warn: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . avocado-bash-utils 3 | 4 | avocado_log WARN $* 5 | -------------------------------------------------------------------------------- /examples/nrunner/recipes/runnable/identifier.json: -------------------------------------------------------------------------------- 1 | {"kind": "noop", "identifier": "test-noop"} 2 | -------------------------------------------------------------------------------- /examples/plugins/tests/rogue/avocado_rogue/__init__.py: -------------------------------------------------------------------------------- 1 | MAGIC_WORD = "x-avocado-runner-rogue" 2 | -------------------------------------------------------------------------------- /docs/source/plugins/optional/results/resultsdb.rst: -------------------------------------------------------------------------------- 1 | ../../../../../optional_plugins/resultsdb/README.rst -------------------------------------------------------------------------------- /docs/source/plugins/optional/spawner_remote.rst: -------------------------------------------------------------------------------- 1 | ../../../../optional_plugins/spawner_remote/README.rst -------------------------------------------------------------------------------- /docs/source/plugins/optional/varianters/cit.rst: -------------------------------------------------------------------------------- 1 | ../../../../../optional_plugins/varianter_cit/README.rst -------------------------------------------------------------------------------- /selftests/functional/nrunner_interface.py.data/recipe_runnable_dry_run.json: -------------------------------------------------------------------------------- 1 | {"kind": "dry-run"} 2 | -------------------------------------------------------------------------------- /docs/source/plugins/optional/varianters/pict.rst: -------------------------------------------------------------------------------- 1 | ../../../../../optional_plugins/varianter_pict/README.rst -------------------------------------------------------------------------------- /docs/source/api/headers/optional: -------------------------------------------------------------------------------- 1 | The following pages document the private APIs of optional Avocado plugins. 2 | -------------------------------------------------------------------------------- /docs/source/plugins/optional/results/result_upload.rst: -------------------------------------------------------------------------------- 1 | ../../../../../optional_plugins/result_upload/README.rst -------------------------------------------------------------------------------- /selftests/.data/hello.deb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avocado-framework/avocado/HEAD/selftests/.data/hello.deb -------------------------------------------------------------------------------- /selftests/.data/hello.rpm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avocado-framework/avocado/HEAD/selftests/.data/hello.rpm -------------------------------------------------------------------------------- /selftests/.data/sample.iso: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avocado-framework/avocado/HEAD/selftests/.data/sample.iso -------------------------------------------------------------------------------- /examples/tests/cabort.py.data/abort.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int 4 | main(void) 5 | { 6 | abort(); 7 | } 8 | -------------------------------------------------------------------------------- /optional_plugins/html/MANIFEST.in: -------------------------------------------------------------------------------- 1 | recursive-include avocado_result_html/templates * 2 | include VERSION README.rst 3 | -------------------------------------------------------------------------------- /selftests/functional/nrunner_interface.py.data/recipe_task_noop.json: -------------------------------------------------------------------------------- 1 | {"id": "1", "runnable": {"kind": "noop"}} 2 | -------------------------------------------------------------------------------- /docs/source/plugins/optional/varianters/yaml_to_mux.rst: -------------------------------------------------------------------------------- 1 | ../../../../../optional_plugins/varianter_yaml_to_mux/README.rst -------------------------------------------------------------------------------- /optional_plugins/varianter_yaml_to_mux/tests/.data/mux-selftest-using.yaml: -------------------------------------------------------------------------------- 1 | !using : /foo 2 | bar: 3 | !using : baz 4 | -------------------------------------------------------------------------------- /selftests/functional/nrunner_interface.py.data/recipe_task_dry_run.json: -------------------------------------------------------------------------------- 1 | {"id": "1", "runnable": {"kind": "dry-run"}} 2 | -------------------------------------------------------------------------------- /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | source = avocado/, optional_plugins/ 3 | concurrency = multiprocessing, thread 4 | parallel = true 5 | -------------------------------------------------------------------------------- /contrib/packages/debian/watch: -------------------------------------------------------------------------------- 1 | version=3 2 | 3 | https://github.com/avocado-framework/avocado/tags .*/(\d[\d\.]+)\.tar\.gz 4 | -------------------------------------------------------------------------------- /examples/nrunner/recipes/runnable/package_check_foo.json: -------------------------------------------------------------------------------- 1 | {"kind": "package", "kwargs": {"action": "check", "name": "foo"}} 2 | -------------------------------------------------------------------------------- /examples/nrunner/recipes/runnable/pip_coverage.json: -------------------------------------------------------------------------------- 1 | {"kind": "pip", "kwargs": {"action": "install", "name": "coverage"}} 2 | -------------------------------------------------------------------------------- /examples/yaml_to_mux/simple.yaml: -------------------------------------------------------------------------------- 1 | # Very simple example with 2 variants and no values in them 2 | !mux 3 | first: 4 | second: 5 | -------------------------------------------------------------------------------- /selftests/deployment/ansible.cfg: -------------------------------------------------------------------------------- 1 | [defaults] 2 | inventory = ./inventory 3 | 4 | [privilege_escalation] 5 | become = false 6 | -------------------------------------------------------------------------------- /selftests/unit/utils/cpu.py.data/risc_v: -------------------------------------------------------------------------------- 1 | hart : 1 2 | isa : rv64imafdc 3 | mmu : sv39 4 | uarch : sifive,rocket0 5 | -------------------------------------------------------------------------------- /selftests/functional/nrunner_interface.py.data/recipe_runnable_tap.json: -------------------------------------------------------------------------------- 1 | {"kind": "tap", "uri": "/usr/bin/echo", "args": ["0..0"]} 2 | -------------------------------------------------------------------------------- /examples/nrunner/recipes/runnable/exec_test_echo_no_newline.json: -------------------------------------------------------------------------------- 1 | {"kind": "exec-test", "uri": "/bin/echo", "args": ["-n", "avocado"]} 2 | -------------------------------------------------------------------------------- /selftests/.data/archive.py.data/xzfile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avocado-framework/avocado/HEAD/selftests/.data/archive.py.data/xzfile -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "static-checks"] 2 | path = static-checks 3 | url = https://github.com/avocado-framework/avocado-static-checks 4 | -------------------------------------------------------------------------------- /examples/nrunner/recipes/runnable/noop_config.json: -------------------------------------------------------------------------------- 1 | {"kind": "noop", "uri": "noop", "config": {"runner.identifier_format": "nothing-op"}} 2 | -------------------------------------------------------------------------------- /examples/nrunner/recipes/tasks/exec-test/1-uname.json: -------------------------------------------------------------------------------- 1 | {"id": 1, "runnable": {"kind": "exec-test", "uri": "/bin/uname", "args": ["-a"]}} 2 | -------------------------------------------------------------------------------- /examples/nrunner/recipes/tasks/exec-test/3-sleep.json: -------------------------------------------------------------------------------- 1 | {"id": 3, "runnable": {"kind": "exec-test", "uri": "/bin/sleep", "args": ["0.01"]}} 2 | -------------------------------------------------------------------------------- /selftests/.data/archive.py.data/bzip2file: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avocado-framework/avocado/HEAD/selftests/.data/archive.py.data/bzip2file -------------------------------------------------------------------------------- /selftests/.data/archive.py.data/gzipfile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avocado-framework/avocado/HEAD/selftests/.data/archive.py.data/gzipfile -------------------------------------------------------------------------------- /selftests/.data/archive.py.data/zipfile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avocado-framework/avocado/HEAD/selftests/.data/archive.py.data/zipfile -------------------------------------------------------------------------------- /selftests/.data/archive.py.data/zstdfile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avocado-framework/avocado/HEAD/selftests/.data/archive.py.data/zstdfile -------------------------------------------------------------------------------- /avocado-static-checks.conf: -------------------------------------------------------------------------------- 1 | [lint] 2 | avocado/utils:static-checks/default_configs/pylintrc 3 | avocado/utils:.pylintrc_utils 4 | .:.pylintrc 5 | -------------------------------------------------------------------------------- /examples/nrunner/recipes/runnable/exec_test_sleep_3.json: -------------------------------------------------------------------------------- 1 | {"kind": "exec-test", "uri": "/bin/sleep", "identifier": "sleep-test", "args": ["3"]} 2 | -------------------------------------------------------------------------------- /examples/nrunner/recipes/runnable/vmimage_fedora.json: -------------------------------------------------------------------------------- 1 | {"kind": "vmimage", "kwargs": {"provider": "fedora", "version": "41", "arch": "x86_64"}} 2 | -------------------------------------------------------------------------------- /examples/nrunner/recipes/tasks/exec-test/2-echo.json: -------------------------------------------------------------------------------- 1 | {"id": 2, "runnable": {"kind": "exec-test", "uri": "/bin/echo", "args": ["-n", "avocado"]}} 2 | -------------------------------------------------------------------------------- /examples/tests/datadir.py.data/datadir.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | printf("Hello Data Dir"); 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /selftests/.data/archive.py.data/archive.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avocado-framework/avocado/HEAD/selftests/.data/archive.py.data/archive.zip -------------------------------------------------------------------------------- /selftests/.data/archive.py.data/avocado.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avocado-framework/avocado/HEAD/selftests/.data/archive.py.data/avocado.gz -------------------------------------------------------------------------------- /selftests/.data/archive.py.data/avocado.xz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avocado-framework/avocado/HEAD/selftests/.data/archive.py.data/avocado.xz -------------------------------------------------------------------------------- /selftests/.data/archive.py.data/avocado.zst: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avocado-framework/avocado/HEAD/selftests/.data/archive.py.data/avocado.zst -------------------------------------------------------------------------------- /selftests/.data/safeloader/data/parent1.py: -------------------------------------------------------------------------------- 1 | import avocado 2 | 3 | 4 | class Class1(avocado.Test): 5 | def test(self): 6 | pass 7 | -------------------------------------------------------------------------------- /selftests/.data/safeloader/data/parent4.py: -------------------------------------------------------------------------------- 1 | import avocado 2 | 3 | 4 | class Class4(avocado.Test): 5 | def test(self): 6 | pass 7 | -------------------------------------------------------------------------------- /selftests/.data/safeloader/data/parent7.py: -------------------------------------------------------------------------------- 1 | import avocado 2 | 3 | 4 | class Class7(avocado.Test): 5 | def test(self): 6 | pass 7 | -------------------------------------------------------------------------------- /selftests/.data/safeloader/data/parent9.py: -------------------------------------------------------------------------------- 1 | import avocado 2 | 3 | 4 | class Class9(avocado.Test): 5 | def test(self): 6 | pass 7 | -------------------------------------------------------------------------------- /examples/nrunner/recipes/runnable/python_unittest.json: -------------------------------------------------------------------------------- 1 | {"kind": "python-unittest", "uri": "selftests/unit/test.py:TestClassTestUnit.test_long_name"} 2 | -------------------------------------------------------------------------------- /selftests/.data/archive.py.data/empty.tar.bz2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avocado-framework/avocado/HEAD/selftests/.data/archive.py.data/empty.tar.bz2 -------------------------------------------------------------------------------- /selftests/.data/archive.py.data/test_file.bz2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avocado-framework/avocado/HEAD/selftests/.data/archive.py.data/test_file.bz2 -------------------------------------------------------------------------------- /selftests/.data/archive.py.data/test_file.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avocado-framework/avocado/HEAD/selftests/.data/archive.py.data/test_file.gz -------------------------------------------------------------------------------- /selftests/.data/archive.py.data/test_file.xz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avocado-framework/avocado/HEAD/selftests/.data/archive.py.data/test_file.xz -------------------------------------------------------------------------------- /selftests/.data/archive.py.data/test_file.zst: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avocado-framework/avocado/HEAD/selftests/.data/archive.py.data/test_file.zst -------------------------------------------------------------------------------- /selftests/.data/safeloader/data/path/parent10.py: -------------------------------------------------------------------------------- 1 | import avocado 2 | 3 | 4 | class Class10(avocado.Test): 5 | def test(self): 6 | pass 7 | -------------------------------------------------------------------------------- /selftests/.data/safeloader/data/path/parent2.py: -------------------------------------------------------------------------------- 1 | import avocado 2 | 3 | 4 | class Class2(avocado.Test): 5 | def test(self): 6 | pass 7 | -------------------------------------------------------------------------------- /selftests/.data/safeloader/data/path/parent3.py: -------------------------------------------------------------------------------- 1 | import avocado 2 | 3 | 4 | class Class3(avocado.Test): 5 | def test(self): 6 | pass 7 | -------------------------------------------------------------------------------- /selftests/.data/safeloader/data/path/parent5.py: -------------------------------------------------------------------------------- 1 | import avocado 2 | 3 | 4 | class Class5(avocado.Test): 5 | def test(self): 6 | pass 7 | -------------------------------------------------------------------------------- /selftests/.data/safeloader/data/path/parent6.py: -------------------------------------------------------------------------------- 1 | import avocado 2 | 3 | 4 | class Class6(avocado.Test): 5 | def test(self): 6 | pass 7 | -------------------------------------------------------------------------------- /selftests/.data/safeloader/data/path/parent8.py: -------------------------------------------------------------------------------- 1 | import avocado 2 | 3 | 4 | class Class8(avocado.Test): 5 | def test(self): 6 | pass 7 | -------------------------------------------------------------------------------- /selftests/functional/nrunner_interface.py.data/recipe_runnable_exec_test.json: -------------------------------------------------------------------------------- 1 | {"kind": "exec-test", "uri": "/usr/bin/python3", "args": ["--version"]} 2 | -------------------------------------------------------------------------------- /examples/hint-files/.avocado.hint.example: -------------------------------------------------------------------------------- 1 | [kinds] 2 | tap = ./tests/unit/*.sh 3 | 4 | [tap] 5 | uri = $testpath 6 | args = --tap 7 | kwargs = DEBUG=1 8 | -------------------------------------------------------------------------------- /selftests/.data/get_data.py.data/get_data.yaml: -------------------------------------------------------------------------------- 1 | !mux 2 | short: 3 | in_variant: True 4 | medium: 5 | in_variant: True 6 | long: 7 | in_variant: True 8 | -------------------------------------------------------------------------------- /selftests/deployment/roles/common/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - include_tasks: aexpect.yml 3 | - include_tasks: repos.yml 4 | - include_tasks: dependencies.yml 5 | -------------------------------------------------------------------------------- /selftests/functional/nrunner_interface.py.data/recipe_task_tap.json: -------------------------------------------------------------------------------- 1 | {"id": "1", "runnable": {"kind": "tap", "uri": "/usr/bin/echo", "args": ["0..0"]}} 2 | -------------------------------------------------------------------------------- /docs/source/blueprints/images/BP003/Resolution.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avocado-framework/avocado/HEAD/docs/source/blueprints/images/BP003/Resolution.png -------------------------------------------------------------------------------- /examples/tests/use_data.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | # A minimal test that depends on the presence of data files 3 | test -f "$(dirname $0)/$(basename $0).data/data" 4 | -------------------------------------------------------------------------------- /selftests/.data/archive.py.data/avocado.gz.metadata: -------------------------------------------------------------------------------- 1 | { 2 | "members": [["avocado", "f6bd93091d5d3df733b53b490f92b8a3f1a7b893928a21f8b0f96d1015b5490d"]] 3 | } 4 | -------------------------------------------------------------------------------- /selftests/.data/archive.py.data/avocado.xz.metadata: -------------------------------------------------------------------------------- 1 | { 2 | "members": [["avocado", "f6bd93091d5d3df733b53b490f92b8a3f1a7b893928a21f8b0f96d1015b5490d"]] 3 | } 4 | -------------------------------------------------------------------------------- /selftests/.data/archive.py.data/avocado.zst.metadata: -------------------------------------------------------------------------------- 1 | { 2 | "members": [["avocado", "f6bd93091d5d3df733b53b490f92b8a3f1a7b893928a21f8b0f96d1015b5490d"]] 3 | } 4 | -------------------------------------------------------------------------------- /selftests/.data/archive.py.data/bzip2file.metadata: -------------------------------------------------------------------------------- 1 | { 2 | "members": [["test_file", "121aa94e3d4c407253323a307716c5ba8c3eb02d00651c20d80f02ad452dc535"]] 3 | } 4 | -------------------------------------------------------------------------------- /selftests/.data/archive.py.data/gzipfile.metadata: -------------------------------------------------------------------------------- 1 | { 2 | "members": [["test_file", "121aa94e3d4c407253323a307716c5ba8c3eb02d00651c20d80f02ad452dc535"]] 3 | } 4 | -------------------------------------------------------------------------------- /selftests/.data/archive.py.data/xzfile.metadata: -------------------------------------------------------------------------------- 1 | { 2 | "members": [["test_file", "121aa94e3d4c407253323a307716c5ba8c3eb02d00651c20d80f02ad452dc535"]] 3 | } 4 | -------------------------------------------------------------------------------- /selftests/.data/safeloader/caveat_multilevel/failure.py: -------------------------------------------------------------------------------- 1 | import l1.l2.l3 2 | 3 | 4 | class Test(l1.l2.l3.BaseTest): 5 | def test(self): 6 | pass 7 | -------------------------------------------------------------------------------- /examples/tests/sleeptest.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | if [ -z ${SLEEP_LENGTH} ]; then 3 | SLEEP_LENGTH=1 4 | fi 5 | 6 | echo "Sleeping $SLEEP_LENGTH" 7 | sleep $SLEEP_LENGTH 8 | -------------------------------------------------------------------------------- /selftests/.data/archive.py.data/tarfile.metadata: -------------------------------------------------------------------------------- 1 | { 2 | "members": [["test_file.txt", "121aa94e3d4c407253323a307716c5ba8c3eb02d00651c20d80f02ad452dc535"]] 3 | } 4 | -------------------------------------------------------------------------------- /selftests/.data/archive.py.data/test_file.bz2.metadata: -------------------------------------------------------------------------------- 1 | { 2 | "members": [["test_file", "121aa94e3d4c407253323a307716c5ba8c3eb02d00651c20d80f02ad452dc535"]] 3 | } 4 | -------------------------------------------------------------------------------- /selftests/.data/archive.py.data/test_file.gz.metadata: -------------------------------------------------------------------------------- 1 | { 2 | "members": [["test_file", "121aa94e3d4c407253323a307716c5ba8c3eb02d00651c20d80f02ad452dc535"]] 3 | } 4 | -------------------------------------------------------------------------------- /selftests/.data/archive.py.data/test_file.xz.metadata: -------------------------------------------------------------------------------- 1 | { 2 | "members": [["test_file", "121aa94e3d4c407253323a307716c5ba8c3eb02d00651c20d80f02ad452dc535"]] 3 | } 4 | -------------------------------------------------------------------------------- /selftests/.data/archive.py.data/zipfile.metadata: -------------------------------------------------------------------------------- 1 | { 2 | "members": [["test_file.txt", "121aa94e3d4c407253323a307716c5ba8c3eb02d00651c20d80f02ad452dc535"]] 3 | } 4 | -------------------------------------------------------------------------------- /selftests/.data/archive.py.data/zstdfile.metadata: -------------------------------------------------------------------------------- 1 | { 2 | "members": [["test_file.txt", "121aa94e3d4c407253323a307716c5ba8c3eb02d00651c20d80f02ad452dc535"]] 3 | } 4 | -------------------------------------------------------------------------------- /selftests/.data/safeloader/caveat_multilevel/success.py: -------------------------------------------------------------------------------- 1 | from l1.l2.l3 import BaseTest 2 | 3 | 4 | class Test(BaseTest): 5 | def test(self): 6 | pass 7 | -------------------------------------------------------------------------------- /selftests/functional/nrunner_interface.py.data/recipe_runnable_robot.json: -------------------------------------------------------------------------------- 1 | {"kind": "robot", "uri": "optional_plugins/robot/tests/avocado.robot:Avocado.NoSleep"} 2 | -------------------------------------------------------------------------------- /docs/source/blueprints/images/BP004/dependency_graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avocado-framework/avocado/HEAD/docs/source/blueprints/images/BP004/dependency_graph.png -------------------------------------------------------------------------------- /docs/source/blueprints/images/requirements-resolver.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avocado-framework/avocado/HEAD/docs/source/blueprints/images/requirements-resolver.png -------------------------------------------------------------------------------- /examples/nrunner/recipes/runnable/asset.json: -------------------------------------------------------------------------------- 1 | {"kind": "asset", "kwargs": {"name": "gpl-2.0.txt", "locations": "https://mirrors.kernel.org/gnu/Licenses/gpl-2.0.txt"}} 2 | -------------------------------------------------------------------------------- /examples/yaml_to_mux/os/windows.yaml: -------------------------------------------------------------------------------- 1 | os_type: windows 2 | username: Administrator 3 | versions: !mux 4 | xp: 5 | shutdown_command: shutdown /s /f /t 0 6 | 7 | -------------------------------------------------------------------------------- /examples/yaml_to_mux/simple_vars.yaml: -------------------------------------------------------------------------------- 1 | # Simple example with 2 variants key/values in them 2 | !mux 3 | first: 4 | variable_one: 1 5 | second: 6 | variable_two: 2 7 | -------------------------------------------------------------------------------- /selftests/.data/archive.py.data/archive.tar.metadata: -------------------------------------------------------------------------------- 1 | { 2 | "members": [["test_file.txt", "121aa94e3d4c407253323a307716c5ba8c3eb02d00651c20d80f02ad452dc535"]] 3 | } 4 | -------------------------------------------------------------------------------- /selftests/.data/archive.py.data/archive.zip.metadata: -------------------------------------------------------------------------------- 1 | { 2 | "members": [["test_file.txt", "121aa94e3d4c407253323a307716c5ba8c3eb02d00651c20d80f02ad452dc535"]] 3 | } 4 | -------------------------------------------------------------------------------- /selftests/.data/archive.py.data/test_file.zst.metadata: -------------------------------------------------------------------------------- 1 | { 2 | "members": [["test_file.txt", "121aa94e3d4c407253323a307716c5ba8c3eb02d00651c20d80f02ad452dc535"]] 3 | } 4 | -------------------------------------------------------------------------------- /docs/source/blueprints/images/BP003/Resolution-to-task.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avocado-framework/avocado/HEAD/docs/source/blueprints/images/BP003/Resolution-to-task.png -------------------------------------------------------------------------------- /docs/source/blueprints/images/BP004/dot_representation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avocado-framework/avocado/HEAD/docs/source/blueprints/images/BP004/dot_representation.png -------------------------------------------------------------------------------- /examples/nrunner/recipes/tasks/exec-status/1-uname-result.json: -------------------------------------------------------------------------------- 1 | {"id": 1, "runnable": {"kind": "exec", "uri": "/bin/uname", "args": ["-a"]}, "status_uris": ["127.0.0.1:8888"]} 2 | -------------------------------------------------------------------------------- /selftests/.data/archive.py.data/test_archive__symlinks.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avocado-framework/avocado/HEAD/selftests/.data/archive.py.data/test_archive__symlinks.zip -------------------------------------------------------------------------------- /selftests/.data/safeloader/caveat_multilevel/l1/l2/l3/__init__.py: -------------------------------------------------------------------------------- 1 | from avocado import Test 2 | 3 | 4 | class BaseTest(Test): 5 | """BaseTest nothing-burguer class""" 6 | -------------------------------------------------------------------------------- /selftests/functional/nrunner_interface.py.data/recipe_runnable_avocado_instrumented.json: -------------------------------------------------------------------------------- 1 | {"kind": "avocado-instrumented", "uri": "examples/tests/passtest.py:PassTest.test"} 2 | -------------------------------------------------------------------------------- /selftests/functional/nrunner_interface.py.data/recipe_task_exec_test.json: -------------------------------------------------------------------------------- 1 | {"id": "1", "runnable": {"kind": "exec-test", "uri": "/usr/bin/python3", "args": ["--version"]}} 2 | -------------------------------------------------------------------------------- /selftests/functional/utils/gdb.py.data/segfault.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | int *p = NULL; 6 | *p = 0xdead; 7 | 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /docs/source/blueprints/images/BP003/Task-scheduler-flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avocado-framework/avocado/HEAD/docs/source/blueprints/images/BP003/Task-scheduler-flow.png -------------------------------------------------------------------------------- /examples/nrunner/recipes/tasks/exec-status/3-sleep-result.json: -------------------------------------------------------------------------------- 1 | {"id": 3, "runnable": {"kind": "exec", "uri": "/bin/sleep", "args": ["0.01"]}, "status_uris": ["127.0.0.1:8888"]} 2 | -------------------------------------------------------------------------------- /examples/nrunner/recipes/tasks/exec-status/4-sleep-long-result.json: -------------------------------------------------------------------------------- 1 | {"id": 3, "runnable": {"kind": "exec", "uri": "/bin/sleep", "args": ["3"]}, "status_uris": ["127.0.0.1:8888"]} 2 | -------------------------------------------------------------------------------- /selftests/functional/nrunner_interface.py.data/recipe_runnable_python_unittest.json: -------------------------------------------------------------------------------- 1 | {"kind": "python-unittest", "uri": "selftests/unit/test.py:TestClassTestUnit.test_long_name"} 2 | -------------------------------------------------------------------------------- /examples/nrunner/recipes/runnable/exec_test_sh_echo_env_var.json: -------------------------------------------------------------------------------- 1 | {"kind": "exec-test", "uri": "/bin/sh", "args": ["-c", "/bin/echo $ENV_VAR"], "kwargs": {"ENV_VAR": "Hello world!"}} 2 | -------------------------------------------------------------------------------- /examples/varianter_pict/params.pict: -------------------------------------------------------------------------------- 1 | arch: intel, amd 2 | block_driver: scsi, ide, virtio 3 | net_driver: rtl8139, e1000, virtio 4 | guest: windows, linux 5 | host: rhel6, rhel7, rhel8 6 | -------------------------------------------------------------------------------- /selftests/.data/guaca.a: -------------------------------------------------------------------------------- 1 | ! 2 | shopping 1627526682 1000 1000 100664 14 ` 3 | avocados, saltrecipe 1627526689 1000 1000 100664 8 ` 4 | cut, mix -------------------------------------------------------------------------------- /selftests/functional/nrunner_interface.py.data/recipe_task_robot.json: -------------------------------------------------------------------------------- 1 | {"id": "1", "runnable": {"kind": "robot", "uri": "optional_plugins/robot/tests/avocado.robot:Avocado.NoSleep"}} 2 | -------------------------------------------------------------------------------- /examples/nrunner/recipes/tasks/unittest-result/1-unittest-testcase-localhost.json: -------------------------------------------------------------------------------- 1 | {"id": 4, "runnable": {"kind": "exec", "uri": "/bin/sleep", "args": ["3"]}, "status_uris": ["127.0.0.1:8888"]} 2 | -------------------------------------------------------------------------------- /selftests/functional/nrunner_interface.py.data/recipe_task_avocado_instrumented.json: -------------------------------------------------------------------------------- 1 | {"id": "1", "runnable": {"kind": "avocado-instrumented", "uri": "examples/tests/passtest.py:PassTest.test"}} 2 | -------------------------------------------------------------------------------- /docs/source/blueprints/images/BP004/current_requirements_resolver.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/avocado-framework/avocado/HEAD/docs/source/blueprints/images/BP004/current_requirements_resolver.png -------------------------------------------------------------------------------- /selftests/functional/nrunner_interface.py.data/recipe_task_python_unittest.json: -------------------------------------------------------------------------------- 1 | {"id": "1", "runnable": {"kind": "python-unittest", "uri": "selftests/unit/test.py:TestClassTestUnit.test_long_name"}} 2 | -------------------------------------------------------------------------------- /selftests/spell.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | echo "** Running spell check..." 3 | 4 | python3 -m pylint -j 1 --disable=all --enable=spelling --spelling-dict=en_US --spelling-private-dict-file=spell.ignore * 5 | -------------------------------------------------------------------------------- /examples/nrunner/recipes/tasks/exec-status/2-dd-result.json: -------------------------------------------------------------------------------- 1 | {"id": 1, "runnable": {"kind": "exec", "uri": "/usr/bin/dd", "args": ["bs=4", "count=1", "if=/dev/urandom"]}, "status_uris": ["127.0.0.1:8888"]} 2 | -------------------------------------------------------------------------------- /examples/tests/sleeptest.py.data/sleeptest.yaml: -------------------------------------------------------------------------------- 1 | !mux 2 | short: 3 | sleep_length: 0.5 4 | medium: 5 | sleep_length: 1 6 | long: 7 | sleep_length: 5 8 | longest: 9 | sleep_length: 10 10 | -------------------------------------------------------------------------------- /examples/tests/sleeptest.sh.data/sleeptest.yaml: -------------------------------------------------------------------------------- 1 | !mux 2 | short: 3 | SLEEP_LENGTH: 0.5 4 | medium: 5 | SLEEP_LENGTH: 1 6 | long: 7 | SLEEP_LENGTH: 5 8 | longest: 9 | SLEEP_LENGTH: 10 10 | -------------------------------------------------------------------------------- /examples/nrunner/resolvers/exec_runnables_recipe.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | echo '[{"kind": "exec-test","uri": "/bin/true","identifier": "true-test"},{"kind": "exec-test","uri": "/bin/false","identifier": "false-test"}]' 3 | -------------------------------------------------------------------------------- /examples/tests/linuxbuild.py.data/linuxbuild.yaml: -------------------------------------------------------------------------------- 1 | linux_src_url: https://www.kernel.org/pub/linux/kernel/v4.x/ 2 | linux_version: 4.15.1 3 | linux_config: /boot/config-4.13.0-31-generic 4 | #do_kernel_install: y 5 | -------------------------------------------------------------------------------- /examples/tests/modify_variable.py.data/print_variable.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char *argv[]) 4 | { 5 | int a = 0; 6 | printf("MY VARIABLE 'A' IS: %x\n", a); 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /selftests/deployment/roles/avocado/tasks/pip/examples.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: (NOT) Installing Avocado examples using PIP 3 | debug: 4 | msg: "Not installing examples via PIP, as there are no packages with them" 5 | -------------------------------------------------------------------------------- /avocado/__main__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Main entry point when called by 'python -m'. 3 | """ 4 | 5 | import sys 6 | 7 | from avocado.core.main import main 8 | 9 | if __name__ == "__main__": 10 | sys.exit(main()) 11 | -------------------------------------------------------------------------------- /examples/gdb-prerun-scripts/README: -------------------------------------------------------------------------------- 1 | This directory contains examples of GDB "prerun" command files. These are 2 | intended to be examples of how to use the "--gdb-prerun-commands" option 3 | of the Avocado GDB plugin. 4 | -------------------------------------------------------------------------------- /examples/tests/custom_env_variable.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # This test demonstrates that executable tests (exec-tests) have 3 | # access to parameters as environment variables. 4 | echo "Custom variable: $CUSTOM_VARIABLE" 5 | 6 | -------------------------------------------------------------------------------- /examples/tests/custom_env_variable.sh.data/variants.yaml: -------------------------------------------------------------------------------- 1 | !mux 2 | short: 3 | CUSTOM_VARIABLE: A 4 | medium: 5 | CUSTOM_VARIABLE: ASDFASDF 6 | long: 7 | CUSTOM_VARIABLE: "This is very long\nmultiline\ntext." 8 | -------------------------------------------------------------------------------- /examples/tests/env_variables.sh.data/env_variables.yaml: -------------------------------------------------------------------------------- 1 | !mux 2 | short: 3 | CUSTOM_VARIABLE: A 4 | medium: 5 | CUSTOM_VARIABLE: ASDFASDF 6 | long: 7 | CUSTOM_VARIABLE: "This is very long\nmultiline\ntext." 8 | -------------------------------------------------------------------------------- /examples/tests/true: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # this mimics the /bin/true binary available on many systems 3 | # and results in a PASS when executed as a test 4 | import sys 5 | 6 | if __name__ == '__main__': 7 | sys.exit(0) 8 | -------------------------------------------------------------------------------- /contrib/packages/debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | # -*- makefile -*- 3 | 4 | clean:: 5 | rm -rf build build-stamp configure-stamp build/ MANIFEST 6 | dh_clean 7 | 8 | %: 9 | dh $@ --with python3 --buildsystem=pybuild 10 | -------------------------------------------------------------------------------- /examples/tests/false: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # this mimics the /bin/false binary available on many systems 3 | # and results in a FAIL when executed as a test 4 | import sys 5 | 6 | if __name__ == '__main__': 7 | sys.exit(1) 8 | -------------------------------------------------------------------------------- /selftests/.data/safeloader/data/infinite_recurse.py: -------------------------------------------------------------------------------- 1 | import infinite_recurse # pylint: disable=W0406 2 | 3 | 4 | # This should fail 5 | class DependsOnSelf(infinite_recurse.DependsOnSelf): 6 | def test(self): 7 | pass 8 | -------------------------------------------------------------------------------- /selftests/deployment/deployment.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Basic install test on Avocado + Plugins 3 | hosts: local 4 | vars_files: 5 | - vars.yml 6 | roles: 7 | - common 8 | - virtualenv 9 | - avocado 10 | - tests 11 | -------------------------------------------------------------------------------- /selftests/deployment/roles/avocado/tasks/rpm/avocado.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Installing Avocado using RPM 3 | dnf: 4 | name: python3-avocado 5 | state: latest 6 | when: 7 | - ansible_facts['distribution_file_variety'] == "RedHat" 8 | -------------------------------------------------------------------------------- /optional_plugins/varianter_yaml_to_mux/tests/.data/mux-šelftest-distro.yaml: -------------------------------------------------------------------------------- 1 | !mux 2 | RHEL: !mux 3 | enterprise: true 4 | 6: 5 | init: 'systemv' 6 | 7: 7 | init: 'systemd' 8 | gentoo: !mux 9 | is_cool: False 10 | -------------------------------------------------------------------------------- /contrib/scripts/docs-change-home.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | # Script to keep the references to a home dir (in docs) without specific names 3 | git grep /home/ -- docs/source/ man/ | cut -d ':' -f 1 | sort -u | xargs sed -i -E 's/\/home\/[a-z]+\//\/home\/user\//' 4 | -------------------------------------------------------------------------------- /examples/nrunner/resolvers/exec_runnables_recipe_kind.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | kind=${1:-exec-test} 3 | echo "[{\"kind\": \"$kind\",\"uri\": \"/bin/true\",\"identifier\": \"true-test\"},{\"kind\": \"$kind\",\"uri\": \"/bin/false\",\"identifier\": \"false-test\"}]" 4 | -------------------------------------------------------------------------------- /avocado/etc/avocado/sysinfo/commands: -------------------------------------------------------------------------------- 1 | df -mP 2 | dmesg 3 | uname -a 4 | lspci -vvnn 5 | gcc --version 6 | ld --version 7 | hostname 8 | uptime 9 | dmidecode 10 | ifconfig -a 11 | brctl show 12 | ip link 13 | numactl --hardware show 14 | lscpu 15 | fdisk -l 16 | -------------------------------------------------------------------------------- /examples/nrunner/recipes/runnables/true_false.json: -------------------------------------------------------------------------------- 1 | [ 2 | {"kind": "exec-test", 3 | "uri": "/bin/true", 4 | "identifier": "true-test"}, 5 | 6 | {"kind": "exec-test", 7 | "uri": "/bin/false", 8 | "identifier": "false-test"} 9 | ] 10 | -------------------------------------------------------------------------------- /optional_plugins/robot/tests/avocado.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation Sleep test cases 3 | 4 | *** Test Cases *** 5 | NoSleep 6 | Sleep 0 7 | Log "got no sleep" 8 | Sleep 9 | Sleep 0.01 10 | Log "got some sleep" 11 | -------------------------------------------------------------------------------- /selftests/deployment/roles/common/tasks/aexpect.yml: -------------------------------------------------------------------------------- 1 | - name: Install python3-aexpect first 2 | dnf: 3 | name: python3-aexpect 4 | state: present 5 | when: 6 | - ansible_facts['distribution_file_variety'] == "RedHat" 7 | - avocado_vt|default(false)|bool == true 8 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include LICENSE 2 | include Makefile 3 | include README.rst 4 | include VERSION 5 | recursive-include avocado/etc * 6 | recursive-include avocado/libexec * 7 | recursive-include avocado/schemas * 8 | recursive-include selftests * 9 | recursive-include examples * 10 | -------------------------------------------------------------------------------- /examples/tests/canceltest.py: -------------------------------------------------------------------------------- 1 | from avocado import Test 2 | 3 | 4 | class CancelTest(Test): 5 | """ 6 | Example test that cancels the current test from inside the test. 7 | """ 8 | 9 | def test(self): 10 | self.cancel("This should end with CANCEL.") 11 | -------------------------------------------------------------------------------- /selftests/.data/exec_test_std/exec_test_1mib.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | if __name__ == "__main__": 6 | data = b"1" * 1024 * 1024 7 | sys.stdout.write(data.decode()) 8 | data = b"2" * 1024 * 1024 9 | sys.stderr.write(data.decode()) 10 | -------------------------------------------------------------------------------- /selftests/.data/exec_test_std/exec_test_64kib.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | if __name__ == "__main__": 6 | data = b"1" * 1024 * 64 7 | sys.stdout.write(data.decode()) 8 | data = b"2" * 1024 * 64 9 | sys.stderr.write(data.decode()) 10 | -------------------------------------------------------------------------------- /examples/jobs/failjob.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | from avocado.core.job import Job 6 | 7 | config = {"resolver.references": ["examples/tests/failtest.py:FailTest.test"]} 8 | 9 | with Job.from_config(job_config=config) as j: 10 | sys.exit(j.run()) 11 | -------------------------------------------------------------------------------- /selftests/unit/utils/cpu.py.data/armv8: -------------------------------------------------------------------------------- 1 | processor : 0 2 | BogoMIPS : 200.00 3 | Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid 4 | CPU implementer : 0x43 5 | CPU architecture: 8 6 | CPU variant : 0x1 7 | CPU part : 0x0a1 8 | CPU revision : 1 9 | -------------------------------------------------------------------------------- /avocado/etc/avocado/scripts/job/pre.d/README: -------------------------------------------------------------------------------- 1 | Put your pre-job scripts here. They need to be readable and executable by 2 | the Avocado user running the jobs. The order of execution is based on their 3 | file names. If order is important, use a prefix, such as 001-myscript, 4 | 002-otherscript, etc. 5 | -------------------------------------------------------------------------------- /selftests/deployment/roles/avocado/tasks/pip/avocado.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Avocado must be installed via pip 3 | pip: 4 | name: "git+{{ avocado_git_url}}@{{ avocado_git_branch }}#egg={{ avocado_egg_name }}" 5 | virtualenv: "{{ temporary_dir.path }}" 6 | virtualenv_site_packages: yes 7 | -------------------------------------------------------------------------------- /avocado/etc/avocado/scripts/job/post.d/README: -------------------------------------------------------------------------------- 1 | Put your post-job scripts here. They need to be readable and executable by 2 | the Avocado user running the jobs. The order of execution is based on their 3 | file names. If order is important, use a prefix, such as 001-myscript, 4 | 002-otherscript, etc. 5 | -------------------------------------------------------------------------------- /examples/tests/passtest.py: -------------------------------------------------------------------------------- 1 | from avocado import Test 2 | 3 | 4 | class PassTest(Test): 5 | """ 6 | Example test that passes. 7 | 8 | :avocado: tags=fast 9 | """ 10 | 11 | def test(self): 12 | """ 13 | A test simply doesn't have to fail in order to pass 14 | """ 15 | -------------------------------------------------------------------------------- /examples/varianter_cit/test_params.cit: -------------------------------------------------------------------------------- 1 | PARAMETERS 2 | color [black, gold, red, green ] 3 | shape[square, triangle, circle] 4 | state[liquid, solid, gas] 5 | material[leather, plastic, aluminum] 6 | coating[anodic, cathodic] 7 | 8 | CONSTRAINTS 9 | color != black 10 | color != gold 11 | color != red 12 | 13 | -------------------------------------------------------------------------------- /optional_plugins/golang/tests/src/countavocados/countavocados.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func Count(container_size int, containers int) int { 6 | return container_size * containers 7 | } 8 | 9 | func main() { 10 | fmt.Println("Let's suppose we count Avocado containers") 11 | } 12 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | coverage: 2 | status: 3 | project: 4 | default: 5 | informational: true 6 | patch: 7 | default: 8 | informational: true 9 | 10 | 11 | # When modifying this file, please validate using 12 | # curl -X POST --data-binary @codecov.yml https://codecov.io/validate 13 | -------------------------------------------------------------------------------- /examples/tests/dependency_pip.py: -------------------------------------------------------------------------------- 1 | from avocado import Test, fail_on 2 | 3 | 4 | class Pip(Test): 5 | """ 6 | :avocado: dependency={"type": "pip", "name": "pip", "action": "install"} 7 | """ 8 | 9 | @fail_on(ImportError) 10 | def test(self): 11 | import pip # pylint: disable=W0611 12 | -------------------------------------------------------------------------------- /.github/actions/version/action.yml: -------------------------------------------------------------------------------- 1 | name: Version 2 | description: Installs and run avocado --version 3 | runs: 4 | using: composite 5 | steps: 6 | - name: Install and run avocado --version 7 | shell: sh 8 | run: | 9 | python3 setup.py develop --user 10 | python3 -m avocado --version 11 | -------------------------------------------------------------------------------- /docs/source/api/headers/core: -------------------------------------------------------------------------------- 1 | Internal APIs that may be of interest to Avocado hackers. 2 | 3 | Everything under :mod:`avocado.core` is part of the application's 4 | infrastructure and should not be used by tests. 5 | 6 | Extensions and Plugins can use the core libraries, but API stability is not 7 | guaranteed at any level. 8 | -------------------------------------------------------------------------------- /examples/jobs/README.rst: -------------------------------------------------------------------------------- 1 | Job API 2 | ======= 3 | 4 | The Job API has been evolving in the direction of the stabilization. Although 5 | it is not a public API yet, meaning it still resides inside the `avocado.core` 6 | module, we encourage users to make use of it. We will provide the best-effort 7 | support in favor of its maturity. 8 | -------------------------------------------------------------------------------- /examples/nrunner/recipes/runnable/sysinfo.json: -------------------------------------------------------------------------------- 1 | {"config":{"sysinfo.collect.commands_timeout": -1, "sysinfo.collect.locale": "C", "sysinfo.collect.installed_packages": false}, 2 | "kind": "sysinfo", 3 | "uri": "pre", 4 | "kwargs": {"sysinfo": {"commands": ["uptime", "dmidecode"], "files": ["/proc/version", "/proc/meminfo"]}}} 5 | -------------------------------------------------------------------------------- /examples/tests/warntest.py: -------------------------------------------------------------------------------- 1 | from avocado import Test 2 | 3 | 4 | class WarnTest(Test): 5 | """ 6 | Functional test for avocado. Throw a TestWarn. 7 | """ 8 | 9 | def test(self): 10 | """ 11 | This should throw a TestWarn. 12 | """ 13 | self.log.warn("This marks test as WARN") 14 | -------------------------------------------------------------------------------- /selftests/unit/utils/cpu.py.data/power9: -------------------------------------------------------------------------------- 1 | processor : 20 2 | cpu : POWER9 (raw), altivec supported 3 | clock : 2050.000000MHz 4 | revision : 1.0 (pvr 004e 0100) 5 | 6 | timebase : 512000000 7 | platform : PowerNV 8 | model : 8375-42A 9 | machine : PowerNV 8375-42A 10 | firmware : OPAL 11 | -------------------------------------------------------------------------------- /examples/tests/abort.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from avocado import Test 4 | 5 | 6 | class AbortTest(Test): 7 | """ 8 | A test that just calls abort() (and abort). 9 | 10 | :avocado: tags=failure_expected 11 | """ 12 | 13 | timeout = 2.0 14 | 15 | @staticmethod 16 | def test(): 17 | os.abort() 18 | -------------------------------------------------------------------------------- /examples/tests/params.py: -------------------------------------------------------------------------------- 1 | from avocado import Test 2 | 3 | 4 | class Params(Test): 5 | def test(self): 6 | """Test that simply lists all parameters.""" 7 | self.log.info("Test params:") 8 | for path, key, value in self.params.iteritems(): 9 | self.log.info("%s:%s ==> %s", path, key, value) 10 | -------------------------------------------------------------------------------- /contrib/containers/ci/selftests/check-copr-rpm-version.docker: -------------------------------------------------------------------------------- 1 | # This container is used in selftests/pre_release/tests/check-copr-rpm-version.sh 2 | FROM fedora:42 3 | LABEL description "Fedora image used on COPR RPM version check" 4 | RUN dnf -y install 'dnf-command(copr)' 5 | RUN dnf -y copr enable @avocado/avocado-latest 6 | RUN dnf -y clean all 7 | -------------------------------------------------------------------------------- /docs/source/plugins/optional/varianters/index.rst: -------------------------------------------------------------------------------- 1 | ================= 2 | Varianter plugins 3 | ================= 4 | 5 | Optional plugins that generate variants (different sets of parameters) 6 | that will allow the same test to cover different scenarios. 7 | 8 | .. toctree:: 9 | :maxdepth: 2 10 | 11 | cit 12 | pict 13 | yaml_to_mux 14 | -------------------------------------------------------------------------------- /examples/plugins/cli-cmd/hello/hello.py: -------------------------------------------------------------------------------- 1 | from avocado.core.output import LOG_UI 2 | from avocado.core.plugin_interfaces import CLICmd 3 | 4 | 5 | class HelloWorld(CLICmd): 6 | 7 | name = "hello" 8 | description = "The classical Hello World! plugin example." 9 | 10 | def run(self, config): 11 | LOG_UI.info(self.description) 12 | -------------------------------------------------------------------------------- /selftests/deployment/vars.yml: -------------------------------------------------------------------------------- 1 | avocado_git_url: https://github.com/avocado-framework/avocado.git 2 | avocado_git_branch: master 3 | avocado_egg_name: avocado-framework 4 | avocado_vt_git_url: https://github.com/avocado-framework/avocado-vt.git 5 | avocado_vt_git_branch: master 6 | avocado_vt_egg_name: avocado-plugins-vt 7 | method: pip 8 | avocado_vt: false 9 | -------------------------------------------------------------------------------- /examples/tests/errortest.py: -------------------------------------------------------------------------------- 1 | from avocado import Test 2 | 3 | 4 | class ErrorTest(Test): 5 | """ 6 | Example test that ends with ERROR. 7 | 8 | :avocado: tags=failure_expected 9 | """ 10 | 11 | def test(self): 12 | """ 13 | This should end with ERROR. 14 | """ 15 | self.error("This should end with ERROR.") 16 | -------------------------------------------------------------------------------- /examples/tests/failtest.py: -------------------------------------------------------------------------------- 1 | from avocado import Test 2 | 3 | 4 | class FailTest(Test): 5 | """ 6 | Example test for avocado. Straight up fail the test. 7 | 8 | :avocado: tags=failure_expected 9 | """ 10 | 11 | def test(self): 12 | """ 13 | Should fail. 14 | """ 15 | self.fail("This test is supposed to fail") 16 | -------------------------------------------------------------------------------- /examples/tests/passtest_with_dependency.py: -------------------------------------------------------------------------------- 1 | from avocado import Test 2 | 3 | 4 | class PassTest(Test): 5 | """ 6 | Example test that passes. 7 | 8 | :avocado: dependency={"type": "package", "name": "hello"} 9 | """ 10 | 11 | def test(self): 12 | """ 13 | A test simply doesn't have to fail in order to pass 14 | """ 15 | -------------------------------------------------------------------------------- /selftests/unit/utils/cpu.py.data/power8: -------------------------------------------------------------------------------- 1 | processor : 88 2 | cpu : POWER8E (raw), altivec supported 3 | clock : 3325.000000MHz 4 | revision : 2.1 (pvr 004b 0201) 5 | 6 | timebase : 512000000 7 | platform : PowerNV 8 | model : 8247-21L 9 | machine : PowerNV 8247-21L 10 | firmware : OPAL v3 11 | -------------------------------------------------------------------------------- /docs/source/guides/contributor/chapters/contact.rst: -------------------------------------------------------------------------------- 1 | Contact information 2 | =================== 3 | 4 | - Avocado-devel mailing list: `https://www.redhat.com/mailman/listinfo/avocado-devel `_ 5 | - Avocado GitHub repository: `https://github.com/avocado-framework/avocado/ `_ 6 | -------------------------------------------------------------------------------- /avocado/etc/avocado/sysinfo/files: -------------------------------------------------------------------------------- 1 | /proc/cmdline 2 | /proc/mounts 3 | /proc/pci 4 | /proc/meminfo 5 | /proc/slabinfo 6 | /proc/version 7 | /proc/cpuinfo 8 | /proc/modules 9 | /proc/interrupts 10 | /proc/partitions 11 | /sys/kernel/debug/sched_features 12 | /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor 13 | /sys/devices/system/clocksource/clocksource0/current_clocksource 14 | -------------------------------------------------------------------------------- /docs/source/guides/writer/index.rst: -------------------------------------------------------------------------------- 1 | =========================== 2 | Avocado Test Writer's Guide 3 | =========================== 4 | 5 | .. toctree:: 6 | :maxdepth: 2 7 | 8 | chapters/basics 9 | chapters/writing 10 | chapters/recipes 11 | chapters/logging 12 | chapters/parameters 13 | chapters/libs 14 | chapters/subclassing 15 | chapters/integrating 16 | -------------------------------------------------------------------------------- /selftests/deployment/roles/virtualenv/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Ensure that Virtualenv is installed 3 | package: 4 | name: python3-virtualenv 5 | state: present 6 | when: 7 | - method == 'pip' 8 | 9 | - name: Temporary dir for Avocado venv 10 | tempfile: 11 | state: directory 12 | register: temporary_dir 13 | when: 14 | - method == 'pip' 15 | -------------------------------------------------------------------------------- /examples/yaml_to_mux/complex.yaml: -------------------------------------------------------------------------------- 1 | # This is an advanced example which includes other files with filters. Note it 2 | # is important to inject this into the default path (/run), otherwise the 3 | # filters won't work properly (simply use `avocado variants -m complex.yaml`) 4 | os: !mux 5 | !include : os/linux.yaml 6 | !include : os/windows.yaml 7 | hw: 8 | !include : hw/hw.yaml 9 | -------------------------------------------------------------------------------- /selftests/.data/get_data.py.data/get_data.json: -------------------------------------------------------------------------------- 1 | [{"paths": ["/run/*"], "variant_id": "short-475e", "variant": [["/run/short", [["/run/short", "in_variant", true]]]]}, {"paths": ["/run/*"], "variant_id": "medium-1a7a", "variant": [["/run/medium", [["/run/medium", "in_variant", true]]]]}, {"paths": ["/run/*"], "variant_id": "long-cbbd", "variant": [["/run/long", [["/run/long", "in_variant", true]]]]}] -------------------------------------------------------------------------------- /examples/tests/logging_custom_level.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | import avocado 4 | 5 | 6 | class Test(avocado.Test): 7 | def test(self): 8 | CUSTOM_LEVEL = 35 9 | logger = logging.getLogger("custom_logger") 10 | logger.setLevel(CUSTOM_LEVEL) 11 | logger.log( 12 | CUSTOM_LEVEL, 13 | "Custom logger and level message", 14 | ) 15 | -------------------------------------------------------------------------------- /examples/yaml_to_mux/os/linux.yaml: -------------------------------------------------------------------------------- 1 | os_type: linux 2 | username: root 3 | shutdown_command: shutdown -h now 4 | distros: 5 | redhat: !mux 6 | fedora: 7 | version: !mux 8 | 20: 9 | 21: 10 | flavor: !mux 11 | workstation: 12 | cloud: 13 | rhel: !mux 14 | 5: 15 | 6: 16 | -------------------------------------------------------------------------------- /examples/tests/simplewarning.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | PATH=$(avocado "exec-path"):$PATH 3 | 4 | avocado_debug "Debug message" 5 | avocado_info "Info message" 6 | avocado_warn "Warning message (should cause this test to finish with warning)" 7 | avocado_error "Error message (ordinary message not changing the results)" 8 | echo "Simple output without log-level specification" 9 | exit 0 # no error reported 10 | -------------------------------------------------------------------------------- /examples/tests/uncaught_exception.py: -------------------------------------------------------------------------------- 1 | from avocado import Test 2 | 3 | 4 | class ErrorTest(Test): 5 | """ 6 | Example test that raises generic exception 7 | 8 | :avocado: tags=failure_expected 9 | """ 10 | 11 | @staticmethod 12 | def test(): 13 | """ 14 | This should end with ERROR. 15 | """ 16 | raise Exception("This is a generic exception") 17 | -------------------------------------------------------------------------------- /.packit.yml: -------------------------------------------------------------------------------- 1 | specfile_path: python-avocado.spec 2 | downstream_package_name: python-avocado 3 | srpm_build_deps: [] 4 | jobs: 5 | - job: copr_build 6 | trigger: pull_request 7 | metadata: 8 | targets: 9 | - fedora-all 10 | - centos-stream-9 11 | - epel-9 12 | - fedora-41-aarch64 13 | - fedora-41-ppc64le 14 | - fedora-41-s390x 15 | enable_net: False 16 | -------------------------------------------------------------------------------- /examples/plugins/cli-cmd/hello/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | if __name__ == "__main__": 4 | setup( 5 | name="avocado-hello-world", 6 | version="1.0", 7 | description="Avocado Hello World CLI command", 8 | py_modules=["hello"], 9 | entry_points={ 10 | "avocado.plugins.cli.cmd": ["hello = hello:HelloWorld"], 11 | }, 12 | ) 13 | -------------------------------------------------------------------------------- /docs/source/releases/88_1.rst: -------------------------------------------------------------------------------- 1 | ================ 2 | 88.1 The Serpent 3 | ================ 4 | 5 | This is a hotfix release for 88.0, with only one change to accommodate 6 | a documentation build error on readthedocs.org caused by a new version 7 | of an external package requirement. 8 | 9 | For the other (more relevant) changes in the 88.x release, please 10 | refer to the :doc:`88.0 Release Notes <88_0>`. 11 | -------------------------------------------------------------------------------- /examples/tests/raise.py.data/raise.yaml: -------------------------------------------------------------------------------- 1 | !mux 2 | sigint: 3 | signal_number: 2 4 | siguser1: 5 | signal_number: 10 6 | sigterm: 7 | signal_number: 15 8 | sigkill: 9 | signal_number: 9 10 | sigquit: 11 | signal_number: 3 12 | sigsegv: 13 | signal_number: 11 14 | invalid: 15 | signal_number: 1024 16 | invalid_negative: 17 | signal_number: -1 18 | is_alive: 19 | signal_number: 0 20 | -------------------------------------------------------------------------------- /examples/tests/failtest_ugly.py: -------------------------------------------------------------------------------- 1 | """ 2 | Please don't get inspired by this ugly code 3 | """ 4 | 5 | import sys 6 | 7 | sys.stdout.write("Direct output to stdout\n") 8 | sys.stderr.write("Direct output to stderr\n") 9 | input("I really want some input on each import") 10 | sys.stdin = "This is my __COOL__ stdin" 11 | sys.stdout = "my stdout" 12 | sys.stderr = "my stderr" 13 | sys.exit(-1) # Exit even on import 14 | -------------------------------------------------------------------------------- /examples/tests/phases.py: -------------------------------------------------------------------------------- 1 | from avocado import Test 2 | 3 | 4 | class Phases(Test): 5 | """ 6 | Example test for checking the reported test phases 7 | """ 8 | 9 | def setUp(self): 10 | self.assertEqual(self.phase, "SETUP") 11 | 12 | def test(self): 13 | self.assertEqual(self.phase, "TEST") 14 | 15 | def tearDown(self): 16 | self.assertEqual(self.phase, "TEARDOWN") 17 | -------------------------------------------------------------------------------- /selftests/deployment/roles/avocado/tasks/rpm/examples.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install Avocado examples using RPM 3 | dnf: 4 | name: 5 | - python3-avocado-examples 6 | state: latest 7 | when: 8 | - method == 'copr' 9 | 10 | - name: Install Avocado examples using RPM 11 | dnf: 12 | name: 13 | - python-avocado-examples 14 | state: latest 15 | when: 16 | - method == 'official' 17 | -------------------------------------------------------------------------------- /avocado/utils/network/exceptions.py: -------------------------------------------------------------------------------- 1 | """Exception hierarchy for network utilities. 2 | 3 | This module defines custom exception classes used throughout network utilities. 4 | All specific network errors should inherit from :class:`NWException` so they can 5 | be handled collectively when required. 6 | """ 7 | 8 | 9 | class NWException(Exception): 10 | """Base Exception Class for all network utility exceptions.""" 11 | -------------------------------------------------------------------------------- /examples/jobs/passjob_html.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | from avocado.core.job import Job 6 | from avocado.core.suite import TestSuite 7 | 8 | config = { 9 | "resolver.references": ["examples/tests/passtest.py:PassTest.test"], 10 | "job.run.result.html.enabled": True, 11 | } 12 | 13 | suite = TestSuite.from_config(config) 14 | with Job(config, [suite]) as j: 15 | sys.exit(j.run()) 16 | -------------------------------------------------------------------------------- /selftests/unit/utils/cpu.py.data/armv7: -------------------------------------------------------------------------------- 1 | Processor : ARMv7 Processor rev 2 (v7l) 2 | BogoMIPS : 994.65 3 | Features : swp half thumb fastmult vfp edsp thumbee neon vfpv3 4 | CPU implementer : 0x41 5 | CPU architecture: 7 6 | CPU variant : 0x2 7 | CPU part : 0xc08 8 | CPU revision : 2 9 | 10 | Hardware : herring 11 | Revision : 0034 12 | Serial : 3534268a5e0700ec 13 | -------------------------------------------------------------------------------- /examples/tests/failtest_with_warning.py: -------------------------------------------------------------------------------- 1 | from avocado import Test 2 | 3 | 4 | class FailTest(Test): 5 | """ 6 | Example test for avocado. Straight up fail the test. 7 | 8 | :avocado: tags=failure_expected 9 | """ 10 | 11 | def test(self): 12 | """ 13 | Should fail. 14 | """ 15 | self.log.warning("This is warning") 16 | self.fail("This test is supposed to fail") 17 | -------------------------------------------------------------------------------- /selftests/unit/utils/pmem.py: -------------------------------------------------------------------------------- 1 | import unittest.mock 2 | 3 | from avocado.utils import pmem 4 | 5 | 6 | class PMem(unittest.TestCase): 7 | def test_no_binaries(self): 8 | with unittest.mock.patch("avocado.utils.path.find_command", return_value=False): 9 | with self.assertRaises(pmem.PMemException): 10 | pmem.PMem() 11 | 12 | 13 | if __name__ == "__main__": 14 | unittest.main() 15 | -------------------------------------------------------------------------------- /examples/yaml_to_mux/hw/hw.yaml: -------------------------------------------------------------------------------- 1 | cpu: !mux 2 | intel: 3 | cpu_CFLAGS: '-march=core2' 4 | amd: 5 | cpu_CFLAGS: '-march=athlon64' 6 | arm: 7 | !filter-only : /run/hw/disk/virtio 8 | !filter-only : /run/os/linux 9 | cpu_CFLAGS: '-mabi=apcs-gnu -march=armv8-a -mtune=arm8' 10 | disk: !mux 11 | scsi: 12 | disk_type: 'scsi' 13 | virtio: 14 | disk_type: 'virtio' 15 | 16 | -------------------------------------------------------------------------------- /contrib/containers/ci/selftests/fedora-40.docker: -------------------------------------------------------------------------------- 1 | FROM fedora:40 2 | LABEL description "Fedora image used on integration checks" 3 | RUN dnf -y install dnf-plugins-core 4 | RUN dnf -y copr enable @avocado/avocado-latest-release 5 | RUN dnf -y install dnf-plugins-core git findutils make which 6 | RUN dnf -y install diffutils python3-isort python3-enchant python3-pylint python3-autopep8 7 | RUN dnf -y builddep python-avocado 8 | RUN dnf -y clean all 9 | -------------------------------------------------------------------------------- /examples/tests/cancelonsetup.py: -------------------------------------------------------------------------------- 1 | from avocado import Test 2 | 3 | 4 | class CancelOnSetupTest(Test): 5 | """ 6 | Example test that cancels the current test, on the setUp phase. 7 | """ 8 | 9 | def setUp(self): 10 | self.cancel("This should end with CANCEL.") 11 | 12 | def test_wont_be_executed(self): 13 | """ 14 | This won't get to be executed, given that setUp calls .cancel(). 15 | """ 16 | -------------------------------------------------------------------------------- /avocado/core/dependencies/requirements/cache/__init__.py: -------------------------------------------------------------------------------- 1 | # The sqlite based backend is the only implementation 2 | from avocado.core.dependencies.requirements.cache.backends.sqlite import ( 3 | delete_environment, 4 | delete_requirement, 5 | get_all_environments_with_requirement, 6 | is_environment_prepared, 7 | is_requirement_in_cache, 8 | set_requirement, 9 | update_environment, 10 | update_requirement_status, 11 | ) 12 | -------------------------------------------------------------------------------- /examples/tests/assert.py: -------------------------------------------------------------------------------- 1 | from avocado import Test 2 | 3 | 4 | class MyException(Exception): 5 | pass 6 | 7 | 8 | def raises_exception(): 9 | raise MyException 10 | 11 | 12 | class Assert(Test): 13 | def test_assert_raises(self): 14 | with self.assertRaises(MyException): 15 | raises_exception() 16 | 17 | def test_fails_to_raise(self): 18 | with self.assertRaises(MyException): 19 | pass 20 | -------------------------------------------------------------------------------- /examples/jobs/passjob_cit_varianter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | from avocado.core.job import Job 6 | from avocado.core.suite import TestSuite 7 | 8 | config = { 9 | "resolver.references": ["examples/tests/passtest.py:PassTest.test"], 10 | "cit_parameter_file": "examples/varianter_cit/test_params.cit", 11 | } 12 | 13 | suite = TestSuite.from_config(config) 14 | with Job(config, [suite]) as j: 15 | sys.exit(j.run()) 16 | -------------------------------------------------------------------------------- /examples/plugins/cli-cmd/hello_priority/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | if __name__ == "__main__": 4 | setup( 5 | name="avocado-hello-world-priority", 6 | version="1.0", 7 | description="Avocado Hello World CLI command, with priority", 8 | py_modules=["hello_priority"], 9 | entry_points={ 10 | "avocado.plugins.cli.cmd": ["hello = hello_priority:HelloWorld"], 11 | }, 12 | ) 13 | -------------------------------------------------------------------------------- /examples/plugins/cli-cmd/hello_option/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | if __name__ == "__main__": 4 | setup( 5 | name="avocado-hello-world-option", 6 | version="1.0", 7 | description="Avocado Hello World CLI command with config option", 8 | py_modules=["hello_option"], 9 | entry_points={ 10 | "avocado.plugins.cli.cmd": ["hello_option = hello_option:HelloWorld"], 11 | }, 12 | ) 13 | -------------------------------------------------------------------------------- /examples/plugins/cli-cmd/hello_parser/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | if __name__ == "__main__": 4 | setup( 5 | name="avocado-hello-world-parser", 6 | version="1.0", 7 | description="Avocado Hello World CLI command with config parser", 8 | py_modules=["hello_parser"], 9 | entry_points={ 10 | "avocado.plugins.cli.cmd": ["hello_parser = hello_parser:HelloWorld"], 11 | }, 12 | ) 13 | -------------------------------------------------------------------------------- /examples/tests/cit_parameters.py: -------------------------------------------------------------------------------- 1 | from avocado import Test 2 | 3 | 4 | class CitParameters(Test): 5 | """ 6 | Example test that fetches the parameters set on examples/cit/params.ini 7 | 8 | :avocado: tags=fast 9 | """ 10 | 11 | def test(self): 12 | self.params.get("color") 13 | self.params.get("shape") 14 | self.params.get("state") 15 | self.params.get("material") 16 | self.params.get("coating") 17 | -------------------------------------------------------------------------------- /examples/jobs/sleepjob_yaml_to_mux.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | from avocado.core.job import Job 6 | from avocado.core.suite import TestSuite 7 | 8 | config = { 9 | "resolver.references": ["examples/tests/sleeptest.py:SleepTest.test"], 10 | "yaml_to_mux.files": ["examples/tests/sleeptest.py.data/sleeptest.yaml"], 11 | } 12 | 13 | suite = TestSuite.from_config(config) 14 | with Job(config, [suite]) as j: 15 | sys.exit(j.run()) 16 | -------------------------------------------------------------------------------- /examples/plugins/cli-cmd/hello_priority/hello_priority.py: -------------------------------------------------------------------------------- 1 | from avocado.core.extension_manager import PluginPriority 2 | from avocado.core.output import LOG_UI 3 | from avocado.core.plugin_interfaces import CLICmd 4 | 5 | 6 | class HelloWorld(CLICmd): 7 | 8 | name = "hello" 9 | description = "The classical Hello World! plugin example." 10 | priority = PluginPriority.HIGH 11 | 12 | def run(self, config): 13 | LOG_UI.info(self.description) 14 | -------------------------------------------------------------------------------- /examples/tests/whiteboard.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import base64 4 | 5 | from avocado import Test 6 | 7 | 8 | class WhiteBoard(Test): 9 | """ 10 | Example of whiteboard usage. 11 | """ 12 | 13 | def test(self): 14 | """ 15 | This should write a message to the whiteboard. 16 | """ 17 | self.whiteboard = base64.encodebytes(b"My message encoded in base64").decode( 18 | "ascii" 19 | ) 20 | -------------------------------------------------------------------------------- /docs/source/guides/reference/index.rst: -------------------------------------------------------------------------------- 1 | ======================= 2 | Avocado Refefence Guide 3 | ======================= 4 | 5 | A collection of technical reference that explains the inner workings 6 | of Avocado. Useful for those trying to understand the Avocado 7 | architecture and expand it either through plugins or modifications to 8 | the core parts. 9 | 10 | .. toctree:: 11 | :maxdepth: 2 12 | 13 | chapters/runners 14 | chapters/avocado_instrumented 15 | -------------------------------------------------------------------------------- /examples/jobs/sleepjob_dict_varianter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | from avocado.core.job import Job 6 | from avocado.core.suite import TestSuite 7 | 8 | config = { 9 | "resolver.references": ["examples/tests/sleeptest.py:SleepTest.test"], 10 | "run.dict_variants": [{"sleep_length": "0.5"}, {"sleep_length": "1.0"}], 11 | } 12 | 13 | suite = TestSuite.from_config(config) 14 | with Job(config, [suite]) as j: 15 | sys.exit(j.run()) 16 | -------------------------------------------------------------------------------- /examples/jobs/sleepjob_json_varianter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | from avocado.core.job import Job 6 | from avocado.core.suite import TestSuite 7 | 8 | config = { 9 | "resolver.references": ["examples/tests/sleeptest.py:SleepTest.test"], 10 | "json.variants.load": "examples/tests/sleeptest.py.data/sleeptest.json", 11 | } 12 | 13 | suite = TestSuite.from_config(config) 14 | with Job(config, [suite]) as j: 15 | sys.exit(j.run()) 16 | -------------------------------------------------------------------------------- /selftests/.data/unittests.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | 4 | class First(unittest.TestCase): 5 | def test_pass(self): 6 | pass 7 | 8 | 9 | class Second(unittest.TestCase): 10 | def test_fail(self): 11 | self.fail("this is suppose to fail") 12 | 13 | def test_error(self): 14 | raise RuntimeError("This is suppose to error") 15 | 16 | @unittest.skip("This is suppose to be skipped") 17 | def test_skip(self): 18 | pass 19 | -------------------------------------------------------------------------------- /docs/source/guides/user/chapters/whatsnext.rst: -------------------------------------------------------------------------------- 1 | What's next? 2 | ============ 3 | 4 | Now that you are familiar with the basic concepts and Avocado usage, you can 5 | write your tests. 6 | 7 | As said before, you can write test on your favorite language. But if you would 8 | like to use the Avocado libraries and facilities, you can use Python or Bash. 9 | 10 | If you would like to move forward on Avocado, we prepared the *"Avocado Test 11 | Writer's Guide"* for you. Have fun! 12 | -------------------------------------------------------------------------------- /examples/jobs/passjob_html_browser.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | from avocado.core.job import Job 6 | from avocado.core.suite import TestSuite 7 | 8 | config = { 9 | "resolver.references": ["examples/tests/passtest.py:PassTest.test"], 10 | "job.run.result.html.enabled": True, 11 | "job.run.result.html.open_browser": True, 12 | } 13 | 14 | suite = TestSuite.from_config(config) 15 | with Job(config, [suite]) as j: 16 | sys.exit(j.run()) 17 | -------------------------------------------------------------------------------- /examples/varianter_cit/params.cit: -------------------------------------------------------------------------------- 1 | PARAMETERS 2 | color[black, gold, red, green ] 3 | shape[square, triangle, circle] 4 | state[liquid, solid, gas] 5 | material[leather, plastic, aluminum] 6 | coating[anodic, cathodic] 7 | p7[1,3,5,6,7] 8 | p8[1,2,5,3,4] 9 | p9[1,2,3,4,5] 10 | p10[1,2,3,4,5] 11 | 12 | CONSTRAINTS 13 | color != black || shape != square 14 | color != black || shape != triangle 15 | color != gold || coating != cathodic 16 | material != aluminum || color != gold 17 | -------------------------------------------------------------------------------- /docs/source/guides/contributor/api/api_utils_heading: -------------------------------------------------------------------------------- 1 | This is a set of utility APIs that Avocado provides as added value to 2 | test writers. 3 | 4 | It's suppose to be generic, without any knowledge of Avocado and reusable 5 | in different projects. 6 | 7 | .. note:: In the current version there is a hidden knowledge of avocado 8 | logging streams. More about this issue can be found here 9 | https://trello.com/c/4QyUgWsW/720-get-rid-of-avocado-test-loggers-from-avocado-utils 10 | -------------------------------------------------------------------------------- /contrib/packages/debian/README: -------------------------------------------------------------------------------- 1 | This is a collection of files that are useful to generate packages for 2 | Debian(-like) systems. Their "contrib" status mean that they should 3 | work, but there's no support for them. 4 | 5 | If there are users out there interested in keeping Debian(-like) 6 | packages update, please step up. 7 | 8 | The basic usage is to run the various targets defined in the Makefile, 9 | such as running `make deb` to have both source and binary packages 10 | generated. 11 | -------------------------------------------------------------------------------- /examples/plugins/README.rst: -------------------------------------------------------------------------------- 1 | ================= 2 | Plugin Examples 3 | ================= 4 | 5 | Here you can find a collection of example code for the various Avocado 6 | Plugin interfaces. 7 | 8 | To try them out on a development environment, you may run:: 9 | 10 | $ cd / 11 | $ python setup.py develop --user 12 | 13 | And to remove them on a development environment, you may run, at the 14 | same directory:: 15 | 16 | $ python setup.py develop --uninstall --user 17 | -------------------------------------------------------------------------------- /docs/source/plugins/optional/results/index.rst: -------------------------------------------------------------------------------- 1 | .. _result-plugins: 2 | 3 | ============== 4 | Result plugins 5 | ============== 6 | 7 | Optional plugins providing various types of job results. 8 | 9 | If you want to run the examples provided below, please fetch the avocado code 10 | where these examples are included. :: 11 | 12 | $ git clone https://github.com/avocado-framework/avocado.git 13 | 14 | 15 | .. toctree:: 16 | :maxdepth: 2 17 | 18 | html 19 | result_upload 20 | resultsdb 21 | mail -------------------------------------------------------------------------------- /examples/tests/sleeptest.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | from avocado import Test 4 | 5 | 6 | class SleepTest(Test): 7 | """ 8 | This test sleeps for 1s by default 9 | 10 | :param sleep_length: Sleep duration 11 | """ 12 | 13 | def test(self): 14 | """ 15 | Sleep for length seconds. 16 | """ 17 | sleep_length = float(self.params.get("sleep_length", default=1)) 18 | self.log.debug("Sleeping for %.2f seconds", sleep_length) 19 | time.sleep(sleep_length) 20 | -------------------------------------------------------------------------------- /docs/source/guides/contributor/chapters/introduction.rst: -------------------------------------------------------------------------------- 1 | Brief introduction 2 | ================== 3 | 4 | First of all, we would like to thank you for taking the time to contribute! We 5 | collected here useful pointers on how to participate in the Avocado community 6 | and how to contribute. 7 | 8 | And keep in mind that our procedures and guides are far from perfection, and 9 | need constant improvements. Feel free to propose changes to this, or any other, 10 | guide in a pull request. 11 | 12 | Happy Hacking! 13 | -------------------------------------------------------------------------------- /examples/tests/sleeptenmin.py.data/sleeptenmin.yaml: -------------------------------------------------------------------------------- 1 | sleeptenmin: !mux 2 | builtin: 3 | sleep_method: builtin 4 | shell: 5 | sleep_method: shell 6 | variants: !mux 7 | one_cycle: 8 | sleep_cycles: 1 9 | sleep_length: 600 10 | six_cycles: 11 | sleep_cycles: 6 12 | sleep_length: 100 13 | one_hundred_cycles: 14 | sleep_cycles: 100 15 | sleep_length: 6 16 | six_hundred_cycles: 17 | sleep_cycles: 600 18 | sleep_length: 1 19 | -------------------------------------------------------------------------------- /examples/hint-files/README.rst: -------------------------------------------------------------------------------- 1 | Hint Files 2 | ========== 3 | 4 | Avocado team has added support to the “hint files”. This feature is present 5 | since Avocado #78 and is a configuration file that you can add to your project 6 | root folder to help Avocado on the “test resolution” phase. 7 | 8 | For more information about hint files, please visit the `The hint files`_ 9 | section on our "User's Guide". 10 | 11 | .. _The hint files: https://avocado-framework.readthedocs.io/en/latest/guides/user/chapters/introduction.html 12 | -------------------------------------------------------------------------------- /examples/plugins/test-pre-post/hello/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | if __name__ == "__main__": 4 | setup( 5 | name="avocado-hello-world-pre-post-test", 6 | version="1.0", 7 | description="Avocado Hello World pre and post test plugin", 8 | py_modules=["hello"], 9 | entry_points={ 10 | "avocado.plugins.test.pre": ["hello_pre = hello:HelloWorld"], 11 | "avocado.plugins.test.post": ["hello_post = hello:HelloWorld"], 12 | }, 13 | ) 14 | -------------------------------------------------------------------------------- /examples/tests/sleeptest.py.data/sleeptest.json: -------------------------------------------------------------------------------- 1 | [{"paths": ["/run/*"], "variant_id": "run-short-beaf", "variant": [["/run/short", [["/run/short", "sleep_length", 0.5]]]]}, {"paths": ["/run/*"], "variant_id": "run-medium-5595", "variant": [["/run/medium", [["/run/medium", "sleep_length", 1]]]]}, {"paths": ["/run/*"], "variant_id": "run-long-f397", "variant": [["/run/long", [["/run/long", "sleep_length", 5]]]]}, {"paths": ["/run/*"], "variant_id": "run-longest-efc4", "variant": [["/run/longest", [["/run/longest", "sleep_length", 10]]]]}] -------------------------------------------------------------------------------- /selftests/.data/archive.py.data/test_archive__symlinks.zip.metadata: -------------------------------------------------------------------------------- 1 | { 2 | "members": [ 3 | ["file", "6deca672ab9a6aff2ef9ec091d3761c02426140299fd6b36471005999dd2aeb4"], 4 | ["dir/file2", "167e0283731e15c428f71c6a2f17b03672656e96243b9a4fa4395c887aba850b"], 5 | ["link_to_file", "symlink:file"], 6 | ["link_to_file2", "symlink:dir/file2"], 7 | ["link_to_dir", "symlink:dir"], 8 | ["dir/2nd_link_to_file", "symlink:../file"], 9 | ["dir/link_to_link_to_file2", "symlink:../link_to_file2"] 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /docs/source/guides/user/index.rst: -------------------------------------------------------------------------------- 1 | ==================== 2 | Avocado User's Guide 3 | ==================== 4 | 5 | .. toctree:: 6 | :maxdepth: 2 7 | 8 | chapters/about 9 | chapters/installing 10 | chapters/introduction 11 | chapters/concepts 12 | chapters/operations 13 | chapters/results 14 | chapters/tags 15 | chapters/configuring 16 | chapters/dependencies 17 | chapters/assets 18 | chapters/datadirs 19 | chapters/logging 20 | chapters/plugins 21 | chapters/advanced 22 | chapters/whatsnext 23 | -------------------------------------------------------------------------------- /examples/jobs/passjob.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import sys 3 | 4 | from avocado.core.job import Job 5 | 6 | job_config = {"resolver.references": ["examples/tests/passtest.py:PassTest.test"]} 7 | 8 | # Automatic helper method (Avocado will try to discovery things from config 9 | # dicts. Since there is magic here, we don't need to pass suite names or suites, 10 | # and test/task id will be prepend with the suite index (in this case 1 and 2) 11 | 12 | with Job.from_config(job_config=job_config) as job: 13 | sys.exit(job.run()) 14 | -------------------------------------------------------------------------------- /contrib/packages/debian/control: -------------------------------------------------------------------------------- 1 | Source: avocado 2 | Section: python 3 | Priority: optional 4 | Maintainer: Lucas Meneghel Rodrigues (lmr) 5 | Build-Depends: debhelper (>=7.0.50~), cdbs (>= 0.4.49), python3, python3-setuptools, dh-python 6 | Standards-Version: 3.8.4 7 | 8 | Package: avocado 9 | Architecture: all 10 | Homepage: http://avocado-framework.github.io/ 11 | X-Python-Version: ${python:Versions} 12 | Depends: ${misc:Depends}, ${python3:Depends} 13 | Description: Avocado is a framework for fully automated testing. 14 | -------------------------------------------------------------------------------- /docs/source/guides/contributor/index.rst: -------------------------------------------------------------------------------- 1 | =========================== 2 | Avocado Contributor's Guide 3 | =========================== 4 | 5 | Useful pointers on how to participate of the Avocado community and contribute. 6 | 7 | .. toctree:: 8 | :maxdepth: 2 9 | 10 | chapters/introduction 11 | chapters/how 12 | chapters/environment 13 | chapters/styleguides 14 | chapters/plugins 15 | chapters/results 16 | chapters/rfc 17 | chapters/releasing 18 | chapters/tips 19 | chapters/contact 20 | chapters/ai_policy 21 | -------------------------------------------------------------------------------- /examples/tests/doublefail.py: -------------------------------------------------------------------------------- 1 | from avocado import Test 2 | 3 | 4 | class DoubleFail(Test): 5 | """ 6 | Functional test for avocado. Straight up fail the test. 7 | 8 | :avocado: tags=failure_expected 9 | 10 | """ 11 | 12 | def test(self): 13 | """ 14 | Should fail. 15 | """ 16 | raise self.fail("This test is supposed to fail") 17 | 18 | def tearDown(self): 19 | """ 20 | Should also fail. 21 | """ 22 | raise self.error("Failing during tearDown. Yay!") 23 | -------------------------------------------------------------------------------- /examples/tests/gendata.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from avocado import Test 4 | 5 | 6 | class GenDataTest(Test): 7 | """ 8 | Simple test that generates data to be persisted after the test is run 9 | """ 10 | 11 | def test_json(self): 12 | import json 13 | 14 | output_path = os.path.join(self.outputdir, "test.json") 15 | output = {"basedir": self.basedir, "outputdir": self.outputdir} 16 | with open(output_path, "w", encoding="utf-8") as output_file: 17 | json.dump(output, output_file) 18 | -------------------------------------------------------------------------------- /examples/tests/sleeptest_async.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | 3 | from avocado import Test 4 | 5 | 6 | class AsyncSleepTest(Test): 7 | """ 8 | This test sleeps for 1s by default 9 | 10 | :param sleep_length: Sleep duration 11 | """ 12 | 13 | async def test(self): 14 | """ 15 | Sleep for length seconds. 16 | """ 17 | sleep_length = float(self.params.get("sleep_length", default=1)) 18 | self.log.debug("Sleeping for %.2f seconds", sleep_length) 19 | await asyncio.sleep(sleep_length) 20 | -------------------------------------------------------------------------------- /selftests/deployment/roles/avocado/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Avocado must be installed via specific method 3 | include_tasks: "roles/avocado/tasks/{{ method }}/avocado.yml" 4 | when: method is defined 5 | 6 | - name: Avocado Plugins must be installed via specific method 7 | include_tasks: "roles/avocado/tasks/{{ method }}/plugins.yml" 8 | when: method is defined 9 | 10 | - name: Avocado examples must be installed via specific method 11 | include_tasks: "roles/avocado/tasks/{{ method }}/examples.yml" 12 | when: method is defined 13 | -------------------------------------------------------------------------------- /Makefile.include: -------------------------------------------------------------------------------- 1 | # This Makefile contains snippets used on other Makefiles 2 | 3 | ifndef PYTHON 4 | PYTHON=$(shell which python3 2>/dev/null || which python 2>/dev/null) 5 | endif 6 | 7 | ifndef VERSION 8 | VERSION=$(shell $(PYTHON) setup.py --version 2>/dev/null) 9 | endif 10 | 11 | ifndef PYTHON_DEVELOP_ARGS 12 | PYTHON_DEVELOP_ARGS=$(shell if ($(PYTHON) setup.py develop --help 2>/dev/null | grep -q '\-\-user'); then echo "--user"; else echo ""; fi) 13 | endif 14 | 15 | pip: 16 | $(PYTHON) -m pip --version || $(PYTHON) -m ensurepip $(PYTHON_DEVELOP_ARGS) 17 | -------------------------------------------------------------------------------- /examples/plugins/test-pre-post/hello/hello.py: -------------------------------------------------------------------------------- 1 | from avocado.core.output import LOG_UI 2 | from avocado.core.plugin_interfaces import PostTest, PreTest 3 | 4 | 5 | class HelloWorld(PreTest, PostTest): 6 | 7 | name = "hello" 8 | description = "The classical Hello World! plugin example." 9 | is_cacheable = True 10 | 11 | def pre_test_runnables(self, test_runnable, suite_config=None): 12 | LOG_UI.info(self.description) 13 | 14 | def post_test_runnables(self, test_runnable, suite_config=None): 15 | LOG_UI.info(self.description) 16 | -------------------------------------------------------------------------------- /examples/jobs/multiple_spawners.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | from avocado.core.job import Job 6 | from avocado.core.suite import TestSuite 7 | 8 | PROCESS_CONFIG = {"resolver.references": ["/bin/true"], "run.spawner": "process"} 9 | 10 | PODMAN_CONFIG = {"resolver.references": ["/bin/true"], "run.spawner": "podman"} 11 | 12 | with Job( 13 | test_suites=[ 14 | TestSuite.from_config(PROCESS_CONFIG, name="process"), 15 | TestSuite.from_config(PODMAN_CONFIG, name="podman"), 16 | ] 17 | ) as j: 18 | sys.exit(j.run()) 19 | -------------------------------------------------------------------------------- /contrib/containers/fedora-40-latest-copr.docker: -------------------------------------------------------------------------------- 1 | FROM fedora:40 2 | LABEL description "Fedora image with the latest Avocado COPR build" 3 | RUN dnf -y install dnf-plugins-core 4 | RUN dnf -y copr enable @avocado/avocado-latest-release 5 | RUN dnf -y install python3-avocado python3-avocado-bash python3-avocado-common python3-avocado-examples python3-avocado-plugins-golang python3-avocado-plugins-output-html python3-avocado-plugins-result-upload python3-avocado-plugins-varianter-cit python3-avocado-plugins-varianter-pict python3-avocado-plugins-varianter-yaml-to-mux 6 | RUN dnf -y clean all 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .project 2 | .pydevproject 3 | .settings 4 | .coverage 5 | .idea/* 6 | coverage.xml 7 | xunit.xml 8 | tmp/* 9 | logs/* 10 | *.pyc 11 | *~ 12 | tags 13 | cscope.* 14 | build 15 | sysinfo-* 16 | MANIFEST 17 | dist 18 | *.egg-info* 19 | docs/source/api/core 20 | docs/source/api/test 21 | docs/source/api/utils 22 | docs/source/api/plugins 23 | docs/source/api/optional-plugins 24 | docs/source/guides/writer/libs/data/vmimage 25 | 26 | # This file should be generated with: 27 | # avocado config reference > docs/source/config/reference.rst 28 | docs/source/config/reference.rst 29 | -------------------------------------------------------------------------------- /selftests/.data/safeloader/data/double_import.py: -------------------------------------------------------------------------------- 1 | """ 2 | isort:skip_file 3 | """ 4 | 5 | import avocado as foo 6 | import avocado as bar # pylint: disable=W0404 7 | 8 | from avocado import Test as Foo 9 | from avocado import Test as Bar # pylint: disable=W0404 10 | 11 | 12 | class Test1(foo.Test): 13 | def test1(self): 14 | pass 15 | 16 | 17 | class Test2(bar.Test): 18 | def test2(self): 19 | pass 20 | 21 | 22 | class Test3(Foo): 23 | def test3(self): 24 | pass 25 | 26 | 27 | class Test4(Bar): 28 | def test4(self): 29 | pass 30 | -------------------------------------------------------------------------------- /examples/apis/utils/ssh_timeout.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | from avocado.utils.ssh import Session 4 | 5 | with Session("host", user="root", key="/path/to/key") as s: 6 | # baseline case 7 | time_start = time.monotonic() 8 | s.cmd("sleep 10") 9 | total_time = time.monotonic() - time_start 10 | print(total_time) 11 | assert total_time >= 10 12 | 13 | # check of timeout enforcement 14 | time_start = time.monotonic() 15 | s.cmd("sleep 10", timeout=1) 16 | total_time = time.monotonic() - time_start 17 | print(total_time) 18 | assert total_time <= 10 19 | -------------------------------------------------------------------------------- /examples/tests/property.py: -------------------------------------------------------------------------------- 1 | from avocado import Test 2 | 3 | 4 | class Property(Test): 5 | @property 6 | def testing_the_existence_of_properties(self): 7 | """ 8 | This is a bad name for property when writing an Avocado test. 9 | 10 | Its name starts with "test", which would usually make it an 11 | Avocado test, but, because it's a property, it's not 12 | considered a valid test. 13 | """ 14 | return True 15 | 16 | def test(self): 17 | self.log.info("Property exists: %s", self.testing_the_existence_of_properties) 18 | -------------------------------------------------------------------------------- /contrib/containers/ci/selftests/magic.docker: -------------------------------------------------------------------------------- 1 | # This dockerfile copies and installs the magic example plugin, and 2 | # thus needs access to the "magic" directory. Make sure the context 3 | # (directory) is correct before building this image. One example 4 | # is by running: 5 | # $ cd examples/plugins/tests 6 | # $ buildah bud -f ../../../contrib/containers/ci/selftests/magic.docker 7 | FROM fedora:40 8 | LABEL description "Image that contains the example magic plugin" 9 | RUN dnf -y install python3-setuptools 10 | COPY magic /tmp/magic 11 | WORKDIR /tmp/magic 12 | RUN python3 setup.py install 13 | -------------------------------------------------------------------------------- /examples/jobs/sleepjob_parameters.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | from avocado.core.job import Job 4 | from avocado.core.nrunner.runnable import Runnable 5 | from avocado.core.suite import TestSuite 6 | 7 | config = {} 8 | 9 | test = Runnable( 10 | "avocado-instrumented", 11 | "examples/tests/sleeptest.py:SleepTest.test", 12 | variant={ 13 | "paths": ["/"], 14 | "variant_id": None, 15 | "variant": [["/", [["/", "sleep_length", "0.01"]]]], 16 | }, 17 | ) 18 | suite = TestSuite("suite_1", tests=[test]) 19 | 20 | with Job(config, [suite]) as j: 21 | sys.exit(j.run()) 22 | -------------------------------------------------------------------------------- /examples/tests/timeouttest.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | from avocado import Test 4 | 5 | 6 | class TimeoutTest(Test): 7 | """ 8 | Functional test for avocado. Throw a TestTimeoutError. 9 | 10 | :param sleep_time: How long should the test sleep 11 | """ 12 | 13 | timeout = 3 14 | 15 | def test(self): 16 | """ 17 | This should throw a TestTimeoutError. 18 | """ 19 | sleep_time = float(self.params.get("sleep_time", default=5.0)) 20 | self.log.info("Sleeping for %.2f seconds (2 more than the timeout)", sleep_time) 21 | time.sleep(sleep_time) 22 | -------------------------------------------------------------------------------- /selftests/unit/task.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from avocado.core.nrunner.runnable import Runnable 4 | from avocado.core.nrunner.task import Task 5 | 6 | 7 | class TaskTest(unittest.TestCase): 8 | def test_default_category(self): 9 | runnable = Runnable("noop", "noop_uri") 10 | task = Task(runnable, "task_id") 11 | self.assertEqual(task.category, "test") 12 | 13 | def test_set_category(self): 14 | runnable = Runnable("noop", "noop_uri") 15 | task = Task(runnable, "task_id", category="new_category") 16 | self.assertEqual(task.category, "new_category") 17 | -------------------------------------------------------------------------------- /avocado/plugins/__init__.py: -------------------------------------------------------------------------------- 1 | # This program is free software; you can redistribute it and/or modify 2 | # it under the terms of the GNU General Public License as published by 3 | # the Free Software Foundation; either version 2 of the License, or 4 | # (at your option) any later version. 5 | # 6 | # This program is distributed in the hope that it will be useful, 7 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 8 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 | # 10 | # See LICENSE for more details. 11 | # 12 | # Copyright: Red Hat Inc. 2015 13 | # Author: Cleber Rosa 14 | -------------------------------------------------------------------------------- /examples/jobs/passjob_with_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | from avocado import Test 6 | from avocado.core.job import Job 7 | 8 | # When using __file__, you need to protect Job.run() within a 9 | # conditional block so that it doesn't get executed *again* and 10 | # generates a loop when loading this file at test execution time. 11 | config = {"resolver.references": [__file__]} 12 | 13 | 14 | class PassTest(Test): 15 | def test(self): 16 | pass 17 | 18 | 19 | if __name__ == "__main__": 20 | with Job.from_config(job_config=config) as j: 21 | sys.exit(j.run()) 22 | -------------------------------------------------------------------------------- /selftests/jobs/passjob_html.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import tempfile 5 | 6 | from avocado.core.job import Job 7 | from avocado.core.suite import TestSuite 8 | 9 | test_results_dir = tempfile.TemporaryDirectory() 10 | 11 | config = { 12 | "run.results_dir": test_results_dir.name, 13 | "resolver.references": ["examples/tests/passtest.py:PassTest.test"], 14 | "job.run.result.html.enabled": True, 15 | } 16 | 17 | suite = TestSuite.from_config(config) 18 | with Job(config, [suite]) as j: 19 | exit_code = j.run() 20 | test_results_dir.cleanup() 21 | sys.exit(exit_code) 22 | -------------------------------------------------------------------------------- /examples/plugins/job-pre-post/sleep/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | name = "avocado_job_sleep" 4 | init_klass = "SleepInit" 5 | klass = "Sleep" 6 | entry_point = f"{name} = {name}:{klass}" 7 | init_entry_point = f"{name} = {name}:{init_klass}" 8 | 9 | if __name__ == "__main__": 10 | setup( 11 | name=name, 12 | version="1.0", 13 | description="Avocado Pre/Post Job Sleep", 14 | py_modules=[name], 15 | entry_points={ 16 | "avocado.plugins.init": [init_entry_point], 17 | "avocado.plugins.job.prepost": [entry_point], 18 | }, 19 | ) 20 | -------------------------------------------------------------------------------- /avocado/utils/external/__init__.py: -------------------------------------------------------------------------------- 1 | # This program is free software; you can redistribute it and/or modify 2 | # it under the terms of the GNU General Public License as published by 3 | # the Free Software Foundation; either version 2 of the License, or 4 | # (at your option) any later version. 5 | # 6 | # This program is distributed in the hope that it will be useful, 7 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 8 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 | # 10 | # See LICENSE for more details. 11 | # 12 | # Copyright: Red Hat Inc. 2015 13 | # Author: Cleber Rosa 14 | -------------------------------------------------------------------------------- /avocado/utils/__init__.py: -------------------------------------------------------------------------------- 1 | # This program is free software; you can redistribute it and/or modify 2 | # it under the terms of the GNU General Public License as published by 3 | # the Free Software Foundation; either version 2 of the License, or 4 | # (at your option) any later version. 5 | # 6 | # This program is distributed in the hope that it will be useful, 7 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 8 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 | # 10 | # See LICENSE for more details. 11 | # 12 | # Copyright: Red Hat Inc. 2013-2014 13 | # Author: Lucas Meneghel Rodrigues 14 | -------------------------------------------------------------------------------- /avocado/core/streams.py: -------------------------------------------------------------------------------- 1 | #: Builtin special keywords to enable set of logging streams 2 | BUILTIN_STREAMS = { 3 | "app": "avocado.app", 4 | "test": "avocado.test", 5 | "job": "avocado.job", 6 | "early": "avocado", 7 | } 8 | 9 | BUILTIN_STREAMS_DESCRIPTION = { 10 | "app": "application output", 11 | "test": "test output", 12 | "job": "job output", 13 | "early": "early logging of other streams, including test (very verbose)", 14 | } 15 | 16 | #: Groups of builtin streams 17 | BUILTIN_STREAM_SETS = { 18 | "all": "all builtin streams", 19 | "none": "disables regular output (leaving only errors enabled)", 20 | } 21 | -------------------------------------------------------------------------------- /optional_plugins/varianter_yaml_to_mux/tests/.data/mux-environment.yaml: -------------------------------------------------------------------------------- 1 | hw: 2 | cpu: !mux 3 | intel: 4 | cpu_CFLAGS: '-march=core2' 5 | amd: 6 | cpu_CFLAGS: '-march=athlon64' 7 | arm: 8 | cpu_CFLAGS: '-mabi=apcs-gnu -march=armv8-a -mtune=arm8' 9 | disk: !mux 10 | scsi: 11 | disk_type: 'scsi' 12 | virtio: 13 | disk_type: 'virtio' 14 | distro: !mux 15 | fedora: 16 | init: 'systemd' 17 | mint: 18 | init: 'systemv' 19 | env: !mux 20 | debug: 21 | opt_CFLAGS: '-O0 -g' 22 | prod: 23 | opt_CFLAGS: '-O2' 24 | -------------------------------------------------------------------------------- /selftests/jobs/passjob_cit_varianter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import tempfile 5 | 6 | from avocado.core.job import Job 7 | from avocado.core.suite import TestSuite 8 | 9 | test_results_dir = tempfile.TemporaryDirectory() 10 | 11 | config = { 12 | "run.results_dir": test_results_dir.name, 13 | "resolver.references": ["examples/tests/passtest.py:PassTest.test"], 14 | "cit_parameter_file": "examples/varianter_cit/test_params.cit", 15 | } 16 | 17 | suite = TestSuite.from_config(config) 18 | with Job(config, [suite]) as j: 19 | exit_code = j.run() 20 | test_results_dir.cleanup() 21 | sys.exit(exit_code) 22 | -------------------------------------------------------------------------------- /selftests/signedoff-check.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | echo "** Running signedoff-check..." 4 | if [ -z "$COMMIT_COUNT" ]; then 5 | COMMIT_COUNT=1 6 | fi 7 | readarray -t commits <<< $(git log --no-merges -n "$COMMIT_COUNT" --format='%H') 8 | for commit in "${commits[@]}"; do 9 | AUTHOR=$(git log -1 --format='%aN <%aE>' "$commit") 10 | HEADER=$(git log -1 --format='%s' "$commit") 11 | echo " Checking commit with header: '$HEADER" 12 | if ! git log -1 --pretty=format:%B "$commit" | grep -i "Signed-off-by: $AUTHOR"; then 13 | echo "The commit message does not contain author's signature (Signed-off-by: $AUTHOR)" 14 | exit 1 15 | fi 16 | done 17 | -------------------------------------------------------------------------------- /examples/tests/errortest_nasty.py: -------------------------------------------------------------------------------- 1 | from avocado import Test 2 | 3 | 4 | class NastyException(Exception): 5 | """Please never use something like this!!!""" 6 | 7 | def __init__(self, msg): # pylint: disable=W0231 8 | self.msg = msg 9 | 10 | def __str__(self): 11 | return self.msg 12 | 13 | 14 | class FailTest(Test): 15 | """ 16 | Very nasty exception test 17 | 18 | :avocado: tags=failure_expected 19 | """ 20 | 21 | @staticmethod 22 | def test(): 23 | """ 24 | Avocado should report this as TestError. 25 | """ 26 | raise NastyException("Nasty-string-like-exception\u017e") 27 | -------------------------------------------------------------------------------- /selftests/jobs/sleepjob_dict_varianter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import tempfile 5 | 6 | from avocado.core.job import Job 7 | from avocado.core.suite import TestSuite 8 | 9 | test_results_dir = tempfile.TemporaryDirectory() 10 | 11 | config = { 12 | "run.results_dir": test_results_dir.name, 13 | "resolver.references": ["examples/tests/sleeptest.py:SleepTest.test"], 14 | "run.dict_variants": [{"sleep_length": "0.5"}, {"sleep_length": "1.0"}], 15 | } 16 | 17 | suite = TestSuite.from_config(config) 18 | with Job(config, [suite]) as j: 19 | exit_code = j.run() 20 | test_results_dir.cleanup() 21 | sys.exit(exit_code) 22 | -------------------------------------------------------------------------------- /selftests/jobs/sleepjob_json_varianter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import tempfile 5 | 6 | from avocado.core.job import Job 7 | from avocado.core.suite import TestSuite 8 | 9 | test_results_dir = tempfile.TemporaryDirectory() 10 | 11 | config = { 12 | "run.results_dir": test_results_dir.name, 13 | "resolver.references": ["examples/tests/sleeptest.py:SleepTest.test"], 14 | "json.variants.load": "examples/tests/sleeptest.py.data/sleeptest.json", 15 | } 16 | 17 | suite = TestSuite.from_config(config) 18 | with Job(config, [suite]) as j: 19 | exit_code = j.run() 20 | test_results_dir.cleanup() 21 | sys.exit(exit_code) 22 | -------------------------------------------------------------------------------- /examples/tests/errortest_nasty3.py: -------------------------------------------------------------------------------- 1 | from avocado import Test 2 | 3 | 4 | class NastyException: 5 | """Please never use something like this!!! (old-style exception)""" 6 | 7 | def __init__(self, msg): 8 | self.msg = msg 9 | 10 | def __str__(self): 11 | return self.msg 12 | 13 | 14 | class FailTest(Test): 15 | """ 16 | This test raises old-style-class exception 17 | 18 | :avocado: tags=failure_expected 19 | """ 20 | 21 | @staticmethod 22 | def test(): 23 | """ 24 | Avocado should report this as TestError. 25 | """ 26 | raise NastyException("Nasty-string-like-exception") # pylint: disable=E0710 27 | -------------------------------------------------------------------------------- /docs/README.rst: -------------------------------------------------------------------------------- 1 | Avocado Documentation 2 | ===================== 3 | 4 | If you want to build the documentation yourself: 5 | 6 | 1) Make sure you have the package ``python-sphinx`` installed. For Fedora:: 7 | 8 | $ sudo yum install python-sphinx 9 | 10 | 2) For Mint/Ubuntu/Debian:: 11 | 12 | $ sudo apt-get install python-sphinx 13 | 14 | 3) Optionally, you can install the read the docs theme, that will make your 15 | in-tree documentation look just like the online version:: 16 | 17 | $ sudo pip install sphinx_rtd_theme 18 | 19 | 4) Build the docs:: 20 | 21 | $ make html 22 | 23 | 5) Once done, point your browser to:: 24 | 25 | $ [your-browser] build/html/index.html 26 | -------------------------------------------------------------------------------- /docs/source/guides/contributor/chapters/rfc.rst: -------------------------------------------------------------------------------- 1 | Request for Comments (RFCs) 2 | =========================== 3 | 4 | What is a RFC? 5 | -------------- 6 | 7 | RFCs were the main mechanism used in the early days of the Avocado 8 | project to discuss larger ideas. RFCs have been pretty much 9 | supplanted by BluePrints (see :doc:`/blueprints/BP000`). 10 | 11 | Previous RFCs 12 | ------------- 13 | 14 | The following list contains archivals of accepted, Request For Comments posted 15 | and discussed on the `Avocado Devel Mailing List`_. 16 | 17 | .. toctree:: 18 | :maxdepth: 1 19 | 20 | ../rfcs/lts 21 | 22 | .. _Avocado Devel Mailing List: https://www.redhat.com/mailman/listinfo/avocado-devel 23 | -------------------------------------------------------------------------------- /optional_plugins/golang/tests/src/countavocados/countavocados_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "testing" 4 | import "fmt" 5 | 6 | func TestEmptyContainers(t *testing.T) { 7 | total := Count(10, 0) 8 | if total != 0 { 9 | t.Errorf("No Avocados supposed to be present, but got %d", total) 10 | } 11 | } 12 | 13 | func TestNoContainers(t *testing.T) { 14 | total := Count(10, 0) 15 | if total != 0 { 16 | t.Errorf("No Avocados supposed to be present, but got %d", total) 17 | } 18 | } 19 | 20 | func TestingButNotReally() { 21 | return 22 | } 23 | 24 | func ExampleContainers() { 25 | fmt.Printf("Have %d Avocados", Count(3, 3)) 26 | // Output: Have 9 Avocados 27 | } 28 | -------------------------------------------------------------------------------- /selftests/functional/plugin/runner_nrunner.py: -------------------------------------------------------------------------------- 1 | from avocado.core.exit_codes import AVOCADO_ALL_OK 2 | from avocado.utils import process 3 | from selftests.utils import AVOCADO, TestCaseTmpDir 4 | 5 | 6 | class NrunnerTest(TestCaseTmpDir): 7 | def test_status_server_uri(self): 8 | result = process.run( 9 | f"{AVOCADO} run " 10 | f"--job-results-dir {self.tmpdir.name} " 11 | f"--disable-sysinfo --status-server-disable-auto " 12 | f"--status-server-uri 127.0.0.1:9999 " 13 | f"examples/tests/true", 14 | ) 15 | self.assertIn("PASS 1 ", result.stdout_text) 16 | self.assertEqual(result.exit_status, AVOCADO_ALL_OK) 17 | -------------------------------------------------------------------------------- /.github/actions/egg/action.yml: -------------------------------------------------------------------------------- 1 | name: Egg 2 | description: Test running avocado from eggs 3 | runs: 4 | using: composite 5 | steps: 6 | - name: Test running avocado from eggs 7 | shell: sh 8 | run: | 9 | python3 setup.py bdist_egg 10 | mv dist/avocado_framework-*egg /tmp 11 | python3 setup.py clean --all 12 | python3 -c 'import sys; import glob; sys.path.insert(0, glob.glob("/tmp/avocado_framework-*.egg")[0]); from avocado.core.main import main; sys.exit(main())' run /bin/true 13 | cd /tmp 14 | python3 -c 'import sys; from pkg_resources import require; require("avocado-framework"); from avocado.core.main import main; sys.exit(main())' run /bin/true 15 | -------------------------------------------------------------------------------- /examples/yaml_to_mux/types.yaml: -------------------------------------------------------------------------------- 1 | # This demonstrates different value types as well as a clash 2 | by_type: !mux 3 | string: 4 | value: "this is string" 5 | int: 6 | value: 1 7 | float: 8 | value: -1.1 9 | 10 | key: value 11 | some: 12 | path: 13 | containing: 14 | value: | 15 | this will produce `self.params.get("value")` clashes as 16 | Avocado can't determine which of those values do you need. 17 | You have to use `self.params.get("value", path="*/by_type/*")` 18 | or `self.params.get("value", path="*/some/path/*")` to 19 | distinguish which `value` you have in mind. 20 | -------------------------------------------------------------------------------- /requirements-dev.txt: -------------------------------------------------------------------------------- 1 | # Avocado development requirements 2 | 3 | # static and style checks 4 | pyenchant==3.2.2 5 | autopep8==1.6.0 6 | 7 | coverage==7.5 8 | 9 | # To run make check 10 | psutil==5.9.5 11 | 12 | # pycdlib is an optional requirement in production 13 | # but is necessary for selftests 14 | pycdlib==1.13.0 15 | 16 | # For avocado.utils.network selftests 17 | netifaces==0.11.0 18 | 19 | # For tests that validate the produced XUnit output 20 | xmlschema==1.7.0; python_version < '3.12' 21 | xmlschema==2.5.0; python_version >= '3.12' 22 | 23 | # For building the manpage 24 | docutils==0.17.1 25 | 26 | # For tests that check content generated by runners 27 | jsonschema==3.2.0 28 | PyYAML>=4.2b2 29 | -------------------------------------------------------------------------------- /docs/source/config/index.rst: -------------------------------------------------------------------------------- 1 | .. _config-reference: 2 | 3 | Avocado's Configuration Reference 4 | ================================= 5 | 6 | This is current Avocado Configuration reference. You can adjust the values by two ways: 7 | 8 | - Configuration file options; 9 | - Command-line options (when available) 10 | 11 | Some options that are used often are available for your convenience also at the command-line. 12 | This list has all options registered with Avocado so far. 13 | 14 | .. note:: Please, keep in mind that we are in constant evolution and doing a 15 | huge improvements on how to configure Avocado, some options here can be changed 16 | in the near future. 17 | 18 | .. include:: reference.rst 19 | -------------------------------------------------------------------------------- /examples/tests/errortest_nasty2.py: -------------------------------------------------------------------------------- 1 | from avocado import Test 2 | 3 | 4 | class NastyException(Exception): 5 | """Please never use something like this!!!""" 6 | 7 | def __init__(self, msg): # pylint: disable=W0231 8 | self.msg = msg 9 | 10 | def __str__(self): 11 | return self.msg 12 | 13 | def __unicode__(self): 14 | return self.msg 15 | 16 | 17 | class FailTest(Test): 18 | """ 19 | Very nasty exception test 20 | 21 | :avocado: tags=failure_expected 22 | """ 23 | 24 | @staticmethod 25 | def test(): 26 | """ 27 | Avocado should report this as TestError. 28 | """ 29 | raise NastyException(None) # str(Exception) fails! 30 | -------------------------------------------------------------------------------- /selftests/unit/status_utils.py: -------------------------------------------------------------------------------- 1 | from unittest import TestCase 2 | 3 | from avocado.core.status import utils 4 | 5 | 6 | class JSON(TestCase): 7 | def test_loads_bytes(self): 8 | self.assertEqual(utils.json_loads(b"{}"), {}) 9 | 10 | def test_loads_str(self): 11 | self.assertEqual(utils.json_loads("{}"), {}) 12 | 13 | def test_loads_invalid(self): 14 | with self.assertRaises(utils.StatusMsgInvalidJSONError): 15 | utils.json_loads("+-+-InvalidJSON-AFAICT-+-+") 16 | 17 | def test_loads_base64(self): 18 | data = '{"__base64_encoded__": "dGhpcyBpcyBob3cgd2UgZW5jb2RlIGJ5dGVz"}' 19 | self.assertEqual(utils.json_loads(data), b"this is how we encode bytes") 20 | -------------------------------------------------------------------------------- /examples/plugins/cli-cmd/hello_option/hello_option.py: -------------------------------------------------------------------------------- 1 | from avocado.core.output import LOG_UI 2 | from avocado.core.plugin_interfaces import CLICmd 3 | from avocado.core.settings import settings 4 | 5 | 6 | class HelloWorld(CLICmd): 7 | 8 | name = "hello" 9 | description = "The classical Hello World plugin example!" 10 | 11 | def configure(self, parser): 12 | settings.register_option( 13 | section="hello", 14 | key="message", 15 | key_type=str, 16 | default=self.description, 17 | help_msg="Configure the message to display", 18 | ) 19 | 20 | def run(self, config): 21 | msg = config.get("hello.message") 22 | LOG_UI.info(msg) 23 | -------------------------------------------------------------------------------- /examples/tests/external_logging_stream.py: -------------------------------------------------------------------------------- 1 | import matplotlib 2 | import matplotlib.pyplot as plt 3 | 4 | from avocado import Test 5 | 6 | 7 | class MatplotlibTest(Test): 8 | def test(self): 9 | matplotlib.use("agg") 10 | _, ax = plt.subplots() 11 | 12 | fruits = ["apple", "blueberry", "cherry", "orange"] 13 | counts = [40, 100, 30, 55] 14 | bar_labels = ["red", "blue", "_red", "orange"] 15 | bar_colors = ["tab:red", "tab:blue", "tab:red", "tab:orange"] 16 | 17 | ax.bar(fruits, counts, label=bar_labels, color=bar_colors) 18 | 19 | ax.set_ylabel("fruit supply") 20 | ax.set_title("Fruit supply by kind and color") 21 | ax.legend(title="Fruit color") 22 | -------------------------------------------------------------------------------- /examples/apis/utils/ssh.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | from avocado.utils.process import SubProcess 4 | from avocado.utils.ssh import Session 5 | 6 | with Session("host", user="root", key="/path/to/key") as s: 7 | print("connected") 8 | procs = [] 9 | cmd = s.get_raw_ssh_command("sleep 5") 10 | for i in range(10): 11 | p = SubProcess(cmd) 12 | print(p.start()) 13 | procs.append(p) 14 | 15 | while True: 16 | for proc in procs: 17 | proc.poll() 18 | 19 | if all([p.result.exit_status is not None for p in procs]): 20 | print("all finished") 21 | break 22 | 23 | time.sleep(1) 24 | print("working...") 25 | 26 | print("session closed") 27 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always missing this feature when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional information** 20 | Add any additional information or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /avocado/libexec/avocado-bash-utils: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # This program is free software; you can redistribute it and/or modify 3 | # it under the terms of the GNU General Public License as published by 4 | # the Free Software Foundation; specifically version 2 of the License. 5 | # 6 | # This program is distributed in the hope that it will be useful, 7 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 8 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 | # 10 | # See LICENSE for more details. 11 | # 12 | # Copyright: Red Hat Inc. 2014 13 | 14 | # Write to avocado_log 15 | # First argument is the log level 16 | avocado_log() { 17 | LEVEL=`printf '%-5s' $1` 18 | shift 19 | echo "`date '+%H:%M:%S'` $LEVEL| $*" 20 | } 21 | -------------------------------------------------------------------------------- /selftests/jobs/passjob.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import sys 3 | import tempfile 4 | 5 | from avocado.core.job import Job 6 | 7 | test_results_dir = tempfile.TemporaryDirectory() 8 | 9 | job_config = { 10 | "run.results_dir": test_results_dir.name, 11 | "resolver.references": ["examples/tests/passtest.py:PassTest.test"], 12 | } 13 | 14 | # Automatic helper method (Avocado will try to discovery things from config 15 | # dicts. Since there is magic here, we don't need to pass suite names or suites, 16 | # and test/task id will be prepend with the suite index (in this case 1 and 2) 17 | 18 | with Job.from_config(job_config=job_config) as job: 19 | exit_code = job.run() 20 | test_results_dir.cleanup() 21 | sys.exit(exit_code) 22 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yaml 2 | # Read the Docs configuration file 3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 4 | 5 | # Required 6 | version: 2 7 | 8 | # Set the version of Python and other tools you might need 9 | build: 10 | os: ubuntu-22.04 11 | tools: 12 | python: "3.11" 13 | 14 | # Build documentation in the docs/ directory with Sphinx 15 | sphinx: 16 | configuration: docs/source/conf.py 17 | fail_on_warning: true 18 | 19 | # We recommend specifying your dependencies to enable reproducible builds: 20 | # https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html 21 | python: 22 | install: 23 | - requirements: requirements-doc.txt 24 | - method: pip 25 | path: . 26 | -------------------------------------------------------------------------------- /examples/tests/cancel_on_exception.py: -------------------------------------------------------------------------------- 1 | import avocado 2 | 3 | 4 | class CancelOnException(avocado.Test): 5 | """ 6 | Test illustrating the usage of the cancel_on decorator. 7 | """ 8 | 9 | @staticmethod 10 | def test(): 11 | """ 12 | This should end with CANCEL. 13 | 14 | Avocado tests should end with ERROR when a generic exception such as 15 | RuntimeError is raised. The avocado.cancel_on decorator allows you 16 | to override this behavior, and turn your generic exceptions into 17 | test CANCEL. 18 | """ 19 | 20 | @avocado.cancel_on(RuntimeError) 21 | def raises_runtime_error(): 22 | raise RuntimeError 23 | 24 | raises_runtime_error() 25 | -------------------------------------------------------------------------------- /optional_plugins/README.rst: -------------------------------------------------------------------------------- 1 | ================== 2 | Optional Plugins 3 | ================== 4 | 5 | This is where plugins shipped with Avocado, but not considered core 6 | functionality can be found. 7 | 8 | To try them out on a development environment, you may run:: 9 | 10 | $ cd / 11 | $ python setup.py develop --user 12 | 13 | And to remove them on a development environment, you may run, at the 14 | same directory:: 15 | 16 | $ python setup.py develop --uninstall --user 17 | 18 | Also, on a development environment, the following command on the 19 | topmost Avocado source code directory will enable all optional 20 | plugins:: 21 | 22 | $ make link 23 | 24 | And this will disable all optional plugins:: 25 | 26 | $ make unlink 27 | -------------------------------------------------------------------------------- /selftests/jobs/pass: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Minimal job that runs an also minimal executable test 4 | 5 | import os 6 | import sys 7 | import tempfile 8 | 9 | from avocado.core.job import Job 10 | from avocado.core.suite import TestSuite 11 | 12 | test_results_dir = tempfile.TemporaryDirectory() 13 | 14 | config = { 15 | "run.results_dir": test_results_dir.name, 16 | 'resolver.references': [ 17 | os.path.join(os.path.dirname(__file__), 'tests', 'pass'), 18 | os.path.join(os.path.dirname(__file__), 'tests', 'passtest.py') 19 | ] 20 | } 21 | 22 | suite = TestSuite.from_config(config) 23 | with Job(config, [suite]) as j: 24 | exit_code = j.run() 25 | test_results_dir.cleanup() 26 | sys.exit(exit_code) 27 | -------------------------------------------------------------------------------- /examples/tests/env_variables.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # This test demonstrates that shell scripts have access to avocado runtime 3 | # information, exported through environment variables. 4 | echo "Avocado Version: $AVOCADO_VERSION" 5 | echo "Avocado Test basedir: $AVOCADO_TEST_BASEDIR" 6 | test -d "$AVOCADO_TEST_BASEDIR" || exit 1 7 | echo "Avocado Test workdir: $AVOCADO_TEST_WORKDIR" 8 | test -d "$AVOCADO_TEST_WORKDIR" || exit 1 9 | echo "Avocado Test logdir: $AVOCADO_TEST_LOGDIR" 10 | test -d "$AVOCADO_TEST_LOGDIR" || exit 1 11 | echo "Avocado Test logfile: $AVOCADO_TEST_LOGFILE" 12 | test -f "$AVOCADO_TEST_LOGFILE" || exit 1 13 | echo "Avocado Test outputdir: $AVOCADO_TEST_OUTPUTDIR" 14 | test -d "$AVOCADO_TEST_OUTPUTDIR" || exit 1 15 | echo "Custom variable: $CUSTOM_VARIABLE" 16 | -------------------------------------------------------------------------------- /examples/tests/fail_on_exception.py: -------------------------------------------------------------------------------- 1 | import avocado 2 | 3 | 4 | class FailOnException(avocado.Test): 5 | """ 6 | Test illustrating the behavior of the fail_on decorator. 7 | 8 | :avocado: tags=failure_expected 9 | """ 10 | 11 | @staticmethod 12 | # @avocado.fail_on(ValueError) also possible 13 | @avocado.fail_on 14 | def test(): 15 | """ 16 | This should end with FAIL. 17 | 18 | Avocado tests should end with ERROR when a generic exception such as 19 | ValueError is raised. The avocado.fail_on_error decorator allows you 20 | to override this behavior, and turn your generic exceptions into 21 | errors. 22 | """ 23 | raise ValueError("This raises a ValueError and should end as a FAIL") 24 | -------------------------------------------------------------------------------- /docs/source/api/headers/test: -------------------------------------------------------------------------------- 1 | At the most basic level, there's the Test APIs which you should use when 2 | writing tests in Python and planning to make use of any other utility library. 3 | 4 | The Test APIs can be found in the :mod:`avocado` main module and its most 5 | important member is the :class:`avocado.Test` class. By conforming to the 6 | :class:`avocado.Test` API, that is, by inheriting from it, you can use the full 7 | set of utility libraries. 8 | 9 | The Test APIs are guaranteed to be stable across a single major version of 10 | Avocado. That means that a test written for a given version of Avocado should 11 | not break on later minor versions because of Test API changes. 12 | 13 | This is the bare minimum set of APIs that users should use, and can rely on, 14 | while writing tests. 15 | -------------------------------------------------------------------------------- /optional_plugins/varianter_yaml_to_mux/tests/.data/mux-selftest-params.yaml: -------------------------------------------------------------------------------- 1 | root: "root" 2 | cache_test: 'cache' 3 | diff_domain: "text1" 4 | ch0: 5 | diff_domain: "text2" 6 | clash1: "equal" 7 | clash3: "also equal" 8 | ch0.1: 9 | ch0.1.1: !mux 10 | ch0.1.1.1: 11 | unique1: "unique1" 12 | clash1: "equal" 13 | ch0.1.1.2: 14 | unique1: "unique1-2" 15 | ch0.1b: !mux 16 | ch0.1.2: 17 | unique3: "unique3" 18 | clash3: "also equal" 19 | ch0.1.3: 20 | clash3: "also equal" 21 | ch1: 22 | unique2: "unique2" 23 | clash3: "also equal" 24 | ch11: 25 | clash2: 'equal' 26 | ch2.1: 27 | unique4: "other_unique" 28 | ch111: 29 | clash2: 'equal' 30 | -------------------------------------------------------------------------------- /examples/jobs/passjob_custom.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | from avocado.core.job import Job 6 | from avocado.core.nrunner.runnable import Runnable 7 | from avocado.core.suite import TestSuite 8 | 9 | # Custom method (no discovery, no guess, no magic) 10 | # Since there is no magic, we need to pass a suite name, otherwise a uuid4 will 11 | # be used for suite.name. Also resolver.references will be ignored (Avocado will not 12 | # creating tests suites for you). 13 | 14 | suite1 = TestSuite(name="suite1", tests=[Runnable("noop", "noop")]) 15 | suite2 = TestSuite(name="suite2", tests=[Runnable("noop", "noop")]) 16 | suite3 = TestSuite(name="suite3", enabled=False, tests=[Runnable("noop", "noop")]) 17 | 18 | with Job(test_suites=[suite1, suite2, suite3]) as j: 19 | sys.exit(j.run()) 20 | -------------------------------------------------------------------------------- /examples/tests/raise.py.data/raise.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* 6 | * Signal numbers are translated to exit code by the shell. 7 | * For example, if SIGUSR1 is raised (sinal number 10) then 8 | * the exit code will be 128+10 = 138. 9 | * 10 | * In the case of avocado.utils.process.SubProcess, the exit code is 11 | * the negative value of the signal, so SIGUSR1 will return -10. 12 | * 13 | * See http://tldp.org/LDP/abs/html/exitcodes.html 14 | */ 15 | 16 | int 17 | main(int argc, char *argv[]) 18 | { 19 | int res; 20 | 21 | if (argc == 1) { 22 | printf("Usage: raise SIGNAL_NUMBER\n"); 23 | return 1; 24 | } 25 | res = raise(atoi(argv[1])); 26 | if (res != 0) 27 | perror("raise"); 28 | else 29 | printf("I'm alive!\n"); 30 | return res; 31 | } 32 | -------------------------------------------------------------------------------- /examples/plugins/tests/README.rst: -------------------------------------------------------------------------------- 1 | ================================ 2 | New Test Types Plugin Examples 3 | ================================ 4 | 5 | Subdirectories of this folder contains "plugins" of at least two 6 | different types: 7 | 8 | * resolvers: they resolve references into proper test descriptions 9 | that Avocado can run 10 | 11 | * runners: these make use of the resolutions made by resolvers and 12 | actually execute the tests, reporting the results back to Avocado 13 | 14 | These are all based on the "nrunner" architecture. To see them in 15 | effect, after enabling them with ``python setup.py develop --user``-like 16 | commands (see parent directory ``README.rst``), you will want to 17 | list tests with:: 18 | 19 | avocado list $REFERENCE 20 | 21 | And run tests with:: 22 | 23 | avocado run $REFERENCE 24 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **Steps to reproduce** 14 | Steps to reproduce the behavior with a reproducible whenever possible. 15 | 16 | **Expected behavior** 17 | A clear and concise description of what you expected to happen. 18 | 19 | **Current behavior** 20 | What you are getting? 21 | 22 | **System information (please complete the following information):** 23 | - OS: `lsb_release -a` 24 | - Avocado version: `avocado -v` 25 | - Avocado installation method: pip, rpm, github ? 26 | 27 | **Additional information** 28 | Add any other information about the problem here. Test details can be added here. 29 | -------------------------------------------------------------------------------- /examples/jobs/multiple_suites_from_config.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | 5 | from avocado.core.job import Job 6 | from avocado.core.suite import TestSuite 7 | 8 | ORDERLY_CONFIG = { 9 | "resolver.references": ["/bin/true", "/bin/true", "/bin/last"], 10 | "run.max_parallel_tasks": 1, 11 | } 12 | 13 | RANDOM_CONFIG = { 14 | "resolver.references": [ 15 | "/bin/true", 16 | "/bin/true", 17 | "/bin/true", 18 | "/bin/true", 19 | "/bin/true", 20 | "/bin/last", 21 | ], 22 | "run.shuffle": True, 23 | "run.max_parallel_tasks": 1, 24 | } 25 | 26 | with Job( 27 | test_suites=[ 28 | TestSuite.from_config(ORDERLY_CONFIG, name="orderly"), 29 | TestSuite.from_config(RANDOM_CONFIG, name="random"), 30 | ] 31 | ) as j: 32 | sys.exit(j.run()) 33 | -------------------------------------------------------------------------------- /selftests/functional/coroutine.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from avocado.utils import process 4 | from selftests.utils import AVOCADO, BASEDIR, TestCaseTmpDir 5 | 6 | 7 | class Coroutine(TestCaseTmpDir): 8 | def test(self): 9 | test_path = os.path.join(BASEDIR, "examples", "tests", "sleeptest_async.py") 10 | os.environ["PYTHONASYNCIODEBUG"] = "1" 11 | cmd = ( 12 | f"{AVOCADO} --show=test run --disable-sysinfo " 13 | f"--job-results-dir {self.tmpdir.name} " 14 | f"-p sleep_length=0 {test_path}" 15 | ) 16 | result = process.run(cmd, ignore_status=True) 17 | self.assertEqual(result.exit_status, 0) 18 | self.assertNotIn( 19 | "RuntimeWarning: coroutine 'AsyncSleepTest.test' was never awaited", 20 | result.stdout_text, 21 | ) 22 | -------------------------------------------------------------------------------- /selftests/.data/safeloader/data/dont_detect_non_avocado.py: -------------------------------------------------------------------------------- 1 | from avocado.core.test import Test # pylint: disable=W0404 2 | 3 | 4 | # On load this will be avocado.Test, but in static analysis it's 5 | # avocado.core.test.Test and should not match. 6 | class StaticallyNotAvocadoTest(Test): 7 | def test(self): 8 | pass 9 | 10 | 11 | # This import should not make the previous import to be 12 | # internally evaluated as "avocado.Test", because it happens 13 | # after the previous class definition 14 | from avocado import Test # pylint: disable=W0404 15 | 16 | 17 | # On recursive discovery this should be imported from 18 | # avocado.core.test and not avocado.Test, therefore it should 19 | # not be detected (ditto for the Python unittest discover behavior) 20 | class NotTest(StaticallyNotAvocadoTest): 21 | def test2(self): 22 | pass 23 | -------------------------------------------------------------------------------- /selftests/unit/safeloader_caveats.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import unittest.mock 4 | 5 | from avocado.core.safeloader.core import find_avocado_tests 6 | from selftests.utils import BASEDIR 7 | 8 | 9 | class Caveats(unittest.TestCase): 10 | def test_no_multilevel_base_class(self): 11 | caveat_dir = os.path.join( 12 | BASEDIR, "selftests", ".data", "safeloader", "caveat_multilevel" 13 | ) 14 | success = os.path.join(caveat_dir, "success.py") 15 | failure = os.path.join(caveat_dir, "failure.py") 16 | sys_path = sys.path + [caveat_dir] 17 | with unittest.mock.patch("sys.path", sys_path): 18 | self.assertEqual( 19 | find_avocado_tests(success)[0], {"Test": [("test", {}, [])]} 20 | ) 21 | self.assertEqual(find_avocado_tests(failure)[0], {}) 22 | -------------------------------------------------------------------------------- /examples/plugins/cli-cmd/hello_parser/hello_parser.py: -------------------------------------------------------------------------------- 1 | from avocado.core.output import LOG_UI 2 | from avocado.core.plugin_interfaces import CLICmd 3 | from avocado.core.settings import settings 4 | 5 | 6 | class HelloWorld(CLICmd): 7 | 8 | name = "hello_parser" 9 | description = "The classical Hello World plugin example!" 10 | 11 | def configure(self, parser): 12 | parser = super().configure(parser) 13 | 14 | settings.register_option( 15 | section="hello", 16 | key="message", 17 | key_type=str, 18 | default=self.description, 19 | help_msg="Configure the message to display", 20 | parser=parser, 21 | long_arg="--hello-message", 22 | ) 23 | 24 | def run(self, config): 25 | msg = config.get("hello.message") 26 | LOG_UI.info(msg) 27 | -------------------------------------------------------------------------------- /selftests/functional/utils/gdb.py.data/return99.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void empty() 6 | { 7 | } 8 | 9 | void write_stdout() 10 | { 11 | fprintf(stdout, "testing output to stdout\n"); 12 | } 13 | 14 | void write_stderr() 15 | { 16 | fprintf(stderr, "testing output to stderr\n"); 17 | } 18 | 19 | int forkme() 20 | { 21 | int pid; 22 | 23 | pid = fork(); 24 | if (pid != 0) 25 | pid = fork(); 26 | if (pid != 0) 27 | pid = fork(); 28 | 29 | return pid; 30 | } 31 | 32 | int main(int argc, char *argv[]) 33 | { 34 | int exit_status = 99; 35 | 36 | if (argc > 1) 37 | exit_status = atoi(argv[1]); 38 | 39 | empty(); 40 | write_stdout(); 41 | write_stderr(); 42 | 43 | if (forkme()) { 44 | fprintf(stdout, "return %i\n", exit_status); 45 | } 46 | 47 | return exit_status; 48 | } 49 | -------------------------------------------------------------------------------- /selftests/unit/utils/linux_modules.py.data/lsmod: -------------------------------------------------------------------------------- 1 | Module Size Used by 2 | ccm 17773 2 3 | ip6t_rpfilter 12546 1 4 | ip6t_REJECT 12939 2 5 | xt_conntrack 12760 9 6 | ebtable_nat 12807 0 7 | ebtable_broute 12731 0 8 | bridge 110862 1 ebtable_broute 9 | stp 12868 1 bridge 10 | llc 13941 2 stp,bridge 11 | ebtable_filter 12827 0 12 | ebtables 30758 3 ebtable_broute,ebtable_nat,ebtable_filter 13 | ip6table_nat 13015 1 14 | nf_conntrack_ipv6 18738 6 15 | nf_defrag_ipv6 34712 1 nf_conntrack_ipv6 16 | nf_nat_ipv6 13213 1 ip6table_nat 17 | ip6table_mangle 12700 1 18 | ip6table_security 12710 1 19 | ip6table_raw 12683 1 20 | ip6table_filter 12815 1 21 | -------------------------------------------------------------------------------- /selftests/deployment/roles/common/tasks/dependencies.yml: -------------------------------------------------------------------------------- 1 | # Install dependencies 2 | - name: Install Basic Dependencies on Red Hat (like) systems specific to pip method 3 | package: 4 | name: 5 | - python3-pip 6 | - git 7 | state: latest 8 | when: 9 | - ansible_facts['distribution_file_variety'] == "RedHat" 10 | - method == 'pip' 11 | 12 | - name: Install Avocado-VT Dependencies on Red Hat (like) systems 13 | dnf: 14 | name: 15 | - git 16 | - gcc 17 | - nc 18 | - python3-devel 19 | - python3-pillow 20 | - python3-netaddr 21 | - python3-netifaces 22 | - qemu-img 23 | - qemu-kvm 24 | - tcpdump 25 | - iproute 26 | - iputils 27 | - xz 28 | state: latest 29 | when: 30 | - ansible_facts['distribution_file_variety'] == "RedHat" 31 | - avocado_vt|default(false)|bool == true 32 | -------------------------------------------------------------------------------- /avocado/core/safeloader/utils.py: -------------------------------------------------------------------------------- 1 | import ast 2 | import collections 3 | 4 | 5 | def get_statement_import_as(statement): 6 | """ 7 | Returns a mapping of imported module names whether using aliases or not 8 | 9 | :param statement: an AST import statement 10 | :type statement: ast.Import 11 | :returns: a mapping of names {: } of modules imported 12 | :rtype: collections.OrderedDict 13 | """ 14 | if not any( 15 | [isinstance(statement, ast.Import), isinstance(statement, ast.ImportFrom)] 16 | ): 17 | raise ValueError("Value given is not an ast import or import from statement") 18 | result = collections.OrderedDict() 19 | for name in statement.names: 20 | if name.asname is not None: 21 | result[name.name] = name.asname 22 | else: 23 | result[name.name] = name.name 24 | return result 25 | -------------------------------------------------------------------------------- /avocado/core/safeloader/__init__.py: -------------------------------------------------------------------------------- 1 | # This program is free software; you can redistribute it and/or modify 2 | # it under the terms of the GNU General Public License as published by 3 | # the Free Software Foundation; either version 2 of the License, or 4 | # (at your option) any later version. 5 | # 6 | # This program is distributed in the hope that it will be useful, 7 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 8 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 | # 10 | # See LICENSE for more details. 11 | # 12 | # Copyright: Red Hat Inc. 2014-2016,2018 13 | # Authors: Cleber Rosa 14 | # Lukas Doktor 15 | 16 | """ 17 | Safe (AST based) test loader module utilities 18 | """ 19 | 20 | from avocado.core.safeloader.core import find_avocado_tests, find_python_unittests 21 | 22 | __all__ = ["find_avocado_tests", "find_python_unittests"] 23 | -------------------------------------------------------------------------------- /examples/tests/dependency_ansible.py: -------------------------------------------------------------------------------- 1 | import os 2 | import pwd 3 | 4 | from avocado import Test 5 | 6 | 7 | class FileByAnsible(Test): 8 | """ 9 | :avocado: dependency={"type": "ansible-module", "uri": "file", "path": "/tmp/ansible_tmp", "state": "touch"} 10 | """ 11 | 12 | def test(self): 13 | files = os.listdir("/tmp") 14 | self.log.info(files) 15 | if not "ansible_tmp" in files: 16 | self.fail("Did not find an ansible created file") 17 | 18 | 19 | class UserByAnsible(Test): 20 | """ 21 | :avocado: dependency={"type": "ansible-module", "uri": "user", "name": "test-user"} 22 | """ 23 | 24 | def test(self): 25 | users = pwd.getpwall() 26 | self.log.info(users) 27 | for user in users: 28 | if user.pw_name == "test-user": 29 | return 30 | self.fail("Did not find an ansible created user") 31 | -------------------------------------------------------------------------------- /selftests/functional/plugin/podman_image.py: -------------------------------------------------------------------------------- 1 | from avocado import Test 2 | from avocado.utils.podman import AsyncPodman 3 | 4 | 5 | class PodmanImageTest(Test): 6 | async def test(self): 7 | """ 8 | :avocado: dependency={"type": "package", "name": "podman", "action": "check"} 9 | :avocado: dependency={"type": "podman-image", "uri": "registry.fedoraproject.org/fedora:38"} 10 | """ 11 | podman = AsyncPodman() 12 | _, stdout, _ = await podman.execute( 13 | "images", 14 | "--filter", 15 | "reference=registry.fedoraproject.org/fedora:38", 16 | "--format", 17 | "{{.Repository}}:{{.Tag}}", 18 | ) 19 | self.assertIn( 20 | "registry.fedoraproject.org/fedora:38", 21 | stdout.decode().splitlines(), 22 | "Podman image does not seem to have been pulled", 23 | ) 24 | -------------------------------------------------------------------------------- /avocado/utils/exit_codes.py: -------------------------------------------------------------------------------- 1 | # This program is free software; you can redistribute it and/or modify 2 | # it under the terms of the GNU General Public License as published by 3 | # the Free Software Foundation; either version 2 of the License, or 4 | # (at your option) any later version. 5 | # 6 | # This program is distributed in the hope that it will be useful, 7 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 8 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 | # 10 | # See LICENSE for more details. 11 | 12 | """ 13 | Avocado Utilities exit codes. 14 | 15 | These codes are returned on the command-line and may be used by the Avocado 16 | command-line utilities. 17 | """ 18 | 19 | #: The utility finished successfully 20 | UTILITY_OK = 0x0000 21 | 22 | #: The utility ran, but needs to signalize a fail. 23 | UTILITY_FAIL = 0x0001 24 | 25 | #: Utility generic crash 26 | UTILITY_GENERIC_CRASH = -1 27 | -------------------------------------------------------------------------------- /avocado/core/version.py: -------------------------------------------------------------------------------- 1 | # This program is free software; you can redistribute it and/or modify 2 | # it under the terms of the GNU General Public License as published by 3 | # the Free Software Foundation; either version 2 of the License, or 4 | # (at your option) any later version. 5 | # 6 | # This program is distributed in the hope that it will be useful, 7 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 8 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 | # 10 | # See LICENSE for more details. 11 | # 12 | # Copyright: Red Hat Inc. 2013-2014 13 | # Author: Lucas Meneghel Rodrigues 14 | 15 | __all__ = ["MAJOR", "MINOR", "VERSION"] 16 | 17 | import pkg_resources 18 | 19 | try: 20 | VERSION = pkg_resources.get_distribution("avocado-framework").version 21 | except pkg_resources.DistributionNotFound: 22 | VERSION = "unknown.unknown" 23 | 24 | MAJOR, MINOR = VERSION.split(".") 25 | -------------------------------------------------------------------------------- /examples/jobs/unix_status_server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | import sys 5 | import tempfile 6 | 7 | from avocado.core.job import Job 8 | from avocado.core.suite import TestSuite 9 | 10 | status_server_dir = tempfile.TemporaryDirectory() 11 | status_server = os.path.join(status_server_dir.name, "status_server.socket") 12 | 13 | config = { 14 | "run.status_server_auto": False, 15 | "run.status_server_listen": status_server, 16 | "run.status_server_uri": status_server, 17 | "resolver.references": ["examples/tests/passtest.py"], 18 | } 19 | 20 | suite = TestSuite.from_config(config, name="1") 21 | with Job(config, [suite]) as j: 22 | result = j.run() 23 | 24 | # Check that one test actually ran and results were recorded. The 25 | # test's success will be checked by the job execution result 26 | assert len(j.result.tests) == 1 27 | 28 | status_server_dir.cleanup() 29 | sys.exit(result) 30 | -------------------------------------------------------------------------------- /examples/plugins/tests/rogue/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | name = "rogue" 4 | module = "avocado_rogue" 5 | resolver_ep = f"{name} = {module}.resolver:RogueResolver" 6 | runner_ep = f"{name} = {module}.runner:RogueRunner" 7 | runner_script = f"avocado-runner-{name} = {module}.runner:main" 8 | 9 | 10 | if __name__ == "__main__": 11 | setup( 12 | name="avocado-rogue", 13 | version="1.0", 14 | description='Avocado "rogue" test type', 15 | long_description=( 16 | "This is a plugin that contains a rogue runner, that is, " 17 | "a runner that will try to never allow to be terminated." 18 | ), 19 | py_modules=[module], 20 | entry_points={ 21 | "avocado.plugins.resolver": [resolver_ep], 22 | "avocado.plugins.runnable.runner": [runner_ep], 23 | "console_scripts": [runner_script], 24 | }, 25 | ) 26 | -------------------------------------------------------------------------------- /examples/tests/multiple_tests.py: -------------------------------------------------------------------------------- 1 | from avocado import Test 2 | 3 | 4 | class MultipleTests(Test): 5 | """ 6 | Following the unittest module pattern, every test method starts 7 | with a literal 'test' prefix, so that 'test_foo' and 'testFoo' are 8 | test methods, but 'division_by_zero' and 'action' are not. 9 | """ 10 | 11 | def setUp(self): 12 | self.hello = "Hi there!" 13 | 14 | def test_hello(self): 15 | self.assertEqual(self.hello, "Hi there!") 16 | 17 | def testIdentity(self): 18 | self.assertIs(1, 1) 19 | 20 | @staticmethod 21 | def division_by_zero(): 22 | """ 23 | This method should never execute 24 | """ 25 | return 1 / 0 26 | 27 | @staticmethod 28 | def action(): 29 | """ 30 | This method should never execute 31 | """ 32 | raise Exception("This action method should never be executed.") 33 | -------------------------------------------------------------------------------- /avocado/core/utils/version.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from avocado.utils import path, process 4 | 5 | 6 | def get_avocado_git_version(): 7 | # if running from git sources, there will be a ".git" directory 8 | # 4 levels up 9 | dn = os.path.dirname 10 | base_dir = dn(dn(dn(dn(__file__)))) 11 | git_dir = os.path.join(base_dir, ".git") 12 | if not os.path.isdir(git_dir): 13 | return 14 | if not os.path.exists(os.path.join(base_dir, "python-avocado.spec")): 15 | return 16 | 17 | try: 18 | git = path.find_command("git") 19 | except path.CmdNotFoundError: 20 | return 21 | 22 | git_dir = os.path.abspath(base_dir) 23 | cmd = f"{git} -C {git_dir} show --summary --pretty='%H'" 24 | res = process.run(cmd, ignore_status=True, verbose=False) 25 | if res.exit_status == 0: 26 | top_commit = res.stdout_text.splitlines()[0][:8] 27 | return f" (GIT commit {top_commit})" 28 | -------------------------------------------------------------------------------- /selftests/unit/references.py: -------------------------------------------------------------------------------- 1 | import unittest.mock 2 | 3 | from avocado.core import references 4 | 5 | 6 | class References(unittest.TestCase): 7 | def test_split_file_does_not_exist(self): 8 | not_a_file = "/should/be/safe/to/assume/it/is/not/a/file:foo" 9 | path, additional_info = references.reference_split(not_a_file) 10 | self.assertEqual(path, "/should/be/safe/to/assume/it/is/not/a/file") 11 | self.assertEqual(additional_info, "foo") 12 | 13 | def test_split_file_exists(self): 14 | file_name = "file_contains_a_colon_:_indeed" 15 | with unittest.mock.patch( 16 | "avocado.core.references.os.path.exists", return_value=True 17 | ): 18 | path, additional_info = references.reference_split(file_name) 19 | self.assertEqual(path, file_name) 20 | self.assertEqual(additional_info, None) 21 | 22 | 23 | if __name__ == "__main__": 24 | unittest.main() 25 | -------------------------------------------------------------------------------- /avocado/core/status/utils.py: -------------------------------------------------------------------------------- 1 | import base64 2 | import json 3 | 4 | 5 | class StatusMsgInvalidJSONError(Exception): 6 | """Status message does not contain valid JSON.""" 7 | 8 | 9 | def json_base64_decode(dct): 10 | """base64 decode object hook for custom JSON encoding.""" 11 | key_name = "__base64_encoded__" 12 | if key_name in dct: 13 | return base64.b64decode(dct[key_name]) 14 | return dct 15 | 16 | 17 | def json_loads(data): 18 | """Loads and decodes JSON, with added base64 decoding. 19 | 20 | :param data: either bytes or a string. If bytes, will be decoded 21 | using the current default encoding. 22 | :raises: 23 | :returns: decoded Python objects 24 | """ 25 | if isinstance(data, bytes): 26 | data = data.decode() 27 | try: 28 | return json.loads(data, object_hook=json_base64_decode) 29 | except json.decoder.JSONDecodeError: 30 | raise StatusMsgInvalidJSONError(data) 31 | -------------------------------------------------------------------------------- /.copr/Makefile: -------------------------------------------------------------------------------- 1 | pkg_install := $(shell dnf -y install git rpm-build) 2 | pwd := $(shell pwd) 3 | git_config_safe_directory := $(shell git config --global --add safe.directory $(pwd)) 4 | commit := $(shell git log --pretty=format:'%H' -n 1) 5 | commit_date := $(shell git log --pretty='format:%cd' --date='format:%Y%m%d' -n 1) 6 | short_commit := $(shell git rev-parse --short=9 HEAD) 7 | 8 | srpm: 9 | if test ! -d SOURCES; then mkdir SOURCES; fi 10 | if test ! -d SPEC; then mkdir SPEC; fi 11 | git archive --prefix="avocado-$(commit)/" -o "SOURCES/avocado-$(short_commit).tar.gz" HEAD 12 | cp python-avocado.spec SPEC 13 | sed -i -e 's/\%global rel_build .*/\%global rel_build 0/' SPEC/python-avocado.spec 14 | sed -i -e 's/\%global commit .*/\%global commit $(commit)/' SPEC/python-avocado.spec 15 | sed -i -e 's/\%global commit_date .*/\%global commit_date $(commit_date)/' SPEC/python-avocado.spec 16 | rpmbuild -D '_topdir .' -bs SPEC/python-avocado.spec 17 | mv SRPMS/*.src.rpm $(outdir) 18 | -------------------------------------------------------------------------------- /examples/tests/cancel_test.py: -------------------------------------------------------------------------------- 1 | from avocado import Test 2 | from avocado.utils.process import run 3 | from avocado.utils.software_manager.manager import SoftwareManager 4 | 5 | 6 | class CancelTest(Test): 7 | """ 8 | Example tests that cancel the current test from inside the test. 9 | """ 10 | 11 | def setUp(self): 12 | sm = SoftwareManager() 13 | self.pkgs = sm.list_all(software_components=False) 14 | 15 | def test_iperf(self): 16 | if "iperf-2.0.8-6.fc25.x86_64" not in self.pkgs: 17 | self.cancel("iperf is not installed or wrong version") 18 | self.assertIn("pthreads", run("iperf -v", ignore_status=True).stderr_text) 19 | 20 | def test_gcc(self): 21 | if "gcc-6.3.1-1.fc25.x86_64" not in self.pkgs: 22 | self.cancel("gcc is not installed or wrong version") 23 | self.assertIn( 24 | "enable-gnu-indirect-function", 25 | run("gcc -v", ignore_status=True).stderr_text, 26 | ) 27 | -------------------------------------------------------------------------------- /selftests/unit/utils/cpu.py.data/i386: -------------------------------------------------------------------------------- 1 | processor : 0 2 | vendor_id : GenuineIntel 3 | cpu family : 6 4 | model : 13 5 | model name : Intel(R) Pentium(R) M processor 2.00GHz 6 | stepping : 8 7 | microcode : 0x20 8 | cpu MHz : 2000.000 9 | cache size : 2048 KB 10 | physical id : 0 11 | siblings : 1 12 | core id : 0 13 | cpu cores : 1 14 | apicid : 0 15 | initial apicid : 0 16 | fdiv_bug : no 17 | f00f_bug : no 18 | coma_bug : no 19 | fpu : yes 20 | fpu_exception : yes 21 | cpuid level : 2 22 | wp : yes 23 | flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov clflush dts acpi mmx fxsr sse sse2 ss tm pbe nx bts cpuid est tm2 24 | bugs : cpu_meltdown spectre_v1 spectre_v2 25 | bogomips : 3990.09 26 | clflush size : 64 27 | cache_alignment : 64 28 | address sizes : 32 bits physical, 32 bits virtual 29 | power management: 30 | -------------------------------------------------------------------------------- /examples/plugins/job-pre-post/sleep/avocado_job_sleep.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | from avocado.core.output import LOG_UI 4 | from avocado.core.plugin_interfaces import Init, JobPost, JobPre 5 | from avocado.core.settings import settings 6 | 7 | 8 | class SleepInit(Init): 9 | name = "sleep-init" 10 | description = "Sleep plugin initialization" 11 | 12 | def initialize(self): 13 | help_msg = "Number of seconds to sleep." 14 | settings.register_option( 15 | section="plugins.job.sleep", key="seconds", default=3, help_msg=help_msg 16 | ) 17 | 18 | 19 | class Sleep(JobPre, JobPost): 20 | name = "sleep" 21 | description = "Sleeps for a number of seconds" 22 | 23 | @staticmethod 24 | def sleep(job): # pylint: disable=W0613 25 | seconds = job.config.get("plugins.job.sleep.seconds") 26 | for i in range(1, seconds + 1): 27 | LOG_UI.info("Sleeping %2i/%s", i, seconds) 28 | time.sleep(1) 29 | 30 | pre = post = sleep 31 | -------------------------------------------------------------------------------- /examples/plugins/tests/magic/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import find_packages, setup 2 | 3 | name = "magic" 4 | module = "avocado_magic" 5 | init_ep = f"{name} = {module}.resolver:MagicInit" 6 | resolver_ep = f"{name} = {module}.resolver:MagicResolver" 7 | discoverer_ep = f"{name} = {module}.resolver:MagicDiscoverer" 8 | runner_ep = f"{name} = {module}.runner:MagicRunner" 9 | runner_script = f"avocado-runner-{name} = {module}.runner:main" 10 | 11 | 12 | if __name__ == "__main__": 13 | setup( 14 | name=name, 15 | version="1.0", 16 | description='Avocado "magic" test type', 17 | py_modules=[module], 18 | entry_points={ 19 | "avocado.plugins.init": [init_ep], 20 | "avocado.plugins.resolver": [resolver_ep], 21 | "avocado.plugins.discoverer": [discoverer_ep], 22 | "avocado.plugins.runnable.runner": [runner_ep], 23 | "console_scripts": [runner_script], 24 | }, 25 | packages=find_packages(), 26 | ) 27 | -------------------------------------------------------------------------------- /examples/tests/sleeptenmin.py: -------------------------------------------------------------------------------- 1 | import os 2 | import time 3 | 4 | from avocado import Test 5 | 6 | 7 | class SleepTenMin(Test): 8 | """ 9 | Sleeps for 10 minutes 10 | 11 | :avocado: tags=slow 12 | 13 | :param sleep_cycles: How many iterations should be executed 14 | :param sleep_length: single sleep duration 15 | :param sleep_method: what method of sleep should be used (builtin|shell) 16 | """ 17 | 18 | def test(self): 19 | """ 20 | Sleep for length seconds. 21 | """ 22 | cycles = int(self.params.get("sleep_cycles", default=1)) 23 | length = int(self.params.get("sleep_length", default=600)) 24 | method = self.params.get("sleep_method", default="builtin") 25 | 26 | for _ in range(0, cycles): 27 | self.log.debug("Sleeping for %.2f seconds", length) 28 | if method == "builtin": 29 | time.sleep(length) 30 | elif method == "shell": 31 | os.system(f"sleep {length}") 32 | -------------------------------------------------------------------------------- /selftests/deployment/roles/avocado/tasks/rpm/plugins.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install Avocado plugins using RPM 3 | dnf: 4 | name: 5 | - python3-avocado-plugins-golang 6 | - python3-avocado-plugins-output-html 7 | - python3-avocado-plugins-result-upload 8 | - python3-avocado-plugins-varianter-cit 9 | - python3-avocado-plugins-varianter-pict 10 | - python3-avocado-plugins-varianter-yaml-to-mux 11 | state: latest 12 | 13 | - name: Install the Avocado VT plugin using RPM 14 | dnf: 15 | name: python3-avocado-vt 16 | state: latest 17 | when: 18 | - ansible_facts['distribution_file_variety'] == "RedHat" 19 | - avocado_vt|default(false)|bool == true 20 | - method == 'official' 21 | 22 | - name: Install the Avocado VT plugin using RPM 23 | dnf: 24 | name: python3-avocado-plugins-vt 25 | state: latest 26 | when: 27 | - ansible_facts['distribution_file_variety'] == "RedHat" 28 | - avocado_vt|default(false)|bool == true 29 | - method == 'copr' 30 | -------------------------------------------------------------------------------- /avocado/plugins/runners/noop.py: -------------------------------------------------------------------------------- 1 | from avocado.core.nrunner.app import BaseRunnerApp 2 | from avocado.core.nrunner.runner import BaseRunner 3 | 4 | 5 | class NoOpRunner(BaseRunner): 6 | """ 7 | Sample runner that performs no action before reporting FINISHED status 8 | 9 | Runnable attributes usage: 10 | 11 | * uri: not used 12 | 13 | * args: not used 14 | """ 15 | 16 | name = "noop" 17 | description = ( 18 | "Sample runner that performs no action before reporting FINISHED status" 19 | ) 20 | 21 | def run(self, runnable): 22 | yield self.prepare_status("started") 23 | yield self.prepare_status("finished", {"result": "pass"}) 24 | 25 | 26 | class RunnerApp(BaseRunnerApp): 27 | PROG_NAME = "avocado-runner-noop" 28 | PROG_DESCRIPTION = "nrunner application for noop tests" 29 | RUNNABLE_KINDS_CAPABLE = ["noop"] 30 | 31 | 32 | def main(): 33 | app = RunnerApp(print) 34 | app.run() 35 | 36 | 37 | if __name__ == "__main__": 38 | main() 39 | -------------------------------------------------------------------------------- /docs/source/api/headers/utils: -------------------------------------------------------------------------------- 1 | Avocado gives to you more than 40 python utility libraries (so far), that can 2 | be found under the :mod:`avocado.utils`. You can use these libraries to avoid 3 | having to write necessary routines for your tests. These are very general in 4 | nature and can help you speed up your test development. 5 | 6 | The utility libraries may receive incompatible changes across minor versions, 7 | but these will be done in a staged fashion. If a given change to an utility 8 | library can cause test breakage, it will first be documented and/or deprecated, 9 | and only on the next subsequent minor version, it will actually be changed. 10 | 11 | What this means is that upon updating to later minor versions of Avocado, you 12 | should look at the Avocado Release Notes for changes that may impact your 13 | tests. 14 | 15 | This is a set of utility APIs that Avocado provides as added value to test 16 | writers. It's suppose to be generic, without any knowledge of Avocado and 17 | reusable in different projects. 18 | -------------------------------------------------------------------------------- /selftests/jobs/status_server_auto: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import tempfile 5 | 6 | from avocado.core.job import Job 7 | from avocado.core.suite import TestSuite 8 | 9 | # This bad location serves to test the "status_server_auto" 10 | # configuration 11 | status_server = '/path/to/a/very/bad/non-existing/location' 12 | 13 | test_results_dir = tempfile.TemporaryDirectory() 14 | 15 | config = { 16 | "run.results_dir": test_results_dir.name, 17 | "run.status_server_auto": True, 18 | "run.status_server_listen": status_server, 19 | "run.status_server_uri": status_server, 20 | "resolver.references": ["examples/tests/passtest.py"], 21 | } 22 | 23 | suite = TestSuite.from_config(config, name="1") 24 | with Job(config, [suite]) as j: 25 | result = j.run() 26 | test_results_dir.cleanup() 27 | # Check that one test actually ran and results were recorded. The 28 | # test's success will be checked by the job execution result 29 | assert len(j.result.tests) == 1 30 | 31 | sys.exit(result) 32 | -------------------------------------------------------------------------------- /avocado/core/job_id.py: -------------------------------------------------------------------------------- 1 | # This program is free software; you can redistribute it and/or modify 2 | # it under the terms of the GNU General Public License as published by 3 | # the Free Software Foundation; either version 2 of the License, or 4 | # (at your option) any later version. 5 | # 6 | # This program is distributed in the hope that it will be useful, 7 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 8 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 | # 10 | # See LICENSE for more details. 11 | # 12 | # Copyright: Red Hat Inc. 2013-2014 13 | # Authors: Lucas Meneghel Rodrigues 14 | 15 | import hashlib 16 | import random 17 | 18 | _RAND_POOL = random.SystemRandom() 19 | 20 | 21 | def create_unique_job_id(): 22 | """ 23 | Create a 40 digit hex number to be used as a job ID string. 24 | (similar to SHA1) 25 | 26 | :return: 40 digit hex number string 27 | :rtype: str 28 | """ 29 | return hashlib.sha1(hex(_RAND_POOL.getrandbits(160)).encode()).hexdigest() 30 | -------------------------------------------------------------------------------- /selftests/functional/settings.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from avocado import Test 4 | from avocado.utils import process 5 | from selftests.utils import AVOCADO 6 | 7 | WRONG_CONFIG = """ 8 | [job.output.testlogs] 9 | statuses = ["CANCEL", "SKIP", "FAIL"] 10 | foo moo 11 | """ 12 | 13 | 14 | class SettingsTest(Test): 15 | def test_wrong_config(self): 16 | config_path = os.path.join(self.workdir, "config") 17 | with open(config_path, mode="w", encoding="utf-8") as config_file: 18 | config_file.write(WRONG_CONFIG) 19 | result = process.run( 20 | f"{AVOCADO} --config={config_path} run " 21 | f"--job-results-dir {self.workdir} " 22 | f"--disable-sysinfo -- examples/tests/passtest.py", 23 | ignore_status=True, 24 | ) 25 | self.assertIn( 26 | f'Avocado crashed unexpectedly: Syntax error in config file {config_path}, please check the value ["CANCEL", "SKIP", "FAIL"]\nfoo moo \n', 27 | result.stderr_text, 28 | ) 29 | -------------------------------------------------------------------------------- /contrib/packages/debian/Makefile: -------------------------------------------------------------------------------- 1 | BUILDIR=$(CURDIR)/debian/avocado 2 | PROJECT=avocado 3 | 4 | all: 5 | @echo 6 | @echo "Debian related targets:" 7 | @echo "deb: Generate both source and binary debian packages" 8 | @echo "deb-src: Generate a source debian package" 9 | @echo "deb-bin: Generate a binary debian package" 10 | @echo 11 | 12 | deb-prepare-source: 13 | # build the source package in the parent directory 14 | # then rename it to project_version.orig.tar.gz 15 | dch -D "vivid" -M -v "$(VERSION)" "Automated (make builddeb) build." 16 | $(PYTHON) setup.py sdist $(COMPILE) --dist-dir=../ 17 | rename -f 's/$(PROJECT)-(.*)\.tar\.gz/$(PROJECT)_$$1\.orig\.tar\.gz/' ../* 18 | 19 | deb-src: deb-prepare-source 20 | # build the source package 21 | dpkg-buildpackage -S -elookkas@gmail.com -rfakeroot 22 | 23 | deb-bin: deb-prepare-source 24 | # build binary package 25 | dpkg-buildpackage -b -rfakeroot 26 | 27 | deb: deb-prepare-source 28 | # build both source and binary packages 29 | dpkg-buildpackage -i -I -rfakeroot 30 | -------------------------------------------------------------------------------- /docs/source/releases/next.rst: -------------------------------------------------------------------------------- 1 | ======================== 2 | 113.0 - TBD 3 | ======================== 4 | 5 | The Avocado team is proud to present another release: Avocado 113.0, 6 | AKA "TBD", is now available! 7 | 8 | Release documentation: `Avocado 113.0 9 | `_ 10 | 11 | Users/Test Writers 12 | ================== 13 | 14 | * 15 | 16 | Utility Modules 17 | =============== 18 | 19 | * 20 | 21 | Bug Fixes 22 | ========= 23 | 24 | * 25 | 26 | Internal changes 27 | ================ 28 | 29 | * 30 | 31 | Additional information 32 | ====================== 33 | 34 | For more information, please check out the complete 35 | `Avocado changelog 36 | `_. 37 | 38 | For more information on the actual issues addressed, please check out 39 | the `milestone information 40 | `_. 41 | 42 | For more information on the release codename, please refer to `IMDb 43 | `_. 44 | -------------------------------------------------------------------------------- /selftests/unit/utils/aurl.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from avocado.utils import aurl 4 | 5 | 6 | class TestAUrl(unittest.TestCase): 7 | def test_valid_urls(self): 8 | valid_urls = [ 9 | "http://www.example.com", 10 | "https://www.example.com/path", 11 | "ftp://ftp.example.com", 12 | "git://github.com/user/repo.git", 13 | ] 14 | for url in valid_urls: 15 | self.assertTrue(aurl.is_url(url), f"Expected {url} to be a valid URL") 16 | 17 | invalid_urls = [ 18 | "www.example.com", 19 | "htt://example", 20 | "file:///path/to/file", 21 | ] 22 | for url in invalid_urls: 23 | self.assertFalse(aurl.is_url(url), f"Expected {url} to be an invalid URL") 24 | 25 | non_urls = [ 26 | "/path/to/file", 27 | "not a url", 28 | "", 29 | ] 30 | for path in non_urls: 31 | self.assertFalse(aurl.is_url(path), f"Expected {path} to not be a URL") 32 | -------------------------------------------------------------------------------- /selftests/check_tmp_dirs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | import sys 5 | import tempfile 6 | 7 | 8 | def check_tmp_dirs(): 9 | dirs_to_check = [tempfile.gettempdir()] 10 | fail = False 11 | for dir_to_check in dirs_to_check: 12 | dir_list = os.listdir(dir_to_check) 13 | avocado_tmp_dirs = [d for d in dir_list 14 | if (d.startswith('avocado') 15 | and os.path.isdir(os.path.join(dir_to_check, d)))] 16 | try: 17 | assert len(avocado_tmp_dirs) == 0 18 | print('No temporary avocado dirs lying around in %s' % 19 | dir_to_check) 20 | except AssertionError: 21 | print('There are temporary avocado dirs lying around after test:', 22 | ', '.join([os.path.join(dir_to_check, _) for _ in avocado_tmp_dirs])) 23 | fail = True 24 | if fail: 25 | sys.exit(1) 26 | else: 27 | sys.exit(0) 28 | 29 | 30 | if __name__ == '__main__': 31 | check_tmp_dirs() 32 | -------------------------------------------------------------------------------- /selftests/unit/output.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import unittest.mock 3 | 4 | from avocado.core import output 5 | from avocado.utils import path as utils_path 6 | 7 | 8 | class TestStdOutput(unittest.TestCase): 9 | def setUp(self): 10 | """Preserve sys.std{out,err} so we can restore them in tearDown""" 11 | self.stdout = sys.stdout 12 | self.stderr = sys.stderr 13 | 14 | def tearDown(self): 15 | sys.stdout = self.stdout 16 | sys.stderr = self.stderr 17 | 18 | def test_paginator_not_available(self): 19 | """Check that without paginator command we proceed without changes""" 20 | std = output.StdOutput() 21 | with unittest.mock.patch( 22 | "avocado.utils.path.find_command", 23 | side_effect=utils_path.CmdNotFoundError("just", ["mocking"]), 24 | ): 25 | std.enable_paginator() 26 | self.assertEqual(self.stdout, sys.stdout) 27 | self.assertEqual(self.stderr, sys.stderr) 28 | 29 | 30 | if __name__ == "__main__": 31 | unittest.main() 32 | -------------------------------------------------------------------------------- /selftests/jobs/unix_status_server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | import sys 5 | import tempfile 6 | 7 | from avocado.core.job import Job 8 | from avocado.core.suite import TestSuite 9 | 10 | status_server_dir = tempfile.TemporaryDirectory() 11 | status_server = os.path.join(status_server_dir.name, "status_server.socket") 12 | 13 | test_results_dir = tempfile.TemporaryDirectory() 14 | 15 | config = { 16 | "run.results_dir": test_results_dir.name, 17 | "run.status_server_auto": False, 18 | "run.status_server_listen": status_server, 19 | "run.status_server_uri": status_server, 20 | "resolver.references": ["examples/tests/passtest.py"], 21 | } 22 | 23 | suite = TestSuite.from_config(config, name="1") 24 | with Job(config, [suite]) as j: 25 | result = j.run() 26 | test_results_dir.cleanup() 27 | 28 | # Check that one test actually ran and results were recorded. The 29 | # test's success will be checked by the job execution result 30 | assert len(j.result.tests) == 1 31 | 32 | status_server_dir.cleanup() 33 | sys.exit(result) 34 | -------------------------------------------------------------------------------- /contrib/job-scripts/coredump-handling/post.d/001-restore-core-pattern: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | # 3 | # This program is free software; you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation; either version 2 of the License, or 6 | # (at your option) any later version. 7 | # 8 | # This program is distributed in the hope that it will be useful, 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 11 | # 12 | # See LICENSE for more details. 13 | # 14 | # Copyright: Red Hat Inc. 2016 15 | # 16 | # This script restores the original settings of the systemwide kernel 17 | # core pattern once the job finishes running tests 18 | # 19 | 20 | if [ -z $AVOCADO_JOB_LOGDIR ]; then 21 | exit 1 22 | fi 23 | 24 | BACKUP_CORE_PATTERN="$AVOCADO_JOB_LOGDIR/coredumps/.backup_core_pattern" 25 | if [ -f $BACKUP_CORE_PATTERN ]; then 26 | cat $BACKUP_CORE_PATTERN > /proc/sys/kernel/core_pattern 27 | rm $BACKUP_CORE_PATTERN 28 | fi 29 | -------------------------------------------------------------------------------- /contrib/packages/debian/copyright: -------------------------------------------------------------------------------- 1 | Upstream Author: 2 | 3 | Lucas Meneghel Rodrigues 4 | 5 | Files: * 6 | Copyright: 7 | 2013-2014, Lucas Meneghel Rodrigues, Rudá Moura 8 | License: GPL 9 | 10 | Files: debian/* 11 | Copyright: 12 | 2012, Lucas Meneghel Rodrigues (lmr) 13 | License: GPL 14 | 15 | License: GPL 16 | This package is free software; you can redistribute it and/or modify 17 | it under the terms of the GNU General Public License as published by 18 | the Free Software Foundation; version 2 only. 19 | 20 | This package is distributed in the hope that it will be useful, 21 | but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | GNU General Public License for more details. 24 | 25 | You should have received a copy of the GNU General Public License 26 | along with this package; if not, see . 27 | 28 | On Debian systems, the complete text of the GNU General 29 | Public License 2 can be found in `/usr/share/common-licenses/GPL-2'. 30 | -------------------------------------------------------------------------------- /examples/tests/datadir.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | 4 | from avocado import Test 5 | from avocado.utils import build, process 6 | 7 | 8 | class DataDirTest(Test): 9 | """ 10 | Test that uses resources from the data dir. 11 | 12 | :avocado: tags=requires_c_compiler 13 | """ 14 | 15 | def setUp(self): 16 | """ 17 | Build 'datadir'. 18 | """ 19 | source = self.params.get("source", default="datadir.c") 20 | c_file = self.get_data(source) 21 | if c_file is None: 22 | self.cancel(f"Test is missing data file {source}") 23 | c_file_name = os.path.basename(c_file) 24 | dest_c_file = os.path.join(self.workdir, c_file_name) 25 | shutil.copy(c_file, dest_c_file) 26 | build.make(self.workdir, env={"CFLAGS": "-g -O0"}, extra_args="datadir") 27 | 28 | def test(self): 29 | """ 30 | Execute 'datadir'. 31 | """ 32 | cmd = os.path.join(self.workdir, "datadir") 33 | cmd_result = process.run(cmd) 34 | self.log.info(cmd_result) 35 | -------------------------------------------------------------------------------- /avocado/plugins/runners/dry_run.py: -------------------------------------------------------------------------------- 1 | from avocado.core.nrunner.app import BaseRunnerApp 2 | from avocado.core.nrunner.runner import BaseRunner 3 | 4 | 5 | class DryRunRunner(BaseRunner): 6 | """ 7 | Runner for --dry-run. 8 | 9 | It performs no action before reporting FINISHED status with cancel result. 10 | 11 | Runnable attributes usage: 12 | 13 | * uri: not used 14 | 15 | * args: not used 16 | """ 17 | 18 | name = "dry-run" 19 | description = "Runner for --dry-run" 20 | 21 | def run(self, runnable): 22 | yield self.prepare_status("started") 23 | yield self.prepare_status( 24 | "finished", 25 | {"result": "cancel", "fail_reason": "Test cancelled due to " "--dry-run"}, 26 | ) 27 | 28 | 29 | class RunnerApp(BaseRunnerApp): 30 | PROG_NAME = "avocado-runner-dry-run" 31 | PROG_DESCRIPTION = "nrunner application for dry-run tests" 32 | RUNNABLE_KINDS_CAPABLE = ["dry-run"] 33 | 34 | 35 | def main(): 36 | app = RunnerApp(print) 37 | app.run() 38 | 39 | 40 | if __name__ == "__main__": 41 | main() 42 | -------------------------------------------------------------------------------- /docs/source/plugins/index.rst: -------------------------------------------------------------------------------- 1 | ================ 2 | Standard plugins 3 | ================ 4 | 5 | Avocado is highly modular, and a lot of its functionality is 6 | implemented as "plugins". On this section, you'll find documentation 7 | for plugins that come standard with Avocado. 8 | 9 | Please note that this is not a fully comprehensive list. 10 | 11 | .. tip:: Running ``avocado plugins`` will show the full list of 12 | plugins installed and available on your system. 13 | 14 | 15 | .. toctree:: 16 | :maxdepth: 3 17 | 18 | standard/distro 19 | standard/teststmpdir 20 | 21 | ================ 22 | Optional plugins 23 | ================ 24 | 25 | The plugins listed here are not automatically available on every 26 | Avocado installation. Depending on the installation method, it may 27 | require additional steps or packages to be installed. 28 | 29 | Some of these plugins may have extra dependencies of their own. 30 | 31 | .. toctree:: 32 | :maxdepth: 3 33 | 34 | optional/golang 35 | optional/results/index 36 | optional/robot 37 | optional/varianters/index 38 | optional/spawner_remote 39 | -------------------------------------------------------------------------------- /selftests/functional/plugin/bystatus.py: -------------------------------------------------------------------------------- 1 | import json 2 | import os 3 | 4 | from avocado.utils import process 5 | from selftests.utils import AVOCADO, TestCaseTmpDir 6 | 7 | 8 | class ByStatusTest(TestCaseTmpDir): 9 | def test_symlinks(self): 10 | result = process.run( 11 | f"{AVOCADO} run " 12 | f"--job-results-dir {self.tmpdir.name} " 13 | f"--disable-sysinfo --json - " 14 | f"examples/tests/true examples/tests/false", 15 | ignore_status=True, 16 | ) 17 | res = json.loads(result.stdout_text) 18 | 19 | for test in res["tests"]: 20 | logdir = test["logdir"] 21 | status = test["status"] 22 | where = os.path.dirname(logdir) 23 | basename = os.path.basename(logdir) 24 | status_dir = os.path.join(where, "by-status", status) 25 | link = os.path.join(status_dir, basename) 26 | sym_link = os.readlink(link) 27 | self.assertTrue(os.path.exists(os.path.join(status_dir, sym_link))) 28 | self.assertTrue(os.path.samefile(logdir, link)) 29 | -------------------------------------------------------------------------------- /docs/source/guides/contributor/chapters/results.rst: -------------------------------------------------------------------------------- 1 | Implementing other result formats 2 | --------------------------------- 3 | 4 | If you are looking to implement a new machine or human readable output 5 | format, you can refer to :mod:`avocado.plugins.xunit` and use it as a 6 | starting point. 7 | 8 | If your result is something that is produced at once, based on the 9 | complete job outcome, you should create a new class that inherits from 10 | :class:`avocado.core.plugin_interfaces.Result` and implements the 11 | :meth:`avocado.core.plugin_interfaces.Result.render` method. 12 | 13 | But, if your result implementation is something that outputs 14 | information live before/during/after tests, then the 15 | :class:`avocado.core.plugin_interfaces.ResultEvents` interface is the 16 | one to look at. It will require you to implement the methods that 17 | will perform actions (write to a file/stream) for each of the defined 18 | events on a Job and test execution. 19 | 20 | You can take a look at :ref:`writing_plugin` for more information on 21 | how to write a plugin that will activate and execute the new result 22 | format. 23 | -------------------------------------------------------------------------------- /avocado/utils/software_manager/backends/dnf.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | from avocado.utils import process 4 | from avocado.utils.software_manager.backends.yum import YumBackend 5 | 6 | log = logging.getLogger("avocado.utils.software_manager") 7 | 8 | 9 | class DnfBackend(YumBackend): 10 | """ 11 | Implements the dnf backend for software manager. 12 | 13 | DNF is the successor to yum in recent Fedora. 14 | """ 15 | 16 | def __init__(self): 17 | """ 18 | Initializes the base command and the DNF package repository. 19 | """ 20 | super().__init__(cmd="dnf") 21 | 22 | def build_dep(self, name): # pylint: disable=W0221 23 | """ 24 | Install build-dependencies for package [name] 25 | 26 | :param name: name of the package 27 | 28 | :return True: If build dependencies are installed properly 29 | """ 30 | try: 31 | process.system(f"{self.base_command} builddep {name}", sudo=True) 32 | return True 33 | except process.CmdError as details: 34 | log.error(details) 35 | return False 36 | -------------------------------------------------------------------------------- /contrib/docker/Dockerfile.fedora: -------------------------------------------------------------------------------- 1 | # This Dockerfile creates an fedora image with avocado framework installed 2 | # from source 3 | # 4 | # VERSION 0.1 5 | ################ 6 | ## Usage example: 7 | ## Checkout avocado source 8 | # git clone github.com/avocado-framework/avocado.git avocado.git 9 | # cd avocado.git 10 | ## Make some changes 11 | # patch -p1 < MY_PATCH 12 | ## Finally build a docker image 13 | # docker build --force-rm -t fedora-avocado-custom -f contrib/docker/Dockerfile.fedora . 14 | ## Run test inside the docker image 15 | # avocado run --docker fedora-avocado-custom passtest.py 16 | # 17 | FROM fedora 18 | 19 | MAINTAINER Dmitry Monakhov dmonakhov@openvz.org 20 | 21 | COPY . /devel/avocado-framework/avocado 22 | 23 | # Install and clean in one step to decrease image size 24 | RUN dnf install -y \ 25 | gcc \ 26 | make \ 27 | python-devel \ 28 | python-pip \ 29 | libvirt-devel \ 30 | libyaml-devel \ 31 | redhat-rpm-config \ 32 | xz-devel \ 33 | which && \ 34 | cd /devel/avocado-framework/avocado && \ 35 | make requirements && \ 36 | make install && \ 37 | dnf clean all 38 | 39 | -------------------------------------------------------------------------------- /avocado/core/nrunner/config.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | 4 | class ConfigDecoder(json.JSONDecoder): 5 | """ 6 | JSON Decoder for config options. 7 | """ 8 | 9 | @staticmethod 10 | def decode_set(config_dict): 11 | for k, v in config_dict.items(): 12 | if isinstance(v, dict): 13 | if "__encoded_set__" in v: 14 | config_dict[k] = set(v["__encoded_set__"]) 15 | return config_dict 16 | 17 | def decode(self, config_str): # pylint: disable=W0221 18 | config_dict = json.JSONDecoder.decode(self, config_str) 19 | return self.decode_set(config_dict) 20 | 21 | 22 | class ConfigEncoder(json.JSONEncoder): 23 | """ 24 | JSON Encoder for config options. 25 | """ 26 | 27 | def default(self, o): 28 | if isinstance(o, set): 29 | return {"__encoded_set__": list(o)} 30 | try: 31 | return json.JSONEncoder.default(self, o) 32 | except TypeError: 33 | # Probably this is a not JSON serializable data. To keep the same 34 | # behavior as before, lets return None 35 | return None 36 | -------------------------------------------------------------------------------- /selftests/run_coverage: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Execute all unittests with coverage and report code coverage. 3 | # 4 | # Copyright: Red Hat Inc. 5 | # License: GPLv2 6 | # Author: Lukas Doktor 7 | 8 | CANDIDATES="coverage3 coverage coverage2" 9 | COVERAGE="$(which $CANDIDATES 2>/dev/null| head -n 1)" 10 | if [ "x$COVERAGE" == "x" ]; then 11 | echo "No coverage utility found, looked for: $CANDIDATES" 12 | exit -1 13 | fi 14 | echo "Using coverage utility: $COVERAGE" 15 | 16 | test_config="--skip=static-checks" 17 | if [ -n "$1" ]; then 18 | test_config=$1 19 | fi 20 | coverage_source="" 21 | coverage_include="" 22 | if [ -n "$2" ]; then 23 | coverage_source="--source=$2" 24 | coverage_include="--include=$2" 25 | fi 26 | 27 | $COVERAGE erase 28 | rm -f .coverage.* 29 | echo -e "import coverage\ncoverage.process_startup()" >> sitecustomize.py 30 | env COVERAGE_PROCESS_START=.coveragerc $COVERAGE run $coverage_source selftests/check.py $test_config 31 | test_status=$? 32 | rm -f sitecustomize.py 33 | $COVERAGE combine -q 34 | echo 35 | $COVERAGE report $coverage_include 36 | $COVERAGE xml $coverage_include 37 | exit $test_status 38 | -------------------------------------------------------------------------------- /avocado/core/utils/eggenv.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import pkg_resources 4 | 5 | 6 | def get_python_path_env_if_egg(): 7 | """ 8 | Returns an environment mapping with an extra PYTHONPATH for the egg or None 9 | 10 | When running Avocado Python modules, the interpreter on the new 11 | process needs to know where Avocado can be found. This is usually 12 | handled by the Avocado installation being available to the 13 | standard Python installation, but if Avocado is running from an 14 | uninstalled egg, it needs extra help. 15 | 16 | :returns: environment mapping with an extra PYTHONPATH for the egg or None 17 | :rtype: os.environ mapping or None 18 | """ 19 | dist = pkg_resources.get_distribution("avocado-framework") 20 | if not (dist.location.endswith(".egg") and os.path.isfile(dist.location)): 21 | return None 22 | 23 | python_path = os.environ.get("PYTHONPATH", "") 24 | python_path_entries = python_path.split(":") 25 | if dist.location in python_path_entries: 26 | return None 27 | 28 | env = os.environ.copy() 29 | env["PYTHONPATH"] = f"{dist.location}:{python_path}" 30 | return env 31 | -------------------------------------------------------------------------------- /.github/workflows/ansible.yml: -------------------------------------------------------------------------------- 1 | name: Ansible deployment test 2 | 3 | on: 4 | schedule: 5 | - cron: "0 5 * * 1" 6 | # Allows you to run this workflow manually from the Actions tab 7 | workflow_dispatch: 8 | 9 | jobs: 10 | 11 | podman: 12 | name: Ansible (${{matrix.extra}}) 13 | runs-on: ubuntu-latest 14 | container: 15 | image: fedora:40 16 | env: 17 | RUN_BEFORE: 'dnf install -y git ansible' 18 | GIT_URL: 'https://github.com/${{github.repository}}' 19 | INVENTORY: 'selftests/deployment/inventory' 20 | PLAYBOOK: 'selftests/deployment/deployment.yml' 21 | strategy: 22 | matrix: 23 | extra: ["method=pip", "method=copr", "method=official", "method=pip avocado_vt=true", "method=copr avocado_vt=true"] 24 | fail-fast: false 25 | 26 | steps: 27 | - uses: actions/checkout@v4 28 | with: 29 | ref: 'master' 30 | fetch-depth: 0 31 | - name: Install Ansible 32 | run: dnf install -y git ansible 33 | - name: Run Ansible playbook 34 | run: ansible-pull -v -U ${{env.GIT_URL}} -i ${{env.INVENTORY}} -c local ${{env.PLAYBOOK}} -e "${{matrix.extra}}" 35 | -------------------------------------------------------------------------------- /selftests/unit/parser.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import unittest 3 | 4 | from avocado.core import parser 5 | 6 | 7 | class SilentParser(argparse.ArgumentParser): 8 | def __init__(self): 9 | super().__init__(prog="avocado") 10 | 11 | def error(self, message): 12 | """ 13 | Don't sys.exit, but only raise RuntimeError 14 | """ 15 | raise RuntimeError(message) 16 | 17 | 18 | class FileOrStdoutActionTest(unittest.TestCase): 19 | def setUp(self): 20 | self.parser = SilentParser() 21 | self.parser.add_argument("--xunit", action=parser.FileOrStdoutAction) 22 | self.parser.add_argument("--json", action=parser.FileOrStdoutAction) 23 | 24 | def test_multiple_files(self): 25 | self.parser.parse_args(["--xunit=results.xml", "--json=results.json"]) 26 | 27 | def test_one_file_and_stdout(self): 28 | self.parser.parse_args(["--xunit=-", "--json=results.json"]) 29 | 30 | def test_multiple_stdout_raises(self): 31 | self.assertRaises( 32 | RuntimeError, self.parser.parse_args, ["--xunit=-", "--json=-"] 33 | ) 34 | 35 | 36 | if __name__ == "__main__": 37 | unittest.main() 38 | -------------------------------------------------------------------------------- /docs/source/releases/lts/next.rst: -------------------------------------------------------------------------------- 1 | .. _lts_next: 2 | 3 | ============ 4 | The Next LTS 5 | ============ 6 | 7 | The Long Term Stability releases of Avocado are the result of the 8 | accumulated changes on regular (non-LTS) releases. 9 | 10 | This section tracks the changes introduced on each regular (non-LTS) 11 | Avocado release, and gives a sneak preview of what will make into the 12 | next LTS release. 13 | 14 | What's new? 15 | =========== 16 | 17 | When compared to the last LTS (82.x), the main changes to be 18 | introduced by the next LTS version are: 19 | 20 | Test Writers 21 | ------------ 22 | 23 | Test APIs 24 | ~~~~~~~~~ 25 | 26 | Utility APIs 27 | ~~~~~~~~~~~~ 28 | 29 | Users 30 | ----- 31 | 32 | Output Plugins 33 | ~~~~~~~~~~~~~~ 34 | 35 | Test Loader Plugins 36 | ~~~~~~~~~~~~~~~~~~~ 37 | 38 | Varianter Plugins 39 | ~~~~~~~~~~~~~~~~~ 40 | 41 | Test Runner Plugins 42 | ~~~~~~~~~~~~~~~~~~~ 43 | 44 | Complete list of changes 45 | ======================== 46 | 47 | For a complete list of changes between the last LTS release (82.0) and 48 | this release, please check out `the Avocado commit changelog 49 | `_. 50 | -------------------------------------------------------------------------------- /examples/tests/cabort.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | 4 | from avocado import Test 5 | from avocado.utils import build, process 6 | 7 | 8 | class CAbort(Test): 9 | """ 10 | A test that calls C standard lib function abort(). 11 | 12 | :avocado: tags=requires_c_compiler 13 | """ 14 | 15 | def setUp(self): 16 | """ 17 | Build 'abort'. 18 | """ 19 | source = self.params.get("source", default="abort.c") 20 | c_file = self.get_data(source) 21 | if c_file is None: 22 | self.cancel(f"Test is missing data file {source}") 23 | c_file_name = os.path.basename(c_file) 24 | dest_c_file = os.path.join(self.workdir, c_file_name) 25 | shutil.copy(c_file, dest_c_file) 26 | build.make(self.workdir, env={"CFLAGS": "-g -O0"}, extra_args="abort") 27 | 28 | def test(self): 29 | """ 30 | Execute 'abort'. 31 | """ 32 | cmd = os.path.join(self.workdir, "abort") 33 | cmd_result = process.run(cmd, ignore_status=True) 34 | self.log.info(cmd_result) 35 | expected_result = -6 # SIGABRT = 6 36 | self.assertEqual(cmd_result.exit_status, expected_result) 37 | -------------------------------------------------------------------------------- /selftests/safeloader.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | # This script tests the "avocado.core.safeloader" module by processing 4 | # either one specific file (the first command line parameter given to 5 | # this script) or all unittest-like files in the selftests directories 6 | 7 | INPUT_FILE="${1:-}" 8 | SAFELOADER_OUTPUT=$(mktemp /tmp/safeloader-XXXXXX) 9 | DEFAULT_LOADER_OUTPUT=$(mktemp /tmp/safeloader-XXXXXX) 10 | 11 | function cleanup() 12 | { 13 | rm $SAFELOADER_OUTPUT $DEFAULT_LOADER_OUTPUT 14 | } 15 | 16 | trap cleanup EXIT 17 | 18 | function check() 19 | { 20 | echo "*** Checking safeloader on $1 ***"; 21 | python3 contrib/scripts/find-python-unittest $1 > $SAFELOADER_OUTPUT; 22 | AVOCADO_SAFELOADER_UNITTEST_ORDER_COMPAT=1 python3 contrib/scripts/avocado-safeloader-find-python-unittest $1 > $DEFAULT_LOADER_OUTPUT; 23 | diff -u $SAFELOADER_OUTPUT $DEFAULT_LOADER_OUTPUT; 24 | } 25 | 26 | if [ -n "$INPUT_FILE" ]; then 27 | check "$INPUT_FILE"; 28 | else 29 | for input_file in $(grep -c -m1 -E 'import unittest$' selftests/unit{,/plugin,/utils}/*.py selftests/functional{,/plugin}/*.py | grep -v -E ':0$' | cut -d ':' -f 1); do 30 | check "$input_file" 31 | done 32 | fi 33 | -------------------------------------------------------------------------------- /selftests/pre_release/tests/check-copr-rpm-version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | # This script accepts a package NVR as its first argument. If not given, 4 | # it will default to a NVR based on the info of the repository given 5 | 6 | # Put here the name of your GIT remote that tracks the official 7 | # repo, that is, https://github.com/avocado-framework/avocado 8 | # (or the git:// url version of the same repo) 9 | ORIGIN=origin 10 | 11 | git fetch $ORIGIN 12 | 13 | ORIGIN_MASTER_COMMIT=$(git log --pretty=format:'%h' -n 1 $ORIGIN/master) 14 | VERSION=$(python setup.py --version 2>/dev/null) 15 | COMMIT_DATE=$(git log --pretty='format:%cd' --date='format:%Y%m%d' -n 1 $ORIGIN/master) 16 | SHORT_COMMIT=$(git rev-parse --short=9 $ORIGIN/master) 17 | RPM_RELEASE_NUMBER=$(grep -E '^Release:\s([0-9]+)' python-avocado.spec | sed -E 's/Release:\s([0-9]+).*/\1/') 18 | DISTRO_VERSION=42 19 | 20 | DEFAULT_RPM_NVR="python3-avocado-${VERSION}-${RPM_RELEASE_NUMBER}.${COMMIT_DATE}git${SHORT_COMMIT}.fc${DISTRO_VERSION}" 21 | RPM_NVR="${1:-$DEFAULT_RPM_NVR}" 22 | 23 | PODMAN=$(which podman 2>/dev/null || which docker) 24 | PODMAN_IMAGE=quay.io/avocado-framework/check-copr-rpm-version 25 | 26 | $PODMAN run --rm -ti $PODMAN_IMAGE /bin/bash -c "dnf -y install ${RPM_NVR}" 27 | -------------------------------------------------------------------------------- /contrib/scripts/vmimage-populate-cache.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | Script that downloads cloud images via avocado.utils.vmimage 5 | """ 6 | 7 | from avocado.core.settings import settings 8 | from avocado.utils import vmimage 9 | 10 | KNOWN_IMAGES = ( 11 | # from https://download.cirros-cloud.net/0.4.0/MD5SUMS 12 | ("cirros", "0.4.0", "aarch64", "ecc9a5132e7a0f11a4c585f513cd0873", "md5"), 13 | ("cirros", "0.4.0", "arm", "7e9cfcb763e83573a4b9d9315f56cc5f", "md5"), 14 | ("cirros", "0.4.0", "i386", "b7d8ac291c698c3f1dc0705ce52a3b64", "md5"), 15 | ("cirros", "0.4.0", "x86_64", "443b7623e27ecf03dc9e01ee93f67afe", "md5"), 16 | ) 17 | 18 | 19 | def main(): 20 | for image in KNOWN_IMAGES: 21 | name, version, arch, checksum, algorithm = image 22 | print(f"{name} version {version} ({arch}): ", end="") 23 | cache_dir = settings.as_dict().get("datadir.paths.cache_dirs")[0] 24 | download = vmimage.get( 25 | name=name, 26 | version=version, 27 | arch=arch, 28 | checksum=checksum, 29 | algorithm=algorithm, 30 | cache_dir=cache_dir, 31 | ) 32 | print(download.base_image) 33 | 34 | 35 | if __name__ == "__main__": 36 | main() 37 | -------------------------------------------------------------------------------- /contrib/scripts/avocado-get-job-results-dir.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # This program is free software; you can redistribute it and/or modify 4 | # it under the terms of the GNU General Public License as published by 5 | # the Free Software Foundation; specifically version 2 of the License. 6 | # 7 | # This program is distributed in the hope that it will be useful, 8 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 10 | # 11 | # See LICENSE for more details. 12 | # 13 | # Copyright: Red Hat Inc. 2016 14 | # Author: Amador Pahim 15 | 16 | # 17 | # Simple script that, given the Job (partial) ID, returns the job 18 | # results directory. 19 | # 20 | # $ python avocado-get-job-results-dir.py 21 | # 22 | 23 | import sys 24 | 25 | from avocado.core import data_dir 26 | 27 | if __name__ == "__main__": 28 | if len(sys.argv) < 2: 29 | sys.stderr.write("Please inform the Job ID.\n") 30 | sys.exit(-1) 31 | 32 | resultsdir = data_dir.get_job_results_dir(sys.argv[1]) 33 | if resultsdir is None: 34 | sys.stderr.write(f"Can't find job results directory for '{sys.argv[1]}'\n") 35 | sys.exit(-1) 36 | 37 | sys.stdout.write(f"{resultsdir}\n") 38 | -------------------------------------------------------------------------------- /examples/tests/logging_streams.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import time 3 | 4 | from avocado import Test 5 | 6 | 7 | class Plant(Test): 8 | """Logs parts of the test progress in an specific logging stream.""" 9 | 10 | def test_plant_organic(self): 11 | progress_log = logging.getLogger("avocado.test.progress") 12 | job_log = logging.getLogger("avocado.job") 13 | rows = int(self.params.get("rows", default=3)) 14 | 15 | # Preparing soil 16 | for row in range(rows): 17 | progress_log.info("preparing soil on row %s", row) 18 | job_log.info("Soil has been prepared.") 19 | 20 | # Letting soil rest 21 | progress_log.info("letting soil rest before throwing seeds") 22 | time.sleep(1) 23 | 24 | # Throwing seeds 25 | for row in range(rows): 26 | progress_log.info("throwing seeds on row %s", row) 27 | 28 | job_log.info("Seeds have been palanted.") 29 | # Let them grow 30 | progress_log.info("waiting for Avocados to grow") 31 | time.sleep(2) 32 | 33 | # Harvest them 34 | for row in range(rows): 35 | progress_log.info("harvesting organic avocados on row %s", row) 36 | 37 | progress_log.error("Avocados are Gone") 38 | -------------------------------------------------------------------------------- /selftests/unit/dependencies_resolver.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from avocado.core.dependencies.dependency import Dependency 4 | from avocado.core.nrunner.runnable import Runnable 5 | from avocado.plugins.dependency import DependencyResolver 6 | 7 | 8 | class BasicTests(unittest.TestCase): 9 | """Basic unit tests for the DependencyResolver class""" 10 | 11 | def test_dependencies_runnables(self): 12 | runnable = Runnable( 13 | kind="package", 14 | uri=None, 15 | dependencies=[ 16 | Dependency("package", kwargs={"name": "foo"}), 17 | Dependency("package", kwargs={"name": "bar"}), 18 | ], 19 | ) 20 | dependency_runnables = DependencyResolver.pre_test_runnables(runnable) 21 | kind = "package" 22 | self.assertEqual(kind, dependency_runnables[0].kind) 23 | self.assertEqual(kind, dependency_runnables[1].kind) 24 | name0 = "foo" 25 | name1 = "bar" 26 | self.assertEqual(name0, dependency_runnables[0].kwargs["name"]) 27 | self.assertEqual(name1, dependency_runnables[1].kwargs["name"]) 28 | self.assertIsNone(dependency_runnables[0].kwargs.get("type")) 29 | 30 | 31 | if __name__ == "__main__": 32 | unittest.main() 33 | --------------------------------------------------------------------------------