BEAKERLIB(1)

๐Ÿ’– NAME ๐Ÿ’–

BeakerLib โ€” the manual name is BEAKERLIB(1), and bestie, this is a shell-level integration testing library. No cap.

๐ŸŒธ DESCRIPTION ๐ŸŒธ

BeakerLib is a shell-level integration testing library that gives you convenience functions to simplify writing, running, and analyzing integration and blackbox tests. Itโ€™s giving โ€œmake testing less painfulโ€ energy, fr fr.

The essential features include:

  • Journal โ€” uniform logging mechanism (logs & results saved in flexible XML format, easy to compare results & generate reports) ๐Ÿ’…
  • Phases โ€” logical grouping of test actions, clear separation of setup / test / cleanup (preventing false fails) โœจ
  • Asserts โ€” common checks affecting the overall results of the individual phases (checking for exit codes, file existence & content...) ๐ŸŽฏ
  • Helpers โ€” convenience functions for common operations such as managing services, backup & restore ๐Ÿ› ๏ธ

The main script sets the BEAKERLIB variable and sources other scripts where the actual functions are defined. You should source it at the beginning of your test with:

. /usr/share/beakerlib/beakerlib.sh

See the EXAMPLES section for quick start inspiration. ๐Ÿ‘€

See the BKRDOC section for more information about Automated documentation generator for BeakerLib tests. ๐Ÿ“š

๐Ÿงฌ Result fingerprint ๐Ÿงฌ

Beakerlib provides two types of fingerprint of the test run. The fingerprints are counted at the phase end and journal end. ๐Ÿซถ

The first one is a phases fingerprint which represents a list of the results of all the executed phases in the order of the execution.

The second one is an asserts fingerprint which represents a list of the results of all the executed asserts in the order of the execution.

The lists are then hashed resulting in a 8 letters string. ๐Ÿ”ฅ

Such fingerprint may be used as a reference result of the respective test run in a particular environment. Periodt.

โœจ FUNCTIONS โœจ

๐Ÿ““ Journalling ๐Ÿ““

๐Ÿ’ซ rlJournalStart

Initialize the journal file.

rlJournalStart

Run on the very beginning of your script to initialize journalling functionality. Like, literally the first thing. ๐ŸŒ…

๐Ÿ›‘ rlJournalEnd

Summarize the test run and upload the journal file.

rlJournalEnd

Run on the very end of your script to print summary of the whole test run, generate OUTPUTFILE and include journal in Beaker logs. ๐Ÿ’Œ

๐Ÿ–จ๏ธ rlJournalPrint

Print the content of the journal in pretty xml format.

rlJournalPrint [type]
  • type โ€” Can be either 'raw' or 'pretty', with the latter as a default. Raw: xml is in raw form, no indentation etc. Pretty: xml is pretty printed, indented, with one record per line.

Example:

<?xml version="1.0"?>
<BEAKER_TEST>
  <test_id>debugging</test_id>
  <package>setup</package>
  <pkgdetails>setup-2.8.9-1.fc12.noarch</pkgdetails>
  <starttime>2010-02-08 15:17:47</starttime>
  <endtime>2010-02-08 15:17:47</endtime>
  <testname>/examples/beakerlib/Sanity/simple</testname>
  <release>Fedora release 12 (Constantine)</release>
  <hostname>localhost</hostname>
  <arch>i686</arch>
  <purpose>PURPOSE of /examples/beakerlib/Sanity/simple
    Description: Minimal BeakerLib sanity test
    Author: Petr Splichal &lt;psplicha@redhat.com&gt;

    This is a minimal sanity test for BeakerLib. It contains a single
    phase with a couple of asserts. We Just check that the "setup"
    package is installed and that there is a sane /etc/passwd file.
  </purpose>
  <log>
    <phase endtime="2010-02-08 15:17:47" name="Test" result="PASS"
            score="0" starttime="2010-02-08 15:17:47" type="FAIL">
      <test message="Checking for the presence of setup rpm">PASS</test>
      <test message="File /etc/passwd should exist">PASS</test>
      <test message="File '/etc/passwd' should contain 'root'">PASS</test>
    </phase>
  </log>
</BEAKER_TEST>

๐Ÿ“œ rlJournalPrintText

Print the content of the journal in pretty text format.

rlJournalPrintText [--full-journal]
  • --full-journal โ€” The option is now deprecated, has no effect and will be removed in a future version. ๐Ÿซ 

Example:

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: [   LOG    ] :: TEST PROTOCOL
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

:: [   LOG    ] :: Test run ID   : debugging
:: [   LOG    ] :: Package       : debugging
:: [   LOG    ] :: Test started  : 2010-02-08 14:45:57
:: [   LOG    ] :: Test finished : 2010-02-08 14:45:58
:: [   LOG    ] :: Test name     :
:: [   LOG    ] :: Distro:       : Fedora release 12 (Constantine)
:: [   LOG    ] :: Hostname      : localhost
:: [   LOG    ] :: Architecture  : i686

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: [   LOG    ] :: Test description
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

PURPOSE of /examples/beakerlib/Sanity/simple
Description: Minimal BeakerLib sanity test
Author: Petr Splichal <psplicha@redhat.com>

This is a minimal sanity test for BeakerLib. It contains a single
phase with a couple of asserts. We Just check that the "setup"
package is installed and that there is a sane /etc/passwd file.

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: [   LOG    ] :: Test
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

:: [   PASS   ] :: Checking for the presence of setup rpm
:: [   PASS   ] :: File /etc/passwd should exist
:: [   PASS   ] :: File '/etc/passwd' should contain 'root'
:: [   LOG    ] :: Duration: 1s
:: [   LOG    ] :: Assertions: 3 good, 0 bad
:: [   PASS   ] :: RESULT: Test

๐Ÿ”Ž rlGetTestState

Returns number of failed asserts so far, or 255 if there are more than 255 failures. The variable ECODE is set to the precise number.

rlGetTestState

๐Ÿ” rlGetPhaseState

Returns number of failed asserts in the current phase so far, or 255 if there are more than 255 failures. The variable ECODE is set to the precise number.

rlGetPhaseState

๐Ÿชต Logging ๐Ÿชต

๐Ÿ“ rlLog, rlLogDebug, rlLogInfo, rlLogWarning, rlLogError, rlLogFatal

Create a time/priority-labelled message in the log. There is a bunch of aliases which can create messages formated as DEBUG/INFO/WARNING/ERROR or FATAL (but you would probably want to use rlDie instead of the last one). ๐Ÿ’€

rlLog message [logfile] [priority] [label]
  • message โ€” Message you want to show (use quotes when invoking).
  • logfile โ€” Log file. If not supplied, OUTPUTFILE is assumed.
  • priority โ€” Priority of the log.
  • label โ€” Print this text instead of time in log label.

๐Ÿ’€ rlDie

Create a time-labelled message in the log, report test result, upload logs, close unfinished phase and terminate the test. Dramatic exit, but make it useful. ๐Ÿ˜ญ

rlDie message [file...]
  • message โ€” Message you want to show (use quotes when invoking) โ€” this option is mandatory.
  • file โ€” Files (logs) you want to upload as well. rlBundleLogs will be used for it. Files which are not readable will be excluded before calling rlBundleLogs, so it is safe to call even with possibly nonexistent logs and it will succeed. ๐Ÿซถ

๐Ÿ“ฆ rlBundleLogs

Create a tarball of files (e.g. logs) and attach them to the test result.

rlBundleLogs package file [file...]
  • package โ€” Name of the package. Will be used as part of the tarball name.
  • file โ€” File(s) to be packed and submitted.

Returns result of submitting the tarball.

๐Ÿ“ค rlFileSubmit

Resolves absolute path to the file, replaces / with - and uploads this renamed file using rhts-submit-log. It also allows you to specify your custom name for the uploaded file.

rlFileSubmit [-s sep] path_to_file [required_name]
  • -s sep โ€” Sets separator (i.e. the replacement of the /) to sep.
  • path_to_file โ€” Either absolute or relative path to file. Relative path is converted to absolute.
  • required_name โ€” Default behavior renames file to full_path_to_file with / replaced for -, if this does not suit your needs, you can specify the name using this option.

Examples:

rlFileSubmit logfile.txt -> logfile.txt cd /etc; rlFileSubmit
./passwd -> etc-passwd rlFileSubmit /etc/passwd -> etc-passwd
rlFileSubmit /etc/passwd my-top-secret_file -> my-top-secret-file
rlFileSubmit -s '_' /etc/passwd -> etc_passwd

โ„น๏ธ Info โ„น๏ธ

๐Ÿท๏ธ rlShowPackageVersion

Shows a message about version of packages.

rlShowPackageVersion package [package...]
  • package โ€” Name of a package(s) you want to log.

