From 573f5187d71298362fd7365dd88f8392c1d81332 Mon Sep 17 00:00:00 2001 From: Vasileios Karakasis Date: Thu, 11 Feb 2021 01:14:41 +0100 Subject: [PATCH 1/2] Various documentation fixes --- README.md | 57 ++---- docs/config_reference.rst | 2 +- docs/configure.rst | 4 +- docs/index.rst | 2 +- docs/started.rst | 182 +++++------------- docs/tutorial_advanced.rst | 2 +- docs/tutorial_basics.rst | 4 +- unittests/resources/checks/hellocheck_make.py | 4 +- unittests/test_buildsystems.py | 22 +-- 9 files changed, 90 insertions(+), 189 deletions(-) diff --git a/README.md b/README.md index cbfc8b8ade..d23aad0871 100644 --- a/README.md +++ b/README.md @@ -27,10 +27,12 @@ The stages of this pipeline take care of all the system interaction details, suc Writing system regression tests in a high-level modern programming language, like Python, poses a great advantage in organizing and maintaining the tests. Users can create their own test hierarchies, create test factories for generating multiple tests at the same time and also customize them in a simple and expressive way. +Please visit the project's documentation [page](https://reframe-hpc.readthedocs.io/) for all the details! -## Getting ReFrame -ReFrame is almost ready to run just after you clone it from Github. +## Installation + +ReFrame is fairly easy to install. All you need is Python 3.6 or above and to run its bootstrap script: ```bash @@ -40,37 +42,19 @@ cd reframe ./bin/reframe -V ``` -### Other installation ways - -You can also install ReFrame through the following channels: - -- Through [PyPI](https://pypi.org/project/ReFrame-HPC/): - - ``` - pip install reframe-hpc - ``` - -- Through [Spack](https://spack.io/): - - ``` - spack install reframe - ``` - -- Through [EasyBuild](https://easybuild.readthedocs.io/): - - ``` - eb easybuild/easyconfigs/r/ReFrame/ReFrame-VERSION.eb -r - ``` +If you want a specific release, please refer to the documentation [page](https://reframe-hpc.readthedocs.io/en/stable/started.html). -Finally, you may access all previous versions of ReFrame [here](https://github.com/eth-cscs/reframe/releases). +### Running the unit tests -## Documentation +You can optionally run the framework's unit tests with the following command: -You may find the official documentation of the latest release and the current master in the following links: +```bash +./test_reframe.py -v +``` -- [Latest release](https://reframe-hpc.readthedocs.io/en/stable) -- [Current master](https://reframe-hpc.readthedocs.io/en/latest) +NOTE: Unit tests require a functional C compiler, available through the `cc` command, that is also able to recognize the ``-O2`` option. +The [GNU Make](https://www.gnu.org/software/make/) build tool is also needed. ### Building the documentation locally @@ -102,21 +86,18 @@ However, they can serve as a very good starting point for implementing your syst You can get in contact with the ReFrame community in the following ways: -### Mailing list - -For keeping up with the latest news about ReFrame, posting questions and, generally getting in touch with other users and the developers, you may follow the mailing list: [reframe@sympa.cscs.ch](mailto:reframe@sympa.cscs.ch). - -Only subscribers may send messages to the list. -To subscribe, please send an empty message to [reframe-subscribe@sympa.cscs.ch](mailto:reframe-subscribe@sympa.cscs.ch). +### Slack -For unsubscribing, you may send an empty message to [reframe-unsubscribe@sympa.cscs.ch](mailto:reframe-unsubscribe@sympa.cscs.ch). +Please join the community's [Slack channel](https://reframe-slack.herokuapp.com) for keeping up with the latest news about ReFrame, posting questions and, generally getting in touch with other users and the developers. -### Slack +### Mailing list -You may also reach the community through Slack [here](https://reframe-slack.herokuapp.com). +You may also [subscribe](mailto:reframe-subscribe@sympa.cscs.ch) to the [mailing list](mailto:reframe@sympa.cscs.ch). +Only subscribers can send messages to the list. +For unsubscribing, you may send an empty message [here](mailto:reframe-unsubscribe@sympa.cscs.ch). ## Contributing back -ReFrame is an open-source project and we welcome third-party contributions. +ReFrame is an open-source project and we welcome and encourage contributions! Check out our Contribution Guide [here](https://github.com/eth-cscs/reframe/wiki/contributing-to-reframe). diff --git a/docs/config_reference.rst b/docs/config_reference.rst index d937290ff2..bde05291d0 100644 --- a/docs/config_reference.rst +++ b/docs/config_reference.rst @@ -115,7 +115,7 @@ System Configuration - ``tmod32``: A synonym of ``tmod``. - ``tmod4``: The `new environment modules `__ implementation (versions older than 4.1 are not supported). - ``lmod``: The `Lua implementation `__ of the environment modules. - - ``spack``: `Spack `'s built-in mechanism for managing modules. + - ``spack``: `Spack `__'s built-in mechanism for managing modules. - ``nomod``: This is to denote that no modules system is used by this system. .. versionadded:: 3.4 diff --git a/docs/configure.rst b/docs/configure.rst index 956e0ed5cf..afe477c98d 100644 --- a/docs/configure.rst +++ b/docs/configure.rst @@ -78,6 +78,7 @@ Each system is associated with a set of properties, which in this case are the f * ``hostnames``: This is a list of hostname patterns following the `Python Regular Expression Syntax `__, which will be used by ReFrame when it tries to automatically select a configuration entry for the current system. * ``modules_system``: In our example, this is only defined for Piz Daint and refers to the environment modules system that should be used for loading environment modules on this system. In this case, the classic Tcl implementation of the `environment modules `__. + For a complete list of the supported modules systems, see `here `__. * ``partitions``: The list of partitions that are defined for this system. Each partition is defined as a separate object. We devote the rest of this section in system partitions, since they are an essential part of ReFrame's configuration. @@ -157,7 +158,7 @@ Let's see how logging is defined in our example configuration, which also repres Logging is configured under the ``logging`` section of the configuration, which is a list of logger objects. Unless you want to configure logging differently for different systems, a single logger object is enough. -Each logger object is associated with a logging level stored in the ``level`` property and has a set of logging handlers that are actually responsible for handling the actual logging records. +Each logger object is associated with a `logging level `__ stored in the ``level`` property and has a set of logging handlers that are actually responsible for handling the actual logging records. ReFrame's output is performed through the logging mechanism, meaning that if you don't specify any logging handler, you will not get any output from ReFrame! The ``handlers`` property of the logger object holds the actual handlers. Notice that you can use multiple handlers at the same time, which enables you to feed ReFrame's output to different sinks and at different verbosity levels. @@ -166,6 +167,7 @@ These are the following: * ``type``: This is the type of the handler, which determines its functionality. Depending on the handler type, handler-specific properties may be allowed or required. + For a complete list of available log handler types, see `here `__. * ``level``: The cut-off level for messages reaching this handler. Any message with a lower level number will be filtered out. * ``format``: A format string for formatting the emitted log record. diff --git a/docs/index.rst b/docs/index.rst index 1214e2af2b..afde3dbfc8 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -49,8 +49,8 @@ Publications :maxdepth: 2 started - configure tutorials + configure topics usecases migration_2_to_3 diff --git a/docs/started.rst b/docs/started.rst index 7cd1d958e9..89aca6eedc 100644 --- a/docs/started.rst +++ b/docs/started.rst @@ -7,82 +7,92 @@ Requirements * Python 3.6 or higher. Python 2 is not supported. -* Required Python packages can be found in the ``requirements.txt`` file. - See :ref:`install-from-source` for more information on how to install ReFrame from source. +* The required Python packages are the following: - ---------------------- -Optional Requirements ---------------------- - -If you want to run the framework's unit tests, you will need a C compiler available through `cc` that is able to compile a "Hello, World!" program and recognize the ``-O3`` option, as well as the `GNU Make `__ build tool. +.. literalinclude:: ../requirements.txt -.. note:: - .. versionchanged:: 2.8 - - A functional TCL modules system is no more required. ReFrame can now operate without a modules system at all. - .. note:: .. versionchanged:: 3.0 Support for Python 3.5 has been dropped. - Getting the Framework --------------------- -ReFrame's latest stable version is available through different channels: +Stable ReFrame releases are available through different channels. -- As a `PyPI `__ package: - .. code:: bash +----- +Spack +----- - pip install reframe-hpc +ReFrame is available as a `Spack `__ package: - .. note:: +.. code:: bash + + spack install reframe - The above method performs a bare installation of ReFrame not including unittests and tutorial examples. +There are the following variants available: -- As a `Spack `__ package: +- ``+docs``: This will install the man pages of ReFrame. +- ``+gelf``: This will install the bindings for handling `Graylog `__ log messages. - .. code:: bash - spack install reframe +--------- +EasyBuild +--------- -- As an `EasyBuild `__ package: +ReFrame is available as an `EasyBuild `__ package: + +.. code:: bash - .. code:: bash + eb ReFrame-VERSION.eb -r - eb easybuild/easyconfigs/r/ReFrame/ReFrame-VERSION.eb -r +This will install the man pages as well as the `Graylog `__ bindings. -.. _install-from-source: -------------------------------- -Getting the Latest and Greatest -------------------------------- +---- +PyPI +---- -If you want the latest development version or any pre-release, you can clone ReFrame from Github: + +ReFrame is available as a `PyPI `__ package: .. code:: bash - git clone https://github.com/eth-cscs/reframe.git + pip install reframe-hpc -Pre-release versions are denoted with the ``devX`` suffix and are `tagged `__ in the repository. -Preparing and running ReFrame from source is pretty straightforward. -All you need is a Python 3.6+ installation with ``pip``: +This is a bare installation of the framework. +It will not install the documentation, the tutorial examples or the bindings for handling `Graylog `__ log messages. -.. code:: bash - git clone https://github.com/eth-cscs/reframe.git - cd reframe - ./bootstrap.sh - ./bin/reframe -V +------ +Github +------ + +Any ReFrame version can be very easily installed directly from Github: + +.. code-block:: bash + + pushd /path/to/install/prefix + git clone -q --depth 1 --branch VERSION_TAG https://github.com/eth-cscs/reframe.git + pushd reframe && ./bootstrap.sh && popd + export PATH=$(pwd)/bin:$PATH + popd + +The ``VERSION_TAG`` is the version number prefixed by ``v``, e.g., ``v3.5.0``. +The ``./bootstrap.sh`` script will fetch ReFrame's requirements under its installation prefix. +It will not set the ``PYTHONPATH``, so it will not affect the user's Python installation. +The ``./bootstrap.sh`` has two additional variant options: + +- ``+docs``: This will also build the documentation. +- ``+pygelf``: This will install the bindings for handling `Graylog `__ log messages. .. note:: .. versionadded:: 3.1 @@ -100,98 +110,6 @@ Auto-completion is supported for Bash, Tcsh and Fish shells. -Running the Unit Tests ----------------------- - -You can optionally run the framework's unit tests to make sure that everything is set up correctly: - - -.. code:: bash - - ./test_reframe.py -v - -The output should look like the following: - -.. code:: bash - - ======================================== test session starts ========================================= - platform darwin -- Python 3.7.3, pytest-4.3.0, py-1.8.0, pluggy-0.9.0 -- /usr/local/opt/python/bin/python3.7 - cachedir: .pytest_cache - rootdir: /Users/karakasv/Repositories/reframe, inifile: - collected 697 items - - unittests/test_argparser.py::test_arguments PASSED [ 0%] - unittests/test_argparser.py::test_parsing PASSED [ 0%] - unittests/test_argparser.py::test_option_precedence PASSED [ 0%] - unittests/test_argparser.py::test_option_with_config PASSED [ 0%] - unittests/test_argparser.py::test_option_envvar_conversion_error PASSED [ 0%] - unittests/test_buildsystems.py::TestMake::test_emit_from_buildsystem PASSED [ 0%] - unittests/test_buildsystems.py::TestMake::test_emit_from_env PASSED [ 1%] - unittests/test_buildsystems.py::TestMake::test_emit_no_env_defaults PASSED [ 1%] - unittests/test_buildsystems.py::TestCMake::test_emit_from_buildsystem PASSED [ 1%] - unittests/test_buildsystems.py::TestCMake::test_emit_from_env PASSED [ 1%] - unittests/test_buildsystems.py::TestCMake::test_emit_no_env_defaults PASSED [ 1%] - unittests/test_buildsystems.py::TestAutotools::test_emit_from_buildsystem PASSED [ 1%] - unittests/test_buildsystems.py::TestAutotools::test_emit_from_env PASSED [ 1%] - unittests/test_buildsystems.py::TestAutotools::test_emit_no_env_defaults PASSED [ 2%] - unittests/test_buildsystems.py::TestSingleSource::test_emit_from_env PASSED [ 2%] - unittests/test_buildsystems.py::TestSingleSource::test_emit_no_env PASSED [ 2%] - unittests/test_check_filters.py::TestCheckFilters::test_have_cpu_only PASSED [ 2%] - unittests/test_check_filters.py::TestCheckFilters::test_have_gpu_only PASSED [ 2%] - unittests/test_check_filters.py::TestCheckFilters::test_have_name PASSED [ 2%] - unittests/test_check_filters.py::TestCheckFilters::test_have_not_name PASSED [ 2%] - unittests/test_check_filters.py::TestCheckFilters::test_have_prgenv PASSED [ 3%] - unittests/test_check_filters.py::TestCheckFilters::test_have_tags PASSED [ 3%] - unittests/test_check_filters.py::TestCheckFilters::test_invalid_regex PASSED [ 3%] - unittests/test_check_filters.py::TestCheckFilters::test_partition PASSED [ 3%] - unittests/test_cli.py::test_check_success PASSED [ 3%] - unittests/test_cli.py::test_check_submit_success SKIPPED [ 3%] - unittests/test_cli.py::test_check_failure PASSED [ 3%] - <... output omitted ...> - unittests/test_utility.py::TestPpretty::test_simple_types PASSED [ 95%] - unittests/test_utility.py::TestPpretty::test_mixed_types PASSED [ 95%] - unittests/test_utility.py::TestPpretty::test_obj_print PASSED [ 95%] - unittests/test_utility.py::TestChangeDirCtxManager::test_change_dir_working PASSED [ 95%] - unittests/test_utility.py::TestChangeDirCtxManager::test_exception_propagation PASSED [ 95%] - unittests/test_utility.py::TestMiscUtilities::test_allx PASSED [ 95%] - unittests/test_utility.py::TestMiscUtilities::test_decamelize PASSED [ 96%] - unittests/test_utility.py::TestMiscUtilities::test_sanitize PASSED [ 96%] - unittests/test_utility.py::TestScopedDict::test_construction PASSED [ 96%] - unittests/test_utility.py::TestScopedDict::test_contains PASSED [ 96%] - unittests/test_utility.py::TestScopedDict::test_delitem PASSED [ 96%] - unittests/test_utility.py::TestScopedDict::test_iter_items PASSED [ 96%] - unittests/test_utility.py::TestScopedDict::test_iter_keys PASSED [ 96%] - unittests/test_utility.py::TestScopedDict::test_iter_values PASSED [ 97%] - unittests/test_utility.py::TestScopedDict::test_key_resolution PASSED [ 97%] - unittests/test_utility.py::TestScopedDict::test_scope_key_name_pseudoconflict PASSED [ 97%] - unittests/test_utility.py::TestScopedDict::test_setitem PASSED [ 97%] - unittests/test_utility.py::TestScopedDict::test_update PASSED [ 97%] - unittests/test_utility.py::TestReadOnlyViews::test_mapping PASSED [ 97%] - unittests/test_utility.py::TestReadOnlyViews::test_sequence PASSED [ 97%] - unittests/test_utility.py::TestOrderedSet::test_concat_files PASSED [ 98%] - unittests/test_utility.py::TestOrderedSet::test_construction PASSED [ 98%] - unittests/test_utility.py::TestOrderedSet::test_construction_empty PASSED [ 98%] - unittests/test_utility.py::TestOrderedSet::test_construction_error PASSED [ 98%] - unittests/test_utility.py::TestOrderedSet::test_difference PASSED [ 98%] - unittests/test_utility.py::TestOrderedSet::test_intersection PASSED [ 98%] - unittests/test_utility.py::TestOrderedSet::test_operators PASSED [ 98%] - unittests/test_utility.py::TestOrderedSet::test_reversed PASSED [ 99%] - unittests/test_utility.py::TestOrderedSet::test_str PASSED [ 99%] - unittests/test_utility.py::TestOrderedSet::test_union PASSED [ 99%] - unittests/test_utility.py::TestOrderedSet::test_unique_abs_paths PASSED [ 99%] - unittests/test_versioning.py::TestVersioning::test_comparing_versions PASSED [ 99%] - unittests/test_versioning.py::TestVersioning::test_version_format PASSED [ 99%] - unittests/test_versioning.py::TestVersioning::test_version_validation PASSED [100%] - - ============================== 620 passed, 77 skipped in 64.58 seconds =============================== - - -You will notice that several tests will be skipped. -ReFrame uses a generic configuration by default, so that it can run on any system. -As a result, all tests for scheduler backends, environment modules, container platforms etc. will be skipped. -As soon as you configure ReFrame specifically for your system, you may rerun the test suite using your system configuration file by passing the ``--rfm-user-config=CONFIG_FILE``. - - Where to Go from Here --------------------- diff --git a/docs/tutorial_advanced.rst b/docs/tutorial_advanced.rst index c071949d28..775864447c 100644 --- a/docs/tutorial_advanced.rst +++ b/docs/tutorial_advanced.rst @@ -674,7 +674,7 @@ First, we need to enable the container platform support in ReFrame's configurati :lines: 38-58 :emphasize-lines: 15-20 -For each partition, users can define a list of container platforms supported using the :js:attr:`container_platforms` configuration parameter. +For each partition, users can define a list of container platforms supported using the :js:attr:`container_platforms` `configuration parameter `__. In this case, we define the `Singularity `__ platform, for which we set the :js:attr:`modules` parameter in order to instruct ReFrame to load the ``singularity`` module, whenever it needs to run with this container platform. The following test will use a Singularity container to run: diff --git a/docs/tutorial_basics.rst b/docs/tutorial_basics.rst index 63a6f15d7f..c7bb1edd3f 100644 --- a/docs/tutorial_basics.rst +++ b/docs/tutorial_basics.rst @@ -327,7 +327,7 @@ Here is how the new configuration file looks like with the needed additions high :emphasize-lines: 3-15,31-42 Here we define a system named ``catalina`` that has one partition named ``default``. -This partition makes no use of any workload manager, but instead launches any jobs locally as OS processes. +This partition makes no use of any `workload manager `__, but instead launches any jobs locally as OS processes. Two programming environments are relevant for that partition, namely ``gnu`` and ``clang``, which are defined in the section :js:attr:`environments` of the configuration file. The ``gnu`` programming environment provides GCC 9, whereas the ``clang`` one provides the Clang compiler from the system. Notice, how you can define the actual commands for invoking the C, C++ and Fortran compilers in each programming environment. @@ -812,7 +812,7 @@ Let's extend our configuration file for Piz Daint. First of all, we need to define a new system and set the list of hostnames that will help ReFrame identify it. -We also set the :js:attr:`modules_system` configuration parameter to instruct ReFrame that this system makes use of the `environment modules `__ for managing the user environment. +We also set the :js:attr:`modules_system <.systems[].modules_system>` `configuration parameter `__ to instruct ReFrame that this system makes use of the `environment modules `__ for managing the user environment. Then we define the system partitions that we want to test. In this case, we define three partitions: diff --git a/unittests/resources/checks/hellocheck_make.py b/unittests/resources/checks/hellocheck_make.py index b652656377..7dd8f96c15 100644 --- a/unittests/resources/checks/hellocheck_make.py +++ b/unittests/resources/checks/hellocheck_make.py @@ -16,8 +16,8 @@ def __init__(self): self.valid_systems = ['*'] self.valid_prog_environs = ['*'] self.build_system = 'Make' - self.build_system.cflags = ['-O3'] - self.build_system.cxxflags = ['-O3'] + self.build_system.cflags = ['-O2'] + self.build_system.cxxflags = ['-O2'] self.executable = './hello_c' self.keep_files = ['hello_c'] self.tags = {'foo', 'bar'} diff --git a/unittests/test_buildsystems.py b/unittests/test_buildsystems.py index dc5e4d2eb2..13dbfaadc8 100644 --- a/unittests/test_buildsystems.py +++ b/unittests/test_buildsystems.py @@ -36,9 +36,9 @@ def build_system_with_flags(build_system): build_system.ftn = 'ftn' build_system.nvcc = 'clang' build_system.cppflags = ['-DFOO'] - build_system.cflags = ['-Wall', '-std=c99', '-O3'] - build_system.cxxflags = ['-Wall', '-std=c++11', '-O3'] - build_system.fflags = ['-Wall', '-O3'] + build_system.cflags = ['-Wall', '-std=c99', '-O2'] + build_system.cxxflags = ['-Wall', '-std=c++11', '-O2'] + build_system.fflags = ['-Wall', '-O2'] build_system.ldflags = ['-static'] return build_system @@ -133,8 +133,8 @@ def _emit_from_buildsystem_Make(build_system_with_flags, environ): build_system_with_flags.max_concurrency = None expected = [ 'make -f Makefile_foo -C foodir -j CC="cc" CXX="CC" FC="ftn" ' - 'NVCC="clang" CPPFLAGS="-DFOO" CFLAGS="-Wall -std=c99 -O3" ' - 'CXXFLAGS="-Wall -std=c++11 -O3" FCFLAGS="-Wall -O3" ' + 'NVCC="clang" CPPFLAGS="-DFOO" CFLAGS="-Wall -std=c99 -O2" ' + 'CXXFLAGS="-Wall -std=c++11 -O2" FCFLAGS="-Wall -O2" ' 'LDFLAGS="-static" FOO=1' ] assert expected == build_system_with_flags.emit_build_commands(environ) @@ -149,9 +149,9 @@ def _emit_from_buildsystem_CMake(build_system_with_flags, environ): 'cd build/foo', 'cmake -DCMAKE_C_COMPILER="cc" -DCMAKE_CXX_COMPILER="CC" ' '-DCMAKE_Fortran_COMPILER="ftn" -DCMAKE_CUDA_COMPILER="clang" ' - '-DCMAKE_C_FLAGS="-DFOO -Wall -std=c99 -O3" ' - '-DCMAKE_CXX_FLAGS="-DFOO -Wall -std=c++11 -O3" ' - '-DCMAKE_Fortran_FLAGS="-DFOO -Wall -O3" ' + '-DCMAKE_C_FLAGS="-DFOO -Wall -std=c99 -O2" ' + '-DCMAKE_CXX_FLAGS="-DFOO -Wall -std=c++11 -O2" ' + '-DCMAKE_Fortran_FLAGS="-DFOO -Wall -O2" ' '-DCMAKE_EXE_LINKER_FLAGS="-static" -DFOO=1 ../..', 'make -j' @@ -167,8 +167,8 @@ def _emit_from_buildsystem_Autotools(build_system_with_flags, environ): 'mkdir -p build/foo', 'cd build/foo', '../../configure CC="cc" CXX="CC" FC="ftn" ' - 'CPPFLAGS="-DFOO" CFLAGS="-Wall -std=c99 -O3" ' - 'CXXFLAGS="-Wall -std=c++11 -O3" FCFLAGS="-Wall -O3" ' + 'CPPFLAGS="-DFOO" CFLAGS="-Wall -std=c99 -O2" ' + 'CXXFLAGS="-Wall -std=c++11 -O2" FCFLAGS="-Wall -O2" ' 'LDFLAGS="-static" FOO=1', 'make -j' @@ -182,7 +182,7 @@ def _emit_from_buildsystem_SingleSource(build_system_with_flags, environ): build_system_with_flags.srcfile = 'foo.c' expected = [ 'cc -DFOO -I foodir/include -I bardir/include ' - '-Wall -std=c99 -O3 foo.c -o foo.x -static' + '-Wall -std=c99 -O2 foo.c -o foo.x -static' ] assert expected == build_system_with_flags.emit_build_commands(environ) From e150c37e149d3c71c2b7893efb4744814df596fd Mon Sep 17 00:00:00 2001 From: Vasileios Karakasis Date: Fri, 12 Feb 2021 13:08:39 +0100 Subject: [PATCH 2/2] Address PR comments --- docs/tutorial_deps.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial_deps.rst b/docs/tutorial_deps.rst index 96a1e1447e..913be3c7a2 100644 --- a/docs/tutorial_deps.rst +++ b/docs/tutorial_deps.rst @@ -34,7 +34,7 @@ The only new thing that comes in with the :class:`OSUBuildTest` test is the foll Here we tell ReFrame that this test depends on a test named :class:`OSUDownloadTest`. This test may or may not be defined in the same test file; all ReFrame needs is the test name. -The :func:`depends_on() ` function will create dependencies between the individual test cases of the :class:`OSUBuildTest` and the :class:`OSUDownloadTest`, such that all the test case of :class:`OSUBuildTest` will depend on the outcome of the :class:`OSUDownloadTest`. +The :func:`depends_on() ` function will create dependencies between the individual test cases of the :class:`OSUBuildTest` and the :class:`OSUDownloadTest`, such that all the test cases of :class:`OSUBuildTest` will depend on the outcome of the :class:`OSUDownloadTest`. This behaviour can be changed, but it is covered in detail in :doc:`dependencies`. You can create arbitrary test dependency graphs, but they need to be acyclic. If ReFrame detects cyclic dependencies, it will refuse to execute the set of tests and will issue an error pointing out the cycle.