๐Ÿ—๏ธ rlGetArch

Sanitize architecture for simplier matching.

Return base arch for the current system (good when you need base arch on a multilib system).

rlGetArch

On any 32-bit Intel (i386, i486, i586, ...) system you will get i386. ๐Ÿ’…

๐Ÿฅ‡ rlGetPrimaryArch

Return primary arch for the current system (good when you need base arch on a multilib system).

rlGetPrimaryArch

On non-RHEL systems if the primary/secondary sedicision fails a fallback to rlGetArch is done.

๐Ÿฅˆ rlGetSecondaryArch

Return base arch for the current system (good when you need base arch on a multilib system).

rlGetSecondaryArch

๐Ÿง rlGetDistroRelease, rlGetDistroVariant

Return release or variant of the distribution on the system.

rlGetDistroRelease
rlGetDistroVariant

For example on the RHEL-4-AS you will get release 4 and variant AS, on the RHEL-5-Client you will get release 5 and variant Client. ๐ŸŒˆ

๐Ÿ–ฅ๏ธ rlShowRunningKernel

Log a message with version of the currently running kernel.

rlShowRunningKernel

๐ŸŽญ Phases ๐ŸŽญ

๐Ÿš€ rlPhaseStart

Starts a phase of a specific type. The final phase result is based on all asserts included in the phase. Do not forget to end phase with rlPhaseEnd when you are done. ๐Ÿซก

rlPhaseStart type [name]
  • type โ€” Type of the phase, one of the following:
    • FAIL โ€” When assert fails here, phase will report a FAIL.
    • WARN โ€” When assert fails here, phase will report a WARN.
  • name โ€” Optional name of the phase (if not provided, one will be generated).

If all asserts included in the phase pass, phase reports PASS. โœจ

๐Ÿ rlPhaseEnd

End current phase, summarize asserts included and report phase result.

rlPhaseEnd

Final phase result is based on included asserts and phase type.

๐Ÿงฐ rlPhaseStartSetup, rlPhaseStartTest, rlPhaseStartCleanup

Start a phase of the specified type: Setup -> WARN, Test -> FAIL, Cleanup -> WARN.

     rlPhaseStartSetup [name]
     rlPhaseStartTest [name]
     rlPhaseStartCleanup [name]
  • name โ€” an optional name for the phase. If you don't pass one, the defaults Setup/Test/Cleanup get used.

And if you're not feeling the shortcuts, bestie? Just use the plain rlPhaseStart function. It's right there. ๐Ÿซถ


๐Ÿ”„ Reboot

Okay so this one is important โ€” a controlled reboot must not be executed inside of an open phase. Otherwise it's possible the Overall result of the test will be reported incorrectly. Not the vibe. ๐Ÿ’€


๐Ÿ“Š Metric

rlLogMetricLow

Logs a metric that should be as low as possible to the journal. Think: memory consumption, run time. Lower = slay.

     rlLogMetricLow name value [tolerance]
  • name โ€” name of the metric. It has to be unique in a phase. No dupes, periodt.
  • value โ€” the value of the metric.
  • tolerance โ€” used when comparing via rcw. It means how larger the second value can be to not trigger a FAIL. Default is 0.2.

When comparing FIRST and SECOND, then:

     FIRST >= SECOND means PASS
     FIRST+FIRST*tolerance >= SECOND means WARN
     FIRST+FIRST*tolerance < SECOND means FAIL

Example: a simple benchmark is compared via this metric type in rcw. It has a tolerance of 0.2. First run had 1 second. So:

     For PASS, second run has to be better or equal to first.
             So any value of second or less is a PASS.
     For WARN, second run can be a little worse than first.
             Tolerance is 0.2, so anything lower than 1.2 means WARN.
     For FAIL, anything worse than 1.2 means FAIL.

rlLogMetricHigh

Logs a metric that should be as high as possible to the journal. Think: number of executions per second. Higher = iconic. ๐Ÿ‘‘

     rlLogMetricHigh name value [tolerance]
  • name โ€” name of the metric. It has to be unique in a phase.
  • value โ€” the value of the metric.
  • tolerance โ€” used when comparing via rcw. It means how lower the second value can be to not trigger a FAIL. Default is 0.2.

When comparing FIRST and SECOND, then:

     FIRST <= SECOND means PASS
     FIRST+FIRST*tolerance <= SECOND means WARN
     FIRST+FIRST*tolerance > SECOND means FAIL

โœ‹ Manual Asserts

rlPass

A manual assertion โ€” it asserts and logs PASS. Literally manifesting success. โœจ

     rlPass comment
  • comment โ€” short test summary.

Returns 0 and asserts PASS.

rlFail

A manual assertion โ€” it asserts and logs FAIL. Sometimes you gotta call it like you see it. ๐Ÿ˜ญ

     rlFail comment
  • comment โ€” short test summary.

Returns 1 and asserts FAIL.


๐Ÿงฎ Arithmetic Asserts

rlAssert0

Assertion checking for the equality of the parameter to zero.

     rlAssert0 comment value
  • comment โ€” short test summary, e.g. "Test if compilation ended successfully".
  • value โ€” integer value (usually the return code of a command).

Returns 0 and asserts PASS when "value == 0".

rlAssertEquals

Assertion checking for the equality of two parameters.

     rlAssertEquals comment value1 value2
  • comment โ€” short test summary, e.g. "Test if all 3 packages have been downloaded".
  • value1 โ€” first parameter to compare, can be a number or a string.
  • value2 โ€” second parameter to compare, can be a number or a string.

Returns 0 and asserts PASS when "value1 == value2".

rlAssertNotEquals

Assertion checking for the non-equality of two parameters.

     rlAssertNotEquals comment value1 value2
  • comment โ€” short test summary, e.g. "Test if return code is not 139".
  • value1 โ€” first parameter to compare, can be a number or a string.
  • value2 โ€” second parameter to compare, can be a number or a string.

Returns 0 and asserts PASS when "value1 != value2".

rlAssertGreater

Assertion checking whether the first parameter is greater than the second one.

     rlAssertGreater comment value1 value2
  • comment โ€” short test summary, e.g. "Test whether there are running more instances of program."
  • value1 โ€” integer value.
  • value2 โ€” integer value.

Returns 0 and asserts PASS when "value1 > value2".

rlAssertGreaterOrEqual

Assertion checking whether the first parameter is greater or equal to the second one.

     rlAssertGreaterOrEqual comment value1 value2
  • comment โ€” short test summary (e.g. "There should present at least one...")
  • value1 โ€” integer value.
  • value2 โ€” integer value.

Returns 0 and asserts PASS when "value1 X= value2". (yup, that's literally what the page says โ€” copying it exactly, don't come for me ๐Ÿ™ˆ)

rlAssertLesser

Assertion checking whether the first parameter is lesser than the second one.

     rlAssertLesser comment value1 value2
  • comment โ€” short test summary, e.g. "Test whether there are running more instances of program."
  • value1 โ€” integer value.
  • value2 โ€” integer value.

Returns 0 and asserts PASS when "value1 < value2".

rlAssertLesserOrEqual

Assertion checking whether the first parameter is lesser or equal to the second one.

     rlAssertLesserOrEqual comment value1 value2
  • comment โ€” short test summary (e.g. "There should present at least one...")
  • value1 โ€” integer value.
  • value2 โ€” integer value.

Returns 0 and asserts PASS when "value1 X= value2". (same energy as above, keeping it 100% verbatim ๐Ÿ’…)


๐Ÿ“ File Asserts

rlAssertExists

Assertion checking for the existence of a file or a directory.

     rlAssertExists file|directory
  • file|directory โ€” path to the file or directory.

Returns 0 and asserts PASS when "file" exists. It's giving "found it, bestie". ๐Ÿฆ‹

rlAssertNotExists

Assertion checking for the non-existence of a file or a directory.

     rlAssertNotExists file|directory
  • file|directory โ€” path to the file or directory.

Returns 0 and asserts PASS when "file" does not exist.

rlAssertGrep

Assertion checking if the file contains a pattern.

     rlAssertGrep pattern file [options]
  • pattern โ€” regular expression to be searched for.
  • file โ€” path to the file.
  • options โ€” optional parameters to be passed to grep, default is "-q". Can be used to perform case insensitive matches (-i), or using extended (-E) or perl (-P) regular expressions.

Returns 0 and asserts PASS when "file" exists and contains the given "pattern". ๐Ÿ”

rlAssertNotGrep

Assertion checking that the file does not contain a pattern.

     rlAssertNotGrep pattern file [options]
  • pattern โ€” regular expression to be searched for.
  • file โ€” path to the file.
  • options โ€” optional parameters to be passed to grep, default is "-q". Can be used to perform case insensitive matches (-i), or using extended (-E) or perl (-P) regular expressions.

Returns 0 and asserts PASS when "file" exists and does not contain the given "pattern".

rlAssertDiffer

Assertion checking that two files differ (are not identical).

     rlAssertDiffer file1 file2
  • file1 โ€” path to first file1
  • file2 โ€” path to second file

Returns 0 and asserts PASS when "file1" and "file2" differs.

rlAssertNotDiffer

Assertion checking that two files do not differ (are identical).

     rlAssertNotDiffer file1 file2
  • file1 โ€” path to first file1
  • file2 โ€” path to second file

Returns 0 and asserts PASS when "file1" and "file2" do not differ.


๐Ÿƒ Run, Watch, Report

rlRun

Runs a command with an optional comment and makes sure its exit code matches expectations. This is the main character of the whole page, ngl. ๐ŸŒŸ

     rlRun [-t] [-l] [-c] [-s] command [status[,status...] [comment]]
  • -t โ€” if specified, stdout and stderr of the command output will be tagged with the strings 'STDOUT: ' and 'STDERR: '.
  • -l โ€” if specified, output of the command (tagged, if -t was specified) is logged using the rlLog function. This is intended for short outputs, and therefore only the last 50 lines are logged this way. Longer outputs should be analysed separately, or uploaded via rlFileSubmit or rlBundleLogs.
  • -c โ€” same as "-l", but only log the command output if it failed.
  • -s โ€” store stdout and stderr to a file (mixed together, as the user would see it on a terminal) and set $rlRun_LOG variable to the name of the file. $rlRun_LOG is now actually an array where the first index holds the last reference to the file. Thus its behavior is not changed if used without an index. The array is consumed by the rlJournalEnd function to remove the leftover files, so no manual file removal is needed anymore. Note that if you need to use such a file after calling the rlJournalEnd function you need to create your own copy of the respective file. When the -t option is used, the content of the file becomes tagged too.

If the -s option is not used, $rlRun_LOG is not modified and keeps its content from the last "rlRun -s".

  • command โ€” command to run.
  • status โ€” expected exit code(s). Optional, default 0. If you expect more exit codes, separate them with a comma (e.g. "0,1" when both 0 and 1 are OK and expected), or use from-to notation (i.e. "2-5" for "2,3,4,5"), or combine them (e.g. "2-4,26" for "2,3,4,26").
  • comment โ€” short summary describing the action (optional, but recommended โ€” explain what you are doing here).

Returns the exit code of the command run. Asserts PASS when the command's exit status is in the list of expected exit codes.

Note:

  • The output of rlRun is buffered when using "-t", "-l" or "-s" option (they use unix pipes, which are buffered by nature). If you need an unbuffered output just make sure that "expect" package is installed on your system (its "unbuffer" tool will automatically be used to produce unbuffered output).
  • Be aware that there are some variables which can collide with your code executed within rlRun. You should avoid using __INTERNAL_rlRun_* variables. ๐Ÿซฃ
  • When any of "-t" "-l", "-c", or "-s" option is used, special file descriptors 111 and 112 are used to avoid the issue with incomplete log file, bz1361246. As there might be an indefinite loop, there's a timeout of two minutes implemented as a fix for bz1416796. Also an error message is issued to signal the possibility of running a subprocess which keeps the file descriptors open.

Do not use these options if you expect process forking and continuous run. Try your own appropriate solution instead.

โš ๏ธ Warning: using the "unbuffer" tool is now disabled because of bug 547686. Yeah. We don't talk about it. ๐Ÿ’€

rlWatchdog

Run "command". If it does not finish in the specified time, then kill it using "signal". Note that the command is executed in a sub-shell so modified environment (e.g. set variables) is not reflected in the test environment. Important detail, bestie โ€” don't get caught out. ๐Ÿ•โ€๐Ÿฆบ

     rlWatchdog command timeout [signal] [callback]
  • command โ€” command to run.
  • timeout โ€” timeout to wait, in seconds.
  • signal โ€” signal to use (optional, default KILL).
  • callback โ€” optional callback function called before the signal is sent. Default is none, bestie. It gets exactly one argument available: the PGID of the process group. ๐Ÿ’…

Returns 0 if the command ends normally, without needing to be killed. That's the return vibe, fr fr.


๐Ÿ’ฌ rlReport ๐Ÿ’ฌ

Report the test result to the test harness. The command used for reporting is set by the respective plugin. You can also use the $BEAKERLIB_COMMAND_REPORT_RESULT variable to use your custom command. โœจ

rlReport name result [score] [log]
  • name โ€” name of the test result.
  • result โ€” result, one of PASS, WARN, FAIL, SKIP. If called with something else, it will use WARN.
  • score โ€” test score (optional).
  • log โ€” optional log file to be submitted instead of default "OUTPUTFILE".

๐Ÿฆ‹ rlCmpVersion ๐Ÿฆ‹

Compare two given versions composed by numbers and letters divided by dot (.), underscore (_), or dash (-).

rlCmpVersion ver1 ver2
  • If ver1 = ver2, the sign '=' is printed to stdout and 0 is returned.
  • If ver1 > ver2, the sign '>' is printed to stdout and 1 is returned.
  • If ver1 < ver2, the sign '<' is printed to stdout and 2 is returned.

๐ŸŒธ rlTestVersion ๐ŸŒธ

Test the relation between two given versions based on the given operator.

rlTestVersion ver1 op ver2
  • op โ€” operator defining the logical expression. It can be '=', '==', '!=', '<', '<=', '=<', '>', '>=', or '=>'.

Returns 0 if the expression ver1 op ver2 is true; 1 if the expression is false; and 2 if something went wrong.


๐Ÿ’ฟ Release Info ๐Ÿ’ฟ

You can use the environment variable BEAKERLIB_OS_RELEASE for alternative os-release information. You can either supply a file path (recognised by starting with /) or directly as a list of environment variables. ๐Ÿซถ

Example:

BEAKERLIB_OS_RELEASE="ID=rhel VERSION_ID=42" rlIsRHEL 42

๐ŸŒˆ rlIsRHEL ๐ŸŒˆ

rlIsRHEL [VERSION_SPEC]...
  • VERSION_SPEC โ€” argument specifies the version of the particular RHEL distribution, eg. 8, 8.4, ">8.4".

For more details see description of rlIsOSVersion.

Returns 0 when we're running on RHEL. With the given version specification in arguments, returns 0 if the particular RHEL version is running.

Prototype:

rlIsRHEL

Returns 0 if we are running on RHEL.

rlIsRHEL 7 '>=8.5'

Returns 0 if we are running any RHEL 7 or RHEL 8.5 and higher.


๐ŸŽ€ rlIsFedora ๐ŸŽ€

rlIsFedora [VERSION_SPEC]...
  • VERSION_SPEC โ€” argument specifies the version of the particular Fedora distribution, eg. 30, ">30".

For more details see description of rlIsOSVersion.

Returns 0 when we're running on Fedora. With the given version specification in arguments, returns 0 if the particular Fedora version is running.

Prototype:

rlIsFedora

Returns 0 if we are running on Fedora.

rlIsFedora 30 32

Returns 0 if we are running Fedora 30 or 32.


๐Ÿงš rlIsCentOS ๐Ÿงš

rlIsCentOS [VERSION_SPEC]...
  • VERSION_SPEC โ€” argument specifies the version of the particular CentOS distribution, eg. 7, ">7".

For more details see description of rlIsOSVersion.

Returns 0 when we're running on CentOS. With the given version specification in arguments, returns 0 if the particular CentOS version is running.

Prototype:

rlIsCentOS

Returns 0 if we are running on CentOS.

rlIsCentOS 7.1 6

Returns 0 if we are running CentOS 7.1 or any CentOS 6.


โญ rlIsOS โญ

rlIsOS ID
  • ID โ€” argument is based on contents of /etc/os-release. Possible options of ID are e.g. fedora, rhel, centos, ol.

Returns 0 when we're running on a system with the respective ID. Returns 1 when the parameter does not match with ID in os-release. Returns 2 when there is no ID defined. Returns 3 when no argument is given.

Prototype:

rlIsOS rhel

Returns 0 if we are running on RHEL.


๐Ÿ“ rlIsOSLike ๐Ÿ“

rlIsOSLike ID_LIKE
  • ID_LIKE โ€” argument is based on contents of /etc/os-release. Possible options of ID_LIKE are e.g. fedora, rhel.

Returns 0 when we're running on a system with the requested ID_LIKE. Returns 1 when the parameter does not match with ID nor ID_LIKE in os-release. Returns 2 when there is no ID or ID_LIKE defined. Returns 3 when no argument is given.

Prototype:

rlIsOSLike rhel

Returns 0 if we are running on RHEL, CentOS, Rocky Linux, etc..

rlIsOSLike fedora

Returns 0 if we are running on Fedora, RHEL, CentOS, Oracle Linux, etc..


๐Ÿ‘‘ rlIsOSVersion ๐Ÿ‘‘

rlIsOsVersion VERSION_SPEC...
  • VERSION_SPEC โ€” parameter is based on VERSION_ID in /etc/os-release. It consists of either "major" or "major"."minor" referring to a particular release.

It accepts multiple arguments separated by space (8.1 8.2 8.3 9).

To specify a group of distributions, an optional operator can be passed in the argument together with the version number as one string ('>8.5'). Operator can be '<', '<=', '=<', '=', '>', '>=' matching whether the currently installed version is lesser, lesser or equal, equal, equal or greater, greater than the version number supplied as the second half of the argument.

โš ๏ธ Note that when using >/< operators you have to either put the argument in quotes or escape the operators to avoid them being interpreted as a bash redirection operator. No cap.

Returns 0 when we're running a distribution of the particular version requested by the argument.

It usually follows after rlIsOS and rlIsOSLike.

Be cautious when using together with rlIsOSLike, as different distributions may use different versioning schema.

Prototype:

rlIsOSVersion 6 7 9

Returns 0 if we are running a distribution with VERSION_ID 6, 7 or 9.

rlIsOSVersion 7.8 8

Returns 0 if we are running distribution 7.8 or any 8.

rlIsOSVersion ">=7.5" or rlIsOSVersion \>=7.5

Returns 0 if we are running distribution 7.5 or higher (both minors or majors).

Note:

rlIsOSVersion '<7.5' || rlIsOSVersion '<8.5'

would also cover 7.9 as it is less than 8.5, which is not what you want. So if you want to construct a condition for a distribution <7.5 within the major 7 or a distribution <8.5 within the major 8, you actually need to use the following construct:

rlIsOSVersion 7 && rlIsOSVersion '<7.5' || rlIsOSVersion 8 && rlIsOSVersion '<8.5'

This returns 0 when running distribution less than 7.5 and less then 8.5, but not 7.9 (nor 6.9).


๐Ÿ’œ rlIsRHELLike ๐Ÿ’œ

rlIsRHELLike [VERSION_SPEC]...
  • VERSION_SPEC โ€” argument specifies the version of the particular RHEL distribution, eg. 8, 8.4, ">8.4".

For more details see description of rlIsOSVersion.

Returns 0 when we're running on a RHEL-like distribution. These are considered to be RHEL, CentOS, Rocky Linux, etc.. With the given version specification in arguments, returns 0 if the particular version of the RHEL-like distribution is running.

Prototype:

rlIsRHELLike

Returns 0 if we are running on a RHEL-like system.

rlIsRHELLike ">=6"

Returns 0 if we are running on a RHEL-like distribution of version 6.0 or higher.


๐Ÿ“ฆ Rpm Handling ๐Ÿ“ฆ

๐Ÿ”ฅ rlCheckRpm ๐Ÿ”ฅ

Check whether a package is installed.

rlCheckRpm name [version] [release] [arch]
  • name โ€” package name like "kernel".
  • version โ€” package version like 2.6.25.6.
  • release โ€” package release like "55.fc9".
  • arch โ€” package architecture like "i386".

Returns 0 if the specified package is installed.


๐Ÿ’– rlAssertRpm ๐Ÿ’–

Assertion making sure that a package is installed.

rlAssertRpm name [version] [release] [arch]>
rlAssertRpm --all
  • name โ€” package name like "kernel".
  • version โ€” package version like 2.6.25.6.
  • release โ€” package release like "55.fc9".
  • arch โ€” package architecture like "i386".
  • --all โ€” assert all packages listed in the $PACKAGES, $REQUIRES, and $COLLECTIONS environment variables.

Returns 0 and asserts PASS if the specified package is installed.


๐Ÿฆ„ rlAssertNotRpm ๐Ÿฆ„

Assertion making sure that a package is not installed. This is just the inverse of rlAssertRpm.

rlAssertNotRpm name [version] [release] [arch]>
  • name โ€” package name like "kernel".
  • version โ€” package version like 2.6.25.6.
  • release โ€” package release like "55.fc9".
  • arch โ€” package architecture like "i386".

Returns 0 and asserts PASS if the specified package is not installed.


๐ŸŒŸ Example ๐ŸŒŸ

The function rlAssertRpm is useful especially in the prepare phase, where it causes an abort if a package is missing, while rlCheckRpm is handy when doing something like:

if ! rlCheckRpm package; then
     yum install package
     rlAssertRpm package
fi

๐Ÿซง rlAssertBinaryOrigin ๐Ÿซง

Assertion making sure that the given binary is owned by (one of) the given package(s).

rlAssertBinaryOrigin binary package [package2 [...]]
PACKAGES=... rlAssertBinaryOrigin binary
  • binary โ€” binary name like "ksh" or "/bin/ksh".
  • package โ€” list of packages like "ksh mksh". The parameter is optional. If missing, contents of the environment variable $PACKAGES are taken into account.

Returns 0 and asserts PASS if the specified binary belongs to (one of) the given package(s). Returns 1 and asserts FAIL if the specified binary does not belong to (any of) the given package(s). Returns 2 and asserts FAIL if the specified binary is not found. Returns 3 and asserts FAIL if no packages are given. Returns 100 and asserts FAIL if invoked with no parameters.


๐ŸŒบ Example ๐ŸŒบ

The function rlAssertBinaryOrigin is useful especially in the prepare phase, where it causes an abort if a binary is missing or is owned by a different package:

PACKAGES=mksh rlAssertBinaryOrigin ksh
or
rlAssertBinaryOrigin ksh mksh

Returns true if ksh is owned by the mksh package (in this case: /bin/ksh is a symlink pointing to /bin/mksh).


๐Ÿงพ rlGetMakefileRequires ๐Ÿงพ

Prints a space-separated list of requirements defined in the Makefile using the 'Requires' attribute.

Return 0 if success.


๐Ÿง rlGetYAMLdeps ๐Ÿง

Prints a space-separated list of requirements defined in metadata.yaml using the 'require' and / or 'recommend' attribute.

Full fmf ids and library references are to be ignored.

rlGetYAMLdeps DEP_TYPE [array_var_name]
  • DEP_TYPE โ€” dependency type defined as a regexp. Expected values are 'require', 'recommend', or 'require|recommend'. The matching attribute values are then processed. Defaults to 'require'.
  • array_var_name โ€” name of the variable to put the output to in a form of an array. This can hold also dependencies with a specific version. If used, the output to stdout is suppressed.

Return 0 if success.


๐Ÿงพ rlCheckRequirements

Okay so rlCheckRequirements is the vibe check for your requirements: it checks that every requirement you pass is covered either by an installed package, by a binary available in your PATHs, or by something a package provides.

rlRun "rlCheckRequirements REQ..."
  • REQ โ€” the requirement to check. It can be a package name, a provides string, or a binary name. You can even write it the same way as Require in a spec file, version spec included, e.g. "bash >= 4.4". The comparison operator can be any of the ones supported by rlTestVersion() โ€” see its manual.

Returns the number of unsatisfied requirements.

โœจ rlCheckMakefileRequires โœจ

Checks whether the required packages / binaries defined in metadata.yaml (provided by tmt) or in the testโ€™s Makefile are present.

It also checks recommended packages / binaries defined in metadata.yaml provided by tmt. Those do not participate in the return code โ€” theyโ€™re just informative. Lowkey just there for the info, fr fr.

Example:

rlRun "rlCheckMakefileRequires"

Returns 255 if requirements could not be retrieved, 0 if all requirements are satisfied, or the number of unsatisfied requirements.

๐Ÿ’– rlGetRequired & rlGetRecommended ๐Ÿ’–

These two pull a list of required or recommended packages / binaries defined in metadata.yaml provided by tmt or in a Makefile of the test.

rlGetRequired [ARRAY_VAR_NAME]
rlGetRecommended [ARRAY_VAR_NAME]
  • ARRAY_VAR_NAME โ€” if provided, the variable is populated as an array with the respective dependencies. Otherwise the dependencies are printed out to the STDOUT.

Returns 255 if requirements could not be retrieved, 0 otherwise.

๐Ÿ” rlCheckRequired, rlCheckRecommended, & rlCheckDependencies ๐Ÿ”

These check the presence of required, recommended, or both packages / binaries defined in metadata.yaml provided by tmt or in a Makefile of the test.

Example:

rlRun "rlCheckRequired"
rlRun "rlCheckRecommended"
rlRun "rlCheckDependencies"

Returns 255 if requirements could not be retrieved, 0 if all requirements are satisfied, or the number of unsatisfied requirements.

๐Ÿ‘‘ rlAssertRequired ๐Ÿ‘‘

Ensures that all required packages provided in either metadata.yaml or Makefile are installed.

rlAssertRequired

Prints out a verbose list of installed/missing packages during operation.

Returns 0 if all required packages are installed, 1 if one or more packages are missing or if no Makefile is present.


๐Ÿ”ฅ Getting RPMs ๐Ÿ”ฅ

๐Ÿ’… Download methods ๐Ÿ’…

Functions handling rpm downloading/installing can use more methods for the actual download of the rpm.

Currently there are two download methods available:

  • direct โ€” use direct download from the build system (brew).
  • yum โ€” use yumdownloader or dnf download.

The methods and their order are defined by the BEAKERLIB_RPM_DOWNLOAD_METHODS variable as a space-separated list. By default it is 'direct yum'. This can be overridden by the user. There may also be additions or changes done to the original value, e.g.:

BEAKERLIB_RPM_DOWNLOAD_METHODS='yum ${BEAKERLIB_RPM_DOWNLOAD_METHODS/yum/}'

Beakerlib is prepared for more Koji-based sources of packages while using the direct download method. By default packages are fetched from Koji, specifically from https://kojipkgs.fedoraproject.org/packages.

โœจ rlRpmInstall โœจ

Tries to install the specified package from local Red Hat sources.

rlRpmInstall [--quiet] package version release arch
  • --quiet โ€” make the download and the install process be quiet.
  • package โ€” package name like "kernel".
  • version โ€” package version like 2.6.25.6.
  • release โ€” package release like "55.fc9".
  • arch โ€” package arch like "i386".

Returns 0 if the specified package was installed successfully.

๐ŸŒ€ rlRpmDownload ๐ŸŒ€

Tries to download the specified package.

rlRpmDownload [--quiet] {package version release arch|N-V-R.A}
rlRpmDownload [--quiet] --source {package version release|N-V-R}
  • --quiet โ€” make the download process be quiet.
  • package โ€” package name like "kernel".
  • version โ€” package version like 2.6.25.6.
  • release โ€” package release like "55.fc9".
  • arch โ€” package arch like "i386".

Returns 0 if the specified package was downloaded successfully.

๐Ÿฆ‹ rlFetchSrcForInstalled ๐Ÿฆ‹

Tries various ways to download the source rpm for the specified installed rpm.

rlFetchSrcForInstalled [--quiet] package
  • --quiet โ€” make the download process be quiet.
  • package โ€” installed package name like "kernel". It accepts in-direct names. E.g. for the package name "krb5-libs" the function will download the "krb5" source rpm.

Returns 0 if the source package was successfully downloaded.


๐Ÿงš Mounting ๐Ÿงš

๐ŸŒˆ rlMount ๐ŸŒˆ

Creates the mount point (if necessary) and mounts an NFS share.

rlMount [-o MOUNT_OPTS] server share mountpoint
  • server โ€” NFS server hostname.
  • share โ€” shared directory name.
  • mountpoint โ€” local mount point.
  • MOUNT_OPTS โ€” mount options.

Returns 0 if mounting the share was successful.

๐Ÿ’œ rlCheckMount ๐Ÿ’œ

Checks if a directory is a mountpoint, if it is a mountpoint to a specific server, or if it is a mountpoint to a specific export on a specific server โ€” and whether it uses specific mount options.

rlCheckMount [-o MOUNT_OPTS] mountpoint
rlCheckMount [-o MOUNT_OPTS] server mountpoint
rlCheckMount [-o MOUNT_OPTS] server share mountpoint
  • mountpoint โ€” local mount point.
  • server โ€” NFS server hostname.
  • share โ€” shared directory name.
  • MOUNT_OPTS โ€” mount options to check (comma-separated list).

With one parameter, returns 0 when the specified directory exists and is a mountpoint. With two parameters, returns 0 when the specific directory exists, is a mountpoint, and an export from the specific server is mounted there. With three parameters, returns 0 if a specific shared directory is mounted on a given server on a given mountpoint.

If the -o option is provided, returns 0 if the mountpoint uses all the given options, 2 otherwise.

๐ŸŽ€ rlAssertMount ๐ŸŽ€

Assertion making sure that the given directory is a mount point, if it is a mountpoint to a specific server, or if it is a mountpoint to a specific export on a specific server โ€” and if it uses specific mount options.

rlAssertMount [-o MOUNT_OPTS]  mountpoint
rlAssertMount [-o MOUNT_OPTS]  server mountpoint
rlAssertMount [-o MOUNT_OPTS]  server share mountpoint
  • mountpoint โ€” local mount point.
  • server โ€” NFS server hostname.
  • share โ€” shared directory name.
  • MOUNT_OPTS โ€” mount options to check (comma-separated list).

With one parameter, returns 0 when the specified directory exists and is a mountpoint. With two parameters, returns 0 when the specific directory exists, is a mountpoint, and an export from the specific server is mounted there. With three parameters, returns 0 if a specific shared directory is mounted on a given server on a given mountpoint. Asserts PASS when the condition is true.

If the -o option is provided, asserts PASS if the above conditions are met and the mountpoint uses all the given options.

๐Ÿ“ rlHash, rlUnhash ๐Ÿ“

Hashes/Unhashes the given string and prints the result to stdout.

rlHash [--decode] [--algorithm HASH_ALG] --stdin|STRING
rlUnhash [--algorithm HASH_ALG] --stdin|STRING
  • --decode โ€” unhash the given string.
  • --algorithm โ€” use the given hash algorithm. Currently supported algorithms:
    • base64
    • base64_ โ€” this is standard base64 where = is replaced by _
    • hex

Defaults to hex. The default algorithm can be overridden using the global variable rlHashAlgorithm.

  • --stdin โ€” get the string from stdin.
  • STRING โ€” string to be hashed/unhashed.

Returns 0 if success.


๐ŸŽ€ Backup and Restore ๐ŸŽ€

๐Ÿฆ‹ rlFileBackup ๐Ÿฆ‹

Creates a backup of files or directories (recursive). Can be used multiple times to add more files to backup. Backing up an already backed up file overwrites the original backup.

rlFileBackup [--clean] [--namespace name] [--missing-ok|--no-missing-ok] file [file...]

You can use rlRun for asserting the result but keep in mind the meaning of exit codes, especially exit code 8, if using without the --clean option.

  • --clean โ€” if this option is provided (it has to be the first option of the command), then the file/dir backed up using this command (provided in the next options) will be (recursively) removed before we restore it. This option implies --missing-ok, which can be overridden by --no-missing-ok.
  • --namespace name โ€” specifies the namespace to use. Namespaces can be used to separate backups and their restoration.
  • --missing-ok โ€” do not raise an error in case of a missing file to backup.
  • --no-missing-ok โ€” do raise an error in case of a missing file to backup. This is useful with --clean. This behaviour can be globally set by the global variable BEAKERLIB_FILEBACKUP_MISSING_OK=false.
  • file โ€” files and/or directories to be backed up.

Returns 0 if the backup was successful. Returns 1 if parsing of parameters was not successful. Returns 2 if no files specification was provided. Returns 3 if the BEAKERLIB_DIR variable is not set, e.g. rlJournalStart was not executed. Returns 4 if creating the main backup destination directories was not successful. Returns 5 if creating the file-specific backup destination directories was not successful. Returns 6 if the copy of backed up files was not successful. Returns 7 if attributes of backed up files were not successfully copied. Returns 8 if backed up files do not exist. This can be suppressed based on other options.

Example with --clean:

touch cleandir/aaa
rlRun "rlFileBackup --clean cleandir/"
touch cleandir/bbb
ls cleandir/
aaa   bbb
rlRun "rlFileRestore"
ls cleandir/
aaa

๐ŸŒธ rlFileRestore ๐ŸŒธ

Restores backed up files to their original location. rlFileRestore does not remove new files appearing after the backup has been made. If you donโ€™t want to leave anything behind, just remove the whole original tree before running rlFileRestore, or see the --clean option of rlFileBackup.

rlFileRestore [--namespace name]

You can use rlRun for asserting the result.

  • --namespace name โ€” specifies the namespace to use. Namespaces can be used to separate backups and their restoration.

Returns 0 if the backup dir is found and files are restored successfully.

Return code bits meaning:

XXXXX
|||||
||||\_ error parsing parameters
|||\__ could not find backup directory
||\___ files cleanup failed
|\____ files restore failed
\_____ no files were restored nor cleaned

๐Ÿ› ๏ธ Services ๐Ÿ› ๏ธ

Okay so these routines are the comfy way to start and stop system services, and the whole point is that you can put them back exactly how they were after your testing is done. Restore-and-chill, basically. ๐Ÿ’…

rlServiceStart

Makes sure the service you named is running with fresh config โ€” like, it starts it if it's stopped and restarts it if it's already running. And here's the cute part: the first time you call it, it saves the current state, so the service can be put back to its original state when your testing wraps up. See rlServiceRestore. โœจ

rlServiceStart service [service...]
  • service โ€” name of the service(s) to start.

Returns the number of services that failed to start/restart, so zero means everything is OK. Zero = slay. ๐ŸŽ€

rlServiceStop

Makes sure the service is stopped. Stop it if it's running, do literally nothing if it's already stopped. Same vibe as above: the first call saves the current state so it can be restored later via rlServiceRestore. ๐Ÿฆ‹

rlServiceStop service [service...]
  • service โ€” name of the service(s) to stop.

Returns the number of services that failed to become stopped; zero when everything is OK. ๐Ÿ’–

rlServiceRestore

Puts the service back into its original state โ€” meaning the state it was in before the first rlServiceStart or rlServiceStop call. Fun detail: if rlServiceStart was called on a service that was already running, then rlServiceRestore will restart the service when it's restoring that state. ๐Ÿ˜ญ

rlServiceRestore [service...]
  • service โ€” name of the service(s) to restore to original state. If you pass no service name at all, all services get restored in reverse order.

Returns the number of services that failed to get back to their original state; zero when everything is OK. ๐Ÿซถ

rlServiceStatus

Prints the status of the SERVICE you gave it โ€” specifically the output of service SERVICE status or systemctl status SERVICE. ๐Ÿ‘‘

rlServiceStatus SERVICE [SERVICE...]
  • SERVICE โ€” the service to get the status of.

Returns the service status return code of the last SERVICE you provided. ๐Ÿ“‹

rlServiceEnable

Enables the selected services if they need it, or does nothing at all if they're already enabled. And yup โ€” first call saves the current state so it can be restored later, see rlServiceRestore. ๐ŸŒธ

rlServiceEnable service [service...]
  • service โ€” name of the service(s) to enable.

Returns the number of services that failed enablement; zero when everything is OK. โญ

rlServiceDisable

Disables the selected services if needed, or does nothing if they're already disabled. First call saves the current state for later restore, see rlServiceRestore. ๐Ÿงš

rlServiceDisable service [service...]
  • service โ€” name of the service(s) to disable.

Returns the number of services that failed disablement; zero when everything is OK. ๐Ÿ’œ


๐Ÿ”Œ Sockets ๐Ÿ”Œ

Same comfy deal, but for system sockets โ€” start/stop them, then put them back the way they were after testing. No cap, it's the exact same energy. โœจ

rlSocketStart

Makes sure the socket is running. Starts it if it's stopped, leaves it alone if it's already running. First call saves the current state so it can be restored later, see rlSocketRestore. ๐Ÿ’ซ

rlSocketStart socket [socket...]
  • socket โ€” name of the socket(s) to start.

Returns the number of sockets that failed to start/restart; zero when everything is OK. ๐Ÿ”ฅ

rlSocketStop

Makes sure the socket is stopped. Stops it if it's running, does nothing if it's already stopped. First call saves the current state for later restore, see rlSocketRestore. ๐ŸŽ€

rlSocketStop socket [socket...]
  • socket โ€” name of the socket(s) to stop.

Returns the number of sockets that failed to become stopped; zero when everything is OK. ๐Ÿ’–

rlSocketRestore

Restores the given socket into its original state โ€” the state it was in before the first rlSocketStart or rlSocketStop call. ๐Ÿฆ‹

Warning !!! The Xinetd process is NOT restored โ€” even though it might have been used. It's recommended to call rlServiceRestore xinetd as well. Like, actually do it, bestie. ๐Ÿ˜ญ
rlSocketRestore socket [socket...]
  • socket โ€” name of the socket(s) to restore to original state.

Returns the number of sockets that failed to get back to their original state; zero when everything is OK. ๐Ÿซถ


๐Ÿงน Cleanup management ๐Ÿงน

Okay so cleanup management works with a so-called cleanup buffer, which is a temporary representation of what should be run at cleanup time, plus a final cleanup script (executable) that gets generated from that buffer and wraps it using BeakerLib essentials (journal initialization, cleanup phase, and so on...). The cleanup script must always be updated on an atomic basis (filesystem-wise) so that a third party โ€” ie. the test watcher โ€” can execute it asynchronously. โšก

Using the test watcher is mandatory for the cleanup management system to work properly, because the test watcher is the thing that actually executes the cleanup script. There is a limited, catastrophe-avoiding mechanism in place even when the test isn't run in the test watcher, but treat that as a backup and avoid that situation whenever you possibly can. ๐Ÿ™ˆ

The cleanup script shares all environment โ€” variables, exported or not, and functions โ€” with the test itself. The cleanup append/prepend functions sample or snapshot the environment at the moment of their call, IOW any changes to the test environment are synchronized to the cleanup script only upon calling append/prepend. And when the append/prepend functions are called inside a function that has local variables, those will show up as global in the cleanup. ๐Ÿ’€

The cleanup script does receive $PWD from the test, but its working dir is set to the initial test execution dir even if $PWD contains something else. Also, you can't reliably use relative paths inside cleanup โ€” certain parts of the cleanup might have been added under different current directories (CWDs). So always use absolute paths in append/prepend cleanup, or make sure you never cd anywhere else (ie. to a TmpDir). ๐Ÿ‘‘

rlCleanupAppend

Appends a string to the cleanup buffer and recreates the cleanup script. ๐Ÿ“

rlCleanupAppend string

Returns 0 if the operation was successful, 1 otherwise. โญ

rlCleanupPrepend

Prepends a string to the cleanup buffer and recreates the cleanup script. ๐Ÿ“

rlCleanupPrepend string

Returns 0 if the operation was successful, 1 otherwise. โญ


โฑ๏ธ Time Performance โฑ๏ธ

rlPerfTime_RunsInTime

Measures how many runs of some commands can be done in a specified amount of time. This approach is suitable for short-time running tasks (up to a few seconds), where averaging a few runs isn't precise. It does the thing several times and the final result is the average of all runs. It prints the number on stdout, so you gotta capture it. ๐Ÿ”ฅ

rlPerfTime_RunsInTime command [time] [runs]
  • command โ€” command to run.
  • time โ€” time in seconds (optional, default=30).
  • runs โ€” number of averaged runs (optional, default=3).

rlPerfTime_AvgFromRuns

Measures the average time of running some task. This approach is suitable for long-time running tasks (tens of seconds and more), where it's precise enough. The measured runs can be preceded by a dry run which is not measured โ€” its whole purpose is to warm up various caches. It prints the number on stdout, so it has to be captured. Or, the result is then stored in the special rl_retval variable. ๐ŸŒˆ

rlPerfTime_AvgFromRuns command [count] [warmup]
  • command โ€” command to run.
  • count โ€” times to run (optional, default=3).
  • warmup โ€” warm-up run, run if this option is not "warmup" (optional, default="warmup").

๐Ÿ” Analyze ๐Ÿ”

rlDejaSum

TODO description ๐Ÿ˜ญ (yes bestie, the manpage literally says that, I'm not making it up)

rlDejaSum par1 par2
  • par1 โ€” TODO description
  • par2 โ€” TODO description

Return 0 if... TODO

rlImport

Imports code provided by one or more libraries into the test namespace. The library search mechanism is based on the Beaker test hierarchy system, i.e.: ๐Ÿ—‚๏ธ

/component/type/test-name/test-file

When test-file calls rlImport with 'foo/bar' as the parameter, the libraries are searched in the following locations โ€” these are the possible path prefixes: ๐Ÿ‘‡

  • colon-separated paths from $BEAKERLIB_LIBRARY_PATH
  • /mnt/tests
  • /usr/share/beakerlib-libraries

The next component of the path is one of the following: ๐Ÿ‘‡

  • /foo/Library/bar
  • /foo/bar
  • /libs/foo/bar
  • /*/foo/Library/bar
  • /*/foo/bar
  • /libs/*/foo/Library/bar
  • /libs/*/foo/bar

The directory path is then constructed as prefix/path/lib.sh. If the library is still not found, an upwards directory traversal is used, and a check for the presence of the library in the above-mentioned possible paths gets performed. Which means: this function needs to be called from the test hierarchy, not from, like, the /tmp directory. ๐Ÿ™ˆ

Once the library is found, it's sourced and a verifier function is called. The verifier function is constructed by composing the library prefix and LibraryLoaded. The library prefix must be defined in the library itself โ€” it should be part of the lib.sh header in this format: '# library-prefix = <PREFIX>'. If the verifier passes, the library is ready to use. Also, the variable <PREFIX>LibraryDir is created and it points to the library folder. ๐ŸŽ€

Usage:

rlImport --all
rlImport LIBRARY [LIBRARY2...]
  • --all โ€” read $BEAKERLIB_DIR/metadata.yaml or ./Makefile, pick up the library requirements and import them all. ๐Ÿ“ฆ
  • LIBRARY โ€” must have '[component/]path' or '.' format. Identifies the library to import. The dot (.) is a special case where the lib.sh from the current directory is used. ๐Ÿ“

Returns 0 if the import of all libraries was successful. Returns non-zero if one or more libraries failed to import. ๐Ÿ’…


๐Ÿงต Process Synchronisation ๐Ÿงต

rlWaitForCmd

Pauses script execution until the command exit status is the expected value. It logs a WARNING and returns 1 if the command didn't exit successfully before the timeout elapsed, or if a maximum number of invocations has been reached. โณ

rlWaitForCmd command [-p PID] [-t time] [-m count] [-d delay] [-r retval]
  • command โ€” command that will be executed until its return code is equal to 0 or the value specified as option to -r.
  • -t time โ€” timeout, in seconds, default 120. If the command doesn't return 0 before the clock runs out, the command gets killed. no survivors ๐Ÿ’€
  • -p PID โ€” the PID of a process that should also be running. If that process bails before the command exits with the expected exit code, the return code gets set to 1.
  • -m count โ€” max number of command executions before it just continues anyway. Default is infinite (as in, no cap, go off forever). Returns 1 if the maximum was actually reached.
  • -d delay โ€” delay between command invocations. Default 1.
  • -r retval โ€” the expected return value of the command. Default 0.

๐Ÿ’ค rlWaitForFile

Pauses script execution until the specified file or directory starts existing. Returns 0 if the file started existing, 1 if the timeout was reached or the PID exited. Return code is greater than 1 in case of error.

rlWaitForFile path [-p PID] [-t time] [-d delay]
  • path โ€” path to the file that should start existing.
  • -t time โ€” timeout in seconds (optional, default 120). If the file isn't opened before the time elapses, the command returns 1.
  • -p PID โ€” PID of the process that should also be running. If the process exits before the file is created, the command returns with status code 1.
  • -d delay โ€” delay between subsequent checks for existence of the file. Default 1.

๐Ÿ”Œ rlWaitForSocket

Pauses script execution until a local socket starts listening. Returns 0 if the socket started listening, 1 if the timeout was reached or the PID exited. Return code is greater than 1 in case of error.

rlWaitForSocket {port|path} [-p PID] [-t time] [-d delay] [--close] [--remote]
  • port|path โ€” network port to wait for opening, or a path to a UNIX socket. Regular expressions are supported too, bestie โœจ
  • -t time โ€” timeout in seconds (optional, default 120). If the socket isn't opened before the time elapses, the command returns 1.
  • -p PID โ€” PID of the process that should also be running. If the process exits before the socket is opened, the command returns with status code 1.
  • -d delay โ€” delay between subsequent checks for availability of the socket. Default 1.
  • --close โ€” wait for the socket to stop listening. flip the script ๐Ÿฆ‹
  • --remote โ€” wait for the remote socket to start listening instead of the local one.

โณ rlWait

Wrapper around the bash builtin wait command. See bash_builtins(1) man page. Kills the process and all its children if the timeout elapses.

rlWait [n ...] [-s SIGNAL] [-t time]
  • n โ€” list of PIDs to wait for. They need to be background tasks of the current shell. See the bash_builtins(1) section for the wait command.
  • -t time โ€” timeout in seconds (optional, default 30). If the wait isn't successful before the time elapses, then all specified tasks are killed.
  • -s SIGNAL โ€” signal used to kill the process, optional, SIGTERM by default.

๐Ÿ–ฅ๏ธ Virtual X Server

Functions providing a simple way how to start and stop a virtual X server. so cozy, so convenient ๐ŸŽ€

rlVirtualXStart

Start a virtual X server on the first free display. Only tries the first N displays, so yeah โ€” you can run out of them ๐Ÿ˜ญ

rlVirtualXStart name [N]
  • name โ€” string identifying the X server.
  • N โ€” maximum number of displays to try. Defaults to 3.

Returns 0 when the server is started successfully.

rlVirtualXGetDisplay

Get the DISPLAY variable for the specified virtual X server.

rlVirtualXGetDisplay name
  • name โ€” string identifying the X server.

Displays the number of the display where the specified virtual X server is running to standard output. Returns 0 on success.

rlVirtualXStop

Kill the specified X server. bye bestie ๐Ÿ’…

rlVirtualXStop name
  • name โ€” string identifying the X server.

Returns 0 when the server is stopped successfully.

๐ŸŒธ Example

Below is a simple example of usage. Note that a lot of useful debugging information is reported on the DEBUG level, so you can run your test with DEBUG=1 make run to get them.

rlVirtualXStart $TEST
rlAssert0 "Virtual X server started" $?
export DISPLAY="$( rlVirtualXGetDisplay $TEST )"
# ...your test which needs X...
rlVirtualXStop $TEST
rlAssert0 "Virtual X server killed" $?

These are Requires lines for your scripts โ€” note the different package names for different RHEL versions:

@echo "Requires: xorg-x11-server-Xvfb" >> $(METADATA) # RHEL-5
@echo "Requires: xorg-x11-Xvfb"        >> $(METADATA) # RHEL-4
@echo "Requires: XFree86-Xvfb"         >> $(METADATA) # RHEL-3

๐Ÿงš rlYash_parse

Parse yaml data to an associative array. very demure, very mindful ๐Ÿ“

rlYash_parse VAR_NAME YAML_DATA
  • VAR_NAME โ€” name of the variable to which the yaml structure will be saved. Note that the variable needs to be predeclared as an associative array. (predeclare it or it's not gonna work, iykyk)
  • YAML_DATA โ€” the actual yaml data.

๐Ÿ”ฅ Beakerlib Profiling

Enable profiling

Set the environment variable BEAKERLIB_PROFILING=1

BEAKERLIB_PROFILING=1 make run

A file /dev/shm/beakerlib_profile will be created for later processing.

Process the profile

/usr/share/beakerlib/profiling.sh process > profile.csv

๐ŸŽ€ OUTPUT FILES ๐ŸŽ€

Location of test results related output files can be configured by setting the BEAKERLIB_DIR variable before running the test. If it's not set, a temporary directory is created. set it, bestie, it's giving organized ๐Ÿ’–

๐Ÿ““ journal.txt

Journal in human readable form. iconic, readable, we love her.

๐Ÿ“„ journal.xml

Journal in XML format โ€” requires python. This dependency can be avoided if the test is run with the variable BEAKERLIB_JOURNAL set to 0, in which case journal.xml is not created.

๐Ÿฆ‹ XSLT

The XML journal can be transformed through an XSLT template. Which template is used is configurable by setting the BEAKERLIB_JOURNAL variable. The value can be either a filename โ€” in which case beakerlib will try to use $INSTALL_DIR/xslt-template/$filename (e.g.: /usr/share/beakerlib/xstl-templates/xunit.xsl) โ€” or it can be a path to a template anywhere on the system.

๐Ÿ‘‘ TestResults

Overall results of the test in a sourceable form. Each line contains a pair VAR=VALUE. All variable names have the TESTRESULT_ prefix.

List of variables:

  • TESTRESULT_STATE โ€” current state of the test run; possible values: started, incomplete and complete.
    • started is set after a Journal is opened.
    • incomplete is set after a Phase is closed.
    • complete is set after a Journal is closed.
  • TESTRESULT_RESULT_STRING โ€” result of the test in a string, e.g.: PASS, FAIL, WARN.
  • TESTRESULT_RESULT_ECODE โ€” result of the test as an integer, 0 equals to PASS.
  • TESTRESULT_PHASES_PASSED โ€” number of phases that ended with PASS.
  • TESTRESULT_PHASES_FAILED โ€” number of phases that ended with a non-PASS result.
  • TESTRESULT_PHASES_SKIPPED โ€” number of skipped phases.
  • TESTRESULT_ASSERTS_FAILED โ€” number of asserts that ended with a non-PASS result in the whole test.
  • TESTRESULT_STARTTIME โ€” time when the test started in seconds since epoch.
  • TESTRESULT_ENDTIME โ€” time when the test ended in seconds since epoch.
  • TESTRESULT_DURATION โ€” duration of the test run in seconds.
  • TESTRESULT_BEAKERLIB_DIR โ€” directory with test results files.
  • TESTRESULT_PHASES_FINGERPRINT โ€” a hash of all phases results which may serve as a reference result in a specific environment.
  • TESTRESULT_ASSERTS_FINGERPRINT โ€” a hash of all asserts results which may serve as a reference result in a specific environment.

๐ŸŒธ EXAMPLES ๐ŸŒธ

โœจ Simple

Okay bestie, here's the most minimal BeakerLib test that's still a whole entire vibe:

. /usr/share/beakerlib/beakerlib.sh

rlJournalStart
    rlPhaseStartTest
        rlAssertRpm "setup"
        rlAssertExists "/etc/passwd"
        rlAssertGrep "root" "/etc/passwd"
    rlPhaseEnd
rlJournalEnd

Like, that's it. That's the whole test. Iconic behavior honestly ๐Ÿ’…


๐ŸŽ€ Phases

Now THIS one's a little more interesting โ€” a test that sets all the recommended variables and actually uses the phases like a good little main character:

# Include the BeakerLib environment
. /usr/share/beakerlib/beakerlib.sh

# Set the full test name
TEST="/examples/beakerlib/Sanity/phases"

# Package being tested
PACKAGE="coreutils"

rlJournalStart
    # Setup phase: Prepare test directory
    rlPhaseStartSetup
        rlAssertRpm $PACKAGE
        rlRun 'TmpDir=$(mktemp -d)' 0 'Creating tmp directory' # no-reboot
        rlRun "pushd $TmpDir"
    rlPhaseEnd

    # Test phase: Testing touch, ls and rm commands
    rlPhaseStartTest
        rlRun "touch foo" 0 "Creating the foo test file"
        rlAssertExists "foo"
        rlRun "ls -l foo" 0 "Listing the foo test file"
        rlRun "rm foo" 0 "Removing the foo test file"
        rlAssertNotExists "foo"
        rlRun "ls -l foo" 2 "Listing foo should now report an error"
    rlPhaseEnd

    # Cleanup phase: Remove test directory
    rlPhaseStartCleanup
        rlRun "popd"
        rlRun "rm -r $TmpDir" 0 "Removing tmp directory"
    rlPhaseEnd
rlJournalEnd

# Print the test report
rlJournalPrintText

And the output of the rlJournalPrintText command? It would produce something similar to this (yes, all of it, we're reading the whole menu):

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::   TEST PROTOCOL
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

    Package       : coreutils
    Installed     : coreutils-8.27-19.fc27.x86_64
    beakerlib RPM : beakerlib-1.17-6.fc27.noarch
    Test started  : 2018-02-08 15:43:03 CET
    Test finished : 2018-02-08 15:43:04 CET
    Test duration : 1 seconds
    Test name     : /examples/beakerlib/Sanity/phases
    Distro        : Fedora release 27 (Twenty Seven)
    Hostname      : localhost
    Architecture  : x86_64
    CPUs          : 4 x Intel Core Processor (Skylake)
    RAM size      : 1992 MB
    HDD size      : 17.55 GB

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::   Test description
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

PURPOSE of /examples/beakerlib/Sanity/phases
Description: Testing BeakerLib phases
Author: Petr Splichal <psplicha@redhat.com>

This example shows how the phases work in the BeakerLib on a
trivial smoke test for the "touch", "ls" and "rm" commands from
the coreutils package.

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::   Setup
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

:: [ 15:43:03 ] :: [   PASS   ] :: Checking for the presence of coreutils rpm
:: [ 15:43:03 ] :: [   LOG    ] :: Package versions:
:: [ 15:43:03 ] :: [   LOG    ] ::   coreutils-8.27-19.fc27.x86_64
:: [ 15:43:03 ] :: [   PASS   ] :: Creating tmp directory (Expected 0, got 0)
:: [ 15:43:03 ] :: [   PASS   ] :: Command 'pushd /tmp/tmp.MMQf7dj9QV' (Expected 0, got 0)
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::   Duration: 1s
::   Assertions: 3 good, 0 bad
::   RESULT: PASS

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::   Test
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

:: [ 15:43:04 ] :: [   PASS   ] :: Creating the foo test file (Expected 0, got 0)
:: [ 15:43:04 ] :: [   PASS   ] :: File foo should exist
:: [ 15:43:04 ] :: [   PASS   ] :: Listing the foo test file (Expected 0, got 0)
:: [ 15:43:04 ] :: [   PASS   ] :: Removing the foo test file (Expected 0, got 0)
:: [ 15:43:04 ] :: [   PASS   ] :: File foo should not exist
:: [ 15:43:04 ] :: [   PASS   ] :: Listing foo should now report an error (Expected 2, got 2)
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::   Duration: 0s
::   Assertions: 6 good, 0 bad
::   RESULT: PASS

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::   Cleanup
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

:: [ 15:43:04 ] :: [   PASS   ] :: Command 'popd' (Expected 0, got 0)
:: [ 15:43:04 ] :: [   PASS   ] :: Removing tmp directory (Expected 0, got 0)
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::   Duration: 0s
::   Assertions: 2 good, 0 bad
::   RESULT: PASS

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::   /examples/beakerlib/Sanity/phases
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

:: [ 15:43:04 ] :: [   LOG    ] :: Phases fingerprint:  ZmU1NmJ
:: [ 15:43:04 ] :: [   LOG    ] :: Asserts fingerprint: YTBiZDE
:: [ 15:43:04 ] :: [   LOG    ] :: JOURNAL XML: /var/tmp/beakerlib-pRiJfWE/journal.xml
:: [ 15:43:04 ] :: [   LOG    ] :: JOURNAL TXT: /var/tmp/beakerlib-pRiJfWE/journal.txt
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::   Duration: 1s
::   Phases: 3 good, 0 bad
::   OVERALL RESULT: PASS
Heads up bestie: that detailed test description is read from a separate file called PURPOSE, placed in the same directory as the test itself. Don't come for me, that's just how it works ๐Ÿ’–

A lot of useful debugging info gets reported on the DEBUG level โ€” you can run your test with DEBUG=1 make run to get all of it.

Verbosity of the test logging can also be changed by setting the LOG_LEVEL variable. Possible values are "ERROR", "WARNING", "INFO" and "DEBUG". You'll see messages like the ones below ๐Ÿซถ

:: [ WARNING  ] :: rlGetArch: Update test to use rlGetPrimaryArch/rlGetSecondaryArch
:: [  DEBUG   ] :: rlGetArch: This is architecture 'x86_64'
:: [  ERROR   ] :: this function was dropped as its development is completely moved to the beaker library
:: [   INFO   ] :: if you realy on this function and you really need to have it present in core beakerlib, file a RFE, please

Setting LOG_LEVEL="DEBUG" is equivalent to DEBUG=1. Same vibe, different outfit โœจ

Set DEBUG_TO_CONSOLE_ONLY=1 in conjuction with DEBUG=1 to avoid storing debug messages in the journal. This also speeds up the execution in debug mode, since those messages are not fully processed than. (Faster test, fewer notes in the diary, yk?)


๐Ÿงš BKRDOC ๐Ÿงš

Description

Bkrdoc is a documentation generator, and it works off tests written using the BeakerLib library. This generator makes documentation from test code with and also without any documentation markup. Versatile queen ๐Ÿ‘‘

What it's good for

For fast, brief and reliable documentation creation. It`s good for a quick start with an unknown BeakerLib test. The created documentation provides information about the documentation credibility. Also, the created documentation shows environmental variables and helps the reader run the test script from which the documentation was created. Literally everything you need to not be lost ๐Ÿฆ‹

Bkrdoc project page

https://github.com/rh-lab-q/bkrdoc


Project Page

https://github.com/beakerlib/beakerlib

Manual

https://github.com/beakerlib/beakerlib/wiki/man

Issues list

https://bugzilla.redhat.com/buglist.cgi?component=beakerlib&&order=bug_status%2Cassigned_to%2Cpriority

https://github.com/beakerlib/beakerlib/issues

Reporting issues

https://bugzilla.redhat.com/enter_bug.cgi?product=Fedora%20EPEL&component=beakerlib

https://github.com/beakerlib/beakerlib/issues/new


๐Ÿ‘‘ AUTHORS ๐Ÿ‘‘

The actual legends who built this:

  • Petr Muller <pmuller@redhat.com>
  • Ondrej Hudlicky <ohudlick@redhat.com>
  • Jan Hutar <jhutar@redhat.com>
  • Petr Splichal <psplicha@redhat.com>
  • Ales Zelinka <azelinka@redhat.com>
  • Dalibor Pospisil <dapospis@redhat.com>
  • Martin Kyral <mkyral@redhat.com>
  • Jakub Prokes <jprokes@redhat.com>
  • Jakub Heger <jheger@redhat.com>

And that's a wrap on the whole page, bestie!! ๐ŸŽ€ This edition was served up by perl v5.32.1, dated 2026-04-07, and it's the BEAKERLIB(1) page โ€” go forth and write slay little tests ๐Ÿ’…โœจ

๐Ÿ“ฆ where this page comes from