Import the kyua test framework.
Having kyua in the base system will simplify automated testing in CI and eliminates bootstrapping issues on new platforms. The build of kyua is controlled by WITH(OUT)_TESTS_SUPPORT. Reviewed by: emaste Obtained from: CheriBSD Sponsored by: DARPA Differential Revision: https://reviews.freebsd.org/D24103
This commit is contained in:
commit
2af35c15f0
23
contrib/kyua/.gitignore
vendored
Normal file
23
contrib/kyua/.gitignore
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
*.a
|
||||
*.o
|
||||
*_helpers
|
||||
*_inttest
|
||||
*_test
|
||||
*~
|
||||
|
||||
.deps
|
||||
.dirstamp
|
||||
Doxyfile
|
||||
Makefile
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
api-docs
|
||||
autom4te.cache
|
||||
config.h
|
||||
config.h.in
|
||||
config.log
|
||||
config.status
|
||||
configure
|
||||
kyua
|
||||
local-kyua
|
||||
stamp-h1
|
49
contrib/kyua/.travis.yml
Normal file
49
contrib/kyua/.travis.yml
Normal file
@ -0,0 +1,49 @@
|
||||
language: cpp
|
||||
sudo: required
|
||||
|
||||
before_install:
|
||||
- ./admin/travis-install-deps.sh
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
dist: xenial
|
||||
compiler: clang
|
||||
env: ARCH=amd64 DO=distcheck AS_ROOT=no
|
||||
- os: linux
|
||||
dist: xenial
|
||||
compiler: gcc
|
||||
env: ARCH=amd64 DO=distcheck AS_ROOT=no
|
||||
- os: linux
|
||||
dist: xenial
|
||||
compiler: clang
|
||||
env: ARCH=amd64 DO=apidocs
|
||||
- os: linux
|
||||
dist: xenial
|
||||
compiler: clang
|
||||
env: ARCH=amd64 DO=style
|
||||
- os: linux
|
||||
dist: xenial
|
||||
compiler: clang
|
||||
env: ARCH=amd64 DO=distcheck AS_ROOT=yes UNPRIVILEGED_USER=no
|
||||
- os: linux
|
||||
dist: xenial
|
||||
compiler: clang
|
||||
env: ARCH=amd64 DO=distcheck AS_ROOT=yes UNPRIVILEGED_USER=yes
|
||||
# TODO(ngie): reenable i386; the libraries were not available in the
|
||||
# Ubuntu Xenial x86_64 docker image.
|
||||
#- os: linux
|
||||
# dist: xenial
|
||||
# compiler: clang
|
||||
# env: ARCH=i386 DO=distcheck AS_ROOT=no
|
||||
#- os: linux
|
||||
# dist: xenial
|
||||
# compiler: gcc
|
||||
# env: ARCH=i386 DO=distcheck AS_ROOT=no
|
||||
|
||||
script:
|
||||
- ./admin/travis-build.sh
|
||||
|
||||
notifications:
|
||||
email:
|
||||
- kyua-log@googlegroups.com
|
11
contrib/kyua/AUTHORS
Normal file
11
contrib/kyua/AUTHORS
Normal file
@ -0,0 +1,11 @@
|
||||
# This is the official list of Kyua authors for copyright purposes.
|
||||
#
|
||||
# This file is distinct from the CONTRIBUTORS files; see the latter for
|
||||
# an explanation.
|
||||
#
|
||||
# Names are sorted alphabetically and should be added to this file as:
|
||||
#
|
||||
# * Name <email address>
|
||||
# * Organization <optional email address>
|
||||
|
||||
* Google Inc.
|
173
contrib/kyua/CONTRIBUTING.md
Normal file
173
contrib/kyua/CONTRIBUTING.md
Normal file
@ -0,0 +1,173 @@
|
||||
Contributing code to Kyua
|
||||
=========================
|
||||
|
||||
Want to contribute? Great! But first, please take a few minutes to read this
|
||||
document in full. Doing so upfront will minimize the turnaround time required
|
||||
to get your changes incorporated.
|
||||
|
||||
|
||||
Legal notes
|
||||
-----------
|
||||
|
||||
* Before we can use your code, you must sign the
|
||||
[Google Individual Contributor License
|
||||
Agreement](https://developers.google.com/open-source/cla/individual),
|
||||
also known as the CLA, which you can easily do online. The CLA is necessary
|
||||
mainly because you own the copyright to your changes, even after your
|
||||
contribution becomes part of our codebase, so we need your permission to use
|
||||
and distribute your code. We also need to be sure of various other
|
||||
things--for instance that you will tell us if you know that your code
|
||||
infringes on other people's patents. You do not have to sign the CLA until
|
||||
after you have submitted your code for review and a member has approved it,
|
||||
but you must do it before we can put your code into our codebase.
|
||||
|
||||
* Contributions made by corporations are covered by a different agreement than
|
||||
the one above: the
|
||||
[Google Software Grant and Corporate Contributor License
|
||||
Agreement](https://developers.google.com/open-source/cla/corporate).
|
||||
Please get your company to sign this agreement instead if your contribution is
|
||||
on their behalf.
|
||||
|
||||
* Unless you have a strong reason not to, please assign copyright of your
|
||||
changes to Google Inc. and use the 3-clause BSD license text included
|
||||
throughout the codebase (see [LICENSE](LICENSE)). Keeping the whole project
|
||||
owned by a single entity is important, particularly to avoid the problem of
|
||||
having to replicate potentially hundreds of different copyright notes in
|
||||
documentation materials, etc.
|
||||
|
||||
|
||||
Communication
|
||||
-------------
|
||||
|
||||
* Before you start working on a larger contribution, you should get in touch
|
||||
with us first through the
|
||||
[kyua-discuss mailing
|
||||
list](https://groups.google.com/forum/#!forum/kyua-discuss)
|
||||
with your idea so that we can help out and possibly guide you. Coordinating
|
||||
upfront makes it much easier to avoid frustration later on.
|
||||
|
||||
* Subscribe to the
|
||||
[kyua-log mailing list](https://groups.google.com/forum/#!forum/kyua-log) to
|
||||
get notifications on new commits, Travis CI results, or changes to bugs.
|
||||
|
||||
|
||||
Git workflow
|
||||
------------
|
||||
|
||||
* Always work on a non-master branch.
|
||||
|
||||
* Make sure the history of your branch is clean. (Ab)use `git rebase -i master`
|
||||
to ensure the sequence of commits you want pulled is easy to follow and that
|
||||
every commit does one (and only one) thing. In particular, commits of the
|
||||
form `Fix previous` or `Fix build` should never ever exist; merge those fixes
|
||||
into the relevant commits so that the history is clean at pull time.
|
||||
|
||||
* Always trigger Travis CI builds for your changes (hence why working on a
|
||||
branch is important). Push your branch to GitHub so that Travis CI picks it
|
||||
up and performs a build. If you have forked the repository, you may need to
|
||||
enable Travis CI builds on your end. Wait for a green result.
|
||||
|
||||
* It is OK and expected for you to `git push --force` on **non-master**
|
||||
branches. This is required if you need to go through the commit/test cycle
|
||||
more than once for any given branch after you have "fixed-up" commits to
|
||||
correct problems spotted in earlier builds.
|
||||
|
||||
* Do not send pull requests that subsume other/older pull requests. Each major
|
||||
change being submitted belongs in a different pull request, which is trivial
|
||||
to achieve if you use one branch per change as requested in this workflow.
|
||||
|
||||
|
||||
Code reviews
|
||||
------------
|
||||
|
||||
* All changes will be subject to code reviews pre-merge time. In other words:
|
||||
all pull requests will be carefully inspected before being accepted and they
|
||||
will be returned to you with comments if there are issues to be fixed.
|
||||
|
||||
* Be careful of stylistic errors in your code (see below for style guidelines).
|
||||
Style violations hinder the review process and distract from the actual code.
|
||||
By keeping your code clean of style issues upfront, you will speed up the
|
||||
review process and avoid frustration along the way.
|
||||
|
||||
* Whenever you are ready to submit a pull request, review the *combined diff*
|
||||
you are requesting to be pulled and look for issues. This is the diff that
|
||||
will be subject to review, not necessarily the individual commits. You can
|
||||
view this diff in GitHub at the bottom of the `Open a pull request` form that
|
||||
appears when you click the button to file a pull request, or you can see the
|
||||
diff by typing `git diff <your-branch> master`.
|
||||
|
||||
|
||||
Commit messages
|
||||
---------------
|
||||
|
||||
* Follow standard Git commit message guidelines. The first line has a maximum
|
||||
length of 50 characters, does not terminate in a period, and has to summarize
|
||||
the whole commit. Then a blank line comes, and then multiple plain-text
|
||||
paragraphs provide details on the commit if necessary with a maximum length of
|
||||
72-75 characters per line. Vim has syntax highlighting for Git commit
|
||||
messages and will let you know when you go above the maximum line lengths.
|
||||
|
||||
* Use the imperative tense. Say `Add foo-bar` or `Fix baz` instead of `Adding
|
||||
blah`, `Adds bleh`, or `Added bloh`.
|
||||
|
||||
|
||||
Handling bug tracker issues
|
||||
---------------------------
|
||||
|
||||
* All changes pushed to `master` should cross-reference one or more issues in
|
||||
the bug tracker. This is particularly important for bug fixes, but also
|
||||
applies to major feature improvements.
|
||||
|
||||
* Unless you have a good reason to do otherwise, name your branch `issue-N`
|
||||
where `N` is the number of the issue being fixed.
|
||||
|
||||
* If the fix to the issue can be done *in a single commit*, terminate the commit
|
||||
message with `Fixes #N.` where `N` is the number of the issue being fixed and
|
||||
include a note in `NEWS` about the issue in the same commit. Such fixes can
|
||||
be merged onto master using fast-forward (the default behavior of `git
|
||||
merge`).
|
||||
|
||||
* If the fix to the issue requires *more than one commit*, do **not** include
|
||||
`Fixes #N.` in any of the individual commit messages of the branch nor include
|
||||
any changes to the `NEWS` file in those commits. These "announcement" changes
|
||||
belong in the merge commit onto `master`, which is done by `git merge --no-ff
|
||||
--no-commit your-branch`, followed by an edit of `NEWS`, and terminated with a
|
||||
`git commit -a` with the proper note on the bug being fixed.
|
||||
|
||||
|
||||
Style guide
|
||||
-----------
|
||||
|
||||
These notes are generic and certainly *non-exhaustive*:
|
||||
|
||||
* Respect formatting of existing files. Note where braces are placed, number of
|
||||
blank lines between code chunks, how continuation lines are indented, how
|
||||
docstrings are typed, etc.
|
||||
|
||||
* Indentation is *always* done using spaces, not tabs. The only exception is in
|
||||
`Makefile`s, where any continuation line within a target must be prefixed by a
|
||||
*single tab*.
|
||||
|
||||
* [Be mindful of spelling and
|
||||
grammar.](http://julipedia.meroh.net/2013/06/readability-mind-your-typos-and-grammar.html)
|
||||
Mistakes of this kind are enough of a reason to return a pull request.
|
||||
|
||||
* Use proper punctuation for all sentences. Always start with a capital letter
|
||||
and terminate with a period.
|
||||
|
||||
* Respect lexicographical sorting wherever possible.
|
||||
|
||||
* Lines must not be over 80 characters.
|
||||
|
||||
* No trailing whitespace.
|
||||
|
||||
* Two spaces after end-of-sentence periods.
|
||||
|
||||
* Two blank lines between functions. If there are two blank lines among code
|
||||
blocks, they usually exist for a reason: keep them.
|
||||
|
||||
* In C++ code, prefix all C identifiers (those coming from `extern "C"`
|
||||
includes) with `::`.
|
||||
|
||||
* Getter functions/methods only need to be documented via `\return`. A
|
||||
redundant summary is not necessary.
|
20
contrib/kyua/CONTRIBUTORS
Normal file
20
contrib/kyua/CONTRIBUTORS
Normal file
@ -0,0 +1,20 @@
|
||||
# This is the list of people who have agreed to one of the CLAs and can
|
||||
# contribute patches to the Kyua project.
|
||||
#
|
||||
# The AUTHORS file lists the copyright holders; this file lists people.
|
||||
# For example: Google employees are listed here but not in AUTHORS
|
||||
# because Google holds the copyright.
|
||||
#
|
||||
# See the following links for details on the CLA:
|
||||
#
|
||||
# https://developers.google.com/open-source/cla/individual
|
||||
# https://developers.google.com/open-source/cla/corporate
|
||||
#
|
||||
# Names are sorted by last name and should be added as:
|
||||
#
|
||||
# * Name <email address>
|
||||
|
||||
* Sergey Bronnikov <sergeyb@openvz.org>
|
||||
* Enji Cooper <yaneurabeya@gmail.com>
|
||||
* Julio Merino <jmmv@google.com>
|
||||
* Craig Rodrigues <rodrigc@crodrigues.org>
|
59
contrib/kyua/Doxyfile.in
Normal file
59
contrib/kyua/Doxyfile.in
Normal file
@ -0,0 +1,59 @@
|
||||
# Copyright 2010 The Kyua Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
BUILTIN_STL_SUPPORT = YES
|
||||
ENABLE_PREPROCESSING = YES
|
||||
EXCLUDE_SYMBOLS = "ATF_TC*"
|
||||
EXTRACT_ANON_NSPACES = YES
|
||||
EXTRACT_LOCAL_CLASSES = YES
|
||||
EXTRACT_PRIVATE = YES
|
||||
EXTRACT_STATIC = YES
|
||||
EXPAND_ONLY_PREDEF = YES
|
||||
EXTENSION_MAPPING = ipp = C++
|
||||
FILE_PATTERNS = *.c *.h *.cpp *.hpp *.ipp
|
||||
GENERATE_LATEX = NO
|
||||
GENERATE_TAGFILE = @top_builddir@/api-docs/api-docs.tag
|
||||
HIDE_FRIEND_COMPOUNDS = YES
|
||||
INPUT = @top_srcdir@
|
||||
INPUT_ENCODING = ISO-8859-1
|
||||
JAVADOC_AUTOBRIEF = YES
|
||||
MACRO_EXPANSION = YES
|
||||
OUTPUT_DIRECTORY = @top_builddir@/api-docs
|
||||
OUTPUT_LANGUAGE = English
|
||||
PREDEFINED += "KYUA_DEFS_NORETURN="
|
||||
PREDEFINED += "KYUA_DEFS_FORMAT_PRINTF(x, y)="
|
||||
PROJECT_NAME = "@PACKAGE_NAME@"
|
||||
PROJECT_NUMBER = @VERSION@
|
||||
QUIET = YES
|
||||
RECURSIVE = YES
|
||||
SORT_BY_SCOPE_NAME = YES
|
||||
SORT_MEMBERS_CTORS_1ST = YES
|
||||
WARN_IF_DOC_ERROR = YES
|
||||
WARN_IF_UNDOCUMENTED = YES
|
||||
WARN_NO_PARAMDOC = YES
|
||||
WARNINGS = YES
|
268
contrib/kyua/INSTALL.md
Normal file
268
contrib/kyua/INSTALL.md
Normal file
@ -0,0 +1,268 @@
|
||||
Installation instructions
|
||||
=========================
|
||||
|
||||
Kyua uses the GNU Automake, GNU Autoconf and GNU Libtool utilities as
|
||||
its build system. These are used only when compiling the application
|
||||
from the source code package. If you want to install Kyua from a binary
|
||||
package, you do not need to read this document.
|
||||
|
||||
For the impatient:
|
||||
|
||||
$ ./configure
|
||||
$ make
|
||||
$ make check
|
||||
Gain root privileges
|
||||
# make install
|
||||
Drop root privileges
|
||||
$ make installcheck
|
||||
|
||||
Or alternatively, install as a regular user into your home directory:
|
||||
|
||||
$ ./configure --prefix ~/local
|
||||
$ make
|
||||
$ make check
|
||||
$ make install
|
||||
$ make installcheck
|
||||
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
To build and use Kyua successfully you need:
|
||||
|
||||
* A standards-compliant C and C++ complier.
|
||||
* Lutok 0.4.
|
||||
* pkg-config.
|
||||
* SQLite 3.6.22.
|
||||
|
||||
To build the Kyua tests, you optionally need:
|
||||
|
||||
* The Automated Testing Framework (ATF), version 0.15 or greater. This
|
||||
is required if you want to create a distribution file.
|
||||
|
||||
If you are building Kyua from the code on the repository, you will also
|
||||
need the following tools:
|
||||
|
||||
* GNU Autoconf.
|
||||
* GNU Automake.
|
||||
* GNU Libtool.
|
||||
|
||||
|
||||
Regenerating the build system
|
||||
-----------------------------
|
||||
|
||||
This is not necessary if you are building from a formal release
|
||||
distribution file.
|
||||
|
||||
On the other hand, if you are building Kyua from code extracted from the
|
||||
repository, you must first regenerate the files used by the build
|
||||
system. You will also need to do this if you modify `configure.ac`,
|
||||
`Makefile.am` or any of the other build system files. To do this, simply
|
||||
run:
|
||||
|
||||
$ autoreconf -i -s
|
||||
|
||||
If ATF is installed in a different prefix than Autoconf, you will also
|
||||
need to tell autoreconf where the ATF M4 macros are located. Otherwise,
|
||||
the configure script will be incomplete and will show confusing syntax
|
||||
errors mentioning, for example, `ATF_CHECK_SH`. To fix this, you have
|
||||
to run autoreconf in the following manner, replacing `<atf-prefix>` with
|
||||
the appropriate path:
|
||||
|
||||
$ autoreconf -i -s -I <atf-prefix>/share/aclocal
|
||||
|
||||
|
||||
General build procedure
|
||||
-----------------------
|
||||
|
||||
To build and install the source package, you must follow these steps:
|
||||
|
||||
1. Configure the sources to adapt to your operating system. This is
|
||||
done using the `configure` script located on the sources' top
|
||||
directory, and it is usually invoked without arguments unless you
|
||||
want to change the installation prefix. More details on this
|
||||
procedure are given on a later section.
|
||||
|
||||
2. Build the sources to generate the binaries and scripts. Simply run
|
||||
`make` on the sources' top directory after configuring them. No
|
||||
problems should arise.
|
||||
|
||||
3. Check that the built programs work by running `make check`. You do
|
||||
not need to be root to do this, but if you are not, some checks will
|
||||
be skipped.
|
||||
|
||||
4. Install the program by running `make install`. You may need to
|
||||
become root to issue this step.
|
||||
|
||||
5. Issue any manual installation steps that may be required. These are
|
||||
described later in their own section.
|
||||
|
||||
6. Check that the installed programs work by running `make
|
||||
installcheck`. You do not need to be root to do this, but if you are
|
||||
not, some checks will be skipped.
|
||||
|
||||
|
||||
Configuration flags
|
||||
-------------------
|
||||
|
||||
The most common, standard flags given to `configure` are:
|
||||
|
||||
* `--prefix=directory`:
|
||||
**Possible values:** Any path.
|
||||
**Default:** `/usr/local`.
|
||||
|
||||
Specifies where the program (binaries and all associated files) will
|
||||
be installed.
|
||||
|
||||
* `--sysconfdir=directory`:
|
||||
**Possible values:** Any path.
|
||||
**Default:** `/usr/local/etc`.
|
||||
|
||||
Specifies where the installed programs will look for configuration
|
||||
files. `/kyua` will be appended to the given path unless
|
||||
`KYUA_CONFSUBDIR` is redefined as explained later on.
|
||||
|
||||
* `--help`:
|
||||
|
||||
Shows information about all available flags and exits immediately,
|
||||
without running any configuration tasks.
|
||||
|
||||
The following environment variables are specific to Kyua's `configure`
|
||||
script:
|
||||
|
||||
* `GDB`:
|
||||
**Possible values:** empty, absolute path to GNU GDB.
|
||||
**Default:** empty.
|
||||
|
||||
Specifies the path to the GNU GDB binary that Kyua will use to gather a
|
||||
stack trace of a crashing test program. If empty, the configure script
|
||||
will try to find a suitable binary for you and, if not found, Kyua will
|
||||
attempt to do the search at run time.
|
||||
|
||||
* `KYUA_ARCHITECTURE`:
|
||||
**Possible values:** name of a CPU architecture (e.g. `x86_64`, `powerpc`).
|
||||
**Default:** autodetected; typically the output of `uname -p`.
|
||||
|
||||
Specifies the name of the CPU architecture on which Kyua will run.
|
||||
This value is used at run-time to determine tests that are not
|
||||
applicable to the host system.
|
||||
|
||||
* `KYUA_CONFSUBDIR`:
|
||||
**Possible values:** empty, a relative path.
|
||||
**Default:** `kyua`.
|
||||
|
||||
Specifies the subdirectory of the configuration directory (given by
|
||||
the `--sysconfdir` argument) under which Kyua will search for its
|
||||
configuration files.
|
||||
|
||||
* `KYUA_CONFIG_FILE_FOR_CHECK`:
|
||||
**Possible values:** none, an absolute path to an existing file.
|
||||
**Default:** none.
|
||||
|
||||
Specifies the `kyua.conf` configuration file to use when running any
|
||||
of the `check`, `installcheck` or `distcheck` targets on this source
|
||||
tree. This setting is exclusively used to customize the test runs of
|
||||
Kyua itself and has no effect whatsoever on the built product.
|
||||
|
||||
* `KYUA_MACHINE`:
|
||||
**Possible values:** name of a machine type (e.g. `amd64`, `macppc`).
|
||||
**Default:** autodetected; typically the output of `uname -m`.
|
||||
|
||||
Specifies the name of the machine type on which Kyua will run. This
|
||||
value is used at run-time to determine tests that are not applicable
|
||||
to the host system.
|
||||
|
||||
* `KYUA_TMPDIR`:
|
||||
**Possible values:** an absolute path to a temporary directory.
|
||||
**Default:** `/tmp`.
|
||||
|
||||
Specifies the path that Kyua will use to create temporary directories
|
||||
in by default.
|
||||
|
||||
The following flags are specific to Kyua's `configure` script:
|
||||
|
||||
* `--enable-developer`:
|
||||
**Possible values:** `yes`, `no`.
|
||||
**Default:** `yes` in Git `HEAD` builds; `no` in formal releases.
|
||||
|
||||
Enables several features useful for development, such as the inclusion
|
||||
of debugging symbols in all objects or the enforcement of compilation
|
||||
warnings.
|
||||
|
||||
The compiler will be executed with an exhaustive collection of warning
|
||||
detection features regardless of the value of this flag. However, such
|
||||
warnings are only fatal when `--enable-developer` is `yes`.
|
||||
|
||||
* `--with-atf`:
|
||||
**Possible values:** `yes`, `no`, `auto`.
|
||||
**Default:** `auto`.
|
||||
|
||||
Enables usage of ATF to build (and later install) the tests.
|
||||
|
||||
Setting this to `yes` causes the configure script to look for ATF
|
||||
unconditionally and abort if not found. Setting this to `auto` lets
|
||||
configure perform the best decision based on availability of ATF.
|
||||
Setting this to `no` explicitly disables ATF usage.
|
||||
|
||||
When support for tests is enabled, the build process will generate the
|
||||
test programs and will later install them into the tests tree.
|
||||
Running `make check` or `make installcheck` from within the source
|
||||
directory will cause these tests to be run with Kyua.
|
||||
|
||||
* `--with-doxygen`:
|
||||
**Possible values:** `yes`, `no`, `auto` or a path.
|
||||
**Default:** `auto`.
|
||||
|
||||
Enables usage of Doxygen to generate documentation for internal APIs.
|
||||
This documentation is *not* installed and is only provided to help the
|
||||
developer of this package. Therefore, enabling or disabling Doxygen
|
||||
causes absolutely no differences on the files installed by this
|
||||
package.
|
||||
|
||||
Setting this to `yes` causes the configure script to look for Doxygen
|
||||
unconditionally and abort if not found. Setting this to `auto` lets
|
||||
configure perform the best decision based on availability of Doxygen.
|
||||
Setting this to `no` explicitly disables Doxygen usage. And, lastly,
|
||||
setting this to a path forces configure to use a specific Doxygen
|
||||
binary, which must exist.
|
||||
|
||||
|
||||
Post-installation steps
|
||||
-----------------------
|
||||
|
||||
Copy the `Kyuafile.top` file installed in the examples directory to the
|
||||
root of your tests hierarchy and name it `Kyuafile`. For example:
|
||||
|
||||
# cp /usr/local/share/kyua/examples/Kyuafile.top \
|
||||
/usr/local/tests/Kyuafile
|
||||
|
||||
This will allow you to simply go into `/usr/tests` and run the tests
|
||||
from there.
|
||||
|
||||
|
||||
Run the tests!
|
||||
--------------
|
||||
|
||||
Lastly, after a successful installation, you should periodically run the
|
||||
tests from the final location to ensure things remain stable. Do so as
|
||||
follows:
|
||||
|
||||
$ cd /usr/local/kyua && kyua test
|
||||
|
||||
The following configuration variables are specific to the 'kyua' test
|
||||
suite and can be given to Kyua with arguments of the form
|
||||
`-v test_suites.kyua.<variable_name>=<value>`:
|
||||
|
||||
* `run_coredump_tests`:
|
||||
**Possible values:** `true` or `false`.
|
||||
**Default:** `true`.
|
||||
|
||||
Avoids running tests that crash subprocesses on purpose to make them
|
||||
dump core. Such tests are particularly slow on macOS, and it is
|
||||
sometimes handy to disable them for quicker development iteration.
|
||||
|
||||
If you see any tests fail, do not hesitate to report them in:
|
||||
|
||||
https://github.com/jmmv/kyua/issues/
|
||||
|
||||
Thank you!
|
18
contrib/kyua/Kyuafile
Normal file
18
contrib/kyua/Kyuafile
Normal file
@ -0,0 +1,18 @@
|
||||
syntax(2)
|
||||
|
||||
test_suite("kyua")
|
||||
|
||||
include("bootstrap/Kyuafile")
|
||||
include("cli/Kyuafile")
|
||||
if fs.exists("doc/Kyuafile") then
|
||||
-- The tests for the docs are not installed because they only cover the
|
||||
-- build-time process of the manual pages.
|
||||
include("doc/Kyuafile")
|
||||
end
|
||||
include("drivers/Kyuafile")
|
||||
include("engine/Kyuafile")
|
||||
include("examples/Kyuafile")
|
||||
include("integration/Kyuafile")
|
||||
include("model/Kyuafile")
|
||||
include("store/Kyuafile")
|
||||
include("utils/Kyuafile")
|
27
contrib/kyua/LICENSE
Normal file
27
contrib/kyua/LICENSE
Normal file
@ -0,0 +1,27 @@
|
||||
Copyright 2010-2015 The Kyua Authors.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of Google Inc. nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
186
contrib/kyua/Makefile.am
Normal file
186
contrib/kyua/Makefile.am
Normal file
@ -0,0 +1,186 @@
|
||||
# Copyright 2010 The Kyua Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
CHECK_BOOTSTRAP_DEPS =
|
||||
CHECK_KYUA_DEPS =
|
||||
CHECK_LOCAL =
|
||||
CLEAN_TARGETS =
|
||||
DIST_HOOKS =
|
||||
PHONY_TARGETS =
|
||||
CLEANFILES =
|
||||
|
||||
EXTRA_DIST =
|
||||
noinst_DATA =
|
||||
noinst_LIBRARIES =
|
||||
noinst_SCRIPTS =
|
||||
|
||||
doc_DATA = AUTHORS CONTRIBUTING.md CONTRIBUTORS LICENSE NEWS.md
|
||||
noinst_DATA += INSTALL.md README.md
|
||||
EXTRA_DIST += $(doc_DATA) INSTALL.md README.md
|
||||
|
||||
if WITH_ATF
|
||||
tests_topdir = $(pkgtestsdir)
|
||||
|
||||
tests_top_DATA = Kyuafile
|
||||
EXTRA_DIST += $(tests_top_DATA)
|
||||
endif
|
||||
|
||||
include admin/Makefile.am.inc
|
||||
include bootstrap/Makefile.am.inc
|
||||
include cli/Makefile.am.inc
|
||||
include doc/Makefile.am.inc
|
||||
include drivers/Makefile.am.inc
|
||||
include engine/Makefile.am.inc
|
||||
include examples/Makefile.am.inc
|
||||
include integration/Makefile.am.inc
|
||||
include misc/Makefile.am.inc
|
||||
include model/Makefile.am.inc
|
||||
include store/Makefile.am.inc
|
||||
include utils/Makefile.am.inc
|
||||
|
||||
bin_PROGRAMS = kyua
|
||||
kyua_SOURCES = main.cpp
|
||||
kyua_CXXFLAGS = $(CLI_CFLAGS) $(ENGINE_CFLAGS) $(UTILS_CFLAGS)
|
||||
kyua_LDADD = $(CLI_LIBS) $(ENGINE_LIBS) $(UTILS_LIBS)
|
||||
|
||||
CHECK_ENVIRONMENT = KYUA_CONFDIR="/non-existent" \
|
||||
KYUA_DOCDIR="$(abs_top_srcdir)" \
|
||||
KYUA_EXAMPLESDIR="$(abs_top_srcdir)/examples" \
|
||||
KYUA_MISCDIR="$(abs_top_srcdir)/misc" \
|
||||
KYUA_STOREDIR="$(abs_top_srcdir)/store" \
|
||||
KYUA_STORETESTDATADIR="$(abs_top_srcdir)/store" \
|
||||
PATH="$(abs_top_builddir):$${PATH}"
|
||||
INSTALLCHECK_ENVIRONMENT = KYUA_CONFDIR="/non-existent" \
|
||||
PATH="$(prefix)/bin:$${PATH}"
|
||||
|
||||
# Generate local-kyua, a wrapper shell script to run the just-built 'kyua'
|
||||
# binary by pointing it to the possibly not-yet-installed data files in the
|
||||
# build tree.
|
||||
noinst_SCRIPTS += local-kyua
|
||||
CLEANFILES += local-kyua local-kyua.tmp
|
||||
local-kyua: Makefile
|
||||
$(AM_V_GEN)echo '#!/bin/sh' >local-kyua.tmp; \
|
||||
echo 'env $(CHECK_ENVIRONMENT) $(TESTS_ENVIRONMENT)' \
|
||||
'"$(abs_top_builddir)/kyua" \
|
||||
--config='$(KYUA_CONFIG_FILE_FOR_CHECK)' \
|
||||
"$${@}"' >>local-kyua.tmp; \
|
||||
chmod +x local-kyua.tmp; \
|
||||
mv -f local-kyua.tmp local-kyua
|
||||
|
||||
if WITH_ATF
|
||||
CHECK_LOCAL += dump-ulimits check-kyua
|
||||
PHONY_TARGETS += check-kyua
|
||||
check-kyua: $(CHECK_KYUA_DEPS)
|
||||
@failed=no; \
|
||||
./local-kyua test \
|
||||
--kyuafile='$(top_srcdir)/Kyuafile' --build-root='$(top_builddir)' \
|
||||
|| failed=yes; \
|
||||
if [ "$${failed}" = yes ]; then \
|
||||
./local-kyua report --results-file='$(abs_top_srcdir)' \
|
||||
--verbose --results-filter=broken,failed; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
installcheck-local: dump-ulimits installcheck-kyua
|
||||
PHONY_TARGETS += installcheck-kyua
|
||||
installcheck-kyua:
|
||||
@failed=no; \
|
||||
cd $(pkgtestsdir) && $(INSTALLCHECK_ENVIRONMENT) $(TESTS_ENVIRONMENT) \
|
||||
kyua --config='$(KYUA_CONFIG_FILE_FOR_CHECK)' test \
|
||||
|| failed=yes; \
|
||||
if [ "$${failed}" = yes ]; then \
|
||||
cd $(pkgtestsdir) && $(INSTALLCHECK_ENVIRONMENT) \
|
||||
$(TESTS_ENVIRONMENT) \
|
||||
kyua --config='$(KYUA_CONFIG_FILE_FOR_CHECK)' report \
|
||||
--verbose --results-filter=broken,failed; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
# TODO(jmmv): kyua should probably be recording this information itself as part
|
||||
# of the execution context, just as we record environment variables.
|
||||
PHONY_TARGETS += dump-ulimits
|
||||
dump-ulimits:
|
||||
@echo "Resource limits:"
|
||||
@{ \
|
||||
ulimit -a | sed -e 's,$$, (soft),'; \
|
||||
ulimit -a -H | sed -e 's,$$, (hard),'; \
|
||||
} | sort | sed -e 's,^, ,'
|
||||
@echo
|
||||
else
|
||||
DIST_HOOKS += forbid-dist
|
||||
PHONY_TARGETS += forbid-dist
|
||||
forbid-dist:
|
||||
@echo "Sorry; cannot make dist without atf."
|
||||
@false
|
||||
endif
|
||||
check-local: $(CHECK_LOCAL)
|
||||
|
||||
if WITH_DOXYGEN
|
||||
# Runs doxygen on the source tree and validates the contents of the docstrings.
|
||||
# We do not do this by default, even if doxygen has been enabled, because this
|
||||
# step takes a long time. Instead, we just rely on a Travis CI build to catch
|
||||
# inconsistencies.
|
||||
PHONY_TARGETS += check-api-docs
|
||||
check-api-docs: api-docs/api-docs.tag
|
||||
@$(AWK) -f $(srcdir)/admin/check-api-docs.awk api-docs/doxygen.out
|
||||
|
||||
api-docs/api-docs.tag: $(builddir)/Doxyfile $(SOURCES)
|
||||
@$(MKDIR_P) api-docs
|
||||
@rm -f api-docs/doxygen.out api-docs/doxygen.out.tmp
|
||||
$(AM_V_GEN)$(DOXYGEN) $(builddir)/Doxyfile \
|
||||
>api-docs/doxygen.out.tmp 2>&1 && \
|
||||
mv api-docs/doxygen.out.tmp api-docs/doxygen.out
|
||||
|
||||
CLEAN_TARGETS += clean-api-docs
|
||||
clean-api-docs:
|
||||
rm -rf api-docs
|
||||
endif
|
||||
|
||||
# Replace Automake's builtin check-news functionality so that we can validate
|
||||
# the NEWS.md file instead of NEWS.
|
||||
DIST_HOOKS += check-news
|
||||
PHONY_TARGETS += check-news
|
||||
check-news:
|
||||
@case "$$(sed 15q "$(srcdir)/NEWS.md")" in \
|
||||
*"$(VERSION)"*) : ;; \
|
||||
*) \
|
||||
echo "NEWS.md not updated; not releasing" 1>&2; \
|
||||
exit 1 \
|
||||
;; \
|
||||
esac
|
||||
|
||||
clean-local: $(CLEAN_TARGETS)
|
||||
dist-hook: $(DIST_HOOKS)
|
||||
|
||||
PHONY_TARGETS += clean-all
|
||||
clean-all:
|
||||
GIT="$(GIT)" $(SH) $(srcdir)/admin/clean-all.sh
|
||||
|
||||
.PHONY: $(PHONY_TARGETS)
|
622
contrib/kyua/NEWS.md
Normal file
622
contrib/kyua/NEWS.md
Normal file
@ -0,0 +1,622 @@
|
||||
Major changes between releases
|
||||
==============================
|
||||
|
||||
|
||||
Changes in version 0.14
|
||||
-----------------------
|
||||
|
||||
**NOT RELEASED YET; STILL UNDER DEVELOPMENT.**
|
||||
|
||||
* Explicitly require C++11 language features when compiling Kyua.
|
||||
|
||||
|
||||
Changes in version 0.13
|
||||
-----------------------
|
||||
|
||||
**Released on August 26th, 2016.**
|
||||
|
||||
* Fixed execution of test cases as an unprivileged user, at least under
|
||||
NetBSD 7.0. Kyua-level failures were probably a regression introduced
|
||||
in Kyua 0.12, but the underlying may have existed for much longer:
|
||||
test cases might have previously failed for mysterious reasons when
|
||||
running under an unprivileged user.
|
||||
|
||||
* Issue #134: Fixed metadata test broken on 32-bit platforms.
|
||||
|
||||
* Issue #139: Added per-test case start/end timestamps to all reports.
|
||||
|
||||
* Issue #156: Fixed crashes due to the invalid handling of cleanup
|
||||
routine data and triggered by the reuse of PIDs in long-running Kyua
|
||||
instances.
|
||||
|
||||
* Issue #159: Fixed TAP parser to ignore case while matching `TODO` and
|
||||
`SKIP` directives, and to also recognize `Skipped`.
|
||||
|
||||
* Fixed potential crash due to a race condition in the unprogramming of
|
||||
timers to control test deadlines.
|
||||
|
||||
|
||||
Changes in version 0.12
|
||||
-----------------------
|
||||
|
||||
**Released on November 22nd, 2015.**
|
||||
|
||||
This is a huge release and marks a major milestone for Kyua as it finally
|
||||
implements a long-standing feature request: the ability to execute test
|
||||
cases in parallel. This is a big deal because test cases are rarely
|
||||
CPU-bound: running them in parallel yields much faster execution times for
|
||||
large test suites, allowing faster iteration of changes during development.
|
||||
|
||||
As an example: the FreeBSD test suite as of this date contains 3285 test
|
||||
cases. With sequential execution, a full test suite run takes around 12
|
||||
minutes to complete, whereas on a 4-core machine with a high level of
|
||||
parallelism it takes a little over 1 minute.
|
||||
|
||||
Implementing parallel execution required rewriting most of Kyua's core and
|
||||
partly explains explains why there has not been a new release for over a
|
||||
year. The current implementation is purely subprocess-based, which works
|
||||
but has some limitations and has resulted in a core that is really complex
|
||||
and difficult to understand. Future versions will investigate the use of
|
||||
threads instead for a simplified programming model and additional
|
||||
parallelization possibilities.
|
||||
|
||||
* Issue #2: Implemented support to execute test cases in parallel when
|
||||
invoking `kyua test`. Parallel execution is *only* enabled when the new
|
||||
`parallelism` configuration variable is set to a value greater than `1`.
|
||||
The default behavior is still to run tests sequentially because some test
|
||||
suites contain test cases with side-effects that might fail when run in
|
||||
parallel. To resolve this, the new metadata property `is_exclusive` can
|
||||
be set to `true` on a test basis to indicate that the test must be run on
|
||||
its own.
|
||||
|
||||
* Known regression: Running `kyua debug` on a TAP-based test program does
|
||||
not currently report the output in real time. The output will only be
|
||||
displayed once the test program completes. This is a shortcoming of
|
||||
the new parallel execution engine and will be resolved.
|
||||
|
||||
* Removed the external C-based testers code in favor of the new built-in
|
||||
implementations. The new approach feels significantly faster than the
|
||||
previous one.
|
||||
|
||||
* Fixed the handling of relative paths in the `fs.*` functions available
|
||||
in `Kyuafile`s. All paths are now resolved relative to the location of
|
||||
the caller `Kyuafile`. `Kyuafile.top` has been updated with these
|
||||
changes and you should update custom copies of this file with the new
|
||||
version.
|
||||
|
||||
* Changed temporary directory creation to always grant search
|
||||
permissions on temporary directories. This is to prevent potential
|
||||
problems when running Kyua as root and executing test cases that require
|
||||
dropping privileges (as they may later be unable to use absolute paths
|
||||
that point inside their work directory).
|
||||
|
||||
* The cleanup of work directories does not longer attempt to deal with
|
||||
mount points. If a test case mounts a file system and forgets to unmount
|
||||
it, the mount point will be left behind. It is now the responsibility of
|
||||
the test case to clean after itself. The reasons for this change are
|
||||
simplicity and clarity: there are many more things that a test case can
|
||||
do that have side-effects on the system and Kyua cannot protect against
|
||||
them all, so it is better to just have the test undo anything it might
|
||||
have done.
|
||||
|
||||
* Improved `kyua report --verbose` to properly handle environment
|
||||
variables with continuation lines in them, and fixed the integration
|
||||
tests for this command to avoid false negatives.
|
||||
|
||||
* Changed the configuration file format to accept the definition of
|
||||
unknown variables without declaring them local. The syntax version
|
||||
number remains at 2. This is to allow configuration files for newer Kyua
|
||||
versions to work on older Kyua versions, as there is no reason to forbid
|
||||
this.
|
||||
|
||||
* Fixed stacktrace gathering with FreeBSD's ancient version of GDB.
|
||||
GDB 6.1.1 (circa 2004) does not have the `-ex` flag so we need to
|
||||
generate a temporary GDB script and feed it to GDB with `-x` instead.
|
||||
|
||||
* Issue #136: Fixed the XML escaping in the JUnit output so that
|
||||
non-printable characters are properly handled when they appear in the
|
||||
process's stdout or stderr.
|
||||
|
||||
* Issue #141: Improved reporting of errors triggered by sqlite3. In
|
||||
particular, all error messages are now tagged with their corresponding
|
||||
database filename and, if they are API-level errors, the name of the
|
||||
sqlite3 function that caused them.
|
||||
|
||||
* Issue #144: Improved documentation on the support for custom properties
|
||||
in the test metadata.
|
||||
|
||||
* Converted the `INSTALL`, `NEWS`, and `README` distribution documents to
|
||||
Markdown for better formatting online.
|
||||
|
||||
|
||||
Changes in version 0.11
|
||||
-----------------------
|
||||
|
||||
**Released on October 23rd, 2014.**
|
||||
|
||||
* Added support to print the details of all test cases (metadata and
|
||||
their output) to `report`. This is via a new `--verbose` flag which
|
||||
replaces the previous `--show-context`.
|
||||
|
||||
* Added support to specify the amount of physical disk space required
|
||||
by a test case. This is in the form of a new `required_disk_space`
|
||||
metadata property, which can also be provided by ATF test cases as
|
||||
`require.diskspace`.
|
||||
|
||||
* Assimilated the contents of all the `kyua-*-tester(1)` and
|
||||
`kyua-*-interface(7)` manual pages into more relevant places. In
|
||||
particular, added more details on test program registration and their
|
||||
metadata to `kyuafile(5)`, and added `kyua-test-isolation(7)`
|
||||
describing the isolation features of the test execution.
|
||||
|
||||
* Assimilated the contents of all auxiliary manual pages, including
|
||||
`kyua-build-root(7)`, `kyua-results-files(7)`, `kyua-test-filters(7)`
|
||||
and `kyua-test-isolation(7)`, into the relevant command-specific
|
||||
manual pages. This is for easier discoverability of relevant
|
||||
information when reading how specific Kyua commands work.
|
||||
|
||||
* Issue #30: Plumbed through support to query configuration variables
|
||||
from ATF's test case heads. This resolves the confusing situation
|
||||
where test cases could only do this from their body and cleanup
|
||||
routines.
|
||||
|
||||
* Issue #49: Extended `report` to support test case filters as
|
||||
command-line arguments. Combined with `--verbose`, this allows
|
||||
inspecting the details of a test case failure after execution.
|
||||
|
||||
* Issue #55: Deprecated support for specifying `test_suite` overrides on
|
||||
a test program basis. This idiom should not be used but support for
|
||||
it remains in place.
|
||||
|
||||
* Issue #72: Added caching support to the `getcwd(3)` test in configure
|
||||
so that the result can be overriden for cross-compilation purposes.
|
||||
|
||||
* Issue #83: Changed manual page headings to include a `kyua` prefix in
|
||||
their name. This prevents some possible confusion when displaying,
|
||||
for example, the `kyua-test` manual page with a plain name of `test`.
|
||||
|
||||
* Issue #84: Started passing test-suite configuration variables to plain
|
||||
and TAP test programs via the environment. The name of the
|
||||
environment variables set this way is prefixed by `TEST_ENV_`, so a
|
||||
configuration variable of the form
|
||||
`test_suites.some_name.allow_unsafe_ops=yes` in `kyua.conf` becomes
|
||||
`TEST_ENV_allow_unsafe_ops=YES` in the environment.
|
||||
|
||||
* Issues #97 and #116: Fixed the build on Illumos.
|
||||
|
||||
* Issue #102: Set `TMPDIR` to the test case's work directory when running
|
||||
the test case. If the test case happens to use the `mktemp(3)` family
|
||||
of functions (due to misunderstandings on how Kyua works or due to
|
||||
the reuse of legacy test code), we don't want it to easily escape the
|
||||
automanaged work directory.
|
||||
|
||||
* Issue #103: Started being more liberal in the parsing of TAP test
|
||||
results by treating the number in `ok` and `not ok` lines as optional.
|
||||
|
||||
* Issue #105: Started using tmpfs instead of md as a temporary file
|
||||
system for tests in FreeBSD so that we do not leak `md(4)` devices.
|
||||
|
||||
* Issue #109: Changed the privilege dropping code to start properly
|
||||
dropping group privileges when `unprivileged_user` is set. Also fixes
|
||||
`testers/run_test:fork_wait__unprivileged_group`.
|
||||
|
||||
* Issue #110: Changed `help` to display version information and clarified
|
||||
the purpose of the `about` command in its documentation.
|
||||
|
||||
* Issue #111: Fixed crash when defining a test program in a `Kyuafile`
|
||||
that has not yet specified the test suite name.
|
||||
|
||||
* Issue #114: Improved the `kyuafile(5)` manual page by clarifying the
|
||||
restrictions of the `include()` directive and by adding abundant
|
||||
examples.
|
||||
|
||||
|
||||
Changes in version 0.10
|
||||
-----------------------
|
||||
|
||||
**Experimental version released on August 14th, 2014.**
|
||||
|
||||
* Merged `kyua-cli` and `kyua-testers` into a single `kyua` package.
|
||||
|
||||
* Dropped the `kyua-atf-compat` package.
|
||||
|
||||
* Issue #100: Do not try to drop privileges to `unprivileged_user` when we
|
||||
are already running as an unprivileged user. Doing so is not possible
|
||||
and thus causes spurious test failures when the current user is not
|
||||
root and the current user and `unprivileged_user` do not match.
|
||||
|
||||
* Issue #79: Mention `kyua.conf(5)` in the *See also* section of `kyua(1)`.
|
||||
|
||||
* Issue #75: Change the `rewrite__expected_signal__bad_arg` test in
|
||||
`testers/atf_result_test` to use a different signal value. This is to
|
||||
prevent triggering a core dump that made the test fail in some platforms.
|
||||
|
||||
|
||||
Changes in kyua-cli version 0.9
|
||||
-------------------------------
|
||||
|
||||
**Experimental version released on August 8th, 2014.**
|
||||
|
||||
Major changes:
|
||||
|
||||
The internal architecture of Kyua to record the results of test suite
|
||||
runs has completely changed in this release. Kyua no longer stores all
|
||||
the different test suite run results as different "actions" within the
|
||||
single `store.db` database. Instead, Kyua now generates a separate
|
||||
results file inside `~/.kyua/store/` for every test suite run.
|
||||
|
||||
Due to the complexity involved in the migration process and the little
|
||||
need for it, this is probably going to be the only release where the
|
||||
`db-migrate` command is able to convert an old `store.db` file to the
|
||||
new scheme.
|
||||
|
||||
Changes in more detail:
|
||||
|
||||
* Added the `report-junit` command to generate JUnit XML result files.
|
||||
The output has been verified to work within Jenkins.
|
||||
|
||||
* Switched to results files specific to their corresponding test suite
|
||||
run. The unified `store.db` file is now gone: `kyua test` creates a
|
||||
new results file for every invocation under `~/.kyua/store/` and the
|
||||
`kyua report*` commands are able to locate the latest file for a
|
||||
corresponding test suite automatically.
|
||||
|
||||
* The `db-migrate` command takes an old `store.db` file and generates
|
||||
one results file for every previously-recorded action, later deleting
|
||||
the `store.db` file.
|
||||
|
||||
* The `--action` flag has been removed from all commands that accepted
|
||||
it. This has been superseded by the tests results files.
|
||||
|
||||
* The `--store` flag that many commands took has been renamed to
|
||||
`--results-file` in line with the semantical changes.
|
||||
|
||||
* The `db-exec` command no longer creates an empty database when none
|
||||
is found. This command is now intended to run only over existing
|
||||
files.
|
||||
|
||||
|
||||
Changes in kyua-testers version 0.3
|
||||
-----------------------------------
|
||||
|
||||
**Experimental version released on August 8th, 2014.**
|
||||
|
||||
* Made the testers set a "sanitized" value for the `HOME` environment
|
||||
variable where, for example, consecutive and trailing slashes have
|
||||
been cleared. Mac OS X has a tendency to append a trailing slash to
|
||||
the value of `TMPDIR`, which can cause third-party tests to fail if
|
||||
they compare `${HOME}` with `$(pwd)`.
|
||||
|
||||
* Issues #85, #86, #90 and #92: Made the TAP parser more complete: mark
|
||||
test cases reported as `TODO` or `SKIP` as passed; handle skip plans;
|
||||
ignore lines that look like `ok` and `not ok` but aren't results; and
|
||||
handle test programs that report a pass but exit with a non-zero code.
|
||||
|
||||
|
||||
Changes in kyua-cli version 0.8
|
||||
-------------------------------
|
||||
|
||||
**Experimental version released on December 7th, 2013.**
|
||||
|
||||
* Added support for Lutok 0.4.
|
||||
|
||||
* Issue #24: Plug the bootstrap tests back into the test suite. Fixes
|
||||
in `kyua-testers` 0.2 to isolate test cases into their own sessions
|
||||
should allow these to run fine.
|
||||
|
||||
* Issue #74: Changed the `kyuafile(5)` parser to automatically discover
|
||||
existing tester interfaces. The various `*_test_program()` functions
|
||||
will now exist (or not) based on tester availability, which simplifies
|
||||
the addition of new testers or the selective installation of them.
|
||||
|
||||
|
||||
Changes in kyua-testers version 0.2
|
||||
-----------------------------------
|
||||
|
||||
**Experimental version released on December 7th, 2013.**
|
||||
|
||||
* Issue #74: Added the `kyua-tap-tester`, a new backend to interact with
|
||||
test programs that comply with the Test Anything Protocol.
|
||||
|
||||
* Issue #69: Cope with the lack of `AM_PROG_AR` in `configure.ac`, which
|
||||
first appeared in Automake 1.11.2. Fixes a problem in Ubuntu 10.04
|
||||
LTS, which appears stuck in 1.11.1.
|
||||
|
||||
* Issue #24: Improve test case isolation by confining the tests to their
|
||||
own session instead of just to their own process group.
|
||||
|
||||
|
||||
Changes in kyua-cli version 0.7
|
||||
-------------------------------
|
||||
|
||||
**Experimental version released on October 18th, 2013.**
|
||||
|
||||
* Made failures from testers more resilent. If a tester fails, the
|
||||
corresponding test case will be marked as broken instead of causing
|
||||
kyua to exit.
|
||||
|
||||
* Added the `--results-filter` option to the `report-html` command and
|
||||
set its default value to skip passed results from HTML reports. This
|
||||
is to keep these reports more succint and to avoid generating tons of
|
||||
detail files that will be, in general, useless.
|
||||
|
||||
* Switched to use Lutok 0.3 to gain compatibility with Lua 5.2.
|
||||
|
||||
* Issue #69: Cope with the lack of `AM_PROG_AR` in `configure.ac`, which
|
||||
first appeared in Automake 1.11.2. Fixes a problem in Ubuntu 10.04
|
||||
LTS, which appears stuck in 1.11.1.
|
||||
|
||||
|
||||
Changes in kyua-cli version 0.6
|
||||
-------------------------------
|
||||
|
||||
**Experimental version released on February 22nd, 2013.**
|
||||
|
||||
* Issue #36: Changed `kyua help` to not fail when the configuration file
|
||||
is bogus. Help should always work.
|
||||
|
||||
* Issue #37: Simplified the `syntax()` calls in configuration and
|
||||
`Kyuafile` files to only specify the requested version instead of also
|
||||
the format name. The format name is implied by the file being loaded, so
|
||||
there is no use in the caller having to specify it. The version number
|
||||
of these file formats has been bumped to 2.
|
||||
|
||||
* Issue #39: Added per-test-case metadata values to the HTML reports.
|
||||
|
||||
* Issue #40: Rewrote the documentation as manual pages and removed the
|
||||
previous GNU Info document.
|
||||
|
||||
* Issue #47: Started using the independent testers in the `kyua-testers`
|
||||
package to run the test cases. Kyua does not implement the logic to
|
||||
invoke test cases any more, which provides for better modularity,
|
||||
extensibility and robustness.
|
||||
|
||||
* Issue #57: Added support to specify arbitrary metadata properties for
|
||||
test programs right from the `Kyuafile`. This is to make plain test
|
||||
programs more versatile, by allowing them to specify any of the
|
||||
requirements (allowed architectures, required files, etc.) supported
|
||||
by Kyua.
|
||||
|
||||
* Reduced automatic screen line wrapping of messages to the `help`
|
||||
command and the output of tables by `db-exec`. Wrapping any other
|
||||
messages (specially anything going to stderr) was very annoying
|
||||
because it prevented natural copy/pasting of text.
|
||||
|
||||
* Increased the granularity of the error codes returned by `kyua(1)` to
|
||||
denote different error conditions. This avoids the overload of `1` to
|
||||
indicate both "expected" errors from specific subcommands and
|
||||
unexpected errors caused by the internals of the code. The manual now
|
||||
correctly explain how the exit codes behave on a command basis.
|
||||
|
||||
* Optimized the database schema to make report generation almost
|
||||
instantaneous.
|
||||
|
||||
* Bumped the database schema to 2. The database now records the
|
||||
metadata of both test programs and test cases generically, without
|
||||
knowledge of their interface.
|
||||
|
||||
* Added the `db-migrate` command to provide a mechanism to upgrade a
|
||||
database with an old schema to the current schema.
|
||||
|
||||
* Removed the GDB build-time configuration variable. This is now part
|
||||
of the `kyua-testers` package.
|
||||
|
||||
* Issue #31: Rewrote the `Kyuafile` parsing code in C++, which results in
|
||||
a much simpler implementation. As a side-effect, this gets rid of the
|
||||
external Lua files required by `kyua`, which in turn make the tool
|
||||
self-contained.
|
||||
|
||||
* Added caching of various configure test results (particularly in those
|
||||
tests that need to execute a test program) so that cross-compilers can
|
||||
predefine the results of the tests without having to run the
|
||||
executables.
|
||||
|
||||
|
||||
Changes in kyua-testers version 0.1
|
||||
-----------------------------------
|
||||
|
||||
**Experimental version released on February 19th, 2013.**
|
||||
|
||||
This is the first public release of the `kyua-testers` package.
|
||||
|
||||
The goal of this first release is to adopt all the test case execution
|
||||
code of `kyua-cli` 0.5 and ship it as a collection of independent tester
|
||||
binaries. The `kyua-cli` package will rely on these binaries to run the
|
||||
tests, which provides better modularity and simplicity to the
|
||||
architecture of Kyua.
|
||||
|
||||
The code in this package is all C as opposed to the current C++ codebase
|
||||
of `kyua-cli`, which means that the overall build times of Kyua are now
|
||||
reduced.
|
||||
|
||||
|
||||
Changes in kyua-cli version 0.5
|
||||
-------------------------------
|
||||
|
||||
**Experimental version released on July 10th, 2012.**
|
||||
|
||||
* Issue #15: Added automatic stacktrace gathering of crashing test cases.
|
||||
This relies on GDB and is a best-effort operation.
|
||||
|
||||
* Issue #32: Added the `--build-root` option to the debug, list and test
|
||||
commands. This allows executing test programs from a different
|
||||
directory than where the `Kyuafile` scripts live. See the *Build roots*
|
||||
section in the manual for more details.
|
||||
|
||||
* Issue #33: Removed the `kyuaify.sh` script. This has been renamed to
|
||||
atf2kyua and moved to the `kyua-atf-compat` module, where it ships as a
|
||||
first-class utility (with a manual page and tests).
|
||||
|
||||
* Issue #34: Changed the HTML reports to include the stdout and stderr of
|
||||
every test case.
|
||||
|
||||
* Fixed the build when using a "build directory" and a clean source tree
|
||||
from the repository.
|
||||
|
||||
|
||||
Changes in kyua-cli version 0.4
|
||||
-------------------------------
|
||||
|
||||
**Experimental version released on June 6th, 2012.**
|
||||
|
||||
* Added the `report-html` command to generate HTML reports of the
|
||||
execution of any recorded action.
|
||||
|
||||
* Changed the `--output` flag of the `report` command to only take a
|
||||
path to the target file, not its format. Different formats are better
|
||||
supported by implementing different subcommands, as the options they
|
||||
may receive will vary from format to format.
|
||||
|
||||
* Added a `--with-atf` flag to the configure script to control whether
|
||||
the ATF tests get built or not. May be useful for packaging systems
|
||||
that do not have ATF in them yet. Disabling ATF also cuts down the
|
||||
build time of Kyua significantly, but with the obvious drawbacks.
|
||||
|
||||
* Grouped `kyua` subcommands by topic both in the output of `help` and
|
||||
in the documentation. In general, the user needs to be aware of
|
||||
commands that rely on a current project and those commands that rely
|
||||
purely on the database to generate reports.
|
||||
|
||||
* Made `help` print the descriptions of options and commands properly
|
||||
tabulated.
|
||||
|
||||
* Changed most informational messages to automatically wrap on screen
|
||||
boundaries.
|
||||
|
||||
* Rewrote the configuration file parsing module for extensibility. This
|
||||
will allow future versions of Kyua to provide additional user-facing
|
||||
options in the configuration file.
|
||||
|
||||
No syntax changes have been made, so existing configuration files
|
||||
(version 1) will continue to be parsed without problems. There is one
|
||||
little exception though: all variables under the top-level
|
||||
`test_suites` tree must be declared as strings.
|
||||
|
||||
Similarly, the `-v` and `--variable` flags to the command line must
|
||||
now carry a `test_suites.` prefix when referencing any variables under
|
||||
such tree.
|
||||
|
||||
|
||||
Changes in kyua-cli version 0.3
|
||||
-------------------------------
|
||||
|
||||
**Experimental version released on February 24th, 2012.**
|
||||
|
||||
* Made the `test` command record the results of the executed test
|
||||
cases into a SQLite database. As a side effect, `test` now supports a
|
||||
`--store` option to indicate where the database lives.
|
||||
|
||||
* Added the `report` command to generate plain-text reports of the
|
||||
test results stored in the database. The interface of this command is
|
||||
certainly subject to change at this point.
|
||||
|
||||
* Added the `db-exec` command to directly interact with the store
|
||||
database.
|
||||
|
||||
* Issue #28: Added support for the `require.memory` test case property
|
||||
introduced in ATF 0.15.
|
||||
|
||||
* Renamed the user-specific configuration file from `~/.kyuarc` to
|
||||
`~/.kyua/kyua.conf` for consistency with other files stored in the
|
||||
`~/.kyua/` subdirectory.
|
||||
|
||||
* Switched to use Lutok instead of our own wrappers over the Lua C
|
||||
library. Lutok is just what used to be our own utils::lua module, but
|
||||
is now distributed separately.
|
||||
|
||||
* Removed the `Atffile`s from the source tree. Kyua is stable enough
|
||||
to generate trustworthy reports, and we do not want to give the
|
||||
impression that atf-run / atf-report are still supported.
|
||||
|
||||
* Enabled logging to stderr for our own test programs. This makes it
|
||||
slightly easier to debug problems in our own code when we get a
|
||||
failing test.
|
||||
|
||||
|
||||
Changes in kyua-cli version 0.2
|
||||
-------------------------------
|
||||
|
||||
**Experimental version released on August 24th, 2011.**
|
||||
|
||||
The biggest change in this release is the ability for Kyua to run test
|
||||
programs implemented using different frameworks. What this means is
|
||||
that, now, a Kyua test suite can include not only ATF-based test
|
||||
programs, but also "legacy" (aka plain) test programs that do not use
|
||||
any framework. I.e. if you have tests that are simple programs that
|
||||
exit with 0 on success and 1 on failure, you can plug them in into a
|
||||
Kyua test suite.
|
||||
|
||||
Other than this, there have been several user-visible changes. The most
|
||||
important are the addition of the new `config` and `debug` subcommands
|
||||
to the `kyua` binary. The former can be used to inspect the runtime
|
||||
configuration of Kyua after parsing, and the latter is useful to
|
||||
interact with failing tests cases in order to get more data about the
|
||||
failure itself.
|
||||
|
||||
Without further ado, here comes the itemized list of changes:
|
||||
|
||||
* Generalized the run-time engine to support executing test programs
|
||||
that implement different interfaces. Test programs that use the ATF
|
||||
libraries are just a special case of this. (Issue #18.)
|
||||
|
||||
* Added support to the engine to run `plain` test programs: i.e. test
|
||||
programs that do not use any framework and report their pass/fail
|
||||
status as an exit code. This is to simplify the integration of legacy
|
||||
test programs into a test suite, and also to demonstrate that the
|
||||
run-time engine is generic enough to support different test
|
||||
interfaces. (Issue #18.)
|
||||
|
||||
* Added the `debug` subcommand. This command allows end users to tweak
|
||||
the execution of a specific test case and to poke into the behavior of
|
||||
its execution. At the moment, all this command allows is to view the
|
||||
stdout and stderr of the command in real time (which the `test`
|
||||
command currently completely hides).
|
||||
|
||||
* Added the `config` subcommand. This command allows the end user to
|
||||
inspect the current configuration variables after evaluation, without
|
||||
having to read through configuration files. (Issue #11.)
|
||||
|
||||
* Removed the `test_suites_var` function from configuration files. This
|
||||
was used to set the value of test-suite-sepecific variables, but it
|
||||
was ugly-looking. It is now possible to use the more natural syntax
|
||||
`test_suites.<test-suite-name>.<variable> = <value>`. (Issue #11.)
|
||||
|
||||
* Added a mechanism to disable the loading of configuration files
|
||||
altogether. Needed for testing purposes and for scriptability.
|
||||
Available by passing the `--config=none` flag.
|
||||
|
||||
* Enabled detection of unused parameters and variables in the code and
|
||||
fixed all warnings. (Issue #23.)
|
||||
|
||||
* Changed the behavior of "developer mode". Compiler warnings are now
|
||||
enabled unconditionally regardless of whether we are in developer mode
|
||||
or not; developer mode is now only used to perform strict warning
|
||||
checks and to enable assertions. Additionally, developer mode is now
|
||||
only automatically enabled when building from the repository, not for
|
||||
formal releases. (Issue #22.)
|
||||
|
||||
* Fixed many build and portability problems to Debian sid with GCC 4.6.3
|
||||
and Ubuntu 10.04.1 LTS. (Issues #20, #21, #26.)
|
||||
|
||||
|
||||
Changes in kyua-cli version 0.1
|
||||
-------------------------------
|
||||
|
||||
**Experimental version released on June 23rd, 2011.**
|
||||
|
||||
This is the first public release of the `kyua-cli` package.
|
||||
|
||||
The scope of this release is to provide functional replacement for the
|
||||
`atf-run` utility included in the atf package. At this point, `kyua`
|
||||
can reliably run the NetBSD 5.99.53 test suite delivering the same
|
||||
results as `atf-run`.
|
||||
|
||||
The reporting facilities of this release are quite limited. There is
|
||||
no replacement for `atf-report` yet, and there is no easy way of
|
||||
debugging failing test programs other than running them by hand. These
|
||||
features will mark future milestones and therefore be part of other
|
||||
releases.
|
||||
|
||||
Be aware that this release has suffered very limited field testing.
|
||||
The test suite for `kyua-cli` is quite comprehensive, but some bugs may
|
||||
be left in any place.
|
84
contrib/kyua/README.md
Normal file
84
contrib/kyua/README.md
Normal file
@ -0,0 +1,84 @@
|
||||
Welcome to the Kyua project!
|
||||
============================
|
||||
|
||||
Kyua is a **testing framework** for infrastructure software, originally
|
||||
designed to equip BSD-based operating systems with a test suite. This
|
||||
means that Kyua is lightweight and simple, and that Kyua integrates well
|
||||
with various build systems and continuous integration frameworks.
|
||||
|
||||
Kyua features an **expressive test suite definition language**, a **safe
|
||||
runtime engine** for test suites and a **powerful report generation
|
||||
engine**.
|
||||
|
||||
Kyua is for **both developers *and* users**, from the developer applying a
|
||||
simple fix to a library to the system administrator deploying a new release
|
||||
on a production machine.
|
||||
|
||||
Kyua is **able to execute test programs written with a plethora of testing
|
||||
libraries and languages**. The library of choice is
|
||||
[ATF](https://github.com/jmmv/atf/), for which Kyua was originally
|
||||
designed, but simple, framework-less test programs and TAP-compliant test
|
||||
programs can also be executed through Kyua.
|
||||
|
||||
Kyua is licensed under a **[liberal BSD 3-clause license](LICENSE)**.
|
||||
This is not an official Google product.
|
||||
|
||||
[Read more about Kyua in the About wiki page.](../../wiki/About)
|
||||
|
||||
|
||||
Download
|
||||
--------
|
||||
|
||||
The latest version of Kyua is 0.13 and was released on August 26th, 2016.
|
||||
|
||||
Download: [kyua-0.13](../../releases/tag/kyua-0.13).
|
||||
|
||||
See the [release notes](NEWS.md) for information about the changes in this
|
||||
and all previous releases.
|
||||
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
You are encouraged to install binary packages for your operating system
|
||||
wherever available:
|
||||
|
||||
* Fedora 20 and above: install the `kyua-cli` package with `yum install
|
||||
kyua-cli`.
|
||||
|
||||
* FreeBSD 10.0 and above: install the `kyua` package with `pkg install kyua`.
|
||||
|
||||
* NetBSD with pkgsrc: install the `pkgsrc/devel/kyua` package.
|
||||
|
||||
* OpenBSD with packages: install the `kyua` package with `pkg_add kyua`.
|
||||
|
||||
* OS X (with Homebrew): install the `kyua` package with `brew install kyua`.
|
||||
|
||||
Should you want to build and install Kyua from the source tree provided
|
||||
here, follow the instructions in the
|
||||
[INSTALL.md file](INSTALL.md).
|
||||
|
||||
You should also install the ATF libraries to assist in the development of
|
||||
test programs. To that end, see the
|
||||
[ATF project page](https://github.com/jmmv/atf/).
|
||||
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
||||
Want to contribute? Great! But please first read the guidelines provided
|
||||
in [CONTRIBUTING.md](CONTRIBUTING.md).
|
||||
|
||||
If you are curious about who made this project possible, you can check out
|
||||
the [list of copyright holders](AUTHORS) and the [list of
|
||||
individuals](CONTRIBUTORS).
|
||||
|
||||
|
||||
Support
|
||||
-------
|
||||
|
||||
Please use the [kyua-discuss mailing
|
||||
list](https://groups.google.com/forum/#!forum/kyua-discuss) for any support
|
||||
inquiries.
|
||||
|
||||
*Homepage:* https://github.com/jmmv/kyua/
|
6
contrib/kyua/admin/.gitignore
vendored
Normal file
6
contrib/kyua/admin/.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
ar-lib
|
||||
compile
|
||||
depcomp
|
||||
install-sh
|
||||
mdate-sh
|
||||
missing
|
41
contrib/kyua/admin/Makefile.am.inc
Normal file
41
contrib/kyua/admin/Makefile.am.inc
Normal file
@ -0,0 +1,41 @@
|
||||
# Copyright 2015 The Kyua Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
PHONY_TARGETS += check-style
|
||||
check-style:
|
||||
@$(srcdir)/admin/check-style.sh \
|
||||
-b "$(abs_top_builddir)" \
|
||||
-s "$(abs_top_srcdir)" \
|
||||
-t "$(PACKAGE_TARNAME)"
|
||||
|
||||
EXTRA_DIST += admin/check-style-common.awk \
|
||||
admin/check-style-cpp.awk \
|
||||
admin/check-style-make.awk \
|
||||
admin/check-style-man.awk \
|
||||
admin/check-style-shell.awk \
|
||||
admin/check-style.sh
|
131
contrib/kyua/admin/build-bintray-dist.sh
Executable file
131
contrib/kyua/admin/build-bintray-dist.sh
Executable file
@ -0,0 +1,131 @@
|
||||
#! /bin/sh
|
||||
# Copyright 2017 The Kyua Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
# \file admin/build-bintray-dist.sh
|
||||
# Builds a full Kyua installation under /usr/local for Ubuntu.
|
||||
#
|
||||
# This script is used to create the bintray distribution packages in lieu
|
||||
# of real Debian packages for Kyua. The result of this script is a
|
||||
# tarball that provides the contents of /usr/local for Kyua.
|
||||
|
||||
set -e -x
|
||||
|
||||
err() {
|
||||
echo "${@}" 1>&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
install_deps() {
|
||||
sudo apt-get update -qq
|
||||
|
||||
local pkgsuffix=
|
||||
local packages=
|
||||
packages="${packages} autoconf"
|
||||
packages="${packages} automake"
|
||||
packages="${packages} clang"
|
||||
packages="${packages} g++"
|
||||
packages="${packages} gdb"
|
||||
packages="${packages} git"
|
||||
packages="${packages} libtool"
|
||||
packages="${packages} make"
|
||||
if [ "${ARCH?}" = i386 ]; then
|
||||
pkgsuffix=:i386
|
||||
packages="${packages} gcc-multilib"
|
||||
packages="${packages} g++-multilib"
|
||||
fi
|
||||
packages="${packages} liblua5.2-0${pkgsuffix}"
|
||||
packages="${packages} liblua5.2-dev${pkgsuffix}"
|
||||
packages="${packages} libsqlite3-0${pkgsuffix}"
|
||||
packages="${packages} libsqlite3-dev${pkgsuffix}"
|
||||
packages="${packages} pkg-config${pkgsuffix}"
|
||||
packages="${packages} sqlite3"
|
||||
sudo apt-get install -y ${packages}
|
||||
}
|
||||
|
||||
install_from_github() {
|
||||
local name="${1}"; shift
|
||||
local release="${1}"; shift
|
||||
|
||||
local distname="${name}-${release}"
|
||||
|
||||
local baseurl="https://github.com/jmmv/${name}"
|
||||
wget --no-check-certificate \
|
||||
"${baseurl}/releases/download/${distname}/${distname}.tar.gz"
|
||||
tar -xzvf "${distname}.tar.gz"
|
||||
|
||||
local archflags=
|
||||
[ "${ARCH?}" != i386 ] || archflags=-m32
|
||||
|
||||
cd "${distname}"
|
||||
./configure \
|
||||
--disable-developer \
|
||||
--without-atf \
|
||||
--without-doxygen \
|
||||
CC="${CC?}" \
|
||||
CFLAGS="${archflags}" \
|
||||
CPPFLAGS="-I/usr/local/include" \
|
||||
CXX="${CXX?}" \
|
||||
CXXFLAGS="${archflags}" \
|
||||
LDFLAGS="-L/usr/local/lib -Wl,-R/usr/local/lib" \
|
||||
PKG_CONFIG_PATH="/usr/local/lib/pkgconfig"
|
||||
make
|
||||
sudo make install
|
||||
cd -
|
||||
|
||||
rm -rf "${distname}" "${distname}.tar.gz"
|
||||
}
|
||||
|
||||
main() {
|
||||
[ "${ARCH+set}" = set ] || err "ARCH must be set in the environment"
|
||||
[ "${CC+set}" = set ] || err "CC must be set in the environment"
|
||||
[ "${CXX+set}" = set ] || err "CXX must be set in the environment"
|
||||
|
||||
[ ! -f /root/local.tgz ] || err "/root/local.tgz already exists"
|
||||
tar -czf /root/local.tgz /usr/local
|
||||
restore() {
|
||||
rm -rf /usr/local
|
||||
tar -xz -C / -f /root/local.tgz
|
||||
rm /root/local.tgz
|
||||
}
|
||||
trap restore EXIT
|
||||
rm -rf /usr/local
|
||||
mkdir /usr/local
|
||||
|
||||
install_deps
|
||||
install_from_github atf 0.21
|
||||
install_from_github lutok 0.4
|
||||
install_from_github kyua 0.13
|
||||
|
||||
local version="$(lsb_release -rs | cut -d . -f 1-2 | tr . -)"
|
||||
local name="$(date +%Y%m%d)-usr-local-kyua"
|
||||
name="${name}-ubuntu-${version}-${ARCH?}-${CC?}.tar.gz"
|
||||
tar -czf "${name}" /usr/local
|
||||
}
|
||||
|
||||
main "${@}"
|
72
contrib/kyua/admin/check-api-docs.awk
Normal file
72
contrib/kyua/admin/check-api-docs.awk
Normal file
@ -0,0 +1,72 @@
|
||||
#! /bin/sh
|
||||
# Copyright 2015 The Kyua Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
BEGIN {
|
||||
failed = 0
|
||||
}
|
||||
|
||||
# Skip empty lines.
|
||||
/^$/ {next}
|
||||
|
||||
# Skip lines that do not directly reference a file.
|
||||
/^[^\/]/ {next}
|
||||
|
||||
# Ignore known problems. As far as I can tell, all the cases listed here are
|
||||
# well-documented in the code but Doxygen fails, for some reason or another, to
|
||||
# properly locate the docstrings.
|
||||
/engine\/kyuafile\.cpp.*no matching class member/ {next}
|
||||
/engine\/scheduler\.hpp.*Member setup\(void\).*friend/ {next}
|
||||
/engine\/scheduler\.hpp.*Member wait_any\(void\)/ {next}
|
||||
/utils\/optional\.ipp.*no matching file member/ {next}
|
||||
/utils\/optional\.hpp.*Member make_optional\(const T &\)/ {next}
|
||||
/utils\/config\/nodes\.hpp.*Member set_lua\(lutok::state &, const int\)/ {next}
|
||||
/utils\/config\/nodes\.hpp.*Member push_lua\(lutok::state &\)/ {next}
|
||||
/utils\/config\/nodes\.hpp.*Member set_string\(const std::string &\)/ {next}
|
||||
/utils\/config\/nodes\.hpp.*Member to_string\(void\)/ {next}
|
||||
/utils\/config\/nodes\.hpp.*Member is_set\(void\)/ {next}
|
||||
/utils\/process\/executor\.hpp.*Member spawn\(Hook.*\)/ {next}
|
||||
/utils\/process\/executor\.hpp.*Member spawn_followup\(Hook.*\)/ {next}
|
||||
/utils\/process\/executor\.hpp.*Member setup\(void\).*friend/ {next}
|
||||
/utils\/signals\/timer\.hpp.*Member detail::invoke_do_fired.*friend/ {next}
|
||||
/utils\/stacktrace_test\.cpp.*no matching class member/ {next}
|
||||
|
||||
# Dump any other problems and account for the failure.
|
||||
{
|
||||
failed = 1
|
||||
print
|
||||
}
|
||||
|
||||
END {
|
||||
if (failed) {
|
||||
print "ERROR: Unexpected docstring problems encountered"
|
||||
exit 1
|
||||
} else {
|
||||
exit 0
|
||||
}
|
||||
}
|
79
contrib/kyua/admin/check-style-common.awk
Normal file
79
contrib/kyua/admin/check-style-common.awk
Normal file
@ -0,0 +1,79 @@
|
||||
# Copyright 2015 The Kyua Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
function warn(msg) {
|
||||
print FILENAME "[" FNR "]: " msg > "/dev/stderr"
|
||||
error = 1
|
||||
}
|
||||
|
||||
BEGIN {
|
||||
skip = 0
|
||||
error = 0
|
||||
}
|
||||
|
||||
/CHECK_STYLE_DISABLE/ {
|
||||
skip = 1
|
||||
next
|
||||
}
|
||||
|
||||
/CHECK_STYLE_ENABLE/ {
|
||||
skip = 0
|
||||
next
|
||||
}
|
||||
|
||||
/CHECK_STYLE_(ENABLE|DISABLE)/ {
|
||||
next
|
||||
}
|
||||
|
||||
{
|
||||
if (skip)
|
||||
next
|
||||
|
||||
if (length > 80 && NF > 1)
|
||||
warn("Line too long to fit on screen")
|
||||
}
|
||||
|
||||
/^ *\t+/ {
|
||||
if (! match(FILENAME, "Makefile"))
|
||||
warn("Tab character used for indentation");
|
||||
}
|
||||
|
||||
/[ \t]+$/ {
|
||||
warn("Trailing spaces or tabs");
|
||||
}
|
||||
|
||||
/^#![^ ]/ {
|
||||
warn("Missing space after #!");
|
||||
}
|
||||
|
||||
END {
|
||||
if (skip)
|
||||
warn("Missing CHECK_STYLE_ENABLE");
|
||||
if (error)
|
||||
exit 1
|
||||
}
|
87
contrib/kyua/admin/check-style-cpp.awk
Normal file
87
contrib/kyua/admin/check-style-cpp.awk
Normal file
@ -0,0 +1,87 @@
|
||||
# Copyright 2015 The Kyua Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
function warn(msg) {
|
||||
print FILENAME "[" FNR "]: " msg > "/dev/stderr"
|
||||
error = 1
|
||||
}
|
||||
|
||||
BEGIN {
|
||||
skip = 0
|
||||
error = 0
|
||||
}
|
||||
|
||||
/CHECK_STYLE_DISABLE/ {
|
||||
skip = 1
|
||||
next
|
||||
}
|
||||
|
||||
/CHECK_STYLE_ENABLE/ {
|
||||
skip = 0
|
||||
next
|
||||
}
|
||||
|
||||
/CHECK_STYLE_(ENABLE|DISABLE)/ {
|
||||
next
|
||||
}
|
||||
|
||||
{
|
||||
if (skip)
|
||||
next
|
||||
}
|
||||
|
||||
/#ifdef/ {
|
||||
warn("Undesired usage of #ifdef; use #if defined()")
|
||||
}
|
||||
|
||||
/#ifndef/ {
|
||||
warn("Undesired usage of #ifndef; use #if !defined()")
|
||||
}
|
||||
|
||||
/assert[ \t]*\(/ {
|
||||
warn("Use the macros in sanity.hpp instead of assert");
|
||||
}
|
||||
|
||||
/#.*include.*assert/ {
|
||||
warn("Do not include assert.h nor cassert");
|
||||
}
|
||||
|
||||
/std::endl/ {
|
||||
warn("Use \\n instead of std::endl");
|
||||
}
|
||||
|
||||
/\/\*/ && ! /\*\// {
|
||||
warn("Do not use multi-line C-style comments");
|
||||
}
|
||||
|
||||
END {
|
||||
if (skip)
|
||||
warn("Missing CHECK_STYLE_ENABLE");
|
||||
if (error)
|
||||
exit 1
|
||||
}
|
71
contrib/kyua/admin/check-style-make.awk
Normal file
71
contrib/kyua/admin/check-style-make.awk
Normal file
@ -0,0 +1,71 @@
|
||||
# Copyright 2015 The Kyua Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
function warn(msg) {
|
||||
print FILENAME "[" FNR "]: " msg > "/dev/stderr"
|
||||
error = 1
|
||||
}
|
||||
|
||||
BEGIN {
|
||||
skip = 0
|
||||
error = 0
|
||||
}
|
||||
|
||||
/CHECK_STYLE_DISABLE/ {
|
||||
skip = 1
|
||||
next
|
||||
}
|
||||
|
||||
/CHECK_STYLE_ENABLE/ {
|
||||
skip = 0
|
||||
next
|
||||
}
|
||||
|
||||
/CHECK_STYLE_(ENABLE|DISABLE)/ {
|
||||
next
|
||||
}
|
||||
|
||||
{
|
||||
if (skip)
|
||||
next
|
||||
}
|
||||
|
||||
/^\t *\t/ {
|
||||
warn("Continuation lines must use a single tab");
|
||||
}
|
||||
|
||||
/mkdir.*-p/ {
|
||||
warn("Use $(MKDIR_P) instead of mkdir -p");
|
||||
}
|
||||
|
||||
END {
|
||||
if (skip)
|
||||
warn("Missing CHECK_STYLE_ENABLE");
|
||||
if (error)
|
||||
exit 1
|
||||
}
|
71
contrib/kyua/admin/check-style-man.awk
Normal file
71
contrib/kyua/admin/check-style-man.awk
Normal file
@ -0,0 +1,71 @@
|
||||
# Copyright 2015 The Kyua Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
function warn(msg) {
|
||||
print FILENAME "[" FNR "]: " msg > "/dev/stderr"
|
||||
error = 1
|
||||
}
|
||||
|
||||
BEGIN {
|
||||
skip = 0
|
||||
error = 0
|
||||
}
|
||||
|
||||
/CHECK_STYLE_DISABLE|^\.Bd/ {
|
||||
skip = 1
|
||||
next
|
||||
}
|
||||
|
||||
/CHECK_STYLE_ENABLE|^\.Ed/ {
|
||||
skip = 0
|
||||
next
|
||||
}
|
||||
|
||||
/CHECK_STYLE_(ENABLE|DISABLE)/ {
|
||||
next
|
||||
}
|
||||
|
||||
/^\.\\"/ {
|
||||
next
|
||||
}
|
||||
|
||||
{
|
||||
if (skip)
|
||||
next
|
||||
}
|
||||
|
||||
/\.\.|e\.g\.|i\.e\./ {
|
||||
next
|
||||
}
|
||||
|
||||
END {
|
||||
if (skip)
|
||||
warn("Missing CHECK_STYLE_ENABLE");
|
||||
if (error)
|
||||
exit 1
|
||||
}
|
95
contrib/kyua/admin/check-style-shell.awk
Normal file
95
contrib/kyua/admin/check-style-shell.awk
Normal file
@ -0,0 +1,95 @@
|
||||
# Copyright 2015 The Kyua Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
function warn(msg) {
|
||||
print FILENAME "[" FNR "]: " msg > "/dev/stderr"
|
||||
error = 1
|
||||
}
|
||||
|
||||
BEGIN {
|
||||
skip = 0
|
||||
error = 0
|
||||
}
|
||||
|
||||
/CHECK_STYLE_DISABLE/ {
|
||||
skip = 1
|
||||
next
|
||||
}
|
||||
|
||||
/CHECK_STYLE_ENABLE/ {
|
||||
skip = 0
|
||||
next
|
||||
}
|
||||
|
||||
/CHECK_STYLE_(ENABLE|DISABLE)/ {
|
||||
next
|
||||
}
|
||||
|
||||
{
|
||||
if (skip)
|
||||
next
|
||||
}
|
||||
|
||||
/^[ \t]*#/ {
|
||||
next
|
||||
}
|
||||
|
||||
/[$ \t]+_[a-zA-Z0-9]+=/ {
|
||||
warn("Variable should not start with an underline")
|
||||
}
|
||||
|
||||
/[^\\]\$[^0-9!'"$?@#*{}(|\/,]+/ {
|
||||
warn("Missing braces around variable name")
|
||||
}
|
||||
|
||||
/=(""|'')/ {
|
||||
warn("Assignment to the empty string does not need quotes");
|
||||
}
|
||||
|
||||
/basename[ \t]+/ {
|
||||
warn("Use parameter expansion instead of basename");
|
||||
}
|
||||
|
||||
/if[ \t]+(test|![ \t]+test)/ {
|
||||
warn("Use [ instead of test");
|
||||
}
|
||||
|
||||
/[ \t]+(test|\[).*==/ {
|
||||
warn("test(1)'s == operator is not portable");
|
||||
}
|
||||
|
||||
/if.*;[ \t]*fi$/ {
|
||||
warn("Avoid using a single-line if conditional");
|
||||
}
|
||||
|
||||
END {
|
||||
if (skip)
|
||||
warn("Missing CHECK_STYLE_ENABLE");
|
||||
if (error)
|
||||
exit 1
|
||||
}
|
170
contrib/kyua/admin/check-style.sh
Executable file
170
contrib/kyua/admin/check-style.sh
Executable file
@ -0,0 +1,170 @@
|
||||
#! /bin/sh
|
||||
# Copyright 2011 The Kyua Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
# \file admin/check-style.sh
|
||||
#
|
||||
# Sanity checks the coding style of all source files in the project tree.
|
||||
|
||||
ProgName="${0##*/}"
|
||||
|
||||
|
||||
# Prints an error message and exits.
|
||||
#
|
||||
# \param ... Parts of the error message; concatenated using a space as the
|
||||
# separator.
|
||||
err() {
|
||||
echo "${ProgName}:" "${@}" 1>&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
|
||||
# Locates all source files within the project directory.
|
||||
#
|
||||
# We require the project to have been configured in a directory that is separate
|
||||
# from the source tree. This is to allow us to easily filter out build
|
||||
# artifacts from our search.
|
||||
#
|
||||
# \param srcdir Absolute path to the source directory.
|
||||
# \param builddir Absolute path to the build directory.
|
||||
# \param tarname Basename of the project's tar file, to skip possible distfile
|
||||
# directories.
|
||||
find_sources() {
|
||||
local srcdir="${1}"; shift
|
||||
local builddir="${1}"; shift
|
||||
local tarname="${1}"; shift
|
||||
|
||||
(
|
||||
cd "${srcdir}"
|
||||
find . -type f -a \
|
||||
\! -path "*/.git/*" \
|
||||
\! -path "*/.deps/*" \
|
||||
\! -path "*/autom4te.cache/*" \
|
||||
\! -path "*/${tarname}-[0-9]*/*" \
|
||||
\! -path "*/${builddir##*/}/*" \
|
||||
\! -name "Makefile.in" \
|
||||
\! -name "aclocal.m4" \
|
||||
\! -name "config.h.in" \
|
||||
\! -name "configure" \
|
||||
\! -name "testsuite"
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
# Prints the style rules applicable to a given file.
|
||||
#
|
||||
# \param file Path to the source file.
|
||||
guess_rules() {
|
||||
local file="${1}"; shift
|
||||
|
||||
case "${file}" in
|
||||
*/ax_cxx_compile_stdcxx.m4) ;;
|
||||
*/ltmain.sh) ;;
|
||||
*Makefile*) echo common make ;;
|
||||
*.[0-9]) echo common man ;;
|
||||
*.cpp|*.hpp) echo common cpp ;;
|
||||
*.sh) echo common shell ;;
|
||||
*) echo common ;;
|
||||
esac
|
||||
}
|
||||
|
||||
|
||||
# Validates a given file against the rules that apply to it.
|
||||
#
|
||||
# \param srcdir Absolute path to the source directory.
|
||||
# \param file Name of the file to validate relative to srcdir.
|
||||
#
|
||||
# \return 0 if the file is valid; 1 otherwise, in which case the style
|
||||
# violations are printed to the output.
|
||||
check_file() {
|
||||
local srcdir="${1}"; shift
|
||||
local file="${1}"; shift
|
||||
|
||||
local err=0
|
||||
for rule in $(guess_rules "${file}"); do
|
||||
awk -f "${srcdir}/admin/check-style-${rule}.awk" \
|
||||
"${srcdir}/${file}" || err=1
|
||||
done
|
||||
|
||||
return ${err}
|
||||
}
|
||||
|
||||
|
||||
# Entry point.
|
||||
main() {
|
||||
local builddir=.
|
||||
local srcdir=.
|
||||
local tarname=UNKNOWN
|
||||
|
||||
local arg
|
||||
while getopts :b:s:t: arg; do
|
||||
case "${arg}" in
|
||||
b)
|
||||
builddir="${OPTARG}"
|
||||
;;
|
||||
|
||||
s)
|
||||
srcdir="${OPTARG}"
|
||||
;;
|
||||
|
||||
t)
|
||||
tarname="${OPTARG}"
|
||||
;;
|
||||
|
||||
\?)
|
||||
err "Unknown option -${OPTARG}"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift $(expr ${OPTIND} - 1)
|
||||
|
||||
srcdir="$(cd "${srcdir}" && pwd -P)"
|
||||
builddir="$(cd "${builddir}" && pwd -P)"
|
||||
[ "${srcdir}" != "${builddir}" ] || \
|
||||
err "srcdir and builddir cannot match; reconfigure the package" \
|
||||
"in a separate directory"
|
||||
|
||||
local sources
|
||||
if [ ${#} -gt 0 ]; then
|
||||
sources="${@}"
|
||||
else
|
||||
sources="$(find_sources "${srcdir}" "${builddir}" "${tarname}")"
|
||||
fi
|
||||
|
||||
local ok=0
|
||||
for file in ${sources}; do
|
||||
local file="$(echo ${file} | sed -e "s,\\./,,")"
|
||||
|
||||
check_file "${srcdir}" "${file}" || ok=1
|
||||
done
|
||||
|
||||
return "${ok}"
|
||||
}
|
||||
|
||||
|
||||
main "${@}"
|
90
contrib/kyua/admin/clean-all.sh
Executable file
90
contrib/kyua/admin/clean-all.sh
Executable file
@ -0,0 +1,90 @@
|
||||
#! /bin/sh
|
||||
# Copyright 2010 The Kyua Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Prog_Name=${0##*/}
|
||||
|
||||
if [ ! -f ./main.cpp ]; then
|
||||
echo "${Prog_Name}: must be run from the source top directory" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f configure ]; then
|
||||
echo "${Prog_Name}: configure not found; nothing to clean?" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
[ -f Makefile ] || ./configure
|
||||
make distclean
|
||||
|
||||
# Top-level directory.
|
||||
rm -f Makefile.in
|
||||
rm -f aclocal.m4
|
||||
rm -rf autom4te.cache
|
||||
rm -f config.h.in
|
||||
rm -f configure
|
||||
rm -f mkinstalldirs
|
||||
rm -f kyua-*.tar.gz
|
||||
|
||||
# admin directory.
|
||||
rm -f admin/ar-lib
|
||||
rm -f admin/compile
|
||||
rm -f admin/config.guess
|
||||
rm -f admin/config.sub
|
||||
rm -f admin/depcomp
|
||||
rm -f admin/install-sh
|
||||
rm -f admin/ltmain.sh
|
||||
rm -f admin/mdate-sh
|
||||
rm -f admin/missing
|
||||
|
||||
# bootstrap directory.
|
||||
rm -f bootstrap/package.m4
|
||||
rm -f bootstrap/testsuite
|
||||
|
||||
# doc directory.
|
||||
rm -f doc/*.info
|
||||
rm -f doc/stamp-vti
|
||||
rm -f doc/version.texi
|
||||
|
||||
# m4 directory.
|
||||
rm -f m4/libtool.m4
|
||||
rm -f m4/lt*.m4
|
||||
|
||||
# Files and directories spread all around the tree.
|
||||
find . -name '#*' | xargs rm -rf
|
||||
find . -name '*~' | xargs rm -rf
|
||||
find . -name .deps | xargs rm -rf
|
||||
find . -name .gdb_history | xargs rm -rf
|
||||
find . -name .libs | xargs rm -rf
|
||||
find . -name .tmp | xargs rm -rf
|
||||
|
||||
# Show remaining files.
|
||||
if [ -n "${GIT}" ]; then
|
||||
echo ">>> untracked and ignored files"
|
||||
"${GIT}" status --porcelain --ignored | grep -E '^(\?\?|!!)' || true
|
||||
fi
|
98
contrib/kyua/admin/travis-build.sh
Executable file
98
contrib/kyua/admin/travis-build.sh
Executable file
@ -0,0 +1,98 @@
|
||||
#! /bin/sh
|
||||
# Copyright 2014 The Kyua Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
set -e -x
|
||||
|
||||
run_autoreconf() {
|
||||
if [ -d /usr/local/share/aclocal ]; then
|
||||
autoreconf -isv -I/usr/local/share/aclocal
|
||||
else
|
||||
autoreconf -isv
|
||||
fi
|
||||
}
|
||||
|
||||
do_apidocs() {
|
||||
run_autoreconf || return 1
|
||||
./configure --with-doxygen || return 1
|
||||
make check-api-docs
|
||||
}
|
||||
|
||||
do_distcheck() {
|
||||
run_autoreconf || return 1
|
||||
./configure || return 1
|
||||
|
||||
sudo sysctl -w "kernel.core_pattern=core.%p"
|
||||
|
||||
local archflags=
|
||||
[ "${ARCH?}" != i386 ] || archflags=-m32
|
||||
|
||||
cat >kyua.conf <<EOF
|
||||
syntax(2)
|
||||
|
||||
-- We do not know how many CPUs the test machine has. However, parallelizing
|
||||
-- the execution of our tests to _any_ degree speeds up the time it takes to
|
||||
-- complete a test run because many of our tests are blocking.
|
||||
parallelism = 4
|
||||
EOF
|
||||
[ "${UNPRIVILEGED_USER:-no}" = no ] || \
|
||||
echo "unprivileged_user = 'travis'" >>kyua.conf
|
||||
|
||||
local f=
|
||||
f="${f} CFLAGS='${archflags}'"
|
||||
f="${f} CPPFLAGS='-I/usr/local/include'"
|
||||
f="${f} CXXFLAGS='${archflags}'"
|
||||
f="${f} LDFLAGS='-L/usr/local/lib -Wl,-R/usr/local/lib'"
|
||||
f="${f} PKG_CONFIG_PATH='/usr/local/lib/pkgconfig'"
|
||||
f="${f} KYUA_CONFIG_FILE_FOR_CHECK=$(pwd)/kyua.conf"
|
||||
if [ "${AS_ROOT:-no}" = yes ]; then
|
||||
sudo -H PATH="${PATH}" make distcheck DISTCHECK_CONFIGURE_FLAGS="${f}"
|
||||
else
|
||||
make distcheck DISTCHECK_CONFIGURE_FLAGS="${f}"
|
||||
fi
|
||||
}
|
||||
|
||||
do_style() {
|
||||
run_autoreconf || return 1
|
||||
mkdir build
|
||||
cd build
|
||||
../configure || return 1
|
||||
make check-style
|
||||
}
|
||||
|
||||
main() {
|
||||
if [ -z "${DO}" ]; then
|
||||
echo "DO must be defined" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
for step in ${DO}; do
|
||||
"do_${DO}" || exit 1
|
||||
done
|
||||
}
|
||||
|
||||
main "${@}"
|
83
contrib/kyua/admin/travis-install-deps.sh
Executable file
83
contrib/kyua/admin/travis-install-deps.sh
Executable file
@ -0,0 +1,83 @@
|
||||
#! /bin/sh
|
||||
# Copyright 2014 The Kyua Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
set -e -x
|
||||
|
||||
install_deps() {
|
||||
local pkgsuffix=
|
||||
local packages=
|
||||
if [ "${ARCH?}" = i386 ]; then
|
||||
pkgsuffix=:i386
|
||||
packages="${packages} gcc-multilib"
|
||||
packages="${packages} g++-multilib"
|
||||
sudo dpkg --add-architecture i386
|
||||
fi
|
||||
packages="${packages} gdb"
|
||||
packages="${packages} liblua5.2-0${pkgsuffix}"
|
||||
packages="${packages} liblua5.2-dev${pkgsuffix}"
|
||||
packages="${packages} libsqlite3-0${pkgsuffix}"
|
||||
packages="${packages} libsqlite3-dev${pkgsuffix}"
|
||||
packages="${packages} pkg-config${pkgsuffix}"
|
||||
packages="${packages} sqlite3"
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -y ${packages}
|
||||
}
|
||||
|
||||
install_kyua() {
|
||||
local name="20190321-usr-local-kyua-ubuntu-16-04-${ARCH?}-${CC?}.tar.gz"
|
||||
wget -O "${name}" "http://dl.bintray.com/ngie-eign/kyua/${name}" || return 1
|
||||
sudo tar -xzvp -C / -f "${name}"
|
||||
rm -f "${name}"
|
||||
}
|
||||
|
||||
do_apidocs() {
|
||||
sudo apt-get install -y doxygen
|
||||
}
|
||||
|
||||
do_distcheck() {
|
||||
:
|
||||
}
|
||||
|
||||
do_style() {
|
||||
:
|
||||
}
|
||||
|
||||
main() {
|
||||
if [ -z "${DO}" ]; then
|
||||
echo "DO must be defined" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
install_deps
|
||||
install_kyua
|
||||
for step in ${DO}; do
|
||||
"do_${DO}" || exit 1
|
||||
done
|
||||
}
|
||||
|
||||
main "${@}"
|
4
contrib/kyua/bootstrap/.gitignore
vendored
Normal file
4
contrib/kyua/bootstrap/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
atconfig
|
||||
package.m4
|
||||
testsuite
|
||||
testsuite.log
|
5
contrib/kyua/bootstrap/Kyuafile
Normal file
5
contrib/kyua/bootstrap/Kyuafile
Normal file
@ -0,0 +1,5 @@
|
||||
syntax(2)
|
||||
|
||||
test_suite("kyua")
|
||||
|
||||
plain_test_program{name="testsuite"}
|
90
contrib/kyua/bootstrap/Makefile.am.inc
Normal file
90
contrib/kyua/bootstrap/Makefile.am.inc
Normal file
@ -0,0 +1,90 @@
|
||||
# Copyright 2010 The Kyua Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
if WITH_ATF
|
||||
tests_bootstrapdir = $(pkgtestsdir)/bootstrap
|
||||
|
||||
tests_bootstrap_DATA = bootstrap/Kyuafile
|
||||
EXTRA_DIST += $(tests_bootstrap_DATA)
|
||||
|
||||
DISTCLEANFILES = bootstrap/atconfig \
|
||||
bootstrap/testsuite.lineno \
|
||||
bootstrap/testsuite.log
|
||||
|
||||
distclean-local: distclean-testsuite
|
||||
distclean-testsuite:
|
||||
-rm -rf bootstrap/testsuite.dir
|
||||
|
||||
EXTRA_DIST += bootstrap/Kyuafile \
|
||||
bootstrap/testsuite \
|
||||
bootstrap/package.m4 \
|
||||
bootstrap/testsuite.at
|
||||
|
||||
tests_bootstrap_PROGRAMS = bootstrap/atf_helpers
|
||||
bootstrap_atf_helpers_SOURCES = bootstrap/atf_helpers.cpp
|
||||
bootstrap_atf_helpers_CXXFLAGS = $(ATF_CXX_CFLAGS)
|
||||
bootstrap_atf_helpers_LDADD = $(ATF_CXX_LIBS)
|
||||
|
||||
tests_bootstrap_PROGRAMS += bootstrap/plain_helpers
|
||||
bootstrap_plain_helpers_SOURCES = bootstrap/plain_helpers.cpp
|
||||
bootstrap_plain_helpers_CXXFLAGS = $(UTILS_CFLAGS)
|
||||
|
||||
tests_bootstrap_SCRIPTS = bootstrap/testsuite
|
||||
@target_srcdir@bootstrap/package.m4: $(top_srcdir)/configure.ac
|
||||
$(AM_V_GEN){ \
|
||||
echo '# Signature of the current package.'; \
|
||||
echo 'm4_define(AT_PACKAGE_NAME, @PACKAGE_NAME@)'; \
|
||||
echo 'm4_define(AT_PACKAGE_TARNAME, @PACKAGE_TARNAME@)'; \
|
||||
echo 'm4_define(AT_PACKAGE_VERSION, @PACKAGE_VERSION@)'; \
|
||||
echo 'm4_define(AT_PACKAGE_STRING, @PACKAGE_STRING@)'; \
|
||||
echo 'm4_define(AT_PACKAGE_BUGREPORT, @PACKAGE_BUGREPORT@)'; \
|
||||
} >$(srcdir)/bootstrap/package.m4
|
||||
|
||||
@target_srcdir@bootstrap/testsuite: $(srcdir)/bootstrap/testsuite.at \
|
||||
@target_srcdir@bootstrap/package.m4
|
||||
$(AM_V_GEN)autom4te --language=Autotest -I $(srcdir) \
|
||||
-I $(srcdir)/bootstrap \
|
||||
$(srcdir)/bootstrap/testsuite.at -o $@.tmp; \
|
||||
mv $@.tmp $@
|
||||
|
||||
CHECK_LOCAL += check-bootstrap
|
||||
PHONY_TARGETS += check-bootstrap
|
||||
check-bootstrap: @target_srcdir@bootstrap/testsuite $(check_PROGRAMS) \
|
||||
$(CHECK_BOOTSTRAP_DEPS)
|
||||
cd bootstrap && $(CHECK_ENVIRONMENT) $(TESTS_ENVIRONMENT) \
|
||||
./testsuite
|
||||
|
||||
if !TARGET_SRCDIR_EMPTY
|
||||
CHECK_BOOTSTRAP_DEPS += copy-bootstrap-testsuite
|
||||
CHECK_KYUA_DEPS += copy-bootstrap-testsuite
|
||||
PHONY_TARGETS += copy-bootstrap-testsuite
|
||||
copy-bootstrap-testsuite:
|
||||
cp -f @target_srcdir@bootstrap/testsuite bootstrap/testsuite
|
||||
CLEANFILES += bootstrap/testsuite
|
||||
endif
|
||||
endif
|
71
contrib/kyua/bootstrap/atf_helpers.cpp
Normal file
71
contrib/kyua/bootstrap/atf_helpers.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
// Copyright 2010 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
|
||||
#include <atf-c++.hpp>
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(fails);
|
||||
ATF_TEST_CASE_BODY(fails)
|
||||
{
|
||||
fail("Failed on purpose");
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(passes);
|
||||
ATF_TEST_CASE_BODY(passes)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(skips);
|
||||
ATF_TEST_CASE_BODY(skips)
|
||||
{
|
||||
skip("Skipped on purpose");
|
||||
}
|
||||
|
||||
|
||||
ATF_INIT_TEST_CASES(tcs)
|
||||
{
|
||||
std::string enabled;
|
||||
|
||||
const char* tests = std::getenv("TESTS");
|
||||
if (tests == NULL)
|
||||
enabled = "fails passes skips";
|
||||
else
|
||||
enabled = tests;
|
||||
|
||||
if (enabled.find("fails") != std::string::npos)
|
||||
ATF_ADD_TEST_CASE(tcs, fails);
|
||||
if (enabled.find("passes") != std::string::npos)
|
||||
ATF_ADD_TEST_CASE(tcs, passes);
|
||||
if (enabled.find("skips") != std::string::npos)
|
||||
ATF_ADD_TEST_CASE(tcs, skips);
|
||||
}
|
141
contrib/kyua/bootstrap/plain_helpers.cpp
Normal file
141
contrib/kyua/bootstrap/plain_helpers.cpp
Normal file
@ -0,0 +1,141 @@
|
||||
// Copyright 2010 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
|
||||
#include "utils/defs.hpp"
|
||||
#include "utils/test_utils.ipp"
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
/// Prints a fake but valid test case list and then aborts.
|
||||
///
|
||||
/// \param argv The original arguments of the program.
|
||||
///
|
||||
/// \return Nothing because this dies before returning.
|
||||
static int
|
||||
helper_abort_test_cases_list(int /* argc */, char** argv)
|
||||
{
|
||||
for (const char* const* arg = argv; *arg != NULL; arg++) {
|
||||
if (std::strcmp(*arg, "-l") == 0) {
|
||||
std::cout << "Content-Type: application/X-atf-tp; "
|
||||
"version=\"1\"\n\n";
|
||||
std::cout << "ident: foo\n";
|
||||
}
|
||||
}
|
||||
utils::abort_without_coredump();
|
||||
}
|
||||
|
||||
|
||||
/// Just returns without printing anything as the test case list.
|
||||
///
|
||||
/// \return Always 0, as required for test programs.
|
||||
static int
|
||||
helper_empty_test_cases_list(int /* argc */, char** /* argv */)
|
||||
{
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/// Prints a correctly-formatted test case list but empty.
|
||||
///
|
||||
/// \param argv The original arguments of the program.
|
||||
///
|
||||
/// \return Always 0, as required for test programs.
|
||||
static int
|
||||
helper_zero_test_cases(int /* argc */, char** argv)
|
||||
{
|
||||
for (const char* const* arg = argv; *arg != NULL; arg++) {
|
||||
if (std::strcmp(*arg, "-l") == 0)
|
||||
std::cout << "Content-Type: application/X-atf-tp; "
|
||||
"version=\"1\"\n\n";
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/// Mapping of the name of a helper to its implementation.
|
||||
struct helper {
|
||||
/// The name of the helper, as will be provided by the user on the CLI.
|
||||
const char* name;
|
||||
|
||||
/// A pointer to the function implementing the helper.
|
||||
int (*hook)(int, char**);
|
||||
};
|
||||
|
||||
|
||||
/// NULL-terminated table mapping helper names to their implementations.
|
||||
static const helper helpers[] = {
|
||||
{ "abort_test_cases_list", helper_abort_test_cases_list, },
|
||||
{ "empty_test_cases_list", helper_empty_test_cases_list, },
|
||||
{ "zero_test_cases", helper_zero_test_cases, },
|
||||
{ NULL, NULL, },
|
||||
};
|
||||
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
/// Entry point to the ATF-less helpers.
|
||||
///
|
||||
/// The caller must select a helper to execute by defining the HELPER
|
||||
/// environment variable to the name of the desired helper. Think of this main
|
||||
/// method as a subprogram dispatcher, to avoid having many individual helper
|
||||
/// binaries.
|
||||
///
|
||||
/// \todo Maybe we should really have individual helper binaries. It would
|
||||
/// avoid a significant amount of complexity here and in the tests, at the
|
||||
/// expense of some extra files and extra build logic.
|
||||
///
|
||||
/// \param argc The user argument count; delegated to the helper.
|
||||
/// \param argv The user arguments; delegated to the helper.
|
||||
///
|
||||
/// \return The exit code of the helper, which depends on the requested helper.
|
||||
int
|
||||
main(int argc, char** argv)
|
||||
{
|
||||
const char* command = std::getenv("HELPER");
|
||||
if (command == NULL) {
|
||||
std::cerr << "Usage error: HELPER must be set to a helper name\n";
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
const struct helper* iter = helpers;
|
||||
for (; iter->name != NULL && std::strcmp(iter->name, command) != 0; iter++)
|
||||
;
|
||||
if (iter->name == NULL) {
|
||||
std::cerr << "Usage error: unknown command " << command << "\n";
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return iter->hook(argc, argv);
|
||||
}
|
200
contrib/kyua/bootstrap/testsuite.at
Normal file
200
contrib/kyua/bootstrap/testsuite.at
Normal file
@ -0,0 +1,200 @@
|
||||
dnl Copyright 2010 The Kyua Authors.
|
||||
dnl All rights reserved.
|
||||
dnl
|
||||
dnl Redistribution and use in source and binary forms, with or without
|
||||
dnl modification, are permitted provided that the following conditions are
|
||||
dnl met:
|
||||
dnl
|
||||
dnl * Redistributions of source code must retain the above copyright
|
||||
dnl notice, this list of conditions and the following disclaimer.
|
||||
dnl * Redistributions in binary form must reproduce the above copyright
|
||||
dnl notice, this list of conditions and the following disclaimer in the
|
||||
dnl documentation and/or other materials provided with the distribution.
|
||||
dnl * Neither the name of Google Inc. nor the names of its contributors
|
||||
dnl may be used to endorse or promote products derived from this software
|
||||
dnl without specific prior written permission.
|
||||
dnl
|
||||
dnl THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
dnl "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
dnl LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
dnl A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
dnl OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
dnl SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
dnl LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
dnl DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
dnl THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
dnl (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
dnl OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
AT_INIT([bootstrapping tests])
|
||||
|
||||
|
||||
m4_define([GUESS_TOPDIR], {
|
||||
old=$(pwd)
|
||||
cd "$(dirname ${as_myself})"
|
||||
# We need to locate a build product, not a source file, because the
|
||||
# test suite may be run outside of the source tree (think distcheck).
|
||||
while test $(pwd) != '/' -a ! -e bootstrap/plain_helpers; do
|
||||
cd ..
|
||||
done
|
||||
topdir=$(pwd)
|
||||
cd ${old}
|
||||
echo ${topdir}
|
||||
})
|
||||
|
||||
|
||||
m4_define([CREATE_ATF_HELPERS], [
|
||||
AT_DATA([Kyuafile], [
|
||||
syntax(2)
|
||||
test_suite("bootstrap")
|
||||
atf_test_program{name="atf_helpers"}
|
||||
])
|
||||
ln -s $(GUESS_TOPDIR)/bootstrap/atf_helpers atf_helpers
|
||||
])
|
||||
m4_define([RUN_ATF_HELPERS],
|
||||
[HOME=$(pwd) TESTS="$1" kyua --config=none \
|
||||
test --results-file=bootstrap.db $2])
|
||||
|
||||
|
||||
m4_define([CREATE_PLAIN_HELPERS], [
|
||||
AT_DATA([Kyuafile], [
|
||||
syntax(2)
|
||||
test_suite("bootstrap")
|
||||
atf_test_program{name="plain_helpers"}
|
||||
])
|
||||
ln -s $(GUESS_TOPDIR)/bootstrap/plain_helpers plain_helpers
|
||||
])
|
||||
m4_define([RUN_PLAIN_HELPER],
|
||||
[HOME=$(pwd) HELPER="$1" kyua --config=none \
|
||||
test --results-file=bootstrap.db])
|
||||
|
||||
|
||||
AT_SETUP([test program crashes in test list])
|
||||
AT_TESTED([kyua])
|
||||
|
||||
CREATE_PLAIN_HELPERS
|
||||
AT_CHECK([RUN_PLAIN_HELPER([abort_test_cases_list])], [1], [stdout], [])
|
||||
re='plain_helpers:__test_cases_list__.*broken.*Test program received signal'
|
||||
AT_CHECK([grep "${re}" stdout], [0], [ignore], [])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
|
||||
AT_SETUP([test program prints an empty test list])
|
||||
AT_TESTED([kyua])
|
||||
|
||||
CREATE_PLAIN_HELPERS
|
||||
AT_CHECK([RUN_PLAIN_HELPER([empty_test_cases_list])], [1], [stdout], [])
|
||||
re="plain_helpers:__test_cases_list__.*broken.*Invalid header.*got ''"
|
||||
AT_CHECK([grep "${re}" stdout], [0], [ignore], [])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
|
||||
AT_SETUP([test program with zero test cases])
|
||||
AT_TESTED([kyua])
|
||||
|
||||
CREATE_PLAIN_HELPERS
|
||||
AT_CHECK([RUN_PLAIN_HELPER([zero_test_cases])], [1], [stdout], [])
|
||||
re='plain_helpers:__test_cases_list__.*broken.*No test cases'
|
||||
AT_CHECK([grep "${re}" stdout], [0], [ignore], [])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
|
||||
AT_SETUP([run test case that passes])
|
||||
AT_TESTED([kyua])
|
||||
|
||||
CREATE_ATF_HELPERS
|
||||
AT_CHECK([RUN_ATF_HELPERS([passes])], [0], [stdout], [])
|
||||
AT_CHECK([grep "atf_helpers:fails" stdout], [1], [], [])
|
||||
AT_CHECK([grep "atf_helpers:passes.*passed" stdout], [0], [ignore], [])
|
||||
AT_CHECK([grep "atf_helpers:skips" stdout], [1], [], [])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
|
||||
AT_SETUP([run test case that fails])
|
||||
AT_TESTED([kyua])
|
||||
|
||||
CREATE_ATF_HELPERS
|
||||
AT_CHECK([RUN_ATF_HELPERS([fails])], [1], [stdout], [])
|
||||
AT_CHECK([grep "atf_helpers:fails.*failed.*Failed on purpose" stdout],
|
||||
[0], [ignore], [])
|
||||
AT_CHECK([grep "atf_helpers:passes" stdout], [1], [], [])
|
||||
AT_CHECK([grep "atf_helpers:skips" stdout], [1], [], [])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
|
||||
AT_SETUP([run test case that skips])
|
||||
AT_TESTED([kyua])
|
||||
|
||||
CREATE_ATF_HELPERS
|
||||
AT_CHECK([RUN_ATF_HELPERS([skips])], [0], [stdout], [])
|
||||
AT_CHECK([grep "atf_helpers:fails" stdout], [1], [], [])
|
||||
AT_CHECK([grep "atf_helpers:passes" stdout], [1], [], [])
|
||||
AT_CHECK([grep "atf_helpers:skips.*skipped.*Skipped on purpose" stdout],
|
||||
[0], [ignore], [])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
|
||||
AT_SETUP([run two test cases, success])
|
||||
AT_TESTED([kyua])
|
||||
|
||||
CREATE_ATF_HELPERS
|
||||
AT_CHECK([RUN_ATF_HELPERS([passes skips])], [0], [stdout], [])
|
||||
AT_CHECK([grep "atf_helpers:fails" stdout], [1], [], [])
|
||||
AT_CHECK([grep "atf_helpers:passes.*passed" stdout], [0], [ignore], [])
|
||||
AT_CHECK([grep "atf_helpers:skips.*skipped.*Skipped on purpose" stdout],
|
||||
[0], [ignore], [])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
|
||||
AT_SETUP([run two test cases, failure])
|
||||
AT_TESTED([kyua])
|
||||
|
||||
CREATE_ATF_HELPERS
|
||||
AT_CHECK([RUN_ATF_HELPERS([fails passes])], [1], [stdout], [])
|
||||
AT_CHECK([grep "atf_helpers:fails.*failure.*Failed on purpose" stdout],
|
||||
[1], [], [])
|
||||
AT_CHECK([grep "atf_helpers:passes.*passed" stdout], [0], [ignore], [])
|
||||
AT_CHECK([grep "atf_helpers:skips" stdout], [1], [], [])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
|
||||
AT_SETUP([run mixed test cases])
|
||||
AT_TESTED([kyua])
|
||||
|
||||
CREATE_ATF_HELPERS
|
||||
AT_CHECK([RUN_ATF_HELPERS([fails passes skips])], [1], [stdout], [])
|
||||
AT_CHECK([grep "atf_helpers:fails.*failure.*Failed on purpose" stdout],
|
||||
[1], [], [])
|
||||
AT_CHECK([grep "atf_helpers:passes.*passed" stdout], [0], [ignore], [])
|
||||
AT_CHECK([grep "atf_helpers:skips.*skipped.*Skipped on purpose" stdout],
|
||||
[0], [ignore], [])
|
||||
|
||||
AT_CLEANUP
|
||||
|
||||
|
||||
AT_SETUP([run tests from build directories])
|
||||
AT_TESTED([kyua])
|
||||
|
||||
CREATE_ATF_HELPERS
|
||||
AT_CHECK([mkdir src], [0], [], [])
|
||||
AT_CHECK([mv Kyuafile src], [0], [], [])
|
||||
AT_CHECK([mkdir obj], [0], [], [])
|
||||
AT_CHECK([mv atf_helpers obj], [0], [], [])
|
||||
AT_CHECK([RUN_ATF_HELPERS([fails passes skips],
|
||||
[--kyuafile=src/Kyuafile --build-root=obj])],
|
||||
[1], [stdout], [])
|
||||
AT_CHECK([grep "atf_helpers:fails.*failure.*Failed on purpose" stdout],
|
||||
[1], [], [])
|
||||
AT_CHECK([grep "atf_helpers:passes.*passed" stdout], [0], [ignore], [])
|
||||
AT_CHECK([grep "atf_helpers:skips.*skipped.*Skipped on purpose" stdout],
|
||||
[0], [ignore], [])
|
||||
|
||||
AT_CLEANUP
|
14
contrib/kyua/cli/Kyuafile
Normal file
14
contrib/kyua/cli/Kyuafile
Normal file
@ -0,0 +1,14 @@
|
||||
syntax(2)
|
||||
|
||||
test_suite("kyua")
|
||||
|
||||
atf_test_program{name="cmd_about_test"}
|
||||
atf_test_program{name="cmd_config_test"}
|
||||
atf_test_program{name="cmd_db_exec_test"}
|
||||
atf_test_program{name="cmd_debug_test"}
|
||||
atf_test_program{name="cmd_help_test"}
|
||||
atf_test_program{name="cmd_list_test"}
|
||||
atf_test_program{name="cmd_test_test"}
|
||||
atf_test_program{name="common_test"}
|
||||
atf_test_program{name="config_test"}
|
||||
atf_test_program{name="main_test"}
|
123
contrib/kyua/cli/Makefile.am.inc
Normal file
123
contrib/kyua/cli/Makefile.am.inc
Normal file
@ -0,0 +1,123 @@
|
||||
# Copyright 2010 The Kyua Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
CLI_CFLAGS = $(DRIVERS_CFLAGS)
|
||||
CLI_LIBS = libcli.a $(DRIVERS_LIBS)
|
||||
|
||||
noinst_LIBRARIES += libcli.a
|
||||
libcli_a_SOURCES = cli/cmd_about.cpp
|
||||
libcli_a_SOURCES += cli/cmd_about.hpp
|
||||
libcli_a_SOURCES += cli/cmd_config.cpp
|
||||
libcli_a_SOURCES += cli/cmd_config.hpp
|
||||
libcli_a_SOURCES += cli/cmd_db_exec.cpp
|
||||
libcli_a_SOURCES += cli/cmd_db_exec.hpp
|
||||
libcli_a_SOURCES += cli/cmd_db_migrate.cpp
|
||||
libcli_a_SOURCES += cli/cmd_db_migrate.hpp
|
||||
libcli_a_SOURCES += cli/cmd_debug.cpp
|
||||
libcli_a_SOURCES += cli/cmd_debug.hpp
|
||||
libcli_a_SOURCES += cli/cmd_help.cpp
|
||||
libcli_a_SOURCES += cli/cmd_help.hpp
|
||||
libcli_a_SOURCES += cli/cmd_list.cpp
|
||||
libcli_a_SOURCES += cli/cmd_list.hpp
|
||||
libcli_a_SOURCES += cli/cmd_report.cpp
|
||||
libcli_a_SOURCES += cli/cmd_report.hpp
|
||||
libcli_a_SOURCES += cli/cmd_report_html.cpp
|
||||
libcli_a_SOURCES += cli/cmd_report_html.hpp
|
||||
libcli_a_SOURCES += cli/cmd_report_junit.cpp
|
||||
libcli_a_SOURCES += cli/cmd_report_junit.hpp
|
||||
libcli_a_SOURCES += cli/cmd_test.cpp
|
||||
libcli_a_SOURCES += cli/cmd_test.hpp
|
||||
libcli_a_SOURCES += cli/common.cpp
|
||||
libcli_a_SOURCES += cli/common.hpp
|
||||
libcli_a_SOURCES += cli/common.ipp
|
||||
libcli_a_SOURCES += cli/config.cpp
|
||||
libcli_a_SOURCES += cli/config.hpp
|
||||
libcli_a_SOURCES += cli/main.cpp
|
||||
libcli_a_SOURCES += cli/main.hpp
|
||||
libcli_a_CPPFLAGS = -DKYUA_CONFDIR="\"$(kyua_confdir)\""
|
||||
libcli_a_CPPFLAGS += -DKYUA_DOCDIR="\"$(docdir)\""
|
||||
libcli_a_CPPFLAGS += -DKYUA_MISCDIR="\"$(miscdir)\""
|
||||
libcli_a_CPPFLAGS += $(DRIVERS_CFLAGS)
|
||||
libcli_a_LIBADD = libutils.a
|
||||
|
||||
if WITH_ATF
|
||||
tests_clidir = $(pkgtestsdir)/cli
|
||||
|
||||
tests_cli_DATA = cli/Kyuafile
|
||||
EXTRA_DIST += $(tests_cli_DATA)
|
||||
|
||||
tests_cli_PROGRAMS = cli/cmd_about_test
|
||||
cli_cmd_about_test_SOURCES = cli/cmd_about_test.cpp
|
||||
cli_cmd_about_test_CXXFLAGS = $(CLI_CFLAGS) $(ATF_CXX_CFLAGS)
|
||||
cli_cmd_about_test_LDADD = $(CLI_LIBS) $(ATF_CXX_LIBS)
|
||||
|
||||
tests_cli_PROGRAMS += cli/cmd_config_test
|
||||
cli_cmd_config_test_SOURCES = cli/cmd_config_test.cpp
|
||||
cli_cmd_config_test_CXXFLAGS = $(CLI_CFLAGS) $(ATF_CXX_CFLAGS)
|
||||
cli_cmd_config_test_LDADD = $(CLI_LIBS) $(ATF_CXX_LIBS)
|
||||
|
||||
tests_cli_PROGRAMS += cli/cmd_db_exec_test
|
||||
cli_cmd_db_exec_test_SOURCES = cli/cmd_db_exec_test.cpp
|
||||
cli_cmd_db_exec_test_CXXFLAGS = $(CLI_CFLAGS) $(ATF_CXX_CFLAGS)
|
||||
cli_cmd_db_exec_test_LDADD = $(CLI_LIBS) $(ATF_CXX_LIBS)
|
||||
|
||||
tests_cli_PROGRAMS += cli/cmd_debug_test
|
||||
cli_cmd_debug_test_SOURCES = cli/cmd_debug_test.cpp
|
||||
cli_cmd_debug_test_CXXFLAGS = $(CLI_CFLAGS) $(ATF_CXX_CFLAGS)
|
||||
cli_cmd_debug_test_LDADD = $(CLI_LIBS) $(ATF_CXX_LIBS)
|
||||
|
||||
tests_cli_PROGRAMS += cli/cmd_help_test
|
||||
cli_cmd_help_test_SOURCES = cli/cmd_help_test.cpp
|
||||
cli_cmd_help_test_CXXFLAGS = $(CLI_CFLAGS) $(ATF_CXX_CFLAGS)
|
||||
cli_cmd_help_test_LDADD = $(CLI_LIBS) $(ATF_CXX_LIBS)
|
||||
|
||||
tests_cli_PROGRAMS += cli/cmd_list_test
|
||||
cli_cmd_list_test_SOURCES = cli/cmd_list_test.cpp
|
||||
cli_cmd_list_test_CXXFLAGS = $(CLI_CFLAGS) $(ATF_CXX_CFLAGS)
|
||||
cli_cmd_list_test_LDADD = $(CLI_LIBS) $(ATF_CXX_LIBS)
|
||||
|
||||
tests_cli_PROGRAMS += cli/cmd_test_test
|
||||
cli_cmd_test_test_SOURCES = cli/cmd_test_test.cpp
|
||||
cli_cmd_test_test_CXXFLAGS = $(CLI_CFLAGS) $(ATF_CXX_CFLAGS)
|
||||
cli_cmd_test_test_LDADD = $(CLI_LIBS) $(ATF_CXX_LIBS)
|
||||
|
||||
tests_cli_PROGRAMS += cli/common_test
|
||||
cli_common_test_SOURCES = cli/common_test.cpp
|
||||
cli_common_test_CXXFLAGS = $(CLI_CFLAGS) $(ATF_CXX_CFLAGS)
|
||||
cli_common_test_LDADD = $(CLI_LIBS) $(ATF_CXX_LIBS)
|
||||
|
||||
tests_cli_PROGRAMS += cli/config_test
|
||||
cli_config_test_SOURCES = cli/config_test.cpp
|
||||
cli_config_test_CXXFLAGS = $(CLI_CFLAGS) $(ATF_CXX_CFLAGS)
|
||||
cli_config_test_LDADD = $(CLI_LIBS) $(ATF_CXX_LIBS)
|
||||
|
||||
tests_cli_PROGRAMS += cli/main_test
|
||||
cli_main_test_SOURCES = cli/main_test.cpp
|
||||
cli_main_test_CXXFLAGS = $(CLI_CFLAGS) $(ATF_CXX_CFLAGS)
|
||||
cli_main_test_LDADD = $(CLI_LIBS) $(ATF_CXX_LIBS)
|
||||
endif
|
160
contrib/kyua/cli/cmd_about.cpp
Normal file
160
contrib/kyua/cli/cmd_about.cpp
Normal file
@ -0,0 +1,160 @@
|
||||
// Copyright 2010 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "cli/cmd_about.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "cli/common.ipp"
|
||||
#include "utils/cmdline/exceptions.hpp"
|
||||
#include "utils/cmdline/parser.ipp"
|
||||
#include "utils/cmdline/ui.hpp"
|
||||
#include "utils/defs.hpp"
|
||||
#include "utils/env.hpp"
|
||||
#include "utils/format/macros.hpp"
|
||||
#include "utils/fs/path.hpp"
|
||||
#include "utils/sanity.hpp"
|
||||
#include "utils/text/regex.hpp"
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
namespace cmdline = utils::cmdline;
|
||||
namespace config = utils::config;
|
||||
namespace fs = utils::fs;
|
||||
namespace text = utils::text;
|
||||
|
||||
using cli::cmd_about;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
/// Print the contents of a document.
|
||||
///
|
||||
/// If the file cannot be opened for whatever reason, an error message is
|
||||
/// printed to the output of the program instead of the contents of the file.
|
||||
///
|
||||
/// \param ui Object to interact with the I/O of the program.
|
||||
/// \param file The file to print.
|
||||
/// \param filter_re Regular expression to match the lines to print. If empty,
|
||||
/// no filtering is applied.
|
||||
///
|
||||
/// \return True if the file was printed, false otherwise.
|
||||
static bool
|
||||
cat_file(cmdline::ui* ui, const fs::path& file,
|
||||
const std::string& filter_re = "")
|
||||
{
|
||||
std::ifstream input(file.c_str());
|
||||
if (!input) {
|
||||
ui->err(F("Failed to open %s") % file);
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string line;
|
||||
if (filter_re.empty()) {
|
||||
while (std::getline(input, line).good()) {
|
||||
ui->out(line);
|
||||
}
|
||||
} else {
|
||||
const text::regex filter = text::regex::compile(filter_re, 0);
|
||||
while (std::getline(input, line).good()) {
|
||||
if (filter.match(line)) {
|
||||
ui->out(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
input.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
/// Default constructor for cmd_about.
|
||||
cmd_about::cmd_about(void) : cli_command(
|
||||
"about", "[authors|license|version]", 0, 1,
|
||||
"Shows detailed authors and contributors; license; and version information")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// Entry point for the "about" subcommand.
|
||||
///
|
||||
/// \param ui Object to interact with the I/O of the program.
|
||||
/// \param cmdline Representation of the command line to the subcommand.
|
||||
///
|
||||
/// \return 0 if everything is OK, 1 if any of the necessary documents cannot be
|
||||
/// opened.
|
||||
int
|
||||
cmd_about::run(cmdline::ui* ui, const cmdline::parsed_cmdline& cmdline,
|
||||
const config::tree& /* user_config */)
|
||||
{
|
||||
const fs::path docdir(utils::getenv_with_default(
|
||||
"KYUA_DOCDIR", KYUA_DOCDIR));
|
||||
|
||||
bool success = true;
|
||||
|
||||
static const char* list_re = "^\\* ";
|
||||
|
||||
if (cmdline.arguments().empty()) {
|
||||
ui->out(PACKAGE " (" PACKAGE_NAME ") " PACKAGE_VERSION);
|
||||
ui->out("");
|
||||
ui->out("License terms:");
|
||||
ui->out("");
|
||||
success &= cat_file(ui, docdir / "LICENSE");
|
||||
ui->out("");
|
||||
ui->out("Brought to you by:");
|
||||
ui->out("");
|
||||
success &= cat_file(ui, docdir / "AUTHORS", list_re);
|
||||
ui->out("");
|
||||
success &= cat_file(ui, docdir / "CONTRIBUTORS", list_re);
|
||||
ui->out("");
|
||||
ui->out(F("Homepage: %s") % PACKAGE_URL);
|
||||
} else {
|
||||
const std::string& topic = cmdline.arguments()[0];
|
||||
|
||||
if (topic == "authors") {
|
||||
success &= cat_file(ui, docdir / "AUTHORS", list_re);
|
||||
success &= cat_file(ui, docdir / "CONTRIBUTORS", list_re);
|
||||
} else if (topic == "license") {
|
||||
success &= cat_file(ui, docdir / "LICENSE");
|
||||
} else if (topic == "version") {
|
||||
write_version_header(ui);
|
||||
} else {
|
||||
throw cmdline::usage_error(F("Invalid about topic '%s'") % topic);
|
||||
}
|
||||
}
|
||||
|
||||
return success ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
57
contrib/kyua/cli/cmd_about.hpp
Normal file
57
contrib/kyua/cli/cmd_about.hpp
Normal file
@ -0,0 +1,57 @@
|
||||
// Copyright 2010 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/// \file cli/cmd_about.hpp
|
||||
/// Provides the cmd_about class.
|
||||
|
||||
#if !defined(CLI_CMD_ABOUT_HPP)
|
||||
#define CLI_CMD_ABOUT_HPP
|
||||
|
||||
#include "cli/common.hpp"
|
||||
|
||||
namespace cli {
|
||||
|
||||
|
||||
/// Implementation of the "about" subcommand.
|
||||
class cmd_about : public cli_command
|
||||
{
|
||||
/// Path to the directory containing the distribution documents.
|
||||
const std::string _docdir;
|
||||
|
||||
public:
|
||||
cmd_about(void);
|
||||
|
||||
int run(utils::cmdline::ui*, const utils::cmdline::parsed_cmdline&,
|
||||
const utils::config::tree&);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cli
|
||||
|
||||
|
||||
#endif // !defined(CLI_CMD_ABOUT_HPP)
|
306
contrib/kyua/cli/cmd_about_test.cpp
Normal file
306
contrib/kyua/cli/cmd_about_test.cpp
Normal file
@ -0,0 +1,306 @@
|
||||
// Copyright 2010 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "cli/cmd_about.hpp"
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include <atf-c++.hpp>
|
||||
|
||||
#include "cli/common.ipp"
|
||||
#include "engine/config.hpp"
|
||||
#include "utils/cmdline/exceptions.hpp"
|
||||
#include "utils/cmdline/parser.hpp"
|
||||
#include "utils/cmdline/ui_mock.hpp"
|
||||
#include "utils/config/tree.ipp"
|
||||
#include "utils/env.hpp"
|
||||
#include "utils/fs/operations.hpp"
|
||||
#include "utils/fs/path.hpp"
|
||||
|
||||
namespace cmdline = utils::cmdline;
|
||||
namespace fs = utils::fs;
|
||||
|
||||
using cli::cmd_about;
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(all_topics__ok);
|
||||
ATF_TEST_CASE_BODY(all_topics__ok)
|
||||
{
|
||||
cmdline::args_vector args;
|
||||
args.push_back("about");
|
||||
|
||||
fs::mkdir(fs::path("fake-docs"), 0755);
|
||||
atf::utils::create_file("fake-docs/AUTHORS",
|
||||
"Content of AUTHORS\n"
|
||||
"* First author\n"
|
||||
" * garbage\n"
|
||||
"* Second author\n");
|
||||
atf::utils::create_file("fake-docs/CONTRIBUTORS",
|
||||
"Content of CONTRIBUTORS\n"
|
||||
"* First contributor\n"
|
||||
" * garbage\n"
|
||||
"* Second contributor\n");
|
||||
atf::utils::create_file("fake-docs/LICENSE", "Content of LICENSE\n");
|
||||
|
||||
utils::setenv("KYUA_DOCDIR", "fake-docs");
|
||||
cmd_about cmd;
|
||||
cmdline::ui_mock ui;
|
||||
ATF_REQUIRE_EQ(EXIT_SUCCESS, cmd.main(&ui, args, engine::default_config()));
|
||||
|
||||
ATF_REQUIRE(atf::utils::grep_string(PACKAGE_NAME, ui.out_log()[0]));
|
||||
ATF_REQUIRE(atf::utils::grep_string(PACKAGE_VERSION, ui.out_log()[0]));
|
||||
|
||||
ATF_REQUIRE(!atf::utils::grep_collection("Content of AUTHORS",
|
||||
ui.out_log()));
|
||||
ATF_REQUIRE(atf::utils::grep_collection("\\* First author", ui.out_log()));
|
||||
ATF_REQUIRE(!atf::utils::grep_collection("garbage", ui.out_log()));
|
||||
ATF_REQUIRE(atf::utils::grep_collection("\\* Second author", ui.out_log()));
|
||||
|
||||
ATF_REQUIRE(!atf::utils::grep_collection("Content of CONTRIBUTORS",
|
||||
ui.out_log()));
|
||||
ATF_REQUIRE(atf::utils::grep_collection("\\* First contributor",
|
||||
ui.out_log()));
|
||||
ATF_REQUIRE(!atf::utils::grep_collection("garbage", ui.out_log()));
|
||||
ATF_REQUIRE(atf::utils::grep_collection("\\* Second contributor",
|
||||
ui.out_log()));
|
||||
|
||||
ATF_REQUIRE(atf::utils::grep_collection("Content of LICENSE",
|
||||
ui.out_log()));
|
||||
|
||||
ATF_REQUIRE(atf::utils::grep_collection("Homepage", ui.out_log()));
|
||||
ATF_REQUIRE(ui.err_log().empty());
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(all_topics__missing_docs);
|
||||
ATF_TEST_CASE_BODY(all_topics__missing_docs)
|
||||
{
|
||||
cmdline::args_vector args;
|
||||
args.push_back("about");
|
||||
|
||||
utils::setenv("KYUA_DOCDIR", "fake-docs");
|
||||
cmd_about cmd;
|
||||
cmdline::ui_mock ui;
|
||||
ATF_REQUIRE_EQ(EXIT_FAILURE, cmd.main(&ui, args, engine::default_config()));
|
||||
|
||||
ATF_REQUIRE(atf::utils::grep_string(PACKAGE_NAME, ui.out_log()[0]));
|
||||
ATF_REQUIRE(atf::utils::grep_string(PACKAGE_VERSION, ui.out_log()[0]));
|
||||
|
||||
ATF_REQUIRE(atf::utils::grep_collection("Homepage", ui.out_log()));
|
||||
|
||||
ATF_REQUIRE(atf::utils::grep_collection("Failed to open.*AUTHORS",
|
||||
ui.err_log()));
|
||||
ATF_REQUIRE(atf::utils::grep_collection("Failed to open.*CONTRIBUTORS",
|
||||
ui.err_log()));
|
||||
ATF_REQUIRE(atf::utils::grep_collection("Failed to open.*LICENSE",
|
||||
ui.err_log()));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(topic_authors__ok);
|
||||
ATF_TEST_CASE_BODY(topic_authors__ok)
|
||||
{
|
||||
cmdline::args_vector args;
|
||||
args.push_back("about");
|
||||
args.push_back("authors");
|
||||
|
||||
fs::mkdir(fs::path("fake-docs"), 0755);
|
||||
atf::utils::create_file("fake-docs/AUTHORS",
|
||||
"Content of AUTHORS\n"
|
||||
"* First author\n"
|
||||
" * garbage\n"
|
||||
"* Second author\n");
|
||||
atf::utils::create_file("fake-docs/CONTRIBUTORS",
|
||||
"Content of CONTRIBUTORS\n"
|
||||
"* First contributor\n"
|
||||
" * garbage\n"
|
||||
"* Second contributor\n");
|
||||
|
||||
utils::setenv("KYUA_DOCDIR", "fake-docs");
|
||||
cmd_about cmd;
|
||||
cmdline::ui_mock ui;
|
||||
ATF_REQUIRE_EQ(EXIT_SUCCESS, cmd.main(&ui, args, engine::default_config()));
|
||||
ATF_REQUIRE(!atf::utils::grep_string(PACKAGE_NAME, ui.out_log()[0]));
|
||||
|
||||
ATF_REQUIRE(!atf::utils::grep_collection("Content of AUTHORS",
|
||||
ui.out_log()));
|
||||
ATF_REQUIRE(atf::utils::grep_collection("\\* First author", ui.out_log()));
|
||||
ATF_REQUIRE(!atf::utils::grep_collection("garbage", ui.out_log()));
|
||||
ATF_REQUIRE(atf::utils::grep_collection("\\* Second author", ui.out_log()));
|
||||
|
||||
ATF_REQUIRE(!atf::utils::grep_collection("Content of CONTRIBUTORS",
|
||||
ui.out_log()));
|
||||
ATF_REQUIRE(atf::utils::grep_collection("\\* First contributor",
|
||||
ui.out_log()));
|
||||
ATF_REQUIRE(!atf::utils::grep_collection("garbage", ui.out_log()));
|
||||
ATF_REQUIRE(atf::utils::grep_collection("\\* Second contributor",
|
||||
ui.out_log()));
|
||||
|
||||
ATF_REQUIRE(!atf::utils::grep_collection("LICENSE", ui.out_log()));
|
||||
ATF_REQUIRE(!atf::utils::grep_collection("Homepage", ui.out_log()));
|
||||
ATF_REQUIRE(ui.err_log().empty());
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(topic_authors__missing_doc);
|
||||
ATF_TEST_CASE_BODY(topic_authors__missing_doc)
|
||||
{
|
||||
cmdline::args_vector args;
|
||||
args.push_back("about");
|
||||
args.push_back("authors");
|
||||
|
||||
utils::setenv("KYUA_DOCDIR", "fake-docs");
|
||||
cmd_about cmd;
|
||||
cmdline::ui_mock ui;
|
||||
ATF_REQUIRE_EQ(EXIT_FAILURE, cmd.main(&ui, args, engine::default_config()));
|
||||
|
||||
ATF_REQUIRE_EQ(0, ui.out_log().size());
|
||||
|
||||
ATF_REQUIRE(atf::utils::grep_collection("Failed to open.*AUTHORS",
|
||||
ui.err_log()));
|
||||
ATF_REQUIRE(atf::utils::grep_collection("Failed to open.*CONTRIBUTORS",
|
||||
ui.err_log()));
|
||||
ATF_REQUIRE(!atf::utils::grep_collection("Failed to open.*LICENSE",
|
||||
ui.err_log()));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(topic_license__ok);
|
||||
ATF_TEST_CASE_BODY(topic_license__ok)
|
||||
{
|
||||
cmdline::args_vector args;
|
||||
args.push_back("about");
|
||||
args.push_back("license");
|
||||
|
||||
fs::mkdir(fs::path("fake-docs"), 0755);
|
||||
atf::utils::create_file("fake-docs/LICENSE", "Content of LICENSE\n");
|
||||
|
||||
utils::setenv("KYUA_DOCDIR", "fake-docs");
|
||||
cmd_about cmd;
|
||||
cmdline::ui_mock ui;
|
||||
ATF_REQUIRE_EQ(EXIT_SUCCESS, cmd.main(&ui, args, engine::default_config()));
|
||||
ATF_REQUIRE(!atf::utils::grep_string(PACKAGE_NAME, ui.out_log()[0]));
|
||||
ATF_REQUIRE(!atf::utils::grep_collection("AUTHORS", ui.out_log()));
|
||||
ATF_REQUIRE(!atf::utils::grep_collection("CONTRIBUTORS", ui.out_log()));
|
||||
ATF_REQUIRE(atf::utils::grep_collection("Content of LICENSE",
|
||||
ui.out_log()));
|
||||
ATF_REQUIRE(!atf::utils::grep_collection("Homepage", ui.out_log()));
|
||||
ATF_REQUIRE(ui.err_log().empty());
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(topic_license__missing_doc);
|
||||
ATF_TEST_CASE_BODY(topic_license__missing_doc)
|
||||
{
|
||||
cmdline::args_vector args;
|
||||
args.push_back("about");
|
||||
args.push_back("license");
|
||||
|
||||
utils::setenv("KYUA_DOCDIR", "fake-docs");
|
||||
cmd_about cmd;
|
||||
cmdline::ui_mock ui;
|
||||
ATF_REQUIRE_EQ(EXIT_FAILURE, cmd.main(&ui, args, engine::default_config()));
|
||||
|
||||
ATF_REQUIRE_EQ(0, ui.out_log().size());
|
||||
|
||||
ATF_REQUIRE(!atf::utils::grep_collection("Failed to open.*AUTHORS",
|
||||
ui.err_log()));
|
||||
ATF_REQUIRE(!atf::utils::grep_collection("Failed to open.*CONTRIBUTORS",
|
||||
ui.err_log()));
|
||||
ATF_REQUIRE(atf::utils::grep_collection("Failed to open.*LICENSE",
|
||||
ui.err_log()));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(topic_version__ok);
|
||||
ATF_TEST_CASE_BODY(topic_version__ok)
|
||||
{
|
||||
cmdline::args_vector args;
|
||||
args.push_back("about");
|
||||
args.push_back("version");
|
||||
|
||||
utils::setenv("KYUA_DOCDIR", "fake-docs");
|
||||
cmd_about cmd;
|
||||
cmdline::ui_mock ui;
|
||||
ATF_REQUIRE_EQ(EXIT_SUCCESS, cmd.main(&ui, args, engine::default_config()));
|
||||
ATF_REQUIRE_EQ(1, ui.out_log().size());
|
||||
ATF_REQUIRE(atf::utils::grep_string(PACKAGE_NAME, ui.out_log()[0]));
|
||||
ATF_REQUIRE(atf::utils::grep_string(PACKAGE_VERSION, ui.out_log()[0]));
|
||||
ATF_REQUIRE(ui.err_log().empty());
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(invalid_args);
|
||||
ATF_TEST_CASE_BODY(invalid_args)
|
||||
{
|
||||
cmdline::args_vector args;
|
||||
args.push_back("about");
|
||||
args.push_back("first");
|
||||
args.push_back("second");
|
||||
|
||||
cmd_about cmd;
|
||||
cmdline::ui_mock ui;
|
||||
ATF_REQUIRE_THROW_RE(cmdline::usage_error, "Too many arguments",
|
||||
cmd.main(&ui, args, engine::default_config()));
|
||||
ATF_REQUIRE(ui.out_log().empty());
|
||||
ATF_REQUIRE(ui.err_log().empty());
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(invalid_topic);
|
||||
ATF_TEST_CASE_BODY(invalid_topic)
|
||||
{
|
||||
cmdline::args_vector args;
|
||||
args.push_back("about");
|
||||
args.push_back("foo");
|
||||
|
||||
cmd_about cmd;
|
||||
cmdline::ui_mock ui;
|
||||
ATF_REQUIRE_THROW_RE(cmdline::usage_error, "Invalid about topic 'foo'",
|
||||
cmd.main(&ui, args, engine::default_config()));
|
||||
ATF_REQUIRE(ui.out_log().empty());
|
||||
ATF_REQUIRE(ui.err_log().empty());
|
||||
}
|
||||
|
||||
|
||||
ATF_INIT_TEST_CASES(tcs)
|
||||
{
|
||||
ATF_ADD_TEST_CASE(tcs, all_topics__ok);
|
||||
ATF_ADD_TEST_CASE(tcs, all_topics__missing_docs);
|
||||
ATF_ADD_TEST_CASE(tcs, topic_authors__ok);
|
||||
ATF_ADD_TEST_CASE(tcs, topic_authors__missing_doc);
|
||||
ATF_ADD_TEST_CASE(tcs, topic_license__ok);
|
||||
ATF_ADD_TEST_CASE(tcs, topic_license__missing_doc);
|
||||
ATF_ADD_TEST_CASE(tcs, topic_version__ok);
|
||||
ATF_ADD_TEST_CASE(tcs, invalid_args);
|
||||
ATF_ADD_TEST_CASE(tcs, invalid_topic);
|
||||
}
|
122
contrib/kyua/cli/cmd_config.cpp
Normal file
122
contrib/kyua/cli/cmd_config.cpp
Normal file
@ -0,0 +1,122 @@
|
||||
// Copyright 2011 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "cli/cmd_config.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include "cli/common.ipp"
|
||||
#include "utils/cmdline/parser.ipp"
|
||||
#include "utils/cmdline/ui.hpp"
|
||||
#include "utils/config/tree.ipp"
|
||||
#include "utils/format/macros.hpp"
|
||||
|
||||
namespace cmdline = utils::cmdline;
|
||||
namespace config = utils::config;
|
||||
|
||||
using cli::cmd_config;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
/// Prints all configuration variables.
|
||||
///
|
||||
/// \param ui Object to interact with the I/O of the program.
|
||||
/// \param properties The key/value map representing all the configuration
|
||||
/// variables.
|
||||
///
|
||||
/// \return 0 for success.
|
||||
static int
|
||||
print_all(cmdline::ui* ui, const config::properties_map& properties)
|
||||
{
|
||||
for (config::properties_map::const_iterator iter = properties.begin();
|
||||
iter != properties.end(); iter++)
|
||||
ui->out(F("%s = %s") % (*iter).first % (*iter).second);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/// Prints the configuration variables that the user requests.
|
||||
///
|
||||
/// \param ui Object to interact with the I/O of the program.
|
||||
/// \param properties The key/value map representing all the configuration
|
||||
/// variables.
|
||||
/// \param filters The names of the configuration variables to print.
|
||||
///
|
||||
/// \return 0 if all specified filters are valid; 1 otherwise.
|
||||
static int
|
||||
print_some(cmdline::ui* ui, const config::properties_map& properties,
|
||||
const cmdline::args_vector& filters)
|
||||
{
|
||||
bool ok = true;
|
||||
|
||||
for (cmdline::args_vector::const_iterator iter = filters.begin();
|
||||
iter != filters.end(); iter++) {
|
||||
const config::properties_map::const_iterator match =
|
||||
properties.find(*iter);
|
||||
if (match == properties.end()) {
|
||||
cmdline::print_warning(ui, F("'%s' is not defined.") % *iter);
|
||||
ok = false;
|
||||
} else
|
||||
ui->out(F("%s = %s") % (*match).first % (*match).second);
|
||||
}
|
||||
|
||||
return ok ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
/// Default constructor for cmd_config.
|
||||
cmd_config::cmd_config(void) : cli_command(
|
||||
"config", "[variable1 .. variableN]", 0, -1,
|
||||
"Inspects the values of configuration variables")
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// Entry point for the "config" subcommand.
|
||||
///
|
||||
/// \param ui Object to interact with the I/O of the program.
|
||||
/// \param cmdline Representation of the command line to the subcommand.
|
||||
/// \param user_config The runtime configuration of the program.
|
||||
///
|
||||
/// \return 0 if everything is OK, 1 if any of the necessary documents cannot be
|
||||
/// opened.
|
||||
int
|
||||
cmd_config::run(cmdline::ui* ui, const cmdline::parsed_cmdline& cmdline,
|
||||
const config::tree& user_config)
|
||||
{
|
||||
const config::properties_map properties = user_config.all_properties();
|
||||
if (cmdline.arguments().empty())
|
||||
return print_all(ui, properties);
|
||||
else
|
||||
return print_some(ui, properties, cmdline.arguments());
|
||||
}
|
54
contrib/kyua/cli/cmd_config.hpp
Normal file
54
contrib/kyua/cli/cmd_config.hpp
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright 2011 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/// \file cli/cmd_config.hpp
|
||||
/// Provides the cmd_config class.
|
||||
|
||||
#if !defined(CLI_CMD_CONFIG_HPP)
|
||||
#define CLI_CMD_CONFIG_HPP
|
||||
|
||||
#include "cli/common.hpp"
|
||||
|
||||
namespace cli {
|
||||
|
||||
|
||||
/// Implementation of the "config" subcommand.
|
||||
class cmd_config : public cli_command
|
||||
{
|
||||
public:
|
||||
cmd_config(void);
|
||||
|
||||
int run(utils::cmdline::ui*, const utils::cmdline::parsed_cmdline&,
|
||||
const utils::config::tree&);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cli
|
||||
|
||||
|
||||
#endif // !defined(CLI_CMD_CONFIG_HPP)
|
144
contrib/kyua/cli/cmd_config_test.cpp
Normal file
144
contrib/kyua/cli/cmd_config_test.cpp
Normal file
@ -0,0 +1,144 @@
|
||||
// Copyright 2011 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "cli/cmd_config.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include <atf-c++.hpp>
|
||||
|
||||
#include "cli/common.ipp"
|
||||
#include "engine/config.hpp"
|
||||
#include "utils/cmdline/globals.hpp"
|
||||
#include "utils/cmdline/parser.hpp"
|
||||
#include "utils/cmdline/ui_mock.hpp"
|
||||
#include "utils/config/tree.ipp"
|
||||
#include "utils/optional.ipp"
|
||||
|
||||
namespace cmdline = utils::cmdline;
|
||||
namespace config = utils::config;
|
||||
|
||||
using cli::cmd_config;
|
||||
using utils::none;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
/// Instantiates a fake user configuration for testing purposes.
|
||||
///
|
||||
/// The user configuration is populated with a collection of test-suite
|
||||
/// properties and some hardcoded values for the generic configuration options.
|
||||
///
|
||||
/// \return A new user configuration object.
|
||||
static config::tree
|
||||
fake_config(void)
|
||||
{
|
||||
config::tree user_config = engine::default_config();
|
||||
user_config.set_string("architecture", "the-architecture");
|
||||
user_config.set_string("parallelism", "128");
|
||||
user_config.set_string("platform", "the-platform");
|
||||
//user_config.set_string("unprivileged_user", "");
|
||||
user_config.set_string("test_suites.foo.bar", "first");
|
||||
user_config.set_string("test_suites.foo.baz", "second");
|
||||
return user_config;
|
||||
}
|
||||
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(all);
|
||||
ATF_TEST_CASE_BODY(all)
|
||||
{
|
||||
cmdline::args_vector args;
|
||||
args.push_back("config");
|
||||
|
||||
cmd_config cmd;
|
||||
cmdline::ui_mock ui;
|
||||
ATF_REQUIRE_EQ(EXIT_SUCCESS, cmd.main(&ui, args, fake_config()));
|
||||
|
||||
ATF_REQUIRE_EQ(5, ui.out_log().size());
|
||||
ATF_REQUIRE_EQ("architecture = the-architecture", ui.out_log()[0]);
|
||||
ATF_REQUIRE_EQ("parallelism = 128", ui.out_log()[1]);
|
||||
ATF_REQUIRE_EQ("platform = the-platform", ui.out_log()[2]);
|
||||
ATF_REQUIRE_EQ("test_suites.foo.bar = first", ui.out_log()[3]);
|
||||
ATF_REQUIRE_EQ("test_suites.foo.baz = second", ui.out_log()[4]);
|
||||
ATF_REQUIRE(ui.err_log().empty());
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(some__ok);
|
||||
ATF_TEST_CASE_BODY(some__ok)
|
||||
{
|
||||
cmdline::args_vector args;
|
||||
args.push_back("config");
|
||||
args.push_back("platform");
|
||||
args.push_back("test_suites.foo.baz");
|
||||
|
||||
cmd_config cmd;
|
||||
cmdline::ui_mock ui;
|
||||
ATF_REQUIRE_EQ(EXIT_SUCCESS, cmd.main(&ui, args, fake_config()));
|
||||
|
||||
ATF_REQUIRE_EQ(2, ui.out_log().size());
|
||||
ATF_REQUIRE_EQ("platform = the-platform", ui.out_log()[0]);
|
||||
ATF_REQUIRE_EQ("test_suites.foo.baz = second", ui.out_log()[1]);
|
||||
ATF_REQUIRE(ui.err_log().empty());
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(some__fail);
|
||||
ATF_TEST_CASE_BODY(some__fail)
|
||||
{
|
||||
cmdline::args_vector args;
|
||||
args.push_back("config");
|
||||
args.push_back("platform");
|
||||
args.push_back("unknown");
|
||||
args.push_back("test_suites.foo.baz");
|
||||
|
||||
cmdline::init("progname");
|
||||
|
||||
cmd_config cmd;
|
||||
cmdline::ui_mock ui;
|
||||
ATF_REQUIRE_EQ(EXIT_FAILURE, cmd.main(&ui, args, fake_config()));
|
||||
|
||||
ATF_REQUIRE_EQ(2, ui.out_log().size());
|
||||
ATF_REQUIRE_EQ("platform = the-platform", ui.out_log()[0]);
|
||||
ATF_REQUIRE_EQ("test_suites.foo.baz = second", ui.out_log()[1]);
|
||||
ATF_REQUIRE_EQ(1, ui.err_log().size());
|
||||
ATF_REQUIRE(atf::utils::grep_string("unknown.*not defined",
|
||||
ui.err_log()[0]));
|
||||
}
|
||||
|
||||
|
||||
ATF_INIT_TEST_CASES(tcs)
|
||||
{
|
||||
ATF_ADD_TEST_CASE(tcs, all);
|
||||
ATF_ADD_TEST_CASE(tcs, some__ok);
|
||||
ATF_ADD_TEST_CASE(tcs, some__fail);
|
||||
}
|
200
contrib/kyua/cli/cmd_db_exec.cpp
Normal file
200
contrib/kyua/cli/cmd_db_exec.cpp
Normal file
@ -0,0 +1,200 @@
|
||||
// Copyright 2011 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "cli/cmd_db_exec.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "cli/common.ipp"
|
||||
#include "store/exceptions.hpp"
|
||||
#include "store/layout.hpp"
|
||||
#include "store/read_backend.hpp"
|
||||
#include "utils/cmdline/options.hpp"
|
||||
#include "utils/cmdline/parser.ipp"
|
||||
#include "utils/cmdline/ui.hpp"
|
||||
#include "utils/defs.hpp"
|
||||
#include "utils/format/macros.hpp"
|
||||
#include "utils/fs/path.hpp"
|
||||
#include "utils/sanity.hpp"
|
||||
#include "utils/sqlite/database.hpp"
|
||||
#include "utils/sqlite/exceptions.hpp"
|
||||
#include "utils/sqlite/statement.hpp"
|
||||
|
||||
namespace cmdline = utils::cmdline;
|
||||
namespace config = utils::config;
|
||||
namespace fs = utils::fs;
|
||||
namespace layout = store::layout;
|
||||
namespace sqlite = utils::sqlite;
|
||||
|
||||
using cli::cmd_db_exec;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
/// Concatenates a vector into a string using ' ' as a separator.
|
||||
///
|
||||
/// \param args The objects to join. This cannot be empty.
|
||||
///
|
||||
/// \return The concatenation of all the objects in the set.
|
||||
static std::string
|
||||
flatten_args(const cmdline::args_vector& args)
|
||||
{
|
||||
std::ostringstream output;
|
||||
std::copy(args.begin(), args.end(),
|
||||
std::ostream_iterator< std::string >(output, " "));
|
||||
|
||||
std::string result = output.str();
|
||||
result.erase(result.end() - 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
/// Formats a particular cell of a statement result.
|
||||
///
|
||||
/// \param stmt The statement whose cell to format.
|
||||
/// \param index The index of the cell to format.
|
||||
///
|
||||
/// \return A textual representation of the cell.
|
||||
std::string
|
||||
cli::format_cell(sqlite::statement& stmt, const int index)
|
||||
{
|
||||
switch (stmt.column_type(index)) {
|
||||
case sqlite::type_blob: {
|
||||
const sqlite::blob blob = stmt.column_blob(index);
|
||||
return F("BLOB of %s bytes") % blob.size;
|
||||
}
|
||||
|
||||
case sqlite::type_float:
|
||||
return F("%s") % stmt.column_double(index);
|
||||
|
||||
case sqlite::type_integer:
|
||||
return F("%s") % stmt.column_int64(index);
|
||||
|
||||
case sqlite::type_null:
|
||||
return "NULL";
|
||||
|
||||
case sqlite::type_text:
|
||||
return stmt.column_text(index);
|
||||
}
|
||||
|
||||
UNREACHABLE;
|
||||
}
|
||||
|
||||
|
||||
/// Formats the column names of a statement for output as CSV.
|
||||
///
|
||||
/// \param stmt The statement whose columns to format.
|
||||
///
|
||||
/// \return A comma-separated list of column names.
|
||||
std::string
|
||||
cli::format_headers(sqlite::statement& stmt)
|
||||
{
|
||||
std::string output;
|
||||
int i = 0;
|
||||
for (; i < stmt.column_count() - 1; ++i)
|
||||
output += stmt.column_name(i) + ',';
|
||||
output += stmt.column_name(i);
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
/// Formats a row of a statement for output as CSV.
|
||||
///
|
||||
/// \param stmt The statement whose current row to format.
|
||||
///
|
||||
/// \return A comma-separated list of values.
|
||||
std::string
|
||||
cli::format_row(sqlite::statement& stmt)
|
||||
{
|
||||
std::string output;
|
||||
int i = 0;
|
||||
for (; i < stmt.column_count() - 1; ++i)
|
||||
output += cli::format_cell(stmt, i) + ',';
|
||||
output += cli::format_cell(stmt, i);
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
/// Default constructor for cmd_db_exec.
|
||||
cmd_db_exec::cmd_db_exec(void) : cli_command(
|
||||
"db-exec", "sql_statement", 1, -1,
|
||||
"Executes an arbitrary SQL statement in a results file and prints "
|
||||
"the resulting table")
|
||||
{
|
||||
add_option(results_file_open_option);
|
||||
add_option(cmdline::bool_option("no-headers", "Do not show headers in the "
|
||||
"output table"));
|
||||
}
|
||||
|
||||
|
||||
/// Entry point for the "db-exec" subcommand.
|
||||
///
|
||||
/// \param ui Object to interact with the I/O of the program.
|
||||
/// \param cmdline Representation of the command line to the subcommand.
|
||||
///
|
||||
/// \return 0 if everything is OK, 1 if the statement is invalid or if there is
|
||||
/// any other problem.
|
||||
int
|
||||
cmd_db_exec::run(cmdline::ui* ui, const cmdline::parsed_cmdline& cmdline,
|
||||
const config::tree& /* user_config */)
|
||||
{
|
||||
try {
|
||||
const fs::path results_file = layout::find_results(
|
||||
results_file_open(cmdline));
|
||||
|
||||
// TODO(jmmv): Shouldn't be using store::detail here...
|
||||
sqlite::database db = store::detail::open_and_setup(
|
||||
results_file, sqlite::open_readwrite);
|
||||
sqlite::statement stmt = db.create_statement(
|
||||
flatten_args(cmdline.arguments()));
|
||||
|
||||
if (stmt.step()) {
|
||||
if (!cmdline.has_option("no-headers"))
|
||||
ui->out(cli::format_headers(stmt));
|
||||
do
|
||||
ui->out(cli::format_row(stmt));
|
||||
while (stmt.step());
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
} catch (const sqlite::error& e) {
|
||||
cmdline::print_error(ui, F("SQLite error: %s.") % e.what());
|
||||
return EXIT_FAILURE;
|
||||
} catch (const store::error& e) {
|
||||
cmdline::print_error(ui, F("%s.") % e.what());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
61
contrib/kyua/cli/cmd_db_exec.hpp
Normal file
61
contrib/kyua/cli/cmd_db_exec.hpp
Normal file
@ -0,0 +1,61 @@
|
||||
// Copyright 2011 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/// \file cli/cmd_db_exec.hpp
|
||||
/// Provides the cmd_db_exec class.
|
||||
|
||||
#if !defined(CLI_CMD_DB_EXEC_HPP)
|
||||
#define CLI_CMD_DB_EXEC_HPP
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "cli/common.hpp"
|
||||
#include "utils/sqlite/statement_fwd.hpp"
|
||||
|
||||
namespace cli {
|
||||
|
||||
|
||||
std::string format_cell(utils::sqlite::statement&, const int);
|
||||
std::string format_headers(utils::sqlite::statement&);
|
||||
std::string format_row(utils::sqlite::statement&);
|
||||
|
||||
|
||||
/// Implementation of the "db-exec" subcommand.
|
||||
class cmd_db_exec : public cli_command
|
||||
{
|
||||
public:
|
||||
cmd_db_exec(void);
|
||||
|
||||
int run(utils::cmdline::ui*, const utils::cmdline::parsed_cmdline&,
|
||||
const utils::config::tree&);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cli
|
||||
|
||||
#endif // !defined(CLI_CMD_DB_EXEC_HPP)
|
165
contrib/kyua/cli/cmd_db_exec_test.cpp
Normal file
165
contrib/kyua/cli/cmd_db_exec_test.cpp
Normal file
@ -0,0 +1,165 @@
|
||||
// Copyright 2011 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "cli/cmd_db_exec.hpp"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include <atf-c++.hpp>
|
||||
|
||||
#include "utils/format/macros.hpp"
|
||||
#include "utils/sqlite/database.hpp"
|
||||
#include "utils/sqlite/statement.ipp"
|
||||
|
||||
namespace sqlite = utils::sqlite;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
/// Performs a test for the cli::format_cell() function.
|
||||
///
|
||||
/// \tparam Cell The type of the value to insert into the test column.
|
||||
/// \param column_type The SQL type of the test column.
|
||||
/// \param value The value to insert into the test column.
|
||||
/// \param exp_value The expected return value of cli::format_cell().
|
||||
template< class Cell >
|
||||
static void
|
||||
do_format_cell_test(const std::string column_type,
|
||||
const Cell& value, const std::string& exp_value)
|
||||
{
|
||||
sqlite::database db = sqlite::database::in_memory();
|
||||
|
||||
sqlite::statement create = db.create_statement(
|
||||
F("CREATE TABLE test (column %s)") % column_type);
|
||||
create.step_without_results();
|
||||
|
||||
sqlite::statement insert = db.create_statement(
|
||||
"INSERT INTO test (column) VALUES (:column)");
|
||||
insert.bind(":column", value);
|
||||
insert.step_without_results();
|
||||
|
||||
sqlite::statement query = db.create_statement("SELECT * FROM test");
|
||||
ATF_REQUIRE(query.step());
|
||||
ATF_REQUIRE_EQ(exp_value, cli::format_cell(query, 0));
|
||||
ATF_REQUIRE(!query.step());
|
||||
}
|
||||
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(format_cell__blob);
|
||||
ATF_TEST_CASE_BODY(format_cell__blob)
|
||||
{
|
||||
const char* contents = "Some random contents";
|
||||
do_format_cell_test(
|
||||
"BLOB", sqlite::blob(contents, std::strlen(contents)),
|
||||
F("BLOB of %s bytes") % strlen(contents));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(format_cell__float);
|
||||
ATF_TEST_CASE_BODY(format_cell__float)
|
||||
{
|
||||
do_format_cell_test("FLOAT", 3.5, "3.5");
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(format_cell__integer);
|
||||
ATF_TEST_CASE_BODY(format_cell__integer)
|
||||
{
|
||||
do_format_cell_test("INTEGER", 123456, "123456");
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(format_cell__null);
|
||||
ATF_TEST_CASE_BODY(format_cell__null)
|
||||
{
|
||||
do_format_cell_test("TEXT", sqlite::null(), "NULL");
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(format_cell__text);
|
||||
ATF_TEST_CASE_BODY(format_cell__text)
|
||||
{
|
||||
do_format_cell_test("TEXT", "Hello, world", "Hello, world");
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(format_headers);
|
||||
ATF_TEST_CASE_BODY(format_headers)
|
||||
{
|
||||
sqlite::database db = sqlite::database::in_memory();
|
||||
|
||||
sqlite::statement create = db.create_statement(
|
||||
"CREATE TABLE test (c1 TEXT, c2 TEXT, c3 TEXT)");
|
||||
create.step_without_results();
|
||||
|
||||
sqlite::statement query = db.create_statement(
|
||||
"SELECT c1, c2, c3 AS c3bis FROM test");
|
||||
ATF_REQUIRE_EQ("c1,c2,c3bis", cli::format_headers(query));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(format_row);
|
||||
ATF_TEST_CASE_BODY(format_row)
|
||||
{
|
||||
sqlite::database db = sqlite::database::in_memory();
|
||||
|
||||
sqlite::statement create = db.create_statement(
|
||||
"CREATE TABLE test (c1 TEXT, c2 BLOB)");
|
||||
create.step_without_results();
|
||||
|
||||
const char* memory = "BLOB contents";
|
||||
sqlite::statement insert = db.create_statement(
|
||||
"INSERT INTO test VALUES (:v1, :v2)");
|
||||
insert.bind(":v1", "A string");
|
||||
insert.bind(":v2", sqlite::blob(memory, std::strlen(memory)));
|
||||
insert.step_without_results();
|
||||
|
||||
sqlite::statement query = db.create_statement("SELECT * FROM test");
|
||||
query.step();
|
||||
ATF_REQUIRE_EQ(
|
||||
(F("A string,BLOB of %s bytes") % std::strlen(memory)).str(),
|
||||
cli::format_row(query));
|
||||
}
|
||||
|
||||
|
||||
ATF_INIT_TEST_CASES(tcs)
|
||||
{
|
||||
ATF_ADD_TEST_CASE(tcs, format_cell__blob);
|
||||
ATF_ADD_TEST_CASE(tcs, format_cell__float);
|
||||
ATF_ADD_TEST_CASE(tcs, format_cell__integer);
|
||||
ATF_ADD_TEST_CASE(tcs, format_cell__null);
|
||||
ATF_ADD_TEST_CASE(tcs, format_cell__text);
|
||||
|
||||
ATF_ADD_TEST_CASE(tcs, format_headers);
|
||||
|
||||
ATF_ADD_TEST_CASE(tcs, format_row);
|
||||
}
|
82
contrib/kyua/cli/cmd_db_migrate.cpp
Normal file
82
contrib/kyua/cli/cmd_db_migrate.cpp
Normal file
@ -0,0 +1,82 @@
|
||||
// Copyright 2013 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "cli/cmd_db_migrate.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include "cli/common.ipp"
|
||||
#include "store/exceptions.hpp"
|
||||
#include "store/layout.hpp"
|
||||
#include "store/migrate.hpp"
|
||||
#include "utils/cmdline/options.hpp"
|
||||
#include "utils/cmdline/ui.hpp"
|
||||
#include "utils/defs.hpp"
|
||||
#include "utils/format/macros.hpp"
|
||||
#include "utils/fs/path.hpp"
|
||||
|
||||
namespace cmdline = utils::cmdline;
|
||||
namespace config = utils::config;
|
||||
namespace fs = utils::fs;
|
||||
namespace layout = store::layout;
|
||||
|
||||
using cli::cmd_db_migrate;
|
||||
|
||||
|
||||
/// Default constructor for cmd_db_migrate.
|
||||
cmd_db_migrate::cmd_db_migrate(void) : cli_command(
|
||||
"db-migrate", "", 0, 0,
|
||||
"Upgrades the schema of an existing results file to the currently "
|
||||
"implemented version. A backup of the results file is created, but "
|
||||
"this operation is not reversible")
|
||||
{
|
||||
add_option(results_file_open_option);
|
||||
}
|
||||
|
||||
|
||||
/// Entry point for the "db-migrate" subcommand.
|
||||
///
|
||||
/// \param ui Object to interact with the I/O of the program.
|
||||
/// \param cmdline Representation of the command line to the subcommand.
|
||||
///
|
||||
/// \return 0 if everything is OK, 1 if the statement is invalid or if there is
|
||||
/// any other problem.
|
||||
int
|
||||
cmd_db_migrate::run(cmdline::ui* ui, const cmdline::parsed_cmdline& cmdline,
|
||||
const config::tree& /* user_config */)
|
||||
{
|
||||
try {
|
||||
const fs::path results_file = layout::find_results(
|
||||
results_file_open(cmdline));
|
||||
store::migrate_schema(results_file);
|
||||
return EXIT_SUCCESS;
|
||||
} catch (const store::error& e) {
|
||||
cmdline::print_error(ui, F("Migration failed: %s.") % e.what());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
54
contrib/kyua/cli/cmd_db_migrate.hpp
Normal file
54
contrib/kyua/cli/cmd_db_migrate.hpp
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright 2013 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/// \file cli/cmd_db_migrate.hpp
|
||||
/// Provides the cmd_db_migrate class.
|
||||
|
||||
#if !defined(CLI_CMD_DB_MIGRATE_HPP)
|
||||
#define CLI_CMD_DB_MIGRATE_HPP
|
||||
|
||||
#include "cli/common.hpp"
|
||||
|
||||
namespace cli {
|
||||
|
||||
|
||||
/// Implementation of the "db-migrate" subcommand.
|
||||
class cmd_db_migrate : public cli_command
|
||||
{
|
||||
public:
|
||||
cmd_db_migrate(void);
|
||||
|
||||
int run(utils::cmdline::ui*, const utils::cmdline::parsed_cmdline&,
|
||||
const utils::config::tree&);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cli
|
||||
|
||||
|
||||
#endif // !defined(CLI_CMD_DB_MIGRATE_HPP)
|
94
contrib/kyua/cli/cmd_debug.cpp
Normal file
94
contrib/kyua/cli/cmd_debug.cpp
Normal file
@ -0,0 +1,94 @@
|
||||
// Copyright 2011 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "cli/cmd_debug.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include "cli/common.ipp"
|
||||
#include "drivers/debug_test.hpp"
|
||||
#include "engine/filters.hpp"
|
||||
#include "utils/cmdline/exceptions.hpp"
|
||||
#include "utils/cmdline/options.hpp"
|
||||
#include "utils/cmdline/parser.ipp"
|
||||
#include "utils/cmdline/ui.hpp"
|
||||
#include "utils/format/macros.hpp"
|
||||
|
||||
namespace cmdline = utils::cmdline;
|
||||
namespace config = utils::config;
|
||||
|
||||
using cli::cmd_debug;
|
||||
|
||||
|
||||
/// Default constructor for cmd_debug.
|
||||
cmd_debug::cmd_debug(void) : cli_command(
|
||||
"debug", "test_case", 1, 1,
|
||||
"Executes a single test case providing facilities for debugging")
|
||||
{
|
||||
add_option(build_root_option);
|
||||
add_option(kyuafile_option);
|
||||
|
||||
add_option(cmdline::path_option(
|
||||
"stdout", "Where to direct the standard output of the test case",
|
||||
"path", "/dev/stdout"));
|
||||
|
||||
add_option(cmdline::path_option(
|
||||
"stderr", "Where to direct the standard error of the test case",
|
||||
"path", "/dev/stderr"));
|
||||
}
|
||||
|
||||
|
||||
/// Entry point for the "debug" subcommand.
|
||||
///
|
||||
/// \param ui Object to interact with the I/O of the program.
|
||||
/// \param cmdline Representation of the command line to the subcommand.
|
||||
/// \param user_config The runtime debuguration of the program.
|
||||
///
|
||||
/// \return 0 if everything is OK, 1 if any of the necessary documents cannot be
|
||||
/// opened.
|
||||
int
|
||||
cmd_debug::run(cmdline::ui* ui, const cmdline::parsed_cmdline& cmdline,
|
||||
const config::tree& user_config)
|
||||
{
|
||||
const std::string& test_case_name = cmdline.arguments()[0];
|
||||
if (test_case_name.find(':') == std::string::npos)
|
||||
throw cmdline::usage_error(F("'%s' is not a test case identifier "
|
||||
"(missing ':'?)") % test_case_name);
|
||||
const engine::test_filter filter = engine::test_filter::parse(
|
||||
test_case_name);
|
||||
|
||||
const drivers::debug_test::result result = drivers::debug_test::drive(
|
||||
kyuafile_path(cmdline), build_root_path(cmdline), filter, user_config,
|
||||
cmdline.get_option< cmdline::path_option >("stdout"),
|
||||
cmdline.get_option< cmdline::path_option >("stderr"));
|
||||
|
||||
ui->out(F("%s -> %s") % cli::format_test_case_id(result.test_case) %
|
||||
cli::format_result(result.test_result));
|
||||
|
||||
return result.test_result.good() ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
54
contrib/kyua/cli/cmd_debug.hpp
Normal file
54
contrib/kyua/cli/cmd_debug.hpp
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright 2011 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/// \file cli/cmd_debug.hpp
|
||||
/// Provides the cmd_debug class.
|
||||
|
||||
#if !defined(CLI_CMD_DEBUG_HPP)
|
||||
#define CLI_CMD_DEBUG_HPP
|
||||
|
||||
#include "cli/common.hpp"
|
||||
|
||||
namespace cli {
|
||||
|
||||
|
||||
/// Implementation of the "debug" subcommand.
|
||||
class cmd_debug : public cli_command
|
||||
{
|
||||
public:
|
||||
cmd_debug(void);
|
||||
|
||||
int run(utils::cmdline::ui*, const utils::cmdline::parsed_cmdline&,
|
||||
const utils::config::tree&);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cli
|
||||
|
||||
|
||||
#endif // !defined(CLI_CMD_DEBUG_HPP)
|
82
contrib/kyua/cli/cmd_debug_test.cpp
Normal file
82
contrib/kyua/cli/cmd_debug_test.cpp
Normal file
@ -0,0 +1,82 @@
|
||||
// Copyright 2011 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "cli/cmd_debug.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <atf-c++.hpp>
|
||||
|
||||
#include "cli/common.ipp"
|
||||
#include "engine/config.hpp"
|
||||
#include "utils/cmdline/exceptions.hpp"
|
||||
#include "utils/cmdline/parser.hpp"
|
||||
#include "utils/cmdline/ui_mock.hpp"
|
||||
#include "utils/config/tree.ipp"
|
||||
|
||||
namespace cmdline = utils::cmdline;
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(invalid_filter);
|
||||
ATF_TEST_CASE_BODY(invalid_filter)
|
||||
{
|
||||
cmdline::args_vector args;
|
||||
args.push_back("debug");
|
||||
args.push_back("incorrect:");
|
||||
|
||||
cli::cmd_debug cmd;
|
||||
cmdline::ui_mock ui;
|
||||
// TODO(jmmv): This error should really be cmdline::usage_error.
|
||||
ATF_REQUIRE_THROW_RE(std::runtime_error, "Test case.*'incorrect:'.*empty",
|
||||
cmd.main(&ui, args, engine::default_config()));
|
||||
ATF_REQUIRE(ui.out_log().empty());
|
||||
ATF_REQUIRE(ui.err_log().empty());
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(filter_without_test_case);
|
||||
ATF_TEST_CASE_BODY(filter_without_test_case)
|
||||
{
|
||||
cmdline::args_vector args;
|
||||
args.push_back("debug");
|
||||
args.push_back("program");
|
||||
|
||||
cli::cmd_debug cmd;
|
||||
cmdline::ui_mock ui;
|
||||
ATF_REQUIRE_THROW_RE(cmdline::error, "'program'.*not a test case",
|
||||
cmd.main(&ui, args, engine::default_config()));
|
||||
ATF_REQUIRE(ui.out_log().empty());
|
||||
ATF_REQUIRE(ui.err_log().empty());
|
||||
}
|
||||
|
||||
|
||||
ATF_INIT_TEST_CASES(tcs)
|
||||
{
|
||||
ATF_ADD_TEST_CASE(tcs, invalid_filter);
|
||||
ATF_ADD_TEST_CASE(tcs, filter_without_test_case);
|
||||
}
|
250
contrib/kyua/cli/cmd_help.cpp
Normal file
250
contrib/kyua/cli/cmd_help.cpp
Normal file
@ -0,0 +1,250 @@
|
||||
// Copyright 2010 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "cli/cmd_help.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "cli/common.ipp"
|
||||
#include "utils/cmdline/commands_map.ipp"
|
||||
#include "utils/cmdline/exceptions.hpp"
|
||||
#include "utils/cmdline/globals.hpp"
|
||||
#include "utils/cmdline/options.hpp"
|
||||
#include "utils/cmdline/parser.hpp"
|
||||
#include "utils/cmdline/ui.hpp"
|
||||
#include "utils/defs.hpp"
|
||||
#include "utils/format/macros.hpp"
|
||||
#include "utils/sanity.hpp"
|
||||
#include "utils/text/table.hpp"
|
||||
|
||||
namespace cmdline = utils::cmdline;
|
||||
namespace config = utils::config;
|
||||
namespace text = utils::text;
|
||||
|
||||
using cli::cmd_help;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
/// Creates a table with the help of a set of options.
|
||||
///
|
||||
/// \param options The set of options to describe. May be empty.
|
||||
///
|
||||
/// \return A 2-column wide table with the description of the options.
|
||||
static text::table
|
||||
options_help(const cmdline::options_vector& options)
|
||||
{
|
||||
text::table table(2);
|
||||
|
||||
for (cmdline::options_vector::const_iterator iter = options.begin();
|
||||
iter != options.end(); iter++) {
|
||||
const cmdline::base_option* option = *iter;
|
||||
|
||||
std::string description = option->description();
|
||||
if (option->needs_arg() && option->has_default_value())
|
||||
description += F(" (default: %s)") % option->default_value();
|
||||
|
||||
text::table_row row;
|
||||
|
||||
if (option->has_short_name())
|
||||
row.push_back(F("%s, %s") % option->format_short_name() %
|
||||
option->format_long_name());
|
||||
else
|
||||
row.push_back(F("%s") % option->format_long_name());
|
||||
row.push_back(F("%s.") % description);
|
||||
|
||||
table.add_row(row);
|
||||
}
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
|
||||
/// Prints the summary of commands and generic options.
|
||||
///
|
||||
/// \param ui Object to interact with the I/O of the program.
|
||||
/// \param options The set of program-wide options for which to print help.
|
||||
/// \param commands The set of commands for which to print help.
|
||||
static void
|
||||
general_help(cmdline::ui* ui, const cmdline::options_vector* options,
|
||||
const cmdline::commands_map< cli::cli_command >* commands)
|
||||
{
|
||||
PRE(!commands->empty());
|
||||
|
||||
cli::write_version_header(ui);
|
||||
ui->out("");
|
||||
ui->out_tag_wrap(
|
||||
"Usage: ",
|
||||
F("%s [general_options] command [command_options] [args]") %
|
||||
cmdline::progname(), false);
|
||||
|
||||
const text::table options_table = options_help(*options);
|
||||
text::widths_vector::value_type first_width =
|
||||
options_table.column_width(0);
|
||||
|
||||
std::map< std::string, text::table > command_tables;
|
||||
|
||||
for (cmdline::commands_map< cli::cli_command >::const_iterator
|
||||
iter = commands->begin(); iter != commands->end(); iter++) {
|
||||
const std::string& category = (*iter).first;
|
||||
const std::set< std::string >& command_names = (*iter).second;
|
||||
|
||||
command_tables.insert(std::map< std::string, text::table >::value_type(
|
||||
category, text::table(2)));
|
||||
text::table& table = command_tables.find(category)->second;
|
||||
|
||||
for (std::set< std::string >::const_iterator i2 = command_names.begin();
|
||||
i2 != command_names.end(); i2++) {
|
||||
const cli::cli_command* command = commands->find(*i2);
|
||||
text::table_row row;
|
||||
row.push_back(command->name());
|
||||
row.push_back(F("%s.") % command->short_description());
|
||||
table.add_row(row);
|
||||
}
|
||||
|
||||
if (table.column_width(0) > first_width)
|
||||
first_width = table.column_width(0);
|
||||
}
|
||||
|
||||
text::table_formatter formatter;
|
||||
formatter.set_column_width(0, first_width);
|
||||
formatter.set_column_width(1, text::table_formatter::width_refill);
|
||||
formatter.set_separator(" ");
|
||||
|
||||
if (!options_table.empty()) {
|
||||
ui->out_wrap("");
|
||||
ui->out_wrap("Available general options:");
|
||||
ui->out_table(options_table, formatter, " ");
|
||||
}
|
||||
|
||||
// Iterate using the same loop as above to preserve ordering.
|
||||
for (cmdline::commands_map< cli::cli_command >::const_iterator
|
||||
iter = commands->begin(); iter != commands->end(); iter++) {
|
||||
const std::string& category = (*iter).first;
|
||||
ui->out_wrap("");
|
||||
ui->out_wrap(F("%s commands:") %
|
||||
(category.empty() ? "Generic" : category));
|
||||
ui->out_table(command_tables.find(category)->second, formatter, " ");
|
||||
}
|
||||
|
||||
ui->out_wrap("");
|
||||
ui->out_wrap("See kyua(1) for more details.");
|
||||
}
|
||||
|
||||
|
||||
/// Prints help for a particular subcommand.
|
||||
///
|
||||
/// \param ui Object to interact with the I/O of the program.
|
||||
/// \param general_options The options that apply to all commands.
|
||||
/// \param command Pointer to the command to describe.
|
||||
static void
|
||||
subcommand_help(cmdline::ui* ui,
|
||||
const utils::cmdline::options_vector* general_options,
|
||||
const cli::cli_command* command)
|
||||
{
|
||||
cli::write_version_header(ui);
|
||||
ui->out("");
|
||||
ui->out_tag_wrap(
|
||||
"Usage: ", F("%s [general_options] %s%s%s") %
|
||||
cmdline::progname() % command->name() %
|
||||
(command->options().empty() ? "" : " [command_options]") %
|
||||
(command->arg_list().empty() ? "" : (" " + command->arg_list())),
|
||||
false);
|
||||
ui->out_wrap("");
|
||||
ui->out_wrap(F("%s.") % command->short_description());
|
||||
|
||||
const text::table general_table = options_help(*general_options);
|
||||
const text::table command_table = options_help(command->options());
|
||||
|
||||
const text::widths_vector::value_type first_width =
|
||||
std::max(general_table.column_width(0), command_table.column_width(0));
|
||||
text::table_formatter formatter;
|
||||
formatter.set_column_width(0, first_width);
|
||||
formatter.set_column_width(1, text::table_formatter::width_refill);
|
||||
formatter.set_separator(" ");
|
||||
|
||||
if (!general_table.empty()) {
|
||||
ui->out_wrap("");
|
||||
ui->out_wrap("Available general options:");
|
||||
ui->out_table(general_table, formatter, " ");
|
||||
}
|
||||
|
||||
if (!command_table.empty()) {
|
||||
ui->out_wrap("");
|
||||
ui->out_wrap("Available command options:");
|
||||
ui->out_table(command_table, formatter, " ");
|
||||
}
|
||||
|
||||
ui->out_wrap("");
|
||||
ui->out_wrap(F("See kyua-%s(1) for more details.") % command->name());
|
||||
}
|
||||
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
/// Default constructor for cmd_help.
|
||||
///
|
||||
/// \param options_ The set of program-wide options for which to provide help.
|
||||
/// \param commands_ The set of commands for which to provide help.
|
||||
cmd_help::cmd_help(const cmdline::options_vector* options_,
|
||||
const cmdline::commands_map< cli_command >* commands_) :
|
||||
cli_command("help", "[subcommand]", 0, 1, "Shows usage information"),
|
||||
_options(options_),
|
||||
_commands(commands_)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// Entry point for the "help" subcommand.
|
||||
///
|
||||
/// \param ui Object to interact with the I/O of the program.
|
||||
/// \param cmdline Representation of the command line to the subcommand.
|
||||
///
|
||||
/// \return 0 to indicate success.
|
||||
int
|
||||
cmd_help::run(utils::cmdline::ui* ui, const cmdline::parsed_cmdline& cmdline,
|
||||
const config::tree& /* user_config */)
|
||||
{
|
||||
if (cmdline.arguments().empty()) {
|
||||
general_help(ui, _options, _commands);
|
||||
} else {
|
||||
INV(cmdline.arguments().size() == 1);
|
||||
const std::string& cmdname = cmdline.arguments()[0];
|
||||
const cli::cli_command* command = _commands->find(cmdname);
|
||||
if (command == NULL)
|
||||
throw cmdline::usage_error(F("The command %s does not exist") %
|
||||
cmdname);
|
||||
else
|
||||
subcommand_help(ui, _options, command);
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
62
contrib/kyua/cli/cmd_help.hpp
Normal file
62
contrib/kyua/cli/cmd_help.hpp
Normal file
@ -0,0 +1,62 @@
|
||||
// Copyright 2010 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/// \file cli/cmd_help.hpp
|
||||
/// Provides the cmd_help class.
|
||||
|
||||
#if !defined(CLI_CMD_HELP_HPP)
|
||||
#define CLI_CMD_HELP_HPP
|
||||
|
||||
#include "cli/common.hpp"
|
||||
#include "utils/cmdline/commands_map_fwd.hpp"
|
||||
|
||||
namespace cli {
|
||||
|
||||
|
||||
/// Implementation of the "help" subcommand.
|
||||
class cmd_help : public cli_command
|
||||
{
|
||||
/// The set of program-wide options for which to provide help.
|
||||
const utils::cmdline::options_vector* _options;
|
||||
|
||||
/// The set of commands for which to provide help.
|
||||
const utils::cmdline::commands_map< cli_command >* _commands;
|
||||
|
||||
public:
|
||||
cmd_help(const utils::cmdline::options_vector*,
|
||||
const utils::cmdline::commands_map< cli_command >*);
|
||||
|
||||
int run(utils::cmdline::ui*, const utils::cmdline::parsed_cmdline&,
|
||||
const utils::config::tree&);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cli
|
||||
|
||||
|
||||
#endif // !defined(CLI_CMD_HELP_HPP)
|
347
contrib/kyua/cli/cmd_help_test.cpp
Normal file
347
contrib/kyua/cli/cmd_help_test.cpp
Normal file
@ -0,0 +1,347 @@
|
||||
// Copyright 2010 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "cli/cmd_help.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <iterator>
|
||||
|
||||
#include <atf-c++.hpp>
|
||||
|
||||
#include "cli/common.ipp"
|
||||
#include "engine/config.hpp"
|
||||
#include "utils/cmdline/commands_map.ipp"
|
||||
#include "utils/cmdline/exceptions.hpp"
|
||||
#include "utils/cmdline/globals.hpp"
|
||||
#include "utils/cmdline/options.hpp"
|
||||
#include "utils/cmdline/parser.hpp"
|
||||
#include "utils/cmdline/ui_mock.hpp"
|
||||
#include "utils/config/tree.ipp"
|
||||
#include "utils/defs.hpp"
|
||||
#include "utils/sanity.hpp"
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
namespace cmdline = utils::cmdline;
|
||||
namespace config = utils::config;
|
||||
|
||||
using cli::cmd_help;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
/// Mock command with a simple definition (no options, no arguments).
|
||||
///
|
||||
/// Attempting to run this command will result in a crash. It is only provided
|
||||
/// to validate the generation of interactive help.
|
||||
class cmd_mock_simple : public cli::cli_command {
|
||||
public:
|
||||
/// Constructs a new mock command.
|
||||
///
|
||||
/// \param name_ The name of the command to create.
|
||||
cmd_mock_simple(const char* name_) : cli::cli_command(
|
||||
name_, "", 0, 0, "Simple command")
|
||||
{
|
||||
}
|
||||
|
||||
/// Runs the mock command.
|
||||
///
|
||||
/// \return Nothing because this function is never called.
|
||||
int
|
||||
run(cmdline::ui* /* ui */,
|
||||
const cmdline::parsed_cmdline& /* cmdline */,
|
||||
const config::tree& /* user_config */)
|
||||
{
|
||||
UNREACHABLE;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// Mock command with a complex definition (some options, some arguments).
|
||||
///
|
||||
/// Attempting to run this command will result in a crash. It is only provided
|
||||
/// to validate the generation of interactive help.
|
||||
class cmd_mock_complex : public cli::cli_command {
|
||||
public:
|
||||
/// Constructs a new mock command.
|
||||
///
|
||||
/// \param name_ The name of the command to create.
|
||||
cmd_mock_complex(const char* name_) : cli::cli_command(
|
||||
name_, "[arg1 .. argN]", 0, 2, "Complex command")
|
||||
{
|
||||
add_option(cmdline::bool_option("flag_a", "Flag A"));
|
||||
add_option(cmdline::bool_option('b', "flag_b", "Flag B"));
|
||||
add_option(cmdline::string_option('c', "flag_c", "Flag C", "c_arg"));
|
||||
add_option(cmdline::string_option("flag_d", "Flag D", "d_arg", "foo"));
|
||||
}
|
||||
|
||||
/// Runs the mock command.
|
||||
///
|
||||
/// \return Nothing because this function is never called.
|
||||
int
|
||||
run(cmdline::ui* /* ui */,
|
||||
const cmdline::parsed_cmdline& /* cmdline */,
|
||||
const config::tree& /* user_config */)
|
||||
{
|
||||
UNREACHABLE;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// Initializes the cmdline library and generates the set of test commands.
|
||||
///
|
||||
/// \param [out] commands A mapping that is updated to contain the commands to
|
||||
/// use for testing.
|
||||
static void
|
||||
setup(cmdline::commands_map< cli::cli_command >& commands)
|
||||
{
|
||||
cmdline::init("progname");
|
||||
|
||||
commands.insert(new cmd_mock_simple("mock_simple"));
|
||||
commands.insert(new cmd_mock_complex("mock_complex"));
|
||||
|
||||
commands.insert(new cmd_mock_simple("mock_simple_2"), "First");
|
||||
commands.insert(new cmd_mock_complex("mock_complex_2"), "First");
|
||||
|
||||
commands.insert(new cmd_mock_simple("mock_simple_3"), "Second");
|
||||
}
|
||||
|
||||
|
||||
/// Performs a test on the global help (not that of a subcommand).
|
||||
///
|
||||
/// \param general_options The genral options supported by the tool, if any.
|
||||
/// \param expected_options Expected lines of help output documenting the
|
||||
/// options in general_options.
|
||||
/// \param ui The cmdline::mock_ui object to which to write the output.
|
||||
static void
|
||||
global_test(const cmdline::options_vector& general_options,
|
||||
const std::vector< std::string >& expected_options,
|
||||
cmdline::ui_mock& ui)
|
||||
{
|
||||
cmdline::commands_map< cli::cli_command > mock_commands;
|
||||
setup(mock_commands);
|
||||
|
||||
cmdline::args_vector args;
|
||||
args.push_back("help");
|
||||
|
||||
cmd_help cmd(&general_options, &mock_commands);
|
||||
ATF_REQUIRE_EQ(EXIT_SUCCESS, cmd.main(&ui, args, engine::default_config()));
|
||||
|
||||
std::vector< std::string > expected;
|
||||
|
||||
expected.push_back(PACKAGE " (" PACKAGE_NAME ") " PACKAGE_VERSION);
|
||||
expected.push_back("");
|
||||
expected.push_back("Usage: progname [general_options] command "
|
||||
"[command_options] [args]");
|
||||
if (!general_options.empty()) {
|
||||
expected.push_back("");
|
||||
expected.push_back("Available general options:");
|
||||
std::copy(expected_options.begin(), expected_options.end(),
|
||||
std::back_inserter(expected));
|
||||
}
|
||||
expected.push_back("");
|
||||
expected.push_back("Generic commands:");
|
||||
expected.push_back(" mock_complex Complex command.");
|
||||
expected.push_back(" mock_simple Simple command.");
|
||||
expected.push_back("");
|
||||
expected.push_back("First commands:");
|
||||
expected.push_back(" mock_complex_2 Complex command.");
|
||||
expected.push_back(" mock_simple_2 Simple command.");
|
||||
expected.push_back("");
|
||||
expected.push_back("Second commands:");
|
||||
expected.push_back(" mock_simple_3 Simple command.");
|
||||
expected.push_back("");
|
||||
expected.push_back("See kyua(1) for more details.");
|
||||
|
||||
ATF_REQUIRE(expected == ui.out_log());
|
||||
ATF_REQUIRE(ui.err_log().empty());
|
||||
}
|
||||
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(global__no_options);
|
||||
ATF_TEST_CASE_BODY(global__no_options)
|
||||
{
|
||||
cmdline::ui_mock ui;
|
||||
|
||||
cmdline::options_vector general_options;
|
||||
|
||||
global_test(general_options, std::vector< std::string >(), ui);
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(global__some_options);
|
||||
ATF_TEST_CASE_BODY(global__some_options)
|
||||
{
|
||||
cmdline::ui_mock ui;
|
||||
|
||||
cmdline::options_vector general_options;
|
||||
const cmdline::bool_option flag_a("flag_a", "Flag A");
|
||||
general_options.push_back(&flag_a);
|
||||
const cmdline::string_option flag_c('c', "lc", "Flag C", "X");
|
||||
general_options.push_back(&flag_c);
|
||||
|
||||
std::vector< std::string > expected;
|
||||
expected.push_back(" --flag_a Flag A.");
|
||||
expected.push_back(" -c X, --lc=X Flag C.");
|
||||
|
||||
global_test(general_options, expected, ui);
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(subcommand__simple);
|
||||
ATF_TEST_CASE_BODY(subcommand__simple)
|
||||
{
|
||||
cmdline::options_vector general_options;
|
||||
|
||||
cmdline::commands_map< cli::cli_command > mock_commands;
|
||||
setup(mock_commands);
|
||||
|
||||
cmdline::args_vector args;
|
||||
args.push_back("help");
|
||||
args.push_back("mock_simple");
|
||||
|
||||
cmd_help cmd(&general_options, &mock_commands);
|
||||
cmdline::ui_mock ui;
|
||||
ATF_REQUIRE_EQ(EXIT_SUCCESS, cmd.main(&ui, args, engine::default_config()));
|
||||
ATF_REQUIRE(atf::utils::grep_collection(
|
||||
"^kyua.*" PACKAGE_VERSION, ui.out_log()));
|
||||
ATF_REQUIRE(atf::utils::grep_collection(
|
||||
"^Usage: progname \\[general_options\\] mock_simple$", ui.out_log()));
|
||||
ATF_REQUIRE(!atf::utils::grep_collection(
|
||||
"Available.*options", ui.out_log()));
|
||||
ATF_REQUIRE(atf::utils::grep_collection(
|
||||
"^See kyua-mock_simple\\(1\\) for more details.", ui.out_log()));
|
||||
ATF_REQUIRE(ui.err_log().empty());
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(subcommand__complex);
|
||||
ATF_TEST_CASE_BODY(subcommand__complex)
|
||||
{
|
||||
cmdline::options_vector general_options;
|
||||
const cmdline::bool_option global_a("global_a", "Global A");
|
||||
general_options.push_back(&global_a);
|
||||
const cmdline::string_option global_c('c', "global_c", "Global C",
|
||||
"c_global");
|
||||
general_options.push_back(&global_c);
|
||||
|
||||
cmdline::commands_map< cli::cli_command > mock_commands;
|
||||
setup(mock_commands);
|
||||
|
||||
cmdline::args_vector args;
|
||||
args.push_back("help");
|
||||
args.push_back("mock_complex");
|
||||
|
||||
cmd_help cmd(&general_options, &mock_commands);
|
||||
cmdline::ui_mock ui;
|
||||
ATF_REQUIRE_EQ(EXIT_SUCCESS, cmd.main(&ui, args, engine::default_config()));
|
||||
ATF_REQUIRE(atf::utils::grep_collection(
|
||||
"^kyua.*" PACKAGE_VERSION, ui.out_log()));
|
||||
ATF_REQUIRE(atf::utils::grep_collection(
|
||||
"^Usage: progname \\[general_options\\] mock_complex "
|
||||
"\\[command_options\\] \\[arg1 .. argN\\]$", ui.out_log()));
|
||||
ATF_REQUIRE(atf::utils::grep_collection("Available general options",
|
||||
ui.out_log()));
|
||||
ATF_REQUIRE(atf::utils::grep_collection("--global_a", ui.out_log()));
|
||||
ATF_REQUIRE(atf::utils::grep_collection("--global_c=c_global",
|
||||
ui.out_log()));
|
||||
ATF_REQUIRE(atf::utils::grep_collection("Available command options",
|
||||
ui.out_log()));
|
||||
ATF_REQUIRE(atf::utils::grep_collection("--flag_a *Flag A",
|
||||
ui.out_log()));
|
||||
ATF_REQUIRE(atf::utils::grep_collection("-b.*--flag_b *Flag B",
|
||||
ui.out_log()));
|
||||
ATF_REQUIRE(atf::utils::grep_collection(
|
||||
"-c c_arg.*--flag_c=c_arg *Flag C", ui.out_log()));
|
||||
ATF_REQUIRE(atf::utils::grep_collection(
|
||||
"--flag_d=d_arg *Flag D.*default.*foo", ui.out_log()));
|
||||
ATF_REQUIRE(atf::utils::grep_collection(
|
||||
"^See kyua-mock_complex\\(1\\) for more details.", ui.out_log()));
|
||||
ATF_REQUIRE(ui.err_log().empty());
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(subcommand__unknown);
|
||||
ATF_TEST_CASE_BODY(subcommand__unknown)
|
||||
{
|
||||
cmdline::options_vector general_options;
|
||||
|
||||
cmdline::commands_map< cli::cli_command > mock_commands;
|
||||
setup(mock_commands);
|
||||
|
||||
cmdline::args_vector args;
|
||||
args.push_back("help");
|
||||
args.push_back("foobar");
|
||||
|
||||
cmd_help cmd(&general_options, &mock_commands);
|
||||
cmdline::ui_mock ui;
|
||||
ATF_REQUIRE_THROW_RE(cmdline::usage_error, "command foobar.*not exist",
|
||||
cmd.main(&ui, args, engine::default_config()));
|
||||
ATF_REQUIRE(ui.out_log().empty());
|
||||
ATF_REQUIRE(ui.err_log().empty());
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(invalid_args);
|
||||
ATF_TEST_CASE_BODY(invalid_args)
|
||||
{
|
||||
cmdline::options_vector general_options;
|
||||
|
||||
cmdline::commands_map< cli::cli_command > mock_commands;
|
||||
setup(mock_commands);
|
||||
|
||||
cmdline::args_vector args;
|
||||
args.push_back("help");
|
||||
args.push_back("mock_simple");
|
||||
args.push_back("mock_complex");
|
||||
|
||||
cmd_help cmd(&general_options, &mock_commands);
|
||||
cmdline::ui_mock ui;
|
||||
ATF_REQUIRE_THROW_RE(cmdline::usage_error, "Too many arguments",
|
||||
cmd.main(&ui, args, engine::default_config()));
|
||||
ATF_REQUIRE(ui.out_log().empty());
|
||||
ATF_REQUIRE(ui.err_log().empty());
|
||||
}
|
||||
|
||||
|
||||
ATF_INIT_TEST_CASES(tcs)
|
||||
{
|
||||
ATF_ADD_TEST_CASE(tcs, global__no_options);
|
||||
ATF_ADD_TEST_CASE(tcs, global__some_options);
|
||||
ATF_ADD_TEST_CASE(tcs, subcommand__simple);
|
||||
ATF_ADD_TEST_CASE(tcs, subcommand__complex);
|
||||
ATF_ADD_TEST_CASE(tcs, subcommand__unknown);
|
||||
ATF_ADD_TEST_CASE(tcs, invalid_args);
|
||||
}
|
161
contrib/kyua/cli/cmd_list.cpp
Normal file
161
contrib/kyua/cli/cmd_list.cpp
Normal file
@ -0,0 +1,161 @@
|
||||
// Copyright 2010 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "cli/cmd_list.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "cli/common.ipp"
|
||||
#include "drivers/list_tests.hpp"
|
||||
#include "engine/filters.hpp"
|
||||
#include "model/metadata.hpp"
|
||||
#include "model/test_case.hpp"
|
||||
#include "model/test_program.hpp"
|
||||
#include "model/types.hpp"
|
||||
#include "utils/cmdline/options.hpp"
|
||||
#include "utils/cmdline/parser.ipp"
|
||||
#include "utils/cmdline/ui.hpp"
|
||||
#include "utils/defs.hpp"
|
||||
#include "utils/format/macros.hpp"
|
||||
#include "utils/fs/path.hpp"
|
||||
|
||||
namespace cmdline = utils::cmdline;
|
||||
namespace config = utils::config;
|
||||
namespace fs = utils::fs;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
/// Hooks for list_tests to print test cases as they come.
|
||||
class progress_hooks : public drivers::list_tests::base_hooks {
|
||||
/// The ui object to which to print the test cases.
|
||||
cmdline::ui* _ui;
|
||||
|
||||
/// Whether to print test case details or just their names.
|
||||
bool _verbose;
|
||||
|
||||
public:
|
||||
/// Initializes the hooks.
|
||||
///
|
||||
/// \param ui_ The ui object to which to print the test cases.
|
||||
/// \param verbose_ Whether to print test case details or just their names.
|
||||
progress_hooks(cmdline::ui* ui_, const bool verbose_) :
|
||||
_ui(ui_),
|
||||
_verbose(verbose_)
|
||||
{
|
||||
}
|
||||
|
||||
/// Reports a test case as soon as it is found.
|
||||
///
|
||||
/// \param test_program The test program containing the test case.
|
||||
/// \param test_case_name The name of the located test case.
|
||||
void
|
||||
got_test_case(const model::test_program& test_program,
|
||||
const std::string& test_case_name)
|
||||
{
|
||||
cli::detail::list_test_case(_ui, _verbose, test_program,
|
||||
test_case_name);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
/// Lists a single test case.
|
||||
///
|
||||
/// \param [out] ui Object to interact with the I/O of the program.
|
||||
/// \param verbose Whether to be verbose or not.
|
||||
/// \param test_program The test program containing the test case to print.
|
||||
/// \param test_case_name The name of the test case to print.
|
||||
void
|
||||
cli::detail::list_test_case(cmdline::ui* ui, const bool verbose,
|
||||
const model::test_program& test_program,
|
||||
const std::string& test_case_name)
|
||||
{
|
||||
const model::test_case& test_case = test_program.find(test_case_name);
|
||||
|
||||
const std::string id = format_test_case_id(test_program, test_case_name);
|
||||
if (!verbose) {
|
||||
ui->out(id);
|
||||
} else {
|
||||
ui->out(F("%s (%s)") % id % test_program.test_suite_name());
|
||||
|
||||
// TODO(jmmv): Running these for every test case is probably not the
|
||||
// fastest thing to do.
|
||||
const model::metadata default_md = model::metadata_builder().build();
|
||||
const model::properties_map default_props = default_md.to_properties();
|
||||
|
||||
const model::metadata& test_md = test_case.get_metadata();
|
||||
const model::properties_map test_props = test_md.to_properties();
|
||||
|
||||
for (model::properties_map::const_iterator iter = test_props.begin();
|
||||
iter != test_props.end(); iter++) {
|
||||
const model::properties_map::const_iterator default_iter =
|
||||
default_props.find((*iter).first);
|
||||
if (default_iter == default_props.end() ||
|
||||
(*iter).second != (*default_iter).second)
|
||||
ui->out(F(" %s = %s") % (*iter).first % (*iter).second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Default constructor for cmd_list.
|
||||
cli::cmd_list::cmd_list(void) :
|
||||
cli_command("list", "[test-program ...]", 0, -1,
|
||||
"Lists test cases and their meta-data")
|
||||
{
|
||||
add_option(build_root_option);
|
||||
add_option(kyuafile_option);
|
||||
add_option(cmdline::bool_option('v', "verbose", "Show properties"));
|
||||
}
|
||||
|
||||
|
||||
/// Entry point for the "list" subcommand.
|
||||
///
|
||||
/// \param ui Object to interact with the I/O of the program.
|
||||
/// \param cmdline Representation of the command line to the subcommand.
|
||||
/// \param user_config The runtime configuration of the program.
|
||||
///
|
||||
/// \return 0 to indicate success.
|
||||
int
|
||||
cli::cmd_list::run(cmdline::ui* ui, const cmdline::parsed_cmdline& cmdline,
|
||||
const config::tree& user_config)
|
||||
{
|
||||
progress_hooks hooks(ui, cmdline.has_option("verbose"));
|
||||
const drivers::list_tests::result result = drivers::list_tests::drive(
|
||||
kyuafile_path(cmdline), build_root_path(cmdline),
|
||||
parse_filters(cmdline.arguments()), user_config, hooks);
|
||||
|
||||
return report_unused_filters(result.unused_filters, ui) ?
|
||||
EXIT_FAILURE : EXIT_SUCCESS;
|
||||
}
|
65
contrib/kyua/cli/cmd_list.hpp
Normal file
65
contrib/kyua/cli/cmd_list.hpp
Normal file
@ -0,0 +1,65 @@
|
||||
// Copyright 2010 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/// \file cli/cmd_list.hpp
|
||||
/// Provides the cmd_list class.
|
||||
|
||||
#if !defined(CLI_CMD_LIST_HPP)
|
||||
#define CLI_CMD_LIST_HPP
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "cli/common.hpp"
|
||||
#include "model/test_program_fwd.hpp"
|
||||
#include "utils/fs/path_fwd.hpp"
|
||||
|
||||
namespace cli {
|
||||
|
||||
|
||||
namespace detail {
|
||||
|
||||
void list_test_case(utils::cmdline::ui*, const bool, const model::test_program&,
|
||||
const std::string&);
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
/// Implementation of the "list" subcommand.
|
||||
class cmd_list : public cli_command
|
||||
{
|
||||
public:
|
||||
cmd_list(void);
|
||||
|
||||
int run(utils::cmdline::ui*, const utils::cmdline::parsed_cmdline&,
|
||||
const utils::config::tree&);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cli
|
||||
|
||||
#endif // !defined(CLI_CMD_LIST_HPP)
|
112
contrib/kyua/cli/cmd_list_test.cpp
Normal file
112
contrib/kyua/cli/cmd_list_test.cpp
Normal file
@ -0,0 +1,112 @@
|
||||
// Copyright 2011 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "cli/cmd_list.hpp"
|
||||
|
||||
#include <atf-c++.hpp>
|
||||
|
||||
#include "model/metadata.hpp"
|
||||
#include "model/test_program.hpp"
|
||||
#include "utils/cmdline/exceptions.hpp"
|
||||
#include "utils/cmdline/parser.hpp"
|
||||
#include "utils/cmdline/ui_mock.hpp"
|
||||
#include "utils/fs/path.hpp"
|
||||
|
||||
namespace cmdline = utils::cmdline;
|
||||
namespace fs = utils::fs;
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(list_test_case__no_verbose);
|
||||
ATF_TEST_CASE_BODY(list_test_case__no_verbose)
|
||||
{
|
||||
const model::metadata md = model::metadata_builder()
|
||||
.set_description("This should not be shown")
|
||||
.build();
|
||||
const model::test_program test_program = model::test_program_builder(
|
||||
"mock", fs::path("the/test-program"), fs::path("root"), "suite")
|
||||
.add_test_case("abc", md)
|
||||
.set_metadata(md)
|
||||
.build();
|
||||
|
||||
cmdline::ui_mock ui;
|
||||
cli::detail::list_test_case(&ui, false, test_program, "abc");
|
||||
ATF_REQUIRE_EQ(1, ui.out_log().size());
|
||||
ATF_REQUIRE_EQ("the/test-program:abc", ui.out_log()[0]);
|
||||
ATF_REQUIRE(ui.err_log().empty());
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(list_test_case__verbose__no_properties);
|
||||
ATF_TEST_CASE_BODY(list_test_case__verbose__no_properties)
|
||||
{
|
||||
const model::test_program test_program = model::test_program_builder(
|
||||
"mock", fs::path("hello/world"), fs::path("root"), "the-suite")
|
||||
.add_test_case("my_name")
|
||||
.build();
|
||||
|
||||
cmdline::ui_mock ui;
|
||||
cli::detail::list_test_case(&ui, true, test_program, "my_name");
|
||||
ATF_REQUIRE_EQ(1, ui.out_log().size());
|
||||
ATF_REQUIRE_EQ("hello/world:my_name (the-suite)", ui.out_log()[0]);
|
||||
ATF_REQUIRE(ui.err_log().empty());
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(list_test_case__verbose__some_properties);
|
||||
ATF_TEST_CASE_BODY(list_test_case__verbose__some_properties)
|
||||
{
|
||||
const model::metadata md = model::metadata_builder()
|
||||
.add_custom("my-property", "value")
|
||||
.set_description("Some description")
|
||||
.set_has_cleanup(true)
|
||||
.build();
|
||||
const model::test_program test_program = model::test_program_builder(
|
||||
"mock", fs::path("hello/world"), fs::path("root"), "the-suite")
|
||||
.add_test_case("my_name", md)
|
||||
.set_metadata(md)
|
||||
.build();
|
||||
|
||||
cmdline::ui_mock ui;
|
||||
cli::detail::list_test_case(&ui, true, test_program, "my_name");
|
||||
ATF_REQUIRE_EQ(4, ui.out_log().size());
|
||||
ATF_REQUIRE_EQ("hello/world:my_name (the-suite)", ui.out_log()[0]);
|
||||
ATF_REQUIRE_EQ(" custom.my-property = value", ui.out_log()[1]);
|
||||
ATF_REQUIRE_EQ(" description = Some description", ui.out_log()[2]);
|
||||
ATF_REQUIRE_EQ(" has_cleanup = true", ui.out_log()[3]);
|
||||
ATF_REQUIRE(ui.err_log().empty());
|
||||
}
|
||||
|
||||
|
||||
ATF_INIT_TEST_CASES(tcs)
|
||||
{
|
||||
ATF_ADD_TEST_CASE(tcs, list_test_case__no_verbose);
|
||||
ATF_ADD_TEST_CASE(tcs, list_test_case__verbose__no_properties);
|
||||
ATF_ADD_TEST_CASE(tcs, list_test_case__verbose__some_properties);
|
||||
|
||||
// Tests for cmd_list::run are located in integration/cmd_list_test.
|
||||
}
|
421
contrib/kyua/cli/cmd_report.cpp
Normal file
421
contrib/kyua/cli/cmd_report.cpp
Normal file
@ -0,0 +1,421 @@
|
||||
// Copyright 2011 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "cli/cmd_report.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <map>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "cli/common.ipp"
|
||||
#include "drivers/scan_results.hpp"
|
||||
#include "model/context.hpp"
|
||||
#include "model/metadata.hpp"
|
||||
#include "model/test_case.hpp"
|
||||
#include "model/test_program.hpp"
|
||||
#include "model/test_result.hpp"
|
||||
#include "model/types.hpp"
|
||||
#include "store/layout.hpp"
|
||||
#include "store/read_transaction.hpp"
|
||||
#include "utils/cmdline/exceptions.hpp"
|
||||
#include "utils/cmdline/options.hpp"
|
||||
#include "utils/cmdline/parser.ipp"
|
||||
#include "utils/cmdline/ui.hpp"
|
||||
#include "utils/datetime.hpp"
|
||||
#include "utils/defs.hpp"
|
||||
#include "utils/format/macros.hpp"
|
||||
#include "utils/fs/path.hpp"
|
||||
#include "utils/optional.ipp"
|
||||
#include "utils/sanity.hpp"
|
||||
#include "utils/stream.hpp"
|
||||
#include "utils/text/operations.ipp"
|
||||
|
||||
namespace cmdline = utils::cmdline;
|
||||
namespace config = utils::config;
|
||||
namespace datetime = utils::datetime;
|
||||
namespace fs = utils::fs;
|
||||
namespace layout = store::layout;
|
||||
namespace text = utils::text;
|
||||
|
||||
using cli::cmd_report;
|
||||
using utils::optional;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
/// Generates a plain-text report intended to be printed to the console.
|
||||
class report_console_hooks : public drivers::scan_results::base_hooks {
|
||||
/// Stream to which to write the report.
|
||||
std::ostream& _output;
|
||||
|
||||
/// Whether to include details in the report or not.
|
||||
const bool _verbose;
|
||||
|
||||
/// Collection of result types to include in the report.
|
||||
const cli::result_types& _results_filters;
|
||||
|
||||
/// Path to the results file being read.
|
||||
const fs::path& _results_file;
|
||||
|
||||
/// The start time of the first test.
|
||||
optional< utils::datetime::timestamp > _start_time;
|
||||
|
||||
/// The end time of the last test.
|
||||
optional< utils::datetime::timestamp > _end_time;
|
||||
|
||||
/// The total run time of the tests. Note that we cannot subtract _end_time
|
||||
/// from _start_time to compute this due to parallel execution.
|
||||
utils::datetime::delta _runtime;
|
||||
|
||||
/// Representation of a single result.
|
||||
struct result_data {
|
||||
/// The relative path to the test program.
|
||||
utils::fs::path binary_path;
|
||||
|
||||
/// The name of the test case.
|
||||
std::string test_case_name;
|
||||
|
||||
/// The result of the test case.
|
||||
model::test_result result;
|
||||
|
||||
/// The duration of the test case execution.
|
||||
utils::datetime::delta duration;
|
||||
|
||||
/// Constructs a new results data.
|
||||
///
|
||||
/// \param binary_path_ The relative path to the test program.
|
||||
/// \param test_case_name_ The name of the test case.
|
||||
/// \param result_ The result of the test case.
|
||||
/// \param duration_ The duration of the test case execution.
|
||||
result_data(const utils::fs::path& binary_path_,
|
||||
const std::string& test_case_name_,
|
||||
const model::test_result& result_,
|
||||
const utils::datetime::delta& duration_) :
|
||||
binary_path(binary_path_), test_case_name(test_case_name_),
|
||||
result(result_), duration(duration_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/// Results received, broken down by their type.
|
||||
///
|
||||
/// Note that this may not include all results, as keeping the whole list in
|
||||
/// memory may be too much.
|
||||
std::map< model::test_result_type, std::vector< result_data > > _results;
|
||||
|
||||
/// Pretty-prints the value of an environment variable.
|
||||
///
|
||||
/// \param indent Prefix for the lines to print. Continuation lines
|
||||
/// use this indentation twice.
|
||||
/// \param name Name of the variable.
|
||||
/// \param value Value of the variable. Can have newlines.
|
||||
void
|
||||
print_env_var(const char* indent, const std::string& name,
|
||||
const std::string& value)
|
||||
{
|
||||
const std::vector< std::string > lines = text::split(value, '\n');
|
||||
if (lines.size() == 0) {
|
||||
_output << F("%s%s=\n") % indent % name;;
|
||||
} else {
|
||||
_output << F("%s%s=%s\n") % indent % name % lines[0];
|
||||
for (std::vector< std::string >::size_type i = 1;
|
||||
i < lines.size(); ++i) {
|
||||
_output << F("%s%s%s\n") % indent % indent % lines[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Prints the execution context to the output.
|
||||
///
|
||||
/// \param context The context to dump.
|
||||
void
|
||||
print_context(const model::context& context)
|
||||
{
|
||||
_output << "===> Execution context\n";
|
||||
|
||||
_output << F("Current directory: %s\n") % context.cwd();
|
||||
const std::map< std::string, std::string >& env = context.env();
|
||||
if (env.empty())
|
||||
_output << "No environment variables recorded\n";
|
||||
else {
|
||||
_output << "Environment variables:\n";
|
||||
for (std::map< std::string, std::string >::const_iterator
|
||||
iter = env.begin(); iter != env.end(); iter++) {
|
||||
print_env_var(" ", (*iter).first, (*iter).second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Dumps a detailed view of the test case.
|
||||
///
|
||||
/// \param result_iter Results iterator pointing at the test case to be
|
||||
/// dumped.
|
||||
void
|
||||
print_test_case_and_result(const store::results_iterator& result_iter)
|
||||
{
|
||||
const model::test_case& test_case =
|
||||
result_iter.test_program()->find(result_iter.test_case_name());
|
||||
const model::properties_map props =
|
||||
test_case.get_metadata().to_properties();
|
||||
|
||||
_output << F("===> %s:%s\n") %
|
||||
result_iter.test_program()->relative_path() %
|
||||
result_iter.test_case_name();
|
||||
_output << F("Result: %s\n") %
|
||||
cli::format_result(result_iter.result());
|
||||
_output << F("Start time: %s\n") %
|
||||
result_iter.start_time().to_iso8601_in_utc();
|
||||
_output << F("End time: %s\n") %
|
||||
result_iter.end_time().to_iso8601_in_utc();
|
||||
_output << F("Duration: %s\n") %
|
||||
cli::format_delta(result_iter.end_time() -
|
||||
result_iter.start_time());
|
||||
|
||||
_output << "\n";
|
||||
_output << "Metadata:\n";
|
||||
for (model::properties_map::const_iterator iter = props.begin();
|
||||
iter != props.end(); ++iter) {
|
||||
if ((*iter).second.empty()) {
|
||||
_output << F(" %s is empty\n") % (*iter).first;
|
||||
} else {
|
||||
_output << F(" %s = %s\n") % (*iter).first % (*iter).second;
|
||||
}
|
||||
}
|
||||
|
||||
const std::string stdout_contents = result_iter.stdout_contents();
|
||||
if (!stdout_contents.empty()) {
|
||||
_output << "\n"
|
||||
<< "Standard output:\n"
|
||||
<< stdout_contents;
|
||||
}
|
||||
|
||||
const std::string stderr_contents = result_iter.stderr_contents();
|
||||
if (!stderr_contents.empty()) {
|
||||
_output << "\n"
|
||||
<< "Standard error:\n"
|
||||
<< stderr_contents;
|
||||
}
|
||||
}
|
||||
|
||||
/// Counts how many results of a given type have been received.
|
||||
///
|
||||
/// \param type Test result type to count results for.
|
||||
///
|
||||
/// \return The number of test results with \p type.
|
||||
std::size_t
|
||||
count_results(const model::test_result_type type)
|
||||
{
|
||||
const std::map< model::test_result_type,
|
||||
std::vector< result_data > >::const_iterator iter =
|
||||
_results.find(type);
|
||||
if (iter == _results.end())
|
||||
return 0;
|
||||
else
|
||||
return (*iter).second.size();
|
||||
}
|
||||
|
||||
/// Prints a set of results.
|
||||
///
|
||||
/// \param type Test result type to print results for.
|
||||
/// \param title Title used when printing results.
|
||||
void
|
||||
print_results(const model::test_result_type type,
|
||||
const char* title)
|
||||
{
|
||||
const std::map< model::test_result_type,
|
||||
std::vector< result_data > >::const_iterator iter2 =
|
||||
_results.find(type);
|
||||
if (iter2 == _results.end())
|
||||
return;
|
||||
const std::vector< result_data >& all = (*iter2).second;
|
||||
|
||||
_output << F("===> %s\n") % title;
|
||||
for (std::vector< result_data >::const_iterator iter = all.begin();
|
||||
iter != all.end(); iter++) {
|
||||
_output << F("%s:%s -> %s [%s]\n") % (*iter).binary_path %
|
||||
(*iter).test_case_name %
|
||||
cli::format_result((*iter).result) %
|
||||
cli::format_delta((*iter).duration);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
/// Constructor for the hooks.
|
||||
///
|
||||
/// \param [out] output_ Stream to which to write the report.
|
||||
/// \param verbose_ Whether to include details in the output or not.
|
||||
/// \param results_filters_ The result types to include in the report.
|
||||
/// Cannot be empty.
|
||||
/// \param results_file_ Path to the results file being read.
|
||||
report_console_hooks(std::ostream& output_, const bool verbose_,
|
||||
const cli::result_types& results_filters_,
|
||||
const fs::path& results_file_) :
|
||||
_output(output_),
|
||||
_verbose(verbose_),
|
||||
_results_filters(results_filters_),
|
||||
_results_file(results_file_)
|
||||
{
|
||||
PRE(!results_filters_.empty());
|
||||
}
|
||||
|
||||
/// Callback executed when the context is loaded.
|
||||
///
|
||||
/// \param context The context loaded from the database.
|
||||
void
|
||||
got_context(const model::context& context)
|
||||
{
|
||||
if (_verbose)
|
||||
print_context(context);
|
||||
}
|
||||
|
||||
/// Callback executed when a test results is found.
|
||||
///
|
||||
/// \param iter Container for the test result's data.
|
||||
void
|
||||
got_result(store::results_iterator& iter)
|
||||
{
|
||||
if (!_start_time || _start_time.get() > iter.start_time())
|
||||
_start_time = iter.start_time();
|
||||
if (!_end_time || _end_time.get() < iter.end_time())
|
||||
_end_time = iter.end_time();
|
||||
|
||||
const datetime::delta duration = iter.end_time() - iter.start_time();
|
||||
|
||||
_runtime += duration;
|
||||
const model::test_result result = iter.result();
|
||||
_results[result.type()].push_back(
|
||||
result_data(iter.test_program()->relative_path(),
|
||||
iter.test_case_name(), iter.result(), duration));
|
||||
|
||||
if (_verbose) {
|
||||
// TODO(jmmv): _results_filters is a list and is small enough for
|
||||
// std::find to not be an expensive operation here (probably). But
|
||||
// we should be using a std::set instead.
|
||||
if (std::find(_results_filters.begin(), _results_filters.end(),
|
||||
iter.result().type()) != _results_filters.end()) {
|
||||
print_test_case_and_result(iter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Prints the tests summary.
|
||||
void
|
||||
end(const drivers::scan_results::result& /* r */)
|
||||
{
|
||||
typedef std::map< model::test_result_type, const char* > types_map;
|
||||
|
||||
types_map titles;
|
||||
titles[model::test_result_broken] = "Broken tests";
|
||||
titles[model::test_result_expected_failure] = "Expected failures";
|
||||
titles[model::test_result_failed] = "Failed tests";
|
||||
titles[model::test_result_passed] = "Passed tests";
|
||||
titles[model::test_result_skipped] = "Skipped tests";
|
||||
|
||||
for (cli::result_types::const_iterator iter = _results_filters.begin();
|
||||
iter != _results_filters.end(); ++iter) {
|
||||
const types_map::const_iterator match = titles.find(*iter);
|
||||
INV_MSG(match != titles.end(), "Conditional does not match user "
|
||||
"input validation in parse_types()");
|
||||
print_results((*match).first, (*match).second);
|
||||
}
|
||||
|
||||
const std::size_t broken = count_results(model::test_result_broken);
|
||||
const std::size_t failed = count_results(model::test_result_failed);
|
||||
const std::size_t passed = count_results(model::test_result_passed);
|
||||
const std::size_t skipped = count_results(model::test_result_skipped);
|
||||
const std::size_t xfail = count_results(
|
||||
model::test_result_expected_failure);
|
||||
const std::size_t total = broken + failed + passed + skipped + xfail;
|
||||
|
||||
_output << "===> Summary\n";
|
||||
_output << F("Results read from %s\n") % _results_file;
|
||||
_output << F("Test cases: %s total, %s skipped, %s expected failures, "
|
||||
"%s broken, %s failed\n") %
|
||||
total % skipped % xfail % broken % failed;
|
||||
if (_verbose && _start_time) {
|
||||
INV(_end_time);
|
||||
_output << F("Start time: %s\n") %
|
||||
_start_time.get().to_iso8601_in_utc();
|
||||
_output << F("End time: %s\n") %
|
||||
_end_time.get().to_iso8601_in_utc();
|
||||
}
|
||||
_output << F("Total time: %s\n") % cli::format_delta(_runtime);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
/// Default constructor for cmd_report.
|
||||
cmd_report::cmd_report(void) : cli_command(
|
||||
"report", "", 0, -1,
|
||||
"Generates a report with the results of a test suite run")
|
||||
{
|
||||
add_option(results_file_open_option);
|
||||
add_option(cmdline::bool_option(
|
||||
"verbose", "Include the execution context and the details of each test "
|
||||
"case in the report"));
|
||||
add_option(cmdline::path_option("output", "Path to the output file", "path",
|
||||
"/dev/stdout"));
|
||||
add_option(results_filter_option);
|
||||
}
|
||||
|
||||
|
||||
/// Entry point for the "report" subcommand.
|
||||
///
|
||||
/// \param ui Object to interact with the I/O of the program.
|
||||
/// \param cmdline Representation of the command line to the subcommand.
|
||||
///
|
||||
/// \return 0 if everything is OK, 1 if the statement is invalid or if there is
|
||||
/// any other problem.
|
||||
int
|
||||
cmd_report::run(cmdline::ui* ui,
|
||||
const cmdline::parsed_cmdline& cmdline,
|
||||
const config::tree& /* user_config */)
|
||||
{
|
||||
std::auto_ptr< std::ostream > output = utils::open_ostream(
|
||||
cmdline.get_option< cmdline::path_option >("output"));
|
||||
|
||||
const fs::path results_file = layout::find_results(
|
||||
results_file_open(cmdline));
|
||||
|
||||
const result_types types = get_result_types(cmdline);
|
||||
report_console_hooks hooks(*output.get(), cmdline.has_option("verbose"),
|
||||
types, results_file);
|
||||
const drivers::scan_results::result result = drivers::scan_results::drive(
|
||||
results_file, parse_filters(cmdline.arguments()), hooks);
|
||||
|
||||
return report_unused_filters(result.unused_filters, ui) ?
|
||||
EXIT_FAILURE : EXIT_SUCCESS;
|
||||
}
|
54
contrib/kyua/cli/cmd_report.hpp
Normal file
54
contrib/kyua/cli/cmd_report.hpp
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright 2011 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/// \file cli/cmd_report.hpp
|
||||
/// Provides the cmd_report class.
|
||||
|
||||
#if !defined(CLI_CMD_REPORT_HPP)
|
||||
#define CLI_CMD_REPORT_HPP
|
||||
|
||||
#include "cli/common.hpp"
|
||||
|
||||
namespace cli {
|
||||
|
||||
|
||||
/// Implementation of the "report" subcommand.
|
||||
class cmd_report : public cli_command
|
||||
{
|
||||
public:
|
||||
cmd_report(void);
|
||||
|
||||
int run(utils::cmdline::ui*, const utils::cmdline::parsed_cmdline&,
|
||||
const utils::config::tree&);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cli
|
||||
|
||||
|
||||
#endif // !defined(CLI_CMD_REPORT_HPP)
|
474
contrib/kyua/cli/cmd_report_html.cpp
Normal file
474
contrib/kyua/cli/cmd_report_html.cpp
Normal file
@ -0,0 +1,474 @@
|
||||
// Copyright 2012 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "cli/cmd_report_html.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cerrno>
|
||||
#include <cstdlib>
|
||||
#include <set>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "cli/common.ipp"
|
||||
#include "drivers/scan_results.hpp"
|
||||
#include "engine/filters.hpp"
|
||||
#include "model/context.hpp"
|
||||
#include "model/metadata.hpp"
|
||||
#include "model/test_case.hpp"
|
||||
#include "model/test_program.hpp"
|
||||
#include "model/test_result.hpp"
|
||||
#include "store/layout.hpp"
|
||||
#include "store/read_transaction.hpp"
|
||||
#include "utils/cmdline/options.hpp"
|
||||
#include "utils/cmdline/parser.ipp"
|
||||
#include "utils/cmdline/ui.hpp"
|
||||
#include "utils/datetime.hpp"
|
||||
#include "utils/env.hpp"
|
||||
#include "utils/format/macros.hpp"
|
||||
#include "utils/fs/exceptions.hpp"
|
||||
#include "utils/fs/operations.hpp"
|
||||
#include "utils/fs/path.hpp"
|
||||
#include "utils/optional.ipp"
|
||||
#include "utils/text/templates.hpp"
|
||||
|
||||
namespace cmdline = utils::cmdline;
|
||||
namespace config = utils::config;
|
||||
namespace datetime = utils::datetime;
|
||||
namespace fs = utils::fs;
|
||||
namespace layout = store::layout;
|
||||
namespace text = utils::text;
|
||||
|
||||
using utils::optional;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
/// Creates the report's top directory and fails if it exists.
|
||||
///
|
||||
/// \param directory The directory to create.
|
||||
/// \param force Whether to wipe an existing directory or not.
|
||||
///
|
||||
/// \throw std::runtime_error If the directory already exists; this is a user
|
||||
/// error that the user must correct.
|
||||
/// \throw fs::error If the directory creation fails for any other reason.
|
||||
static void
|
||||
create_top_directory(const fs::path& directory, const bool force)
|
||||
{
|
||||
if (force) {
|
||||
if (fs::exists(directory))
|
||||
fs::rm_r(directory);
|
||||
}
|
||||
|
||||
try {
|
||||
fs::mkdir(directory, 0755);
|
||||
} catch (const fs::system_error& e) {
|
||||
if (e.original_errno() == EEXIST)
|
||||
throw std::runtime_error(F("Output directory '%s' already exists; "
|
||||
"maybe use --force?") %
|
||||
directory);
|
||||
else
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Generates a flat unique filename for a given test case.
|
||||
///
|
||||
/// \param test_program The test program for which to genereate the name.
|
||||
/// \param test_case_name The test case name.
|
||||
///
|
||||
/// \return A filename unique within a directory with a trailing HTML extension.
|
||||
static std::string
|
||||
test_case_filename(const model::test_program& test_program,
|
||||
const std::string& test_case_name)
|
||||
{
|
||||
static const char* special_characters = "/:";
|
||||
|
||||
std::string name = cli::format_test_case_id(test_program, test_case_name);
|
||||
std::string::size_type pos = name.find_first_of(special_characters);
|
||||
while (pos != std::string::npos) {
|
||||
name.replace(pos, 1, "_");
|
||||
pos = name.find_first_of(special_characters, pos + 1);
|
||||
}
|
||||
return name + ".html";
|
||||
}
|
||||
|
||||
|
||||
/// Adds a string to string map to the templates.
|
||||
///
|
||||
/// \param [in,out] templates The templates to add the map to.
|
||||
/// \param props The map to add to the templates.
|
||||
/// \param key_vector Name of the template vector that holds the keys.
|
||||
/// \param value_vector Name of the template vector that holds the values.
|
||||
static void
|
||||
add_map(text::templates_def& templates, const config::properties_map& props,
|
||||
const std::string& key_vector, const std::string& value_vector)
|
||||
{
|
||||
templates.add_vector(key_vector);
|
||||
templates.add_vector(value_vector);
|
||||
|
||||
for (config::properties_map::const_iterator iter = props.begin();
|
||||
iter != props.end(); ++iter) {
|
||||
templates.add_to_vector(key_vector, (*iter).first);
|
||||
templates.add_to_vector(value_vector, (*iter).second);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Generates an HTML report.
|
||||
class html_hooks : public drivers::scan_results::base_hooks {
|
||||
/// User interface object where to report progress.
|
||||
cmdline::ui* _ui;
|
||||
|
||||
/// The top directory in which to create the HTML files.
|
||||
fs::path _directory;
|
||||
|
||||
/// Collection of result types to include in the report.
|
||||
const cli::result_types& _results_filters;
|
||||
|
||||
/// The start time of the first test.
|
||||
optional< utils::datetime::timestamp > _start_time;
|
||||
|
||||
/// The end time of the last test.
|
||||
optional< utils::datetime::timestamp > _end_time;
|
||||
|
||||
/// The total run time of the tests. Note that we cannot subtract _end_time
|
||||
/// from _start_time to compute this due to parallel execution.
|
||||
utils::datetime::delta _runtime;
|
||||
|
||||
/// Templates accumulator to generate the index.html file.
|
||||
text::templates_def _summary_templates;
|
||||
|
||||
/// Mapping of result types to the amount of tests with such result.
|
||||
std::map< model::test_result_type, std::size_t > _types_count;
|
||||
|
||||
/// Generates a common set of templates for all of our files.
|
||||
///
|
||||
/// \return A new templates object with common parameters.
|
||||
static text::templates_def
|
||||
common_templates(void)
|
||||
{
|
||||
text::templates_def templates;
|
||||
templates.add_variable("css", "report.css");
|
||||
return templates;
|
||||
}
|
||||
|
||||
/// Adds a test case result to the summary.
|
||||
///
|
||||
/// \param test_program The test program with the test case to be added.
|
||||
/// \param test_case_name Name of the test case.
|
||||
/// \param result The result of the test case.
|
||||
/// \param has_detail If true, the result of the test case has not been
|
||||
/// filtered and therefore there exists a separate file for the test
|
||||
/// with all of its information.
|
||||
void
|
||||
add_to_summary(const model::test_program& test_program,
|
||||
const std::string& test_case_name,
|
||||
const model::test_result& result,
|
||||
const bool has_detail)
|
||||
{
|
||||
++_types_count[result.type()];
|
||||
|
||||
if (!has_detail)
|
||||
return;
|
||||
|
||||
std::string test_cases_vector;
|
||||
std::string test_cases_file_vector;
|
||||
switch (result.type()) {
|
||||
case model::test_result_broken:
|
||||
test_cases_vector = "broken_test_cases";
|
||||
test_cases_file_vector = "broken_test_cases_file";
|
||||
break;
|
||||
|
||||
case model::test_result_expected_failure:
|
||||
test_cases_vector = "xfail_test_cases";
|
||||
test_cases_file_vector = "xfail_test_cases_file";
|
||||
break;
|
||||
|
||||
case model::test_result_failed:
|
||||
test_cases_vector = "failed_test_cases";
|
||||
test_cases_file_vector = "failed_test_cases_file";
|
||||
break;
|
||||
|
||||
case model::test_result_passed:
|
||||
test_cases_vector = "passed_test_cases";
|
||||
test_cases_file_vector = "passed_test_cases_file";
|
||||
break;
|
||||
|
||||
case model::test_result_skipped:
|
||||
test_cases_vector = "skipped_test_cases";
|
||||
test_cases_file_vector = "skipped_test_cases_file";
|
||||
break;
|
||||
}
|
||||
INV(!test_cases_vector.empty());
|
||||
INV(!test_cases_file_vector.empty());
|
||||
|
||||
_summary_templates.add_to_vector(
|
||||
test_cases_vector,
|
||||
cli::format_test_case_id(test_program, test_case_name));
|
||||
_summary_templates.add_to_vector(
|
||||
test_cases_file_vector,
|
||||
test_case_filename(test_program, test_case_name));
|
||||
}
|
||||
|
||||
/// Instantiate a template to generate an HTML file in the output directory.
|
||||
///
|
||||
/// \param templates The templates to use.
|
||||
/// \param template_name The name of the template. This is automatically
|
||||
/// searched for in the installed directory, so do not provide a path.
|
||||
/// \param output_name The name of the output file. This is a basename to
|
||||
/// be created within the output directory.
|
||||
///
|
||||
/// \throw text::error If there is any problem applying the templates.
|
||||
void
|
||||
generate(const text::templates_def& templates,
|
||||
const std::string& template_name,
|
||||
const std::string& output_name) const
|
||||
{
|
||||
const fs::path miscdir(utils::getenv_with_default(
|
||||
"KYUA_MISCDIR", KYUA_MISCDIR));
|
||||
const fs::path template_file = miscdir / template_name;
|
||||
const fs::path output_path(_directory / output_name);
|
||||
|
||||
_ui->out(F("Generating %s") % output_path);
|
||||
text::instantiate(templates, template_file, output_path);
|
||||
}
|
||||
|
||||
/// Gets the number of tests with a given result type.
|
||||
///
|
||||
/// \param type The type to be queried.
|
||||
///
|
||||
/// \return The number of tests of the given type, or 0 if none have yet
|
||||
/// been registered by add_to_summary().
|
||||
std::size_t
|
||||
get_count(const model::test_result_type type) const
|
||||
{
|
||||
const std::map< model::test_result_type, std::size_t >::const_iterator
|
||||
iter = _types_count.find(type);
|
||||
if (iter == _types_count.end())
|
||||
return 0;
|
||||
else
|
||||
return (*iter).second;
|
||||
}
|
||||
|
||||
public:
|
||||
/// Constructor for the hooks.
|
||||
///
|
||||
/// \param ui_ User interface object where to report progress.
|
||||
/// \param directory_ The directory in which to create the HTML files.
|
||||
/// \param results_filters_ The result types to include in the report.
|
||||
/// Cannot be empty.
|
||||
html_hooks(cmdline::ui* ui_, const fs::path& directory_,
|
||||
const cli::result_types& results_filters_) :
|
||||
_ui(ui_),
|
||||
_directory(directory_),
|
||||
_results_filters(results_filters_),
|
||||
_summary_templates(common_templates())
|
||||
{
|
||||
PRE(!results_filters_.empty());
|
||||
|
||||
// Keep in sync with add_to_summary().
|
||||
_summary_templates.add_vector("broken_test_cases");
|
||||
_summary_templates.add_vector("broken_test_cases_file");
|
||||
_summary_templates.add_vector("xfail_test_cases");
|
||||
_summary_templates.add_vector("xfail_test_cases_file");
|
||||
_summary_templates.add_vector("failed_test_cases");
|
||||
_summary_templates.add_vector("failed_test_cases_file");
|
||||
_summary_templates.add_vector("passed_test_cases");
|
||||
_summary_templates.add_vector("passed_test_cases_file");
|
||||
_summary_templates.add_vector("skipped_test_cases");
|
||||
_summary_templates.add_vector("skipped_test_cases_file");
|
||||
}
|
||||
|
||||
/// Callback executed when the context is loaded.
|
||||
///
|
||||
/// \param context The context loaded from the database.
|
||||
void
|
||||
got_context(const model::context& context)
|
||||
{
|
||||
text::templates_def templates = common_templates();
|
||||
templates.add_variable("cwd", context.cwd().str());
|
||||
add_map(templates, context.env(), "env_var", "env_var_value");
|
||||
generate(templates, "context.html", "context.html");
|
||||
}
|
||||
|
||||
/// Callback executed when a test results is found.
|
||||
///
|
||||
/// \param iter Container for the test result's data.
|
||||
void
|
||||
got_result(store::results_iterator& iter)
|
||||
{
|
||||
const model::test_program_ptr test_program = iter.test_program();
|
||||
const std::string& test_case_name = iter.test_case_name();
|
||||
const model::test_result result = iter.result();
|
||||
|
||||
if (std::find(_results_filters.begin(), _results_filters.end(),
|
||||
result.type()) == _results_filters.end()) {
|
||||
add_to_summary(*test_program, test_case_name, result, false);
|
||||
return;
|
||||
}
|
||||
|
||||
add_to_summary(*test_program, test_case_name, result, true);
|
||||
|
||||
if (!_start_time || _start_time.get() > iter.start_time())
|
||||
_start_time = iter.start_time();
|
||||
if (!_end_time || _end_time.get() < iter.end_time())
|
||||
_end_time = iter.end_time();
|
||||
|
||||
const datetime::delta duration = iter.end_time() - iter.start_time();
|
||||
|
||||
_runtime += duration;
|
||||
|
||||
text::templates_def templates = common_templates();
|
||||
templates.add_variable("test_case",
|
||||
cli::format_test_case_id(*test_program,
|
||||
test_case_name));
|
||||
templates.add_variable("test_program",
|
||||
test_program->absolute_path().str());
|
||||
templates.add_variable("result", cli::format_result(result));
|
||||
templates.add_variable("start_time",
|
||||
iter.start_time().to_iso8601_in_utc());
|
||||
templates.add_variable("end_time",
|
||||
iter.end_time().to_iso8601_in_utc());
|
||||
templates.add_variable("duration", cli::format_delta(duration));
|
||||
|
||||
const model::test_case& test_case = test_program->find(test_case_name);
|
||||
add_map(templates, test_case.get_metadata().to_properties(),
|
||||
"metadata_var", "metadata_value");
|
||||
|
||||
{
|
||||
const std::string stdout_text = iter.stdout_contents();
|
||||
if (!stdout_text.empty())
|
||||
templates.add_variable("stdout", stdout_text);
|
||||
}
|
||||
{
|
||||
const std::string stderr_text = iter.stderr_contents();
|
||||
if (!stderr_text.empty())
|
||||
templates.add_variable("stderr", stderr_text);
|
||||
}
|
||||
|
||||
generate(templates, "test_result.html",
|
||||
test_case_filename(*test_program, test_case_name));
|
||||
}
|
||||
|
||||
/// Writes the index.html file in the output directory.
|
||||
///
|
||||
/// This should only be called once all the processing has been done;
|
||||
/// i.e. when the scan_results driver returns.
|
||||
void
|
||||
write_summary(void)
|
||||
{
|
||||
const std::size_t n_passed = get_count(model::test_result_passed);
|
||||
const std::size_t n_failed = get_count(model::test_result_failed);
|
||||
const std::size_t n_skipped = get_count(model::test_result_skipped);
|
||||
const std::size_t n_xfail = get_count(
|
||||
model::test_result_expected_failure);
|
||||
const std::size_t n_broken = get_count(model::test_result_broken);
|
||||
|
||||
const std::size_t n_bad = n_broken + n_failed;
|
||||
|
||||
if (_start_time) {
|
||||
INV(_end_time);
|
||||
_summary_templates.add_variable(
|
||||
"start_time", _start_time.get().to_iso8601_in_utc());
|
||||
_summary_templates.add_variable(
|
||||
"end_time", _end_time.get().to_iso8601_in_utc());
|
||||
} else {
|
||||
_summary_templates.add_variable("start_time", "No tests run");
|
||||
_summary_templates.add_variable("end_time", "No tests run");
|
||||
}
|
||||
_summary_templates.add_variable("duration",
|
||||
cli::format_delta(_runtime));
|
||||
_summary_templates.add_variable("passed_tests_count",
|
||||
F("%s") % n_passed);
|
||||
_summary_templates.add_variable("failed_tests_count",
|
||||
F("%s") % n_failed);
|
||||
_summary_templates.add_variable("skipped_tests_count",
|
||||
F("%s") % n_skipped);
|
||||
_summary_templates.add_variable("xfail_tests_count",
|
||||
F("%s") % n_xfail);
|
||||
_summary_templates.add_variable("broken_tests_count",
|
||||
F("%s") % n_broken);
|
||||
_summary_templates.add_variable("bad_tests_count", F("%s") % n_bad);
|
||||
|
||||
generate(text::templates_def(), "report.css", "report.css");
|
||||
generate(_summary_templates, "index.html", "index.html");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
/// Default constructor for cmd_report_html.
|
||||
cli::cmd_report_html::cmd_report_html(void) : cli_command(
|
||||
"report-html", "", 0, 0,
|
||||
"Generates an HTML report with the result of a test suite run")
|
||||
{
|
||||
add_option(results_file_open_option);
|
||||
add_option(cmdline::bool_option(
|
||||
"force", "Wipe the output directory before generating the new report; "
|
||||
"use care"));
|
||||
add_option(cmdline::path_option(
|
||||
"output", "The directory in which to store the HTML files",
|
||||
"path", "html"));
|
||||
add_option(cmdline::list_option(
|
||||
"results-filter", "Comma-separated list of result types to include in "
|
||||
"the report", "types", "skipped,xfail,broken,failed"));
|
||||
}
|
||||
|
||||
|
||||
/// Entry point for the "report-html" subcommand.
|
||||
///
|
||||
/// \param ui Object to interact with the I/O of the program.
|
||||
/// \param cmdline Representation of the command line to the subcommand.
|
||||
///
|
||||
/// \return 0 if everything is OK, 1 if the statement is invalid or if there is
|
||||
/// any other problem.
|
||||
int
|
||||
cli::cmd_report_html::run(cmdline::ui* ui,
|
||||
const cmdline::parsed_cmdline& cmdline,
|
||||
const config::tree& /* user_config */)
|
||||
{
|
||||
const result_types types = get_result_types(cmdline);
|
||||
|
||||
const fs::path results_file = layout::find_results(
|
||||
results_file_open(cmdline));
|
||||
|
||||
const fs::path directory =
|
||||
cmdline.get_option< cmdline::path_option >("output");
|
||||
create_top_directory(directory, cmdline.has_option("force"));
|
||||
html_hooks hooks(ui, directory, types);
|
||||
drivers::scan_results::drive(results_file,
|
||||
std::set< engine::test_filter >(),
|
||||
hooks);
|
||||
hooks.write_summary();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
55
contrib/kyua/cli/cmd_report_html.hpp
Normal file
55
contrib/kyua/cli/cmd_report_html.hpp
Normal file
@ -0,0 +1,55 @@
|
||||
// Copyright 2012 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/// \file cli/cmd_report_html.hpp
|
||||
/// Provides the cmd_report_html class.
|
||||
|
||||
#if !defined(CLI_CMD_REPORT_HTML_HPP)
|
||||
#define CLI_CMD_REPORT_HTML_HPP
|
||||
|
||||
#include "cli/common.hpp"
|
||||
#include "utils/cmdline/ui_fwd.hpp"
|
||||
|
||||
namespace cli {
|
||||
|
||||
|
||||
/// Implementation of the "report-html" subcommand.
|
||||
class cmd_report_html : public cli_command
|
||||
{
|
||||
public:
|
||||
cmd_report_html(void);
|
||||
|
||||
int run(utils::cmdline::ui*, const utils::cmdline::parsed_cmdline&,
|
||||
const utils::config::tree&);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cli
|
||||
|
||||
|
||||
#endif // !defined(CLI_CMD_REPORT_HTML_HPP)
|
89
contrib/kyua/cli/cmd_report_junit.cpp
Normal file
89
contrib/kyua/cli/cmd_report_junit.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
// Copyright 2014 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "cli/cmd_report_junit.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <set>
|
||||
|
||||
#include "cli/common.ipp"
|
||||
#include "drivers/report_junit.hpp"
|
||||
#include "drivers/scan_results.hpp"
|
||||
#include "engine/filters.hpp"
|
||||
#include "store/layout.hpp"
|
||||
#include "utils/cmdline/options.hpp"
|
||||
#include "utils/cmdline/parser.ipp"
|
||||
#include "utils/defs.hpp"
|
||||
#include "utils/optional.ipp"
|
||||
#include "utils/stream.hpp"
|
||||
|
||||
namespace cmdline = utils::cmdline;
|
||||
namespace config = utils::config;
|
||||
namespace fs = utils::fs;
|
||||
namespace layout = store::layout;
|
||||
|
||||
using cli::cmd_report_junit;
|
||||
using utils::optional;
|
||||
|
||||
|
||||
/// Default constructor for cmd_report.
|
||||
cmd_report_junit::cmd_report_junit(void) : cli_command(
|
||||
"report-junit", "", 0, 0,
|
||||
"Generates a JUnit report with the result of a test suite run")
|
||||
{
|
||||
add_option(results_file_open_option);
|
||||
add_option(cmdline::path_option("output", "Path to the output file", "path",
|
||||
"/dev/stdout"));
|
||||
}
|
||||
|
||||
|
||||
/// Entry point for the "report" subcommand.
|
||||
///
|
||||
/// \param cmdline Representation of the command line to the subcommand.
|
||||
///
|
||||
/// \return 0 if everything is OK, 1 if the statement is invalid or if there is
|
||||
/// any other problem.
|
||||
int
|
||||
cmd_report_junit::run(cmdline::ui* /* ui */,
|
||||
const cmdline::parsed_cmdline& cmdline,
|
||||
const config::tree& /* user_config */)
|
||||
{
|
||||
const fs::path results_file = layout::find_results(
|
||||
results_file_open(cmdline));
|
||||
|
||||
std::auto_ptr< std::ostream > output = utils::open_ostream(
|
||||
cmdline.get_option< cmdline::path_option >("output"));
|
||||
|
||||
drivers::report_junit_hooks hooks(*output.get());
|
||||
drivers::scan_results::drive(results_file,
|
||||
std::set< engine::test_filter >(),
|
||||
hooks);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
54
contrib/kyua/cli/cmd_report_junit.hpp
Normal file
54
contrib/kyua/cli/cmd_report_junit.hpp
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright 2014 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/// \file cli/cmd_report_junit.hpp
|
||||
/// Provides the cmd_report_junit class.
|
||||
|
||||
#if !defined(CLI_CMD_REPORT_JUNIT_HPP)
|
||||
#define CLI_CMD_REPORT_JUNIT_HPP
|
||||
|
||||
#include "cli/common.hpp"
|
||||
|
||||
namespace cli {
|
||||
|
||||
|
||||
/// Implementation of the "report-junit" subcommand.
|
||||
class cmd_report_junit : public cli_command
|
||||
{
|
||||
public:
|
||||
cmd_report_junit(void);
|
||||
|
||||
int run(utils::cmdline::ui*, const utils::cmdline::parsed_cmdline&,
|
||||
const utils::config::tree&);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cli
|
||||
|
||||
|
||||
#endif // !defined(CLI_CMD_REPORT_JUNIT_HPP)
|
186
contrib/kyua/cli/cmd_test.cpp
Normal file
186
contrib/kyua/cli/cmd_test.cpp
Normal file
@ -0,0 +1,186 @@
|
||||
// Copyright 2010 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "cli/cmd_test.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include "cli/common.ipp"
|
||||
#include "drivers/run_tests.hpp"
|
||||
#include "model/test_program.hpp"
|
||||
#include "model/test_result.hpp"
|
||||
#include "store/layout.hpp"
|
||||
#include "utils/cmdline/options.hpp"
|
||||
#include "utils/cmdline/parser.ipp"
|
||||
#include "utils/cmdline/ui.hpp"
|
||||
#include "utils/config/tree.ipp"
|
||||
#include "utils/datetime.hpp"
|
||||
#include "utils/format/macros.hpp"
|
||||
#include "utils/fs/path.hpp"
|
||||
|
||||
namespace cmdline = utils::cmdline;
|
||||
namespace config = utils::config;
|
||||
namespace datetime = utils::datetime;
|
||||
namespace fs = utils::fs;
|
||||
namespace layout = store::layout;
|
||||
|
||||
using cli::cmd_test;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
/// Hooks to print a progress report of the execution of the tests.
|
||||
class print_hooks : public drivers::run_tests::base_hooks {
|
||||
/// Object to interact with the I/O of the program.
|
||||
cmdline::ui* _ui;
|
||||
|
||||
/// Whether the tests are executed in parallel or not.
|
||||
bool _parallel;
|
||||
|
||||
public:
|
||||
/// The amount of positive test results found so far.
|
||||
unsigned long good_count;
|
||||
|
||||
/// The amount of negative test results found so far.
|
||||
unsigned long bad_count;
|
||||
|
||||
/// Constructor for the hooks.
|
||||
///
|
||||
/// \param ui_ Object to interact with the I/O of the program.
|
||||
/// \param parallel_ True if we are executing more than one test at once.
|
||||
print_hooks(cmdline::ui* ui_, const bool parallel_) :
|
||||
_ui(ui_),
|
||||
_parallel(parallel_),
|
||||
good_count(0),
|
||||
bad_count(0)
|
||||
{
|
||||
}
|
||||
|
||||
/// Called when the processing of a test case begins.
|
||||
///
|
||||
/// \param test_program The test program containing the test case.
|
||||
/// \param test_case_name The name of the test case being executed.
|
||||
virtual void
|
||||
got_test_case(const model::test_program& test_program,
|
||||
const std::string& test_case_name)
|
||||
{
|
||||
if (!_parallel) {
|
||||
_ui->out(F("%s -> ") %
|
||||
cli::format_test_case_id(test_program, test_case_name),
|
||||
false);
|
||||
}
|
||||
}
|
||||
|
||||
/// Called when a result of a test case becomes available.
|
||||
///
|
||||
/// \param test_program The test program containing the test case.
|
||||
/// \param test_case_name The name of the test case being executed.
|
||||
/// \param result The result of the execution of the test case.
|
||||
/// \param duration The time it took to run the test.
|
||||
virtual void
|
||||
got_result(const model::test_program& test_program,
|
||||
const std::string& test_case_name,
|
||||
const model::test_result& result,
|
||||
const datetime::delta& duration)
|
||||
{
|
||||
if (_parallel) {
|
||||
_ui->out(F("%s -> ") %
|
||||
cli::format_test_case_id(test_program, test_case_name),
|
||||
false);
|
||||
}
|
||||
_ui->out(F("%s [%s]") % cli::format_result(result) %
|
||||
cli::format_delta(duration));
|
||||
if (result.good())
|
||||
good_count++;
|
||||
else
|
||||
bad_count++;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
/// Default constructor for cmd_test.
|
||||
cmd_test::cmd_test(void) : cli_command(
|
||||
"test", "[test-program ...]", 0, -1, "Run tests")
|
||||
{
|
||||
add_option(build_root_option);
|
||||
add_option(kyuafile_option);
|
||||
add_option(results_file_create_option);
|
||||
}
|
||||
|
||||
|
||||
/// Entry point for the "test" subcommand.
|
||||
///
|
||||
/// \param ui Object to interact with the I/O of the program.
|
||||
/// \param cmdline Representation of the command line to the subcommand.
|
||||
/// \param user_config The runtime configuration of the program.
|
||||
///
|
||||
/// \return 0 if all tests passed, 1 otherwise.
|
||||
int
|
||||
cmd_test::run(cmdline::ui* ui, const cmdline::parsed_cmdline& cmdline,
|
||||
const config::tree& user_config)
|
||||
{
|
||||
const layout::results_id_file_pair results = layout::new_db(
|
||||
results_file_create(cmdline), kyuafile_path(cmdline).branch_path());
|
||||
|
||||
const bool parallel = (user_config.lookup< config::positive_int_node >(
|
||||
"parallelism") > 1);
|
||||
|
||||
print_hooks hooks(ui, parallel);
|
||||
const drivers::run_tests::result result = drivers::run_tests::drive(
|
||||
kyuafile_path(cmdline), build_root_path(cmdline), results.second,
|
||||
parse_filters(cmdline.arguments()), user_config, hooks);
|
||||
|
||||
int exit_code;
|
||||
if (hooks.good_count > 0 || hooks.bad_count > 0) {
|
||||
ui->out("");
|
||||
if (!results.first.empty()) {
|
||||
ui->out(F("Results file id is %s") % results.first);
|
||||
}
|
||||
ui->out(F("Results saved to %s") % results.second);
|
||||
ui->out("");
|
||||
|
||||
ui->out(F("%s/%s passed (%s failed)") % hooks.good_count %
|
||||
(hooks.good_count + hooks.bad_count) % hooks.bad_count);
|
||||
|
||||
exit_code = (hooks.bad_count == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
|
||||
} else {
|
||||
// TODO(jmmv): Delete created empty file; it's useless!
|
||||
if (!results.first.empty()) {
|
||||
ui->out(F("Results file id is %s") % results.first);
|
||||
}
|
||||
ui->out(F("Results saved to %s") % results.second);
|
||||
exit_code = EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
return report_unused_filters(result.unused_filters, ui) ?
|
||||
EXIT_FAILURE : exit_code;
|
||||
}
|
54
contrib/kyua/cli/cmd_test.hpp
Normal file
54
contrib/kyua/cli/cmd_test.hpp
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright 2010 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/// \file cli/cmd_test.hpp
|
||||
/// Provides the cmd_test class.
|
||||
|
||||
#if !defined(CLI_CMD_TEST_HPP)
|
||||
#define CLI_CMD_TEST_HPP
|
||||
|
||||
#include "cli/common.hpp"
|
||||
|
||||
namespace cli {
|
||||
|
||||
|
||||
/// Implementation of the "test" subcommand.
|
||||
class cmd_test : public cli_command
|
||||
{
|
||||
public:
|
||||
cmd_test(void);
|
||||
|
||||
int run(utils::cmdline::ui*, const utils::cmdline::parsed_cmdline&,
|
||||
const utils::config::tree&);
|
||||
};
|
||||
|
||||
|
||||
} // namespace cli
|
||||
|
||||
|
||||
#endif // !defined(CLI_CMD_TEST_HPP)
|
63
contrib/kyua/cli/cmd_test_test.cpp
Normal file
63
contrib/kyua/cli/cmd_test_test.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
// Copyright 2011 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "cli/cmd_test.hpp"
|
||||
|
||||
#include <atf-c++.hpp>
|
||||
|
||||
#include "cli/common.ipp"
|
||||
#include "engine/config.hpp"
|
||||
#include "utils/cmdline/exceptions.hpp"
|
||||
#include "utils/cmdline/parser.hpp"
|
||||
#include "utils/cmdline/ui_mock.hpp"
|
||||
#include "utils/config/tree.ipp"
|
||||
|
||||
namespace cmdline = utils::cmdline;
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(invalid_filter);
|
||||
ATF_TEST_CASE_BODY(invalid_filter)
|
||||
{
|
||||
cmdline::args_vector args;
|
||||
args.push_back("test");
|
||||
args.push_back("correct");
|
||||
args.push_back("incorrect:");
|
||||
|
||||
cli::cmd_test cmd;
|
||||
cmdline::ui_mock ui;
|
||||
ATF_REQUIRE_THROW_RE(cmdline::error, "Test case.*'incorrect:'.*empty",
|
||||
cmd.main(&ui, args, engine::default_config()));
|
||||
ATF_REQUIRE(ui.out_log().empty());
|
||||
ATF_REQUIRE(ui.err_log().empty());
|
||||
}
|
||||
|
||||
|
||||
ATF_INIT_TEST_CASES(tcs)
|
||||
{
|
||||
ATF_ADD_TEST_CASE(tcs, invalid_filter);
|
||||
}
|
411
contrib/kyua/cli/common.cpp
Normal file
411
contrib/kyua/cli/common.cpp
Normal file
@ -0,0 +1,411 @@
|
||||
// Copyright 2011 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "cli/common.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "engine/filters.hpp"
|
||||
#include "model/test_program.hpp"
|
||||
#include "model/test_result.hpp"
|
||||
#include "store/layout.hpp"
|
||||
#include "utils/cmdline/exceptions.hpp"
|
||||
#include "utils/cmdline/options.hpp"
|
||||
#include "utils/cmdline/parser.ipp"
|
||||
#include "utils/cmdline/ui.hpp"
|
||||
#include "utils/datetime.hpp"
|
||||
#include "utils/env.hpp"
|
||||
#include "utils/format/macros.hpp"
|
||||
#include "utils/logging/macros.hpp"
|
||||
#include "utils/fs/exceptions.hpp"
|
||||
#include "utils/fs/operations.hpp"
|
||||
#include "utils/fs/path.hpp"
|
||||
#include "utils/optional.ipp"
|
||||
#include "utils/sanity.hpp"
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
namespace cmdline = utils::cmdline;
|
||||
namespace datetime = utils::datetime;
|
||||
namespace fs = utils::fs;
|
||||
namespace layout = store::layout;
|
||||
|
||||
using utils::none;
|
||||
using utils::optional;
|
||||
|
||||
|
||||
/// Standard definition of the option to specify the build root.
|
||||
const cmdline::path_option cli::build_root_option(
|
||||
"build-root",
|
||||
"Path to the built test programs, if different from the location of the "
|
||||
"Kyuafile scripts",
|
||||
"path");
|
||||
|
||||
|
||||
/// Standard definition of the option to specify a Kyuafile.
|
||||
const cmdline::path_option cli::kyuafile_option(
|
||||
'k', "kyuafile",
|
||||
"Path to the test suite definition",
|
||||
"file", "Kyuafile");
|
||||
|
||||
|
||||
/// Standard definition of the option to specify filters on test results.
|
||||
const cmdline::list_option cli::results_filter_option(
|
||||
"results-filter", "Comma-separated list of result types to include in "
|
||||
"the report", "types", "skipped,xfail,broken,failed");
|
||||
|
||||
|
||||
/// Standard definition of the option to specify the results file.
|
||||
///
|
||||
/// TODO(jmmv): Should support a git-like syntax to go back in time, like
|
||||
/// --results-file=LATEST^N where N indicates how many runs to go back to.
|
||||
const cmdline::string_option cli::results_file_create_option(
|
||||
'r', "results-file",
|
||||
"Path to the results file to create; if left to the default value, the "
|
||||
"name of the file is automatically computed for the current test suite",
|
||||
"file", layout::results_auto_create_name);
|
||||
|
||||
|
||||
/// Standard definition of the option to specify the results file.
|
||||
///
|
||||
/// TODO(jmmv): Should support a git-like syntax to go back in time, like
|
||||
/// --results-file=LATEST^N where N indicates how many runs to go back to.
|
||||
const cmdline::string_option cli::results_file_open_option(
|
||||
'r', "results-file",
|
||||
"Path to the results file to open or the identifier of the current test "
|
||||
"suite or a previous results file for automatic lookup; if left to the "
|
||||
"default value, uses the current directory as the test suite name",
|
||||
"file", layout::results_auto_open_name);
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
/// Gets the path to the historical database if it exists.
|
||||
///
|
||||
/// TODO(jmmv): This function should go away. It only exists as a temporary
|
||||
/// transitional path to force the use of the stale ~/.kyua/store.db if it
|
||||
/// exists.
|
||||
///
|
||||
/// \return A path if the file is found; none otherwise.
|
||||
static optional< fs::path >
|
||||
get_historical_db(void)
|
||||
{
|
||||
optional< fs::path > home = utils::get_home();
|
||||
if (home) {
|
||||
const fs::path old_db = home.get() / ".kyua/store.db";
|
||||
if (fs::exists(old_db)) {
|
||||
if (old_db.is_absolute())
|
||||
return utils::make_optional(old_db);
|
||||
else
|
||||
return utils::make_optional(old_db.to_absolute());
|
||||
} else {
|
||||
return none;
|
||||
}
|
||||
} else {
|
||||
return none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Converts a set of result type names to identifiers.
|
||||
///
|
||||
/// \param names The collection of names to process; may be empty.
|
||||
///
|
||||
/// \return The result type identifiers corresponding to the input names.
|
||||
///
|
||||
/// \throw std::runtime_error If any name in the input names is invalid.
|
||||
static cli::result_types
|
||||
parse_types(const std::vector< std::string >& names)
|
||||
{
|
||||
typedef std::map< std::string, model::test_result_type > types_map;
|
||||
types_map valid_types;
|
||||
valid_types["broken"] = model::test_result_broken;
|
||||
valid_types["failed"] = model::test_result_failed;
|
||||
valid_types["passed"] = model::test_result_passed;
|
||||
valid_types["skipped"] = model::test_result_skipped;
|
||||
valid_types["xfail"] = model::test_result_expected_failure;
|
||||
|
||||
cli::result_types types;
|
||||
for (std::vector< std::string >::const_iterator iter = names.begin();
|
||||
iter != names.end(); ++iter) {
|
||||
const types_map::const_iterator match = valid_types.find(*iter);
|
||||
if (match == valid_types.end())
|
||||
throw std::runtime_error(F("Unknown result type '%s'") % *iter);
|
||||
else
|
||||
types.push_back((*match).second);
|
||||
}
|
||||
return types;
|
||||
}
|
||||
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
/// Gets the path to the build root, if any.
|
||||
///
|
||||
/// This is just syntactic sugar to simplify quierying the 'build_root_option'.
|
||||
///
|
||||
/// \param cmdline The parsed command line.
|
||||
///
|
||||
/// \return The path to the build root, if specified; none otherwise.
|
||||
optional< fs::path >
|
||||
cli::build_root_path(const cmdline::parsed_cmdline& cmdline)
|
||||
{
|
||||
optional< fs::path > build_root;
|
||||
if (cmdline.has_option(build_root_option.long_name()))
|
||||
build_root = cmdline.get_option< cmdline::path_option >(
|
||||
build_root_option.long_name());
|
||||
return build_root;
|
||||
}
|
||||
|
||||
|
||||
/// Gets the path to the Kyuafile to be loaded.
|
||||
///
|
||||
/// This is just syntactic sugar to simplify quierying the 'kyuafile_option'.
|
||||
///
|
||||
/// \param cmdline The parsed command line.
|
||||
///
|
||||
/// \return The path to the Kyuafile to be loaded.
|
||||
fs::path
|
||||
cli::kyuafile_path(const cmdline::parsed_cmdline& cmdline)
|
||||
{
|
||||
return cmdline.get_option< cmdline::path_option >(
|
||||
kyuafile_option.long_name());
|
||||
}
|
||||
|
||||
|
||||
/// Gets the value of the results-file flag for the creation of a new file.
|
||||
///
|
||||
/// \param cmdline The parsed command line from which to extract any possible
|
||||
/// override for the location of the database via the --results-file flag.
|
||||
///
|
||||
/// \return The path to the database to be used.
|
||||
///
|
||||
/// \throw cmdline::error If the value passed to the flag is invalid.
|
||||
std::string
|
||||
cli::results_file_create(const cmdline::parsed_cmdline& cmdline)
|
||||
{
|
||||
std::string results_file = cmdline.get_option< cmdline::string_option >(
|
||||
results_file_create_option.long_name());
|
||||
if (results_file == results_file_create_option.default_value()) {
|
||||
const optional< fs::path > historical_db = get_historical_db();
|
||||
if (historical_db)
|
||||
results_file = historical_db.get().str();
|
||||
} else {
|
||||
try {
|
||||
(void)fs::path(results_file);
|
||||
} catch (const fs::error& e) {
|
||||
throw cmdline::usage_error(F("Invalid value passed to --%s") %
|
||||
results_file_create_option.long_name());
|
||||
}
|
||||
}
|
||||
return results_file;
|
||||
}
|
||||
|
||||
|
||||
/// Gets the value of the results-file flag for the lookup of the file.
|
||||
///
|
||||
/// \param cmdline The parsed command line from which to extract any possible
|
||||
/// override for the location of the database via the --results-file flag.
|
||||
///
|
||||
/// \return The path to the database to be used.
|
||||
///
|
||||
/// \throw cmdline::error If the value passed to the flag is invalid.
|
||||
std::string
|
||||
cli::results_file_open(const cmdline::parsed_cmdline& cmdline)
|
||||
{
|
||||
std::string results_file = cmdline.get_option< cmdline::string_option >(
|
||||
results_file_open_option.long_name());
|
||||
if (results_file == results_file_open_option.default_value()) {
|
||||
const optional< fs::path > historical_db = get_historical_db();
|
||||
if (historical_db)
|
||||
results_file = historical_db.get().str();
|
||||
} else {
|
||||
try {
|
||||
(void)fs::path(results_file);
|
||||
} catch (const fs::error& e) {
|
||||
throw cmdline::usage_error(F("Invalid value passed to --%s") %
|
||||
results_file_open_option.long_name());
|
||||
}
|
||||
}
|
||||
return results_file;
|
||||
}
|
||||
|
||||
|
||||
/// Gets the filters for the result types.
|
||||
///
|
||||
/// \param cmdline The parsed command line.
|
||||
///
|
||||
/// \return A collection of result types to be used for filtering.
|
||||
///
|
||||
/// \throw std::runtime_error If any of the user-provided filters is invalid.
|
||||
cli::result_types
|
||||
cli::get_result_types(const utils::cmdline::parsed_cmdline& cmdline)
|
||||
{
|
||||
result_types types = parse_types(
|
||||
cmdline.get_option< cmdline::list_option >("results-filter"));
|
||||
if (types.empty()) {
|
||||
types.push_back(model::test_result_passed);
|
||||
types.push_back(model::test_result_skipped);
|
||||
types.push_back(model::test_result_expected_failure);
|
||||
types.push_back(model::test_result_broken);
|
||||
types.push_back(model::test_result_failed);
|
||||
}
|
||||
return types;
|
||||
}
|
||||
|
||||
|
||||
/// Parses a set of command-line arguments to construct test filters.
|
||||
///
|
||||
/// \param args The command-line arguments representing test filters.
|
||||
///
|
||||
/// \return A set of test filters.
|
||||
///
|
||||
/// \throw cmdline:error If any of the arguments is invalid, or if they
|
||||
/// represent a non-disjoint collection of filters.
|
||||
std::set< engine::test_filter >
|
||||
cli::parse_filters(const cmdline::args_vector& args)
|
||||
{
|
||||
std::set< engine::test_filter > filters;
|
||||
|
||||
try {
|
||||
for (cmdline::args_vector::const_iterator iter = args.begin();
|
||||
iter != args.end(); iter++) {
|
||||
const engine::test_filter filter(engine::test_filter::parse(*iter));
|
||||
if (filters.find(filter) != filters.end())
|
||||
throw cmdline::error(F("Duplicate filter '%s'") % filter.str());
|
||||
filters.insert(filter);
|
||||
}
|
||||
check_disjoint_filters(filters);
|
||||
} catch (const std::runtime_error& e) {
|
||||
throw cmdline::error(e.what());
|
||||
}
|
||||
|
||||
return filters;
|
||||
}
|
||||
|
||||
|
||||
/// Reports the filters that have not matched any tests as errors.
|
||||
///
|
||||
/// \param unused The collection of unused filters to report.
|
||||
/// \param ui The user interface object through which errors are to be reported.
|
||||
///
|
||||
/// \return True if there are any unused filters. The caller should report this
|
||||
/// as an error to the user by means of a non-successful exit code.
|
||||
bool
|
||||
cli::report_unused_filters(const std::set< engine::test_filter >& unused,
|
||||
cmdline::ui* ui)
|
||||
{
|
||||
for (std::set< engine::test_filter >::const_iterator iter = unused.begin();
|
||||
iter != unused.end(); iter++) {
|
||||
cmdline::print_warning(ui, F("No test cases matched by the filter "
|
||||
"'%s'.") % (*iter).str());
|
||||
}
|
||||
|
||||
return !unused.empty();
|
||||
}
|
||||
|
||||
|
||||
/// Formats a time delta for user presentation.
|
||||
///
|
||||
/// \param delta The time delta to format.
|
||||
///
|
||||
/// \return A user-friendly representation of the time delta.
|
||||
std::string
|
||||
cli::format_delta(const datetime::delta& delta)
|
||||
{
|
||||
return F("%.3ss") % (delta.seconds + (delta.useconds / 1000000.0));
|
||||
}
|
||||
|
||||
|
||||
/// Formats a test case result for user presentation.
|
||||
///
|
||||
/// \param result The result to format.
|
||||
///
|
||||
/// \return A user-friendly representation of the result.
|
||||
std::string
|
||||
cli::format_result(const model::test_result& result)
|
||||
{
|
||||
std::string text;
|
||||
|
||||
switch (result.type()) {
|
||||
case model::test_result_broken: text = "broken"; break;
|
||||
case model::test_result_expected_failure: text = "expected_failure"; break;
|
||||
case model::test_result_failed: text = "failed"; break;
|
||||
case model::test_result_passed: text = "passed"; break;
|
||||
case model::test_result_skipped: text = "skipped"; break;
|
||||
}
|
||||
INV(!text.empty());
|
||||
|
||||
if (!result.reason().empty())
|
||||
text += ": " + result.reason();
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
|
||||
/// Formats the identifier of a test case for user presentation.
|
||||
///
|
||||
/// \param test_program The test program containing the test case.
|
||||
/// \param test_case_name The name of the test case.
|
||||
///
|
||||
/// \return A string representing the test case uniquely within a test suite.
|
||||
std::string
|
||||
cli::format_test_case_id(const model::test_program& test_program,
|
||||
const std::string& test_case_name)
|
||||
{
|
||||
return F("%s:%s") % test_program.relative_path() % test_case_name;
|
||||
}
|
||||
|
||||
|
||||
/// Formats a filter using the same syntax of a test case.
|
||||
///
|
||||
/// \param test_filter The filter to format.
|
||||
///
|
||||
/// \return A string representing the test filter.
|
||||
std::string
|
||||
cli::format_test_case_id(const engine::test_filter& test_filter)
|
||||
{
|
||||
return F("%s:%s") % test_filter.test_program % test_filter.test_case;
|
||||
}
|
||||
|
||||
|
||||
/// Prints the version header information to the interface output.
|
||||
///
|
||||
/// \param ui Interface to which to write the version details.
|
||||
void
|
||||
cli::write_version_header(utils::cmdline::ui* ui)
|
||||
{
|
||||
ui->out(PACKAGE " (" PACKAGE_NAME ") " PACKAGE_VERSION);
|
||||
}
|
104
contrib/kyua/cli/common.hpp
Normal file
104
contrib/kyua/cli/common.hpp
Normal file
@ -0,0 +1,104 @@
|
||||
// Copyright 2011 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/// \file cli/common.hpp
|
||||
/// Utility functions to implement CLI subcommands.
|
||||
|
||||
#if !defined(CLI_COMMON_HPP)
|
||||
#define CLI_COMMON_HPP
|
||||
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include "engine/filters_fwd.hpp"
|
||||
#include "model/test_program_fwd.hpp"
|
||||
#include "model/test_result.hpp"
|
||||
#include "utils/cmdline/base_command.hpp"
|
||||
#include "utils/cmdline/options_fwd.hpp"
|
||||
#include "utils/cmdline/parser_fwd.hpp"
|
||||
#include "utils/cmdline/ui_fwd.hpp"
|
||||
#include "utils/config/tree_fwd.hpp"
|
||||
#include "utils/datetime_fwd.hpp"
|
||||
#include "utils/fs/path_fwd.hpp"
|
||||
#include "utils/optional_fwd.hpp"
|
||||
|
||||
namespace cli {
|
||||
|
||||
|
||||
extern const utils::cmdline::path_option build_root_option;
|
||||
extern const utils::cmdline::path_option kyuafile_option;
|
||||
extern const utils::cmdline::string_option results_file_create_option;
|
||||
extern const utils::cmdline::string_option results_file_open_option;
|
||||
extern const utils::cmdline::list_option results_filter_option;
|
||||
extern const utils::cmdline::property_option variable_option;
|
||||
|
||||
|
||||
/// Base type for commands defined in the cli module.
|
||||
///
|
||||
/// All commands in Kyua receive a configuration object as their runtime
|
||||
/// data parameter because the configuration file applies to all the
|
||||
/// commands.
|
||||
typedef utils::cmdline::base_command< utils::config::tree > cli_command;
|
||||
|
||||
|
||||
/// Scoped, strictly owned pointer to a cli_command.
|
||||
typedef std::auto_ptr< cli_command > cli_command_ptr;
|
||||
|
||||
|
||||
/// Collection of result types.
|
||||
///
|
||||
/// This is a vector rather than a set because we want to respect the order in
|
||||
/// which the user provided the types.
|
||||
typedef std::vector< model::test_result_type > result_types;
|
||||
|
||||
|
||||
utils::optional< utils::fs::path > build_root_path(
|
||||
const utils::cmdline::parsed_cmdline&);
|
||||
utils::fs::path kyuafile_path(const utils::cmdline::parsed_cmdline&);
|
||||
std::string results_file_create(const utils::cmdline::parsed_cmdline&);
|
||||
std::string results_file_open(const utils::cmdline::parsed_cmdline&);
|
||||
result_types get_result_types(const utils::cmdline::parsed_cmdline&);
|
||||
|
||||
std::set< engine::test_filter > parse_filters(
|
||||
const utils::cmdline::args_vector&);
|
||||
bool report_unused_filters(const std::set< engine::test_filter >&,
|
||||
utils::cmdline::ui*);
|
||||
|
||||
std::string format_delta(const utils::datetime::delta&);
|
||||
std::string format_result(const model::test_result&);
|
||||
std::string format_test_case_id(const model::test_program&, const std::string&);
|
||||
std::string format_test_case_id(const engine::test_filter&);
|
||||
|
||||
|
||||
void write_version_header(utils::cmdline::ui*);
|
||||
|
||||
|
||||
} // namespace cli
|
||||
|
||||
#endif // !defined(CLI_COMMON_HPP)
|
30
contrib/kyua/cli/common.ipp
Normal file
30
contrib/kyua/cli/common.ipp
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright 2011 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "cli/common.hpp"
|
||||
#include "utils/cmdline/base_command.ipp"
|
488
contrib/kyua/cli/common_test.cpp
Normal file
488
contrib/kyua/cli/common_test.cpp
Normal file
@ -0,0 +1,488 @@
|
||||
// Copyright 2011 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "cli/common.hpp"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include <atf-c++.hpp>
|
||||
|
||||
#include "engine/exceptions.hpp"
|
||||
#include "engine/filters.hpp"
|
||||
#include "model/metadata.hpp"
|
||||
#include "model/test_program.hpp"
|
||||
#include "model/test_result.hpp"
|
||||
#include "store/layout.hpp"
|
||||
#include "utils/cmdline/exceptions.hpp"
|
||||
#include "utils/cmdline/globals.hpp"
|
||||
#include "utils/cmdline/options.hpp"
|
||||
#include "utils/cmdline/parser.ipp"
|
||||
#include "utils/cmdline/ui_mock.hpp"
|
||||
#include "utils/datetime.hpp"
|
||||
#include "utils/env.hpp"
|
||||
#include "utils/format/macros.hpp"
|
||||
#include "utils/fs/exceptions.hpp"
|
||||
#include "utils/fs/operations.hpp"
|
||||
#include "utils/fs/path.hpp"
|
||||
#include "utils/optional.ipp"
|
||||
#include "utils/sanity.hpp"
|
||||
|
||||
namespace cmdline = utils::cmdline;
|
||||
namespace config = utils::config;
|
||||
namespace datetime = utils::datetime;
|
||||
namespace fs = utils::fs;
|
||||
namespace layout = store::layout;
|
||||
|
||||
using utils::optional;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
/// Syntactic sugar to instantiate engine::test_filter objects.
|
||||
///
|
||||
/// \param test_program Test program.
|
||||
/// \param test_case Test case.
|
||||
///
|
||||
/// \return A \code test_filter \endcode object, based on \p test_program and
|
||||
/// \p test_case.
|
||||
inline engine::test_filter
|
||||
mkfilter(const char* test_program, const char* test_case)
|
||||
{
|
||||
return engine::test_filter(fs::path(test_program), test_case);
|
||||
}
|
||||
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(build_root_path__default);
|
||||
ATF_TEST_CASE_BODY(build_root_path__default)
|
||||
{
|
||||
std::map< std::string, std::vector< std::string > > options;
|
||||
const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector());
|
||||
|
||||
ATF_REQUIRE(!cli::build_root_path(mock_cmdline));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(build_root_path__explicit);
|
||||
ATF_TEST_CASE_BODY(build_root_path__explicit)
|
||||
{
|
||||
std::map< std::string, std::vector< std::string > > options;
|
||||
options["build-root"].push_back("/my//path");
|
||||
const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector());
|
||||
|
||||
ATF_REQUIRE(cli::build_root_path(mock_cmdline));
|
||||
ATF_REQUIRE_EQ("/my/path", cli::build_root_path(mock_cmdline).get().str());
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(kyuafile_path__default);
|
||||
ATF_TEST_CASE_BODY(kyuafile_path__default)
|
||||
{
|
||||
std::map< std::string, std::vector< std::string > > options;
|
||||
options["kyuafile"].push_back(cli::kyuafile_option.default_value());
|
||||
const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector());
|
||||
|
||||
ATF_REQUIRE_EQ(cli::kyuafile_option.default_value(),
|
||||
cli::kyuafile_path(mock_cmdline).str());
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(kyuafile_path__explicit);
|
||||
ATF_TEST_CASE_BODY(kyuafile_path__explicit)
|
||||
{
|
||||
std::map< std::string, std::vector< std::string > > options;
|
||||
options["kyuafile"].push_back("/my//path");
|
||||
const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector());
|
||||
|
||||
ATF_REQUIRE_EQ("/my/path", cli::kyuafile_path(mock_cmdline).str());
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(result_types__default);
|
||||
ATF_TEST_CASE_BODY(result_types__default)
|
||||
{
|
||||
std::map< std::string, std::vector< std::string > > options;
|
||||
options["results-filter"].push_back(
|
||||
cli::results_filter_option.default_value());
|
||||
const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector());
|
||||
|
||||
cli::result_types exp_types;
|
||||
exp_types.push_back(model::test_result_skipped);
|
||||
exp_types.push_back(model::test_result_expected_failure);
|
||||
exp_types.push_back(model::test_result_broken);
|
||||
exp_types.push_back(model::test_result_failed);
|
||||
ATF_REQUIRE(exp_types == cli::get_result_types(mock_cmdline));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(result_types__empty);
|
||||
ATF_TEST_CASE_BODY(result_types__empty)
|
||||
{
|
||||
std::map< std::string, std::vector< std::string > > options;
|
||||
options["results-filter"].push_back("");
|
||||
const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector());
|
||||
|
||||
cli::result_types exp_types;
|
||||
exp_types.push_back(model::test_result_passed);
|
||||
exp_types.push_back(model::test_result_skipped);
|
||||
exp_types.push_back(model::test_result_expected_failure);
|
||||
exp_types.push_back(model::test_result_broken);
|
||||
exp_types.push_back(model::test_result_failed);
|
||||
ATF_REQUIRE(exp_types == cli::get_result_types(mock_cmdline));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(result_types__explicit__all);
|
||||
ATF_TEST_CASE_BODY(result_types__explicit__all)
|
||||
{
|
||||
std::map< std::string, std::vector< std::string > > options;
|
||||
options["results-filter"].push_back("passed,skipped,xfail,broken,failed");
|
||||
const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector());
|
||||
|
||||
cli::result_types exp_types;
|
||||
exp_types.push_back(model::test_result_passed);
|
||||
exp_types.push_back(model::test_result_skipped);
|
||||
exp_types.push_back(model::test_result_expected_failure);
|
||||
exp_types.push_back(model::test_result_broken);
|
||||
exp_types.push_back(model::test_result_failed);
|
||||
ATF_REQUIRE(exp_types == cli::get_result_types(mock_cmdline));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(result_types__explicit__some);
|
||||
ATF_TEST_CASE_BODY(result_types__explicit__some)
|
||||
{
|
||||
std::map< std::string, std::vector< std::string > > options;
|
||||
options["results-filter"].push_back("skipped,broken");
|
||||
const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector());
|
||||
|
||||
cli::result_types exp_types;
|
||||
exp_types.push_back(model::test_result_skipped);
|
||||
exp_types.push_back(model::test_result_broken);
|
||||
ATF_REQUIRE(exp_types == cli::get_result_types(mock_cmdline));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(result_types__explicit__invalid);
|
||||
ATF_TEST_CASE_BODY(result_types__explicit__invalid)
|
||||
{
|
||||
std::map< std::string, std::vector< std::string > > options;
|
||||
options["results-filter"].push_back("skipped,foo,broken");
|
||||
const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector());
|
||||
|
||||
ATF_REQUIRE_THROW_RE(std::runtime_error, "Unknown result type 'foo'",
|
||||
cli::get_result_types(mock_cmdline));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(results_file_create__default__new);
|
||||
ATF_TEST_CASE_BODY(results_file_create__default__new)
|
||||
{
|
||||
std::map< std::string, std::vector< std::string > > options;
|
||||
options["results-file"].push_back(
|
||||
cli::results_file_create_option.default_value());
|
||||
const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector());
|
||||
|
||||
const fs::path home("homedir");
|
||||
utils::setenv("HOME", home.str());
|
||||
|
||||
ATF_REQUIRE_EQ(cli::results_file_create_option.default_value(),
|
||||
cli::results_file_create(mock_cmdline));
|
||||
ATF_REQUIRE(!fs::exists(home / ".kyua"));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(results_file_create__default__historical);
|
||||
ATF_TEST_CASE_BODY(results_file_create__default__historical)
|
||||
{
|
||||
std::map< std::string, std::vector< std::string > > options;
|
||||
options["results-file"].push_back(
|
||||
cli::results_file_create_option.default_value());
|
||||
const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector());
|
||||
|
||||
const fs::path home("homedir");
|
||||
utils::setenv("HOME", home.str());
|
||||
fs::mkdir_p(fs::path("homedir/.kyua"), 0755);
|
||||
atf::utils::create_file("homedir/.kyua/store.db", "fake store");
|
||||
|
||||
ATF_REQUIRE_EQ(fs::path("homedir/.kyua/store.db").to_absolute(),
|
||||
fs::path(cli::results_file_create(mock_cmdline)));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(results_file_create__explicit);
|
||||
ATF_TEST_CASE_BODY(results_file_create__explicit)
|
||||
{
|
||||
std::map< std::string, std::vector< std::string > > options;
|
||||
options["results-file"].push_back("/my//path/f.db");
|
||||
const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector());
|
||||
|
||||
ATF_REQUIRE_EQ("/my//path/f.db",
|
||||
cli::results_file_create(mock_cmdline));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(results_file_open__default__latest);
|
||||
ATF_TEST_CASE_BODY(results_file_open__default__latest)
|
||||
{
|
||||
std::map< std::string, std::vector< std::string > > options;
|
||||
options["results-file"].push_back(
|
||||
cli::results_file_open_option.default_value());
|
||||
const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector());
|
||||
|
||||
const fs::path home("homedir");
|
||||
utils::setenv("HOME", home.str());
|
||||
|
||||
ATF_REQUIRE_EQ(cli::results_file_open_option.default_value(),
|
||||
cli::results_file_open(mock_cmdline));
|
||||
ATF_REQUIRE(!fs::exists(home / ".kyua"));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(results_file_open__default__historical);
|
||||
ATF_TEST_CASE_BODY(results_file_open__default__historical)
|
||||
{
|
||||
std::map< std::string, std::vector< std::string > > options;
|
||||
options["results-file"].push_back(
|
||||
cli::results_file_open_option.default_value());
|
||||
const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector());
|
||||
|
||||
const fs::path home("homedir");
|
||||
utils::setenv("HOME", home.str());
|
||||
fs::mkdir_p(fs::path("homedir/.kyua"), 0755);
|
||||
atf::utils::create_file("homedir/.kyua/store.db", "fake store");
|
||||
|
||||
ATF_REQUIRE_EQ(fs::path("homedir/.kyua/store.db").to_absolute(),
|
||||
fs::path(cli::results_file_open(mock_cmdline)));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(results_file_open__explicit);
|
||||
ATF_TEST_CASE_BODY(results_file_open__explicit)
|
||||
{
|
||||
std::map< std::string, std::vector< std::string > > options;
|
||||
options["results-file"].push_back("/my//path/f.db");
|
||||
const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector());
|
||||
|
||||
ATF_REQUIRE_EQ("/my//path/f.db", cli::results_file_open(mock_cmdline));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(parse_filters__none);
|
||||
ATF_TEST_CASE_BODY(parse_filters__none)
|
||||
{
|
||||
const cmdline::args_vector args;
|
||||
const std::set< engine::test_filter > filters = cli::parse_filters(args);
|
||||
ATF_REQUIRE(filters.empty());
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(parse_filters__ok);
|
||||
ATF_TEST_CASE_BODY(parse_filters__ok)
|
||||
{
|
||||
cmdline::args_vector args;
|
||||
args.push_back("foo");
|
||||
args.push_back("bar/baz");
|
||||
args.push_back("other:abc");
|
||||
args.push_back("other:bcd");
|
||||
const std::set< engine::test_filter > filters = cli::parse_filters(args);
|
||||
|
||||
std::set< engine::test_filter > exp_filters;
|
||||
exp_filters.insert(mkfilter("foo", ""));
|
||||
exp_filters.insert(mkfilter("bar/baz", ""));
|
||||
exp_filters.insert(mkfilter("other", "abc"));
|
||||
exp_filters.insert(mkfilter("other", "bcd"));
|
||||
|
||||
ATF_REQUIRE(exp_filters == filters);
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(parse_filters__duplicate);
|
||||
ATF_TEST_CASE_BODY(parse_filters__duplicate)
|
||||
{
|
||||
cmdline::args_vector args;
|
||||
args.push_back("foo/bar//baz");
|
||||
args.push_back("hello/world:yes");
|
||||
args.push_back("foo//bar/baz");
|
||||
ATF_REQUIRE_THROW_RE(cmdline::error, "Duplicate.*'foo/bar/baz'",
|
||||
cli::parse_filters(args));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(parse_filters__nondisjoint);
|
||||
ATF_TEST_CASE_BODY(parse_filters__nondisjoint)
|
||||
{
|
||||
cmdline::args_vector args;
|
||||
args.push_back("foo/bar");
|
||||
args.push_back("hello/world:yes");
|
||||
args.push_back("foo/bar:baz");
|
||||
ATF_REQUIRE_THROW_RE(cmdline::error, "'foo/bar'.*'foo/bar:baz'.*disjoint",
|
||||
cli::parse_filters(args));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(report_unused_filters__none);
|
||||
ATF_TEST_CASE_BODY(report_unused_filters__none)
|
||||
{
|
||||
std::set< engine::test_filter > unused;
|
||||
|
||||
cmdline::ui_mock ui;
|
||||
ATF_REQUIRE(!cli::report_unused_filters(unused, &ui));
|
||||
ATF_REQUIRE(ui.out_log().empty());
|
||||
ATF_REQUIRE(ui.err_log().empty());
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(report_unused_filters__some);
|
||||
ATF_TEST_CASE_BODY(report_unused_filters__some)
|
||||
{
|
||||
std::set< engine::test_filter > unused;
|
||||
unused.insert(mkfilter("a/b", ""));
|
||||
unused.insert(mkfilter("hey/d", "yes"));
|
||||
|
||||
cmdline::ui_mock ui;
|
||||
cmdline::init("progname");
|
||||
ATF_REQUIRE(cli::report_unused_filters(unused, &ui));
|
||||
ATF_REQUIRE(ui.out_log().empty());
|
||||
ATF_REQUIRE_EQ(2, ui.err_log().size());
|
||||
ATF_REQUIRE( atf::utils::grep_collection("No.*matched.*'a/b'",
|
||||
ui.err_log()));
|
||||
ATF_REQUIRE( atf::utils::grep_collection("No.*matched.*'hey/d:yes'",
|
||||
ui.err_log()));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(format_delta);
|
||||
ATF_TEST_CASE_BODY(format_delta)
|
||||
{
|
||||
ATF_REQUIRE_EQ("0.000s", cli::format_delta(datetime::delta()));
|
||||
ATF_REQUIRE_EQ("0.012s", cli::format_delta(datetime::delta(0, 12300)));
|
||||
ATF_REQUIRE_EQ("0.999s", cli::format_delta(datetime::delta(0, 999000)));
|
||||
ATF_REQUIRE_EQ("51.321s", cli::format_delta(datetime::delta(51, 321000)));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(format_result__no_reason);
|
||||
ATF_TEST_CASE_BODY(format_result__no_reason)
|
||||
{
|
||||
ATF_REQUIRE_EQ("passed", cli::format_result(
|
||||
model::test_result(model::test_result_passed)));
|
||||
ATF_REQUIRE_EQ("failed", cli::format_result(
|
||||
model::test_result(model::test_result_failed)));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(format_result__with_reason);
|
||||
ATF_TEST_CASE_BODY(format_result__with_reason)
|
||||
{
|
||||
ATF_REQUIRE_EQ("broken: Something", cli::format_result(
|
||||
model::test_result(model::test_result_broken, "Something")));
|
||||
ATF_REQUIRE_EQ("expected_failure: A B C", cli::format_result(
|
||||
model::test_result(model::test_result_expected_failure, "A B C")));
|
||||
ATF_REQUIRE_EQ("failed: More text", cli::format_result(
|
||||
model::test_result(model::test_result_failed, "More text")));
|
||||
ATF_REQUIRE_EQ("skipped: Bye", cli::format_result(
|
||||
model::test_result(model::test_result_skipped, "Bye")));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(format_test_case_id__test_case);
|
||||
ATF_TEST_CASE_BODY(format_test_case_id__test_case)
|
||||
{
|
||||
const model::test_program test_program = model::test_program_builder(
|
||||
"mock", fs::path("foo/bar/baz"), fs::path("unused-root"),
|
||||
"unused-suite-name")
|
||||
.add_test_case("abc")
|
||||
.build();
|
||||
ATF_REQUIRE_EQ("foo/bar/baz:abc",
|
||||
cli::format_test_case_id(test_program, "abc"));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(format_test_case_id__test_filter);
|
||||
ATF_TEST_CASE_BODY(format_test_case_id__test_filter)
|
||||
{
|
||||
const engine::test_filter filter(fs::path("foo/bar"), "baz");
|
||||
ATF_REQUIRE_EQ("foo/bar:baz", cli::format_test_case_id(filter));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(write_version_header);
|
||||
ATF_TEST_CASE_BODY(write_version_header)
|
||||
{
|
||||
cmdline::ui_mock ui;
|
||||
cli::write_version_header(&ui);
|
||||
ATF_REQUIRE_EQ(1, ui.out_log().size());
|
||||
ATF_REQUIRE_MATCH("^kyua .*[0-9]+\\.[0-9]+$", ui.out_log()[0]);
|
||||
ATF_REQUIRE(ui.err_log().empty());
|
||||
}
|
||||
|
||||
|
||||
ATF_INIT_TEST_CASES(tcs)
|
||||
{
|
||||
ATF_ADD_TEST_CASE(tcs, build_root_path__default);
|
||||
ATF_ADD_TEST_CASE(tcs, build_root_path__explicit);
|
||||
|
||||
ATF_ADD_TEST_CASE(tcs, kyuafile_path__default);
|
||||
ATF_ADD_TEST_CASE(tcs, kyuafile_path__explicit);
|
||||
|
||||
ATF_ADD_TEST_CASE(tcs, result_types__default);
|
||||
ATF_ADD_TEST_CASE(tcs, result_types__empty);
|
||||
ATF_ADD_TEST_CASE(tcs, result_types__explicit__all);
|
||||
ATF_ADD_TEST_CASE(tcs, result_types__explicit__some);
|
||||
ATF_ADD_TEST_CASE(tcs, result_types__explicit__invalid);
|
||||
|
||||
ATF_ADD_TEST_CASE(tcs, results_file_create__default__new);
|
||||
ATF_ADD_TEST_CASE(tcs, results_file_create__default__historical);
|
||||
ATF_ADD_TEST_CASE(tcs, results_file_create__explicit);
|
||||
|
||||
ATF_ADD_TEST_CASE(tcs, results_file_open__default__latest);
|
||||
ATF_ADD_TEST_CASE(tcs, results_file_open__default__historical);
|
||||
ATF_ADD_TEST_CASE(tcs, results_file_open__explicit);
|
||||
|
||||
ATF_ADD_TEST_CASE(tcs, parse_filters__none);
|
||||
ATF_ADD_TEST_CASE(tcs, parse_filters__ok);
|
||||
ATF_ADD_TEST_CASE(tcs, parse_filters__duplicate);
|
||||
ATF_ADD_TEST_CASE(tcs, parse_filters__nondisjoint);
|
||||
|
||||
ATF_ADD_TEST_CASE(tcs, report_unused_filters__none);
|
||||
ATF_ADD_TEST_CASE(tcs, report_unused_filters__some);
|
||||
|
||||
ATF_ADD_TEST_CASE(tcs, format_delta);
|
||||
|
||||
ATF_ADD_TEST_CASE(tcs, format_result__no_reason);
|
||||
ATF_ADD_TEST_CASE(tcs, format_result__with_reason);
|
||||
|
||||
ATF_ADD_TEST_CASE(tcs, format_test_case_id__test_case);
|
||||
ATF_ADD_TEST_CASE(tcs, format_test_case_id__test_filter);
|
||||
|
||||
ATF_ADD_TEST_CASE(tcs, write_version_header);
|
||||
}
|
223
contrib/kyua/cli/config.cpp
Normal file
223
contrib/kyua/cli/config.cpp
Normal file
@ -0,0 +1,223 @@
|
||||
// Copyright 2011 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "cli/config.hpp"
|
||||
|
||||
#include "cli/common.hpp"
|
||||
#include "engine/config.hpp"
|
||||
#include "engine/exceptions.hpp"
|
||||
#include "utils/cmdline/options.hpp"
|
||||
#include "utils/cmdline/parser.ipp"
|
||||
#include "utils/config/tree.ipp"
|
||||
#include "utils/format/macros.hpp"
|
||||
#include "utils/fs/exceptions.hpp"
|
||||
#include "utils/fs/operations.hpp"
|
||||
#include "utils/fs/path.hpp"
|
||||
#include "utils/env.hpp"
|
||||
#include "utils/logging/macros.hpp"
|
||||
#include "utils/optional.ipp"
|
||||
|
||||
namespace cmdline = utils::cmdline;
|
||||
namespace config = utils::config;
|
||||
namespace fs = utils::fs;
|
||||
|
||||
using utils::optional;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
/// Basename of the configuration file.
|
||||
static const char* config_basename = "kyua.conf";
|
||||
|
||||
|
||||
/// Magic string to disable loading of configuration files.
|
||||
static const char* none_config = "none";
|
||||
|
||||
|
||||
/// Textual description of the default configuration files.
|
||||
///
|
||||
/// This is just an auxiliary string required to define the option below, which
|
||||
/// requires a pointer to a static C string.
|
||||
///
|
||||
/// \todo If the user overrides the KYUA_CONFDIR environment variable, we don't
|
||||
/// reflect this fact here. We don't want to query the variable during program
|
||||
/// initialization due to the side-effects it may have. Therefore, fixing this
|
||||
/// is tricky as it may require a whole rethink of this module.
|
||||
static const std::string config_lookup_names =
|
||||
(fs::path("~/.kyua") / config_basename).str() + " or " +
|
||||
(fs::path(KYUA_CONFDIR) / config_basename).str();
|
||||
|
||||
|
||||
/// Loads the configuration file for this session, if any.
|
||||
///
|
||||
/// This is a helper function that does not apply user-specified overrides. See
|
||||
/// the documentation for cli::load_config() for more details.
|
||||
///
|
||||
/// \param cmdline The parsed command line.
|
||||
///
|
||||
/// \return The loaded configuration file, or the configuration defaults if the
|
||||
/// loading is disabled.
|
||||
///
|
||||
/// \throw engine::error If the parsing of the configuration file fails.
|
||||
/// TODO(jmmv): I'm not sure if this is the raised exception. And even if
|
||||
/// it is, we should make it more accurate.
|
||||
config::tree
|
||||
load_config_file(const cmdline::parsed_cmdline& cmdline)
|
||||
{
|
||||
// TODO(jmmv): We should really be able to use cmdline.has_option here to
|
||||
// detect whether the option was provided or not instead of checking against
|
||||
// the default value.
|
||||
const fs::path filename = cmdline.get_option< cmdline::path_option >(
|
||||
cli::config_option.long_name());
|
||||
if (filename.str() == none_config) {
|
||||
LD("Configuration loading disabled; using defaults");
|
||||
return engine::default_config();
|
||||
} else if (filename.str() != cli::config_option.default_value())
|
||||
return engine::load_config(filename);
|
||||
|
||||
const optional< fs::path > home = utils::get_home();
|
||||
if (home) {
|
||||
const fs::path path = home.get() / ".kyua" / config_basename;
|
||||
try {
|
||||
if (fs::exists(path))
|
||||
return engine::load_config(path);
|
||||
} catch (const fs::error& e) {
|
||||
// Fall through. If we fail to load the user-specific configuration
|
||||
// file because it cannot be openend, we try to load the system-wide
|
||||
// one.
|
||||
LW(F("Failed to load user-specific configuration file '%s': %s") %
|
||||
path % e.what());
|
||||
}
|
||||
}
|
||||
|
||||
const fs::path confdir(utils::getenv_with_default(
|
||||
"KYUA_CONFDIR", KYUA_CONFDIR));
|
||||
|
||||
const fs::path path = confdir / config_basename;
|
||||
if (fs::exists(path)) {
|
||||
return engine::load_config(path);
|
||||
} else {
|
||||
return engine::default_config();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Loads the configuration file for this session, if any.
|
||||
///
|
||||
/// This is a helper function for cli::load_config() that attempts to load the
|
||||
/// configuration unconditionally.
|
||||
///
|
||||
/// \param cmdline The parsed command line.
|
||||
///
|
||||
/// \return The loaded configuration file data.
|
||||
///
|
||||
/// \throw engine::error If the parsing of the configuration file fails.
|
||||
static config::tree
|
||||
load_required_config(const cmdline::parsed_cmdline& cmdline)
|
||||
{
|
||||
config::tree user_config = load_config_file(cmdline);
|
||||
|
||||
if (cmdline.has_option(cli::variable_option.long_name())) {
|
||||
typedef std::pair< std::string, std::string > override_pair;
|
||||
|
||||
const std::vector< override_pair >& overrides =
|
||||
cmdline.get_multi_option< cmdline::property_option >(
|
||||
cli::variable_option.long_name());
|
||||
|
||||
for (std::vector< override_pair >::const_iterator
|
||||
iter = overrides.begin(); iter != overrides.end(); iter++) {
|
||||
try {
|
||||
user_config.set_string((*iter).first, (*iter).second);
|
||||
} catch (const config::error& e) {
|
||||
// TODO(jmmv): Raising this type from here is obviously the
|
||||
// wrong thing to do.
|
||||
throw engine::error(e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return user_config;
|
||||
}
|
||||
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
/// Standard definition of the option to specify a configuration file.
|
||||
///
|
||||
/// You must use load_config() to load a configuration file while honoring the
|
||||
/// value of this flag.
|
||||
const cmdline::path_option cli::config_option(
|
||||
'c', "config",
|
||||
(std::string("Path to the configuration file; '") + none_config +
|
||||
"' to disable loading").c_str(),
|
||||
"file", config_lookup_names.c_str());
|
||||
|
||||
|
||||
/// Standard definition of the option to specify a configuration variable.
|
||||
const cmdline::property_option cli::variable_option(
|
||||
'v', "variable",
|
||||
"Overrides a particular configuration variable",
|
||||
"K=V");
|
||||
|
||||
|
||||
/// Loads the configuration file for this session, if any.
|
||||
///
|
||||
/// The algorithm implemented here is as follows:
|
||||
/// 1) If ~/.kyua/kyua.conf exists, load it.
|
||||
/// 2) Otherwise, if sysconfdir/kyua.conf exists, load it.
|
||||
/// 3) Otherwise, use the built-in settings.
|
||||
/// 4) Lastly, apply any user-provided overrides.
|
||||
///
|
||||
/// \param cmdline The parsed command line.
|
||||
/// \param required Whether the loading of the configuration file must succeed.
|
||||
/// Some commands should run regardless, and therefore we need to set this
|
||||
/// to false for those commands.
|
||||
///
|
||||
/// \return The loaded configuration file data. If required was set to false,
|
||||
/// this might be the default configuration data if the requested file could not
|
||||
/// be properly loaded.
|
||||
///
|
||||
/// \throw engine::error If the parsing of the configuration file fails.
|
||||
config::tree
|
||||
cli::load_config(const cmdline::parsed_cmdline& cmdline,
|
||||
const bool required)
|
||||
{
|
||||
try {
|
||||
return load_required_config(cmdline);
|
||||
} catch (const engine::error& e) {
|
||||
if (required) {
|
||||
throw;
|
||||
} else {
|
||||
LW(F("Ignoring failure to load configuration because the requested "
|
||||
"command should not fail: %s") % e.what());
|
||||
return engine::default_config();
|
||||
}
|
||||
}
|
||||
}
|
55
contrib/kyua/cli/config.hpp
Normal file
55
contrib/kyua/cli/config.hpp
Normal file
@ -0,0 +1,55 @@
|
||||
// Copyright 2011 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/// \file cli/config.hpp
|
||||
/// Utility functions to load configuration files.
|
||||
///
|
||||
/// \todo All this should probably just be merged into the main module
|
||||
/// as nothing else should have access to this.
|
||||
|
||||
#if !defined(CLI_CONFIG_HPP)
|
||||
#define CLI_CONFIG_HPP
|
||||
|
||||
#include "utils/cmdline/options_fwd.hpp"
|
||||
#include "utils/cmdline/parser_fwd.hpp"
|
||||
#include "utils/config/tree_fwd.hpp"
|
||||
|
||||
namespace cli {
|
||||
|
||||
|
||||
extern const utils::cmdline::path_option config_option;
|
||||
extern const utils::cmdline::property_option variable_option;
|
||||
|
||||
|
||||
utils::config::tree load_config(const utils::cmdline::parsed_cmdline&,
|
||||
const bool);
|
||||
|
||||
|
||||
} // namespace cli
|
||||
|
||||
#endif // !defined(CLI_CONFIG_HPP)
|
351
contrib/kyua/cli/config_test.cpp
Normal file
351
contrib/kyua/cli/config_test.cpp
Normal file
@ -0,0 +1,351 @@
|
||||
// Copyright 2011 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "cli/config.hpp"
|
||||
|
||||
#include <atf-c++.hpp>
|
||||
|
||||
#include "engine/config.hpp"
|
||||
#include "engine/exceptions.hpp"
|
||||
#include "utils/cmdline/options.hpp"
|
||||
#include "utils/cmdline/parser.ipp"
|
||||
#include "utils/config/tree.ipp"
|
||||
#include "utils/env.hpp"
|
||||
#include "utils/format/macros.hpp"
|
||||
#include "utils/fs/operations.hpp"
|
||||
#include "utils/fs/path.hpp"
|
||||
|
||||
namespace cmdline = utils::cmdline;
|
||||
namespace config = utils::config;
|
||||
namespace fs = utils::fs;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
/// Creates a configuration file for testing purposes.
|
||||
///
|
||||
/// To ensure that the loaded file is the one created by this function, use
|
||||
/// validate_mock_config().
|
||||
///
|
||||
/// \param name The name of the configuration file to create.
|
||||
/// \param cookie The magic value to set in the configuration file, or NULL if a
|
||||
/// broken configuration file is desired.
|
||||
static void
|
||||
create_mock_config(const char* name, const char* cookie)
|
||||
{
|
||||
if (cookie != NULL) {
|
||||
atf::utils::create_file(
|
||||
name,
|
||||
F("syntax(2)\n"
|
||||
"test_suites.suite.magic_value = '%s'\n") % cookie);
|
||||
} else {
|
||||
atf::utils::create_file(name, "syntax(200)\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Creates an invalid system configuration.
|
||||
///
|
||||
/// \param cookie The magic value to set in the configuration file, or NULL if a
|
||||
/// broken configuration file is desired.
|
||||
static void
|
||||
mock_system_config(const char* cookie)
|
||||
{
|
||||
fs::mkdir(fs::path("system-dir"), 0755);
|
||||
utils::setenv("KYUA_CONFDIR", (fs::current_path() / "system-dir").str());
|
||||
create_mock_config("system-dir/kyua.conf", cookie);
|
||||
}
|
||||
|
||||
|
||||
/// Creates an invalid user configuration.
|
||||
///
|
||||
/// \param cookie The magic value to set in the configuration file, or NULL if a
|
||||
/// broken configuration file is desired.
|
||||
static void
|
||||
mock_user_config(const char* cookie)
|
||||
{
|
||||
fs::mkdir(fs::path("user-dir"), 0755);
|
||||
fs::mkdir(fs::path("user-dir/.kyua"), 0755);
|
||||
utils::setenv("HOME", (fs::current_path() / "user-dir").str());
|
||||
create_mock_config("user-dir/.kyua/kyua.conf", cookie);
|
||||
}
|
||||
|
||||
|
||||
/// Ensures that a loaded configuration was created with create_mock_config().
|
||||
///
|
||||
/// \param user_config The configuration to validate.
|
||||
/// \param cookie The magic value to expect in the configuration file.
|
||||
static void
|
||||
validate_mock_config(const config::tree& user_config, const char* cookie)
|
||||
{
|
||||
const config::properties_map& properties = user_config.all_properties(
|
||||
"test_suites.suite", true);
|
||||
const config::properties_map::const_iterator iter =
|
||||
properties.find("magic_value");
|
||||
ATF_REQUIRE(iter != properties.end());
|
||||
ATF_REQUIRE_EQ(cookie, (*iter).second);
|
||||
}
|
||||
|
||||
|
||||
/// Ensures that two configuration trees are equal.
|
||||
///
|
||||
/// \param exp_tree The expected configuration tree.
|
||||
/// \param actual_tree The configuration tree being validated against exp_tree.
|
||||
static void
|
||||
require_eq(const config::tree& exp_tree, const config::tree& actual_tree)
|
||||
{
|
||||
ATF_REQUIRE(exp_tree.all_properties() == actual_tree.all_properties());
|
||||
}
|
||||
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(load_config__none);
|
||||
ATF_TEST_CASE_BODY(load_config__none)
|
||||
{
|
||||
utils::setenv("KYUA_CONFDIR", "/the/system/does/not/exist");
|
||||
utils::setenv("HOME", "/the/user/does/not/exist");
|
||||
|
||||
std::map< std::string, std::vector< std::string > > options;
|
||||
options["config"].push_back(cli::config_option.default_value());
|
||||
const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector());
|
||||
|
||||
require_eq(engine::default_config(),
|
||||
cli::load_config(mock_cmdline, true));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(load_config__explicit__ok);
|
||||
ATF_TEST_CASE_BODY(load_config__explicit__ok)
|
||||
{
|
||||
mock_system_config(NULL);
|
||||
mock_user_config(NULL);
|
||||
|
||||
create_mock_config("test-file", "hello");
|
||||
|
||||
std::map< std::string, std::vector< std::string > > options;
|
||||
options["config"].push_back("test-file");
|
||||
const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector());
|
||||
|
||||
const config::tree user_config = cli::load_config(mock_cmdline, true);
|
||||
validate_mock_config(user_config, "hello");
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(load_config__explicit__disable);
|
||||
ATF_TEST_CASE_BODY(load_config__explicit__disable)
|
||||
{
|
||||
mock_system_config(NULL);
|
||||
mock_user_config(NULL);
|
||||
|
||||
std::map< std::string, std::vector< std::string > > options;
|
||||
options["config"].push_back("none");
|
||||
const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector());
|
||||
|
||||
require_eq(engine::default_config(),
|
||||
cli::load_config(mock_cmdline, true));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(load_config__explicit__fail);
|
||||
ATF_TEST_CASE_BODY(load_config__explicit__fail)
|
||||
{
|
||||
mock_system_config("ok1");
|
||||
mock_user_config("ok2");
|
||||
|
||||
create_mock_config("test-file", NULL);
|
||||
|
||||
std::map< std::string, std::vector< std::string > > options;
|
||||
options["config"].push_back("test-file");
|
||||
const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector());
|
||||
|
||||
ATF_REQUIRE_THROW_RE(engine::error, "200",
|
||||
cli::load_config(mock_cmdline, true));
|
||||
|
||||
const config::tree config = cli::load_config(mock_cmdline, false);
|
||||
require_eq(engine::default_config(), config);
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(load_config__user__ok);
|
||||
ATF_TEST_CASE_BODY(load_config__user__ok)
|
||||
{
|
||||
mock_system_config(NULL);
|
||||
mock_user_config("I am the user config");
|
||||
|
||||
std::map< std::string, std::vector< std::string > > options;
|
||||
options["config"].push_back(cli::config_option.default_value());
|
||||
const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector());
|
||||
|
||||
const config::tree user_config = cli::load_config(mock_cmdline, true);
|
||||
validate_mock_config(user_config, "I am the user config");
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(load_config__user__fail);
|
||||
ATF_TEST_CASE_BODY(load_config__user__fail)
|
||||
{
|
||||
mock_system_config("valid");
|
||||
mock_user_config(NULL);
|
||||
|
||||
std::map< std::string, std::vector< std::string > > options;
|
||||
options["config"].push_back(cli::config_option.default_value());
|
||||
const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector());
|
||||
|
||||
ATF_REQUIRE_THROW_RE(engine::error, "200",
|
||||
cli::load_config(mock_cmdline, true));
|
||||
|
||||
const config::tree config = cli::load_config(mock_cmdline, false);
|
||||
require_eq(engine::default_config(), config);
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(load_config__user__bad_home);
|
||||
ATF_TEST_CASE_BODY(load_config__user__bad_home)
|
||||
{
|
||||
mock_system_config("Fallback system config");
|
||||
utils::setenv("HOME", "");
|
||||
|
||||
std::map< std::string, std::vector< std::string > > options;
|
||||
options["config"].push_back(cli::config_option.default_value());
|
||||
const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector());
|
||||
|
||||
const config::tree user_config = cli::load_config(mock_cmdline, true);
|
||||
validate_mock_config(user_config, "Fallback system config");
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(load_config__system__ok);
|
||||
ATF_TEST_CASE_BODY(load_config__system__ok)
|
||||
{
|
||||
mock_system_config("I am the system config");
|
||||
utils::setenv("HOME", "/the/user/does/not/exist");
|
||||
|
||||
std::map< std::string, std::vector< std::string > > options;
|
||||
options["config"].push_back(cli::config_option.default_value());
|
||||
const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector());
|
||||
|
||||
const config::tree user_config = cli::load_config(mock_cmdline, true);
|
||||
validate_mock_config(user_config, "I am the system config");
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(load_config__system__fail);
|
||||
ATF_TEST_CASE_BODY(load_config__system__fail)
|
||||
{
|
||||
mock_system_config(NULL);
|
||||
utils::setenv("HOME", "/the/user/does/not/exist");
|
||||
|
||||
std::map< std::string, std::vector< std::string > > options;
|
||||
options["config"].push_back(cli::config_option.default_value());
|
||||
const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector());
|
||||
|
||||
ATF_REQUIRE_THROW_RE(engine::error, "200",
|
||||
cli::load_config(mock_cmdline, true));
|
||||
|
||||
const config::tree config = cli::load_config(mock_cmdline, false);
|
||||
require_eq(engine::default_config(), config);
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(load_config__overrides__no);
|
||||
ATF_TEST_CASE_BODY(load_config__overrides__no)
|
||||
{
|
||||
utils::setenv("KYUA_CONFDIR", fs::current_path().str());
|
||||
|
||||
std::map< std::string, std::vector< std::string > > options;
|
||||
options["config"].push_back(cli::config_option.default_value());
|
||||
options["variable"].push_back("architecture=1");
|
||||
options["variable"].push_back("platform=2");
|
||||
const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector());
|
||||
|
||||
const config::tree user_config = cli::load_config(mock_cmdline, true);
|
||||
ATF_REQUIRE_EQ("1",
|
||||
user_config.lookup< config::string_node >("architecture"));
|
||||
ATF_REQUIRE_EQ("2",
|
||||
user_config.lookup< config::string_node >("platform"));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(load_config__overrides__yes);
|
||||
ATF_TEST_CASE_BODY(load_config__overrides__yes)
|
||||
{
|
||||
atf::utils::create_file(
|
||||
"config",
|
||||
"syntax(2)\n"
|
||||
"architecture = 'do not see me'\n"
|
||||
"platform = 'see me'\n");
|
||||
|
||||
std::map< std::string, std::vector< std::string > > options;
|
||||
options["config"].push_back("config");
|
||||
options["variable"].push_back("architecture=overriden");
|
||||
const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector());
|
||||
|
||||
const config::tree user_config = cli::load_config(mock_cmdline, true);
|
||||
ATF_REQUIRE_EQ("overriden",
|
||||
user_config.lookup< config::string_node >("architecture"));
|
||||
ATF_REQUIRE_EQ("see me",
|
||||
user_config.lookup< config::string_node >("platform"));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(load_config__overrides__fail);
|
||||
ATF_TEST_CASE_BODY(load_config__overrides__fail)
|
||||
{
|
||||
utils::setenv("KYUA_CONFDIR", fs::current_path().str());
|
||||
|
||||
std::map< std::string, std::vector< std::string > > options;
|
||||
options["config"].push_back(cli::config_option.default_value());
|
||||
options["variable"].push_back(".a=d");
|
||||
const cmdline::parsed_cmdline mock_cmdline(options, cmdline::args_vector());
|
||||
|
||||
ATF_REQUIRE_THROW_RE(engine::error, "Empty component in key.*'\\.a'",
|
||||
cli::load_config(mock_cmdline, true));
|
||||
|
||||
const config::tree config = cli::load_config(mock_cmdline, false);
|
||||
require_eq(engine::default_config(), config);
|
||||
}
|
||||
|
||||
|
||||
ATF_INIT_TEST_CASES(tcs)
|
||||
{
|
||||
ATF_ADD_TEST_CASE(tcs, load_config__none);
|
||||
ATF_ADD_TEST_CASE(tcs, load_config__explicit__ok);
|
||||
ATF_ADD_TEST_CASE(tcs, load_config__explicit__disable);
|
||||
ATF_ADD_TEST_CASE(tcs, load_config__explicit__fail);
|
||||
ATF_ADD_TEST_CASE(tcs, load_config__user__ok);
|
||||
ATF_ADD_TEST_CASE(tcs, load_config__user__fail);
|
||||
ATF_ADD_TEST_CASE(tcs, load_config__user__bad_home);
|
||||
ATF_ADD_TEST_CASE(tcs, load_config__system__ok);
|
||||
ATF_ADD_TEST_CASE(tcs, load_config__system__fail);
|
||||
ATF_ADD_TEST_CASE(tcs, load_config__overrides__no);
|
||||
ATF_ADD_TEST_CASE(tcs, load_config__overrides__yes);
|
||||
ATF_ADD_TEST_CASE(tcs, load_config__overrides__fail);
|
||||
}
|
356
contrib/kyua/cli/main.cpp
Normal file
356
contrib/kyua/cli/main.cpp
Normal file
@ -0,0 +1,356 @@
|
||||
// Copyright 2010 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "cli/main.hpp"
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
}
|
||||
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "cli/cmd_about.hpp"
|
||||
#include "cli/cmd_config.hpp"
|
||||
#include "cli/cmd_db_exec.hpp"
|
||||
#include "cli/cmd_db_migrate.hpp"
|
||||
#include "cli/cmd_debug.hpp"
|
||||
#include "cli/cmd_help.hpp"
|
||||
#include "cli/cmd_list.hpp"
|
||||
#include "cli/cmd_report.hpp"
|
||||
#include "cli/cmd_report_html.hpp"
|
||||
#include "cli/cmd_report_junit.hpp"
|
||||
#include "cli/cmd_test.hpp"
|
||||
#include "cli/common.ipp"
|
||||
#include "cli/config.hpp"
|
||||
#include "engine/atf.hpp"
|
||||
#include "engine/plain.hpp"
|
||||
#include "engine/scheduler.hpp"
|
||||
#include "engine/tap.hpp"
|
||||
#include "store/exceptions.hpp"
|
||||
#include "utils/cmdline/commands_map.ipp"
|
||||
#include "utils/cmdline/exceptions.hpp"
|
||||
#include "utils/cmdline/globals.hpp"
|
||||
#include "utils/cmdline/options.hpp"
|
||||
#include "utils/cmdline/parser.ipp"
|
||||
#include "utils/cmdline/ui.hpp"
|
||||
#include "utils/config/tree.ipp"
|
||||
#include "utils/env.hpp"
|
||||
#include "utils/format/macros.hpp"
|
||||
#include "utils/fs/operations.hpp"
|
||||
#include "utils/fs/path.hpp"
|
||||
#include "utils/logging/macros.hpp"
|
||||
#include "utils/logging/operations.hpp"
|
||||
#include "utils/optional.ipp"
|
||||
#include "utils/sanity.hpp"
|
||||
#include "utils/signals/exceptions.hpp"
|
||||
|
||||
namespace cmdline = utils::cmdline;
|
||||
namespace config = utils::config;
|
||||
namespace fs = utils::fs;
|
||||
namespace logging = utils::logging;
|
||||
namespace signals = utils::signals;
|
||||
namespace scheduler = engine::scheduler;
|
||||
|
||||
using utils::none;
|
||||
using utils::optional;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
/// Registers all valid scheduler interfaces.
|
||||
///
|
||||
/// This is part of Kyua's setup but it is a bit strange to find it here. I am
|
||||
/// not sure what a better location would be though, so for now this is good
|
||||
/// enough.
|
||||
static void
|
||||
register_scheduler_interfaces(void)
|
||||
{
|
||||
scheduler::register_interface(
|
||||
"atf", std::shared_ptr< scheduler::interface >(
|
||||
new engine::atf_interface()));
|
||||
scheduler::register_interface(
|
||||
"plain", std::shared_ptr< scheduler::interface >(
|
||||
new engine::plain_interface()));
|
||||
scheduler::register_interface(
|
||||
"tap", std::shared_ptr< scheduler::interface >(
|
||||
new engine::tap_interface()));
|
||||
}
|
||||
|
||||
|
||||
/// Executes the given subcommand with proper usage_error reporting.
|
||||
///
|
||||
/// \param ui Object to interact with the I/O of the program.
|
||||
/// \param command The subcommand to execute.
|
||||
/// \param args The part of the command line passed to the subcommand. The
|
||||
/// first item of this collection must match the command name.
|
||||
/// \param user_config The runtime configuration to pass to the subcommand.
|
||||
///
|
||||
/// \return The exit code of the command. Typically 0 on success, some other
|
||||
/// integer otherwise.
|
||||
///
|
||||
/// \throw cmdline::usage_error If the user input to the subcommand is invalid.
|
||||
/// This error does not encode the command name within it, so this function
|
||||
/// extends the message in the error to specify which subcommand was
|
||||
/// affected.
|
||||
/// \throw std::exception This propagates any uncaught exception. Such
|
||||
/// exceptions are bugs, but we let them propagate so that the runtime will
|
||||
/// abort and dump core.
|
||||
static int
|
||||
run_subcommand(cmdline::ui* ui, cli::cli_command* command,
|
||||
const cmdline::args_vector& args,
|
||||
const config::tree& user_config)
|
||||
{
|
||||
try {
|
||||
PRE(command->name() == args[0]);
|
||||
return command->main(ui, args, user_config);
|
||||
} catch (const cmdline::usage_error& e) {
|
||||
throw std::pair< std::string, cmdline::usage_error >(
|
||||
command->name(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Exception-safe version of main.
|
||||
///
|
||||
/// This function provides the real meat of the entry point of the program. It
|
||||
/// is allowed to throw some known exceptions which are parsed by the caller.
|
||||
/// Doing so keeps this function simpler and allow tests to actually validate
|
||||
/// that the errors reported are accurate.
|
||||
///
|
||||
/// \return The exit code of the program. Should be EXIT_SUCCESS on success and
|
||||
/// EXIT_FAILURE on failure. The caller extends this to additional integers for
|
||||
/// errors reported through exceptions.
|
||||
///
|
||||
/// \param ui Object to interact with the I/O of the program.
|
||||
/// \param argc The number of arguments passed on the command line.
|
||||
/// \param argv NULL-terminated array containing the command line arguments.
|
||||
/// \param mock_command An extra command provided for testing purposes; should
|
||||
/// just be NULL other than for tests.
|
||||
///
|
||||
/// \throw cmdline::usage_error If the user ran the program with invalid
|
||||
/// arguments.
|
||||
/// \throw std::exception This propagates any uncaught exception. Such
|
||||
/// exceptions are bugs, but we let them propagate so that the runtime will
|
||||
/// abort and dump core.
|
||||
static int
|
||||
safe_main(cmdline::ui* ui, int argc, const char* const argv[],
|
||||
cli::cli_command_ptr mock_command)
|
||||
{
|
||||
cmdline::options_vector options;
|
||||
options.push_back(&cli::config_option);
|
||||
options.push_back(&cli::variable_option);
|
||||
const cmdline::string_option loglevel_option(
|
||||
"loglevel", "Level of the messages to log", "level", "info");
|
||||
options.push_back(&loglevel_option);
|
||||
const cmdline::path_option logfile_option(
|
||||
"logfile", "Path to the log file", "file",
|
||||
cli::detail::default_log_name().c_str());
|
||||
options.push_back(&logfile_option);
|
||||
|
||||
cmdline::commands_map< cli::cli_command > commands;
|
||||
|
||||
commands.insert(new cli::cmd_about());
|
||||
commands.insert(new cli::cmd_config());
|
||||
commands.insert(new cli::cmd_db_exec());
|
||||
commands.insert(new cli::cmd_db_migrate());
|
||||
commands.insert(new cli::cmd_help(&options, &commands));
|
||||
|
||||
commands.insert(new cli::cmd_debug(), "Workspace");
|
||||
commands.insert(new cli::cmd_list(), "Workspace");
|
||||
commands.insert(new cli::cmd_test(), "Workspace");
|
||||
|
||||
commands.insert(new cli::cmd_report(), "Reporting");
|
||||
commands.insert(new cli::cmd_report_html(), "Reporting");
|
||||
commands.insert(new cli::cmd_report_junit(), "Reporting");
|
||||
|
||||
if (mock_command.get() != NULL)
|
||||
commands.insert(mock_command);
|
||||
|
||||
const cmdline::parsed_cmdline cmdline = cmdline::parse(argc, argv, options);
|
||||
|
||||
const fs::path logfile(cmdline.get_option< cmdline::path_option >(
|
||||
"logfile"));
|
||||
fs::mkdir_p(logfile.branch_path(), 0755);
|
||||
LD(F("Log file is %s") % logfile);
|
||||
utils::install_crash_handlers(logfile.str());
|
||||
try {
|
||||
logging::set_persistency(cmdline.get_option< cmdline::string_option >(
|
||||
"loglevel"), logfile);
|
||||
} catch (const std::range_error& e) {
|
||||
throw cmdline::usage_error(e.what());
|
||||
}
|
||||
|
||||
if (cmdline.arguments().empty())
|
||||
throw cmdline::usage_error("No command provided");
|
||||
const std::string cmdname = cmdline.arguments()[0];
|
||||
|
||||
const config::tree user_config = cli::load_config(cmdline,
|
||||
cmdname != "help");
|
||||
|
||||
cli::cli_command* command = commands.find(cmdname);
|
||||
if (command == NULL)
|
||||
throw cmdline::usage_error(F("Unknown command '%s'") % cmdname);
|
||||
register_scheduler_interfaces();
|
||||
return run_subcommand(ui, command, cmdline.arguments(), user_config);
|
||||
}
|
||||
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
/// Gets the name of the default log file.
|
||||
///
|
||||
/// \return The path to the log file.
|
||||
fs::path
|
||||
cli::detail::default_log_name(void)
|
||||
{
|
||||
// Update doc/troubleshooting.texi if you change this algorithm.
|
||||
const optional< std::string > home(utils::getenv("HOME"));
|
||||
if (home) {
|
||||
return logging::generate_log_name(fs::path(home.get()) / ".kyua" /
|
||||
"logs", cmdline::progname());
|
||||
} else {
|
||||
const optional< std::string > tmpdir(utils::getenv("TMPDIR"));
|
||||
if (tmpdir) {
|
||||
return logging::generate_log_name(fs::path(tmpdir.get()),
|
||||
cmdline::progname());
|
||||
} else {
|
||||
return logging::generate_log_name(fs::path("/tmp"),
|
||||
cmdline::progname());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Testable entry point, with catch-all exception handlers.
|
||||
///
|
||||
/// This entry point does not perform any initialization of global state; it is
|
||||
/// provided to allow unit-testing of the utility's entry point.
|
||||
///
|
||||
/// \param ui Object to interact with the I/O of the program.
|
||||
/// \param argc The number of arguments passed on the command line.
|
||||
/// \param argv NULL-terminated array containing the command line arguments.
|
||||
/// \param mock_command An extra command provided for testing purposes; should
|
||||
/// just be NULL other than for tests.
|
||||
///
|
||||
/// \return 0 on success, some other integer on error.
|
||||
///
|
||||
/// \throw std::exception This propagates any uncaught exception. Such
|
||||
/// exceptions are bugs, but we let them propagate so that the runtime will
|
||||
/// abort and dump core.
|
||||
int
|
||||
cli::main(cmdline::ui* ui, const int argc, const char* const* const argv,
|
||||
cli_command_ptr mock_command)
|
||||
{
|
||||
try {
|
||||
const int exit_code = safe_main(ui, argc, argv, mock_command);
|
||||
|
||||
// Codes above 1 are reserved to report conditions captured as
|
||||
// exceptions below.
|
||||
INV(exit_code == EXIT_SUCCESS || exit_code == EXIT_FAILURE);
|
||||
|
||||
return exit_code;
|
||||
} catch (const signals::interrupted_error& e) {
|
||||
cmdline::print_error(ui, F("%s.") % e.what());
|
||||
// Re-deliver the interruption signal to self so that we terminate with
|
||||
// the right status. At this point we should NOT have any custom signal
|
||||
// handlers in place.
|
||||
::kill(getpid(), e.signo());
|
||||
LD("Interrupt signal re-delivery did not terminate program");
|
||||
// If we reach this, something went wrong because we did not exit as
|
||||
// intended. Return an internal error instead. (Would be nicer to
|
||||
// abort in principle, but it wouldn't be a nice experience if it ever
|
||||
// happened.)
|
||||
return 2;
|
||||
} catch (const std::pair< std::string, cmdline::usage_error >& e) {
|
||||
const std::string message = F("Usage error for command %s: %s.") %
|
||||
e.first % e.second.what();
|
||||
LE(message);
|
||||
ui->err(message);
|
||||
ui->err(F("Type '%s help %s' for usage information.") %
|
||||
cmdline::progname() % e.first);
|
||||
return 3;
|
||||
} catch (const cmdline::usage_error& e) {
|
||||
const std::string message = F("Usage error: %s.") % e.what();
|
||||
LE(message);
|
||||
ui->err(message);
|
||||
ui->err(F("Type '%s help' for usage information.") %
|
||||
cmdline::progname());
|
||||
return 3;
|
||||
} catch (const store::old_schema_error& e) {
|
||||
const std::string message = F("The database has schema version %s, "
|
||||
"which is too old; please use db-migrate "
|
||||
"to upgrade it.") % e.old_version();
|
||||
cmdline::print_error(ui, message);
|
||||
return 2;
|
||||
} catch (const std::runtime_error& e) {
|
||||
cmdline::print_error(ui, F("%s.") % e.what());
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Delegate for ::main().
|
||||
///
|
||||
/// This function is supposed to be called directly from the top-level ::main()
|
||||
/// function. It takes care of initializing internal libraries and then calls
|
||||
/// main(ui, argc, argv).
|
||||
///
|
||||
/// \pre This function can only be called once.
|
||||
///
|
||||
/// \throw std::exception This propagates any uncaught exception. Such
|
||||
/// exceptions are bugs, but we let them propagate so that the runtime will
|
||||
/// abort and dump core.
|
||||
int
|
||||
cli::main(const int argc, const char* const* const argv)
|
||||
{
|
||||
logging::set_inmemory();
|
||||
|
||||
LI(F("%s %s") % PACKAGE % VERSION);
|
||||
|
||||
std::string plain_args;
|
||||
for (const char* const* arg = argv; *arg != NULL; arg++)
|
||||
plain_args += F(" %s") % *arg;
|
||||
LI(F("Command line:%s") % plain_args);
|
||||
|
||||
cmdline::init(argv[0]);
|
||||
cmdline::ui ui;
|
||||
|
||||
const int exit_code = main(&ui, argc, argv);
|
||||
LI(F("Clean exit with code %s") % exit_code);
|
||||
return exit_code;
|
||||
}
|
61
contrib/kyua/cli/main.hpp
Normal file
61
contrib/kyua/cli/main.hpp
Normal file
@ -0,0 +1,61 @@
|
||||
// Copyright 2010 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/// \file cli/main.hpp
|
||||
/// Entry point for the program.
|
||||
///
|
||||
/// These entry points are separate from the top-level ::main() function to
|
||||
/// allow unit-testing of the main code.
|
||||
|
||||
#if !defined(CLI_MAIN_HPP)
|
||||
#define CLI_MAIN_HPP
|
||||
|
||||
#include "cli/common.hpp"
|
||||
#include "utils/cmdline/ui_fwd.hpp"
|
||||
#include "utils/fs/path_fwd.hpp"
|
||||
|
||||
namespace cli {
|
||||
|
||||
|
||||
namespace detail {
|
||||
|
||||
|
||||
utils::fs::path default_log_name(void);
|
||||
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
int main(utils::cmdline::ui*, const int, const char* const* const,
|
||||
cli_command_ptr = cli_command_ptr());
|
||||
int main(const int, const char* const* const);
|
||||
|
||||
|
||||
} // namespace cli
|
||||
|
||||
#endif // !defined(CLI_MAIN_HPP)
|
489
contrib/kyua/cli/main_test.cpp
Normal file
489
contrib/kyua/cli/main_test.cpp
Normal file
@ -0,0 +1,489 @@
|
||||
// Copyright 2010 The Kyua Authors.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "cli/main.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include <signal.h>
|
||||
}
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include <atf-c++.hpp>
|
||||
|
||||
#include "utils/cmdline/base_command.ipp"
|
||||
#include "utils/cmdline/exceptions.hpp"
|
||||
#include "utils/cmdline/globals.hpp"
|
||||
#include "utils/cmdline/options.hpp"
|
||||
#include "utils/cmdline/parser.hpp"
|
||||
#include "utils/cmdline/ui_mock.hpp"
|
||||
#include "utils/datetime.hpp"
|
||||
#include "utils/defs.hpp"
|
||||
#include "utils/env.hpp"
|
||||
#include "utils/fs/operations.hpp"
|
||||
#include "utils/fs/path.hpp"
|
||||
#include "utils/logging/macros.hpp"
|
||||
#include "utils/logging/operations.hpp"
|
||||
#include "utils/process/child.ipp"
|
||||
#include "utils/process/status.hpp"
|
||||
#include "utils/test_utils.ipp"
|
||||
|
||||
namespace cmdline = utils::cmdline;
|
||||
namespace config = utils::config;
|
||||
namespace datetime = utils::datetime;
|
||||
namespace fs = utils::fs;
|
||||
namespace logging = utils::logging;
|
||||
namespace process = utils::process;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
/// Fake command implementation that crashes during its execution.
|
||||
class cmd_mock_crash : public cli::cli_command {
|
||||
public:
|
||||
/// Constructs a new mock command.
|
||||
///
|
||||
/// All command parameters are set to irrelevant values.
|
||||
cmd_mock_crash(void) :
|
||||
cli::cli_command("mock_error", "", 0, 0, "Mock command that crashes")
|
||||
{
|
||||
}
|
||||
|
||||
/// Runs the mock command.
|
||||
///
|
||||
/// \return Nothing because this function always aborts.
|
||||
int
|
||||
run(cmdline::ui* /* ui */,
|
||||
const cmdline::parsed_cmdline& /* cmdline */,
|
||||
const config::tree& /* user_config */)
|
||||
{
|
||||
utils::abort_without_coredump();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// Fake command implementation that throws an exception during its execution.
|
||||
class cmd_mock_error : public cli::cli_command {
|
||||
/// Whether the command raises an exception captured by the parent or not.
|
||||
///
|
||||
/// If this is true, the command will raise a std::runtime_error exception
|
||||
/// or a subclass of it. The main program is in charge of capturing these
|
||||
/// and reporting them appropriately. If false, this raises another
|
||||
/// exception that does not inherit from std::runtime_error.
|
||||
bool _unhandled;
|
||||
|
||||
public:
|
||||
/// Constructs a new mock command.
|
||||
///
|
||||
/// \param unhandled If true, make run raise an exception not catched by the
|
||||
/// main program.
|
||||
cmd_mock_error(const bool unhandled) :
|
||||
cli::cli_command("mock_error", "", 0, 0,
|
||||
"Mock command that raises an error"),
|
||||
_unhandled(unhandled)
|
||||
{
|
||||
}
|
||||
|
||||
/// Runs the mock command.
|
||||
///
|
||||
/// \return Nothing because this function always aborts.
|
||||
///
|
||||
/// \throw std::logic_error If _unhandled is true.
|
||||
/// \throw std::runtime_error If _unhandled is false.
|
||||
int
|
||||
run(cmdline::ui* /* ui */,
|
||||
const cmdline::parsed_cmdline& /* cmdline */,
|
||||
const config::tree& /* user_config */)
|
||||
{
|
||||
if (_unhandled)
|
||||
throw std::logic_error("This is unhandled");
|
||||
else
|
||||
throw std::runtime_error("Runtime error");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// Fake command implementation that prints messages during its execution.
|
||||
class cmd_mock_write : public cli::cli_command {
|
||||
public:
|
||||
/// Constructs a new mock command.
|
||||
///
|
||||
/// All command parameters are set to irrelevant values.
|
||||
cmd_mock_write(void) : cli::cli_command(
|
||||
"mock_write", "", 0, 0, "Mock command that prints output")
|
||||
{
|
||||
}
|
||||
|
||||
/// Runs the mock command.
|
||||
///
|
||||
/// \param ui Object to interact with the I/O of the program.
|
||||
///
|
||||
/// \return Nothing because this function always aborts.
|
||||
int
|
||||
run(cmdline::ui* ui,
|
||||
const cmdline::parsed_cmdline& /* cmdline */,
|
||||
const config::tree& /* user_config */)
|
||||
{
|
||||
ui->out("stdout message from subcommand");
|
||||
ui->err("stderr message from subcommand");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(detail__default_log_name__home);
|
||||
ATF_TEST_CASE_BODY(detail__default_log_name__home)
|
||||
{
|
||||
datetime::set_mock_now(2011, 2, 21, 21, 10, 30, 0);
|
||||
cmdline::init("progname1");
|
||||
|
||||
utils::setenv("HOME", "/home//fake");
|
||||
utils::setenv("TMPDIR", "/do/not/use/this");
|
||||
ATF_REQUIRE_EQ(
|
||||
fs::path("/home/fake/.kyua/logs/progname1.20110221-211030.log"),
|
||||
cli::detail::default_log_name());
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(detail__default_log_name__tmpdir);
|
||||
ATF_TEST_CASE_BODY(detail__default_log_name__tmpdir)
|
||||
{
|
||||
datetime::set_mock_now(2011, 2, 21, 21, 10, 50, 987);
|
||||
cmdline::init("progname2");
|
||||
|
||||
utils::unsetenv("HOME");
|
||||
utils::setenv("TMPDIR", "/a/b//c");
|
||||
ATF_REQUIRE_EQ(fs::path("/a/b/c/progname2.20110221-211050.log"),
|
||||
cli::detail::default_log_name());
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(detail__default_log_name__hardcoded);
|
||||
ATF_TEST_CASE_BODY(detail__default_log_name__hardcoded)
|
||||
{
|
||||
datetime::set_mock_now(2011, 2, 21, 21, 15, 00, 123456);
|
||||
cmdline::init("progname3");
|
||||
|
||||
utils::unsetenv("HOME");
|
||||
utils::unsetenv("TMPDIR");
|
||||
ATF_REQUIRE_EQ(fs::path("/tmp/progname3.20110221-211500.log"),
|
||||
cli::detail::default_log_name());
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(main__no_args);
|
||||
ATF_TEST_CASE_BODY(main__no_args)
|
||||
{
|
||||
logging::set_inmemory();
|
||||
cmdline::init("progname");
|
||||
|
||||
const int argc = 1;
|
||||
const char* const argv[] = {"progname", NULL};
|
||||
|
||||
cmdline::ui_mock ui;
|
||||
ATF_REQUIRE_EQ(3, cli::main(&ui, argc, argv));
|
||||
ATF_REQUIRE(ui.out_log().empty());
|
||||
ATF_REQUIRE(atf::utils::grep_collection("Usage error: No command provided",
|
||||
ui.err_log()));
|
||||
ATF_REQUIRE(atf::utils::grep_collection("Type.*progname help",
|
||||
ui.err_log()));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(main__unknown_command);
|
||||
ATF_TEST_CASE_BODY(main__unknown_command)
|
||||
{
|
||||
logging::set_inmemory();
|
||||
cmdline::init("progname");
|
||||
|
||||
const int argc = 2;
|
||||
const char* const argv[] = {"progname", "foo", NULL};
|
||||
|
||||
cmdline::ui_mock ui;
|
||||
ATF_REQUIRE_EQ(3, cli::main(&ui, argc, argv));
|
||||
ATF_REQUIRE(ui.out_log().empty());
|
||||
ATF_REQUIRE(atf::utils::grep_collection("Usage error: Unknown command.*foo",
|
||||
ui.err_log()));
|
||||
ATF_REQUIRE(atf::utils::grep_collection("Type.*progname help",
|
||||
ui.err_log()));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(main__logfile__default);
|
||||
ATF_TEST_CASE_BODY(main__logfile__default)
|
||||
{
|
||||
logging::set_inmemory();
|
||||
datetime::set_mock_now(2011, 2, 21, 21, 30, 00, 0);
|
||||
cmdline::init("progname");
|
||||
|
||||
const int argc = 1;
|
||||
const char* const argv[] = {"progname", NULL};
|
||||
|
||||
cmdline::ui_mock ui;
|
||||
ATF_REQUIRE(!fs::exists(fs::path(
|
||||
".kyua/logs/progname.20110221-213000.log")));
|
||||
ATF_REQUIRE_EQ(3, cli::main(&ui, argc, argv));
|
||||
ATF_REQUIRE(fs::exists(fs::path(
|
||||
".kyua/logs/progname.20110221-213000.log")));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(main__logfile__override);
|
||||
ATF_TEST_CASE_BODY(main__logfile__override)
|
||||
{
|
||||
logging::set_inmemory();
|
||||
datetime::set_mock_now(2011, 2, 21, 21, 30, 00, 321);
|
||||
cmdline::init("progname");
|
||||
|
||||
const int argc = 2;
|
||||
const char* const argv[] = {"progname", "--logfile=test.log", NULL};
|
||||
|
||||
cmdline::ui_mock ui;
|
||||
ATF_REQUIRE(!fs::exists(fs::path("test.log")));
|
||||
ATF_REQUIRE_EQ(3, cli::main(&ui, argc, argv));
|
||||
ATF_REQUIRE(!fs::exists(fs::path(
|
||||
".kyua/logs/progname.20110221-213000.log")));
|
||||
ATF_REQUIRE(fs::exists(fs::path("test.log")));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(main__loglevel__default);
|
||||
ATF_TEST_CASE_BODY(main__loglevel__default)
|
||||
{
|
||||
logging::set_inmemory();
|
||||
cmdline::init("progname");
|
||||
|
||||
const int argc = 2;
|
||||
const char* const argv[] = {"progname", "--logfile=test.log", NULL};
|
||||
|
||||
LD("Mock debug message");
|
||||
LE("Mock error message");
|
||||
LI("Mock info message");
|
||||
LW("Mock warning message");
|
||||
|
||||
cmdline::ui_mock ui;
|
||||
ATF_REQUIRE_EQ(3, cli::main(&ui, argc, argv));
|
||||
ATF_REQUIRE(!atf::utils::grep_file("Mock debug message", "test.log"));
|
||||
ATF_REQUIRE(atf::utils::grep_file("Mock error message", "test.log"));
|
||||
ATF_REQUIRE(atf::utils::grep_file("Mock info message", "test.log"));
|
||||
ATF_REQUIRE(atf::utils::grep_file("Mock warning message", "test.log"));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(main__loglevel__higher);
|
||||
ATF_TEST_CASE_BODY(main__loglevel__higher)
|
||||
{
|
||||
logging::set_inmemory();
|
||||
cmdline::init("progname");
|
||||
|
||||
const int argc = 3;
|
||||
const char* const argv[] = {"progname", "--logfile=test.log",
|
||||
"--loglevel=debug", NULL};
|
||||
|
||||
LD("Mock debug message");
|
||||
LE("Mock error message");
|
||||
LI("Mock info message");
|
||||
LW("Mock warning message");
|
||||
|
||||
cmdline::ui_mock ui;
|
||||
ATF_REQUIRE_EQ(3, cli::main(&ui, argc, argv));
|
||||
ATF_REQUIRE(atf::utils::grep_file("Mock debug message", "test.log"));
|
||||
ATF_REQUIRE(atf::utils::grep_file("Mock error message", "test.log"));
|
||||
ATF_REQUIRE(atf::utils::grep_file("Mock info message", "test.log"));
|
||||
ATF_REQUIRE(atf::utils::grep_file("Mock warning message", "test.log"));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(main__loglevel__lower);
|
||||
ATF_TEST_CASE_BODY(main__loglevel__lower)
|
||||
{
|
||||
logging::set_inmemory();
|
||||
cmdline::init("progname");
|
||||
|
||||
const int argc = 3;
|
||||
const char* const argv[] = {"progname", "--logfile=test.log",
|
||||
"--loglevel=warning", NULL};
|
||||
|
||||
LD("Mock debug message");
|
||||
LE("Mock error message");
|
||||
LI("Mock info message");
|
||||
LW("Mock warning message");
|
||||
|
||||
cmdline::ui_mock ui;
|
||||
ATF_REQUIRE_EQ(3, cli::main(&ui, argc, argv));
|
||||
ATF_REQUIRE(!atf::utils::grep_file("Mock debug message", "test.log"));
|
||||
ATF_REQUIRE(atf::utils::grep_file("Mock error message", "test.log"));
|
||||
ATF_REQUIRE(!atf::utils::grep_file("Mock info message", "test.log"));
|
||||
ATF_REQUIRE(atf::utils::grep_file("Mock warning message", "test.log"));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(main__loglevel__error);
|
||||
ATF_TEST_CASE_BODY(main__loglevel__error)
|
||||
{
|
||||
logging::set_inmemory();
|
||||
cmdline::init("progname");
|
||||
|
||||
const int argc = 3;
|
||||
const char* const argv[] = {"progname", "--logfile=test.log",
|
||||
"--loglevel=i-am-invalid", NULL};
|
||||
|
||||
cmdline::ui_mock ui;
|
||||
ATF_REQUIRE_EQ(3, cli::main(&ui, argc, argv));
|
||||
ATF_REQUIRE(atf::utils::grep_collection("Usage error.*i-am-invalid",
|
||||
ui.err_log()));
|
||||
ATF_REQUIRE(!fs::exists(fs::path("test.log")));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(main__subcommand__ok);
|
||||
ATF_TEST_CASE_BODY(main__subcommand__ok)
|
||||
{
|
||||
logging::set_inmemory();
|
||||
cmdline::init("progname");
|
||||
|
||||
const int argc = 2;
|
||||
const char* const argv[] = {"progname", "mock_write", NULL};
|
||||
|
||||
cmdline::ui_mock ui;
|
||||
ATF_REQUIRE_EQ(EXIT_FAILURE,
|
||||
cli::main(&ui, argc, argv,
|
||||
cli::cli_command_ptr(new cmd_mock_write())));
|
||||
ATF_REQUIRE_EQ(1, ui.out_log().size());
|
||||
ATF_REQUIRE_EQ("stdout message from subcommand", ui.out_log()[0]);
|
||||
ATF_REQUIRE_EQ(1, ui.err_log().size());
|
||||
ATF_REQUIRE_EQ("stderr message from subcommand", ui.err_log()[0]);
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(main__subcommand__invalid_args);
|
||||
ATF_TEST_CASE_BODY(main__subcommand__invalid_args)
|
||||
{
|
||||
logging::set_inmemory();
|
||||
cmdline::init("progname");
|
||||
|
||||
const int argc = 3;
|
||||
const char* const argv[] = {"progname", "mock_write", "bar", NULL};
|
||||
|
||||
cmdline::ui_mock ui;
|
||||
ATF_REQUIRE_EQ(3,
|
||||
cli::main(&ui, argc, argv,
|
||||
cli::cli_command_ptr(new cmd_mock_write())));
|
||||
ATF_REQUIRE(ui.out_log().empty());
|
||||
ATF_REQUIRE(atf::utils::grep_collection(
|
||||
"Usage error for command mock_write: Too many arguments.",
|
||||
ui.err_log()));
|
||||
ATF_REQUIRE(atf::utils::grep_collection("Type.*progname help",
|
||||
ui.err_log()));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(main__subcommand__runtime_error);
|
||||
ATF_TEST_CASE_BODY(main__subcommand__runtime_error)
|
||||
{
|
||||
logging::set_inmemory();
|
||||
cmdline::init("progname");
|
||||
|
||||
const int argc = 2;
|
||||
const char* const argv[] = {"progname", "mock_error", NULL};
|
||||
|
||||
cmdline::ui_mock ui;
|
||||
ATF_REQUIRE_EQ(2, cli::main(&ui, argc, argv,
|
||||
cli::cli_command_ptr(new cmd_mock_error(false))));
|
||||
ATF_REQUIRE(ui.out_log().empty());
|
||||
ATF_REQUIRE(atf::utils::grep_collection("progname: E: Runtime error.",
|
||||
ui.err_log()));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(main__subcommand__unhandled_exception);
|
||||
ATF_TEST_CASE_BODY(main__subcommand__unhandled_exception)
|
||||
{
|
||||
logging::set_inmemory();
|
||||
cmdline::init("progname");
|
||||
|
||||
const int argc = 2;
|
||||
const char* const argv[] = {"progname", "mock_error", NULL};
|
||||
|
||||
cmdline::ui_mock ui;
|
||||
ATF_REQUIRE_THROW(std::logic_error, cli::main(&ui, argc, argv,
|
||||
cli::cli_command_ptr(new cmd_mock_error(true))));
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
do_subcommand_crash(void)
|
||||
{
|
||||
logging::set_inmemory();
|
||||
cmdline::init("progname");
|
||||
|
||||
const int argc = 2;
|
||||
const char* const argv[] = {"progname", "mock_error", NULL};
|
||||
|
||||
cmdline::ui_mock ui;
|
||||
cli::main(&ui, argc, argv,
|
||||
cli::cli_command_ptr(new cmd_mock_crash()));
|
||||
}
|
||||
|
||||
|
||||
ATF_TEST_CASE_WITHOUT_HEAD(main__subcommand__crash);
|
||||
ATF_TEST_CASE_BODY(main__subcommand__crash)
|
||||
{
|
||||
const process::status status = process::child::fork_files(
|
||||
do_subcommand_crash, fs::path("stdout.txt"),
|
||||
fs::path("stderr.txt"))->wait();
|
||||
ATF_REQUIRE(status.signaled());
|
||||
ATF_REQUIRE_EQ(SIGABRT, status.termsig());
|
||||
ATF_REQUIRE(atf::utils::grep_file("Fatal signal", "stderr.txt"));
|
||||
}
|
||||
|
||||
|
||||
ATF_INIT_TEST_CASES(tcs)
|
||||
{
|
||||
ATF_ADD_TEST_CASE(tcs, detail__default_log_name__home);
|
||||
ATF_ADD_TEST_CASE(tcs, detail__default_log_name__tmpdir);
|
||||
ATF_ADD_TEST_CASE(tcs, detail__default_log_name__hardcoded);
|
||||
|
||||
ATF_ADD_TEST_CASE(tcs, main__no_args);
|
||||
ATF_ADD_TEST_CASE(tcs, main__unknown_command);
|
||||
ATF_ADD_TEST_CASE(tcs, main__logfile__default);
|
||||
ATF_ADD_TEST_CASE(tcs, main__logfile__override);
|
||||
ATF_ADD_TEST_CASE(tcs, main__loglevel__default);
|
||||
ATF_ADD_TEST_CASE(tcs, main__loglevel__higher);
|
||||
ATF_ADD_TEST_CASE(tcs, main__loglevel__lower);
|
||||
ATF_ADD_TEST_CASE(tcs, main__loglevel__error);
|
||||
ATF_ADD_TEST_CASE(tcs, main__subcommand__ok);
|
||||
ATF_ADD_TEST_CASE(tcs, main__subcommand__invalid_args);
|
||||
ATF_ADD_TEST_CASE(tcs, main__subcommand__runtime_error);
|
||||
ATF_ADD_TEST_CASE(tcs, main__subcommand__unhandled_exception);
|
||||
ATF_ADD_TEST_CASE(tcs, main__subcommand__crash);
|
||||
}
|
173
contrib/kyua/configure.ac
Normal file
173
contrib/kyua/configure.ac
Normal file
@ -0,0 +1,173 @@
|
||||
dnl Copyright 2010 The Kyua Authors.
|
||||
dnl All rights reserved.
|
||||
dnl
|
||||
dnl Redistribution and use in source and binary forms, with or without
|
||||
dnl modification, are permitted provided that the following conditions are
|
||||
dnl met:
|
||||
dnl
|
||||
dnl * Redistributions of source code must retain the above copyright
|
||||
dnl notice, this list of conditions and the following disclaimer.
|
||||
dnl * Redistributions in binary form must reproduce the above copyright
|
||||
dnl notice, this list of conditions and the following disclaimer in the
|
||||
dnl documentation and/or other materials provided with the distribution.
|
||||
dnl * Neither the name of Google Inc. nor the names of its contributors
|
||||
dnl may be used to endorse or promote products derived from this software
|
||||
dnl without specific prior written permission.
|
||||
dnl
|
||||
dnl THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
dnl "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
dnl LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
dnl A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
dnl OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
dnl SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
dnl LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
dnl DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
dnl THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
dnl (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
dnl OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
AC_INIT([Kyua], [0.14], [kyua-discuss@googlegroups.com], [kyua],
|
||||
[https://github.com/jmmv/kyua/])
|
||||
AC_PREREQ([2.65])
|
||||
|
||||
|
||||
AC_COPYRIGHT([Copyright 2010 The Kyua Authors.])
|
||||
AC_CONFIG_AUX_DIR([admin])
|
||||
AC_CONFIG_FILES([Doxyfile Makefile utils/defs.hpp])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_CONFIG_SRCDIR([main.cpp])
|
||||
AC_CONFIG_TESTDIR([bootstrap])
|
||||
|
||||
|
||||
AM_INIT_AUTOMAKE([1.9 foreign subdir-objects -Wall])
|
||||
|
||||
|
||||
AC_LANG([C++])
|
||||
AC_PROG_CXX
|
||||
AX_CXX_COMPILE_STDCXX([11], [noext], [mandatory])
|
||||
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
|
||||
KYUA_DEVELOPER_MODE([C++])
|
||||
KYUA_ATTRIBUTE_NORETURN
|
||||
KYUA_ATTRIBUTE_PURE
|
||||
KYUA_ATTRIBUTE_UNUSED
|
||||
KYUA_FS_MODULE
|
||||
KYUA_GETOPT
|
||||
KYUA_LAST_SIGNO
|
||||
KYUA_MEMORY
|
||||
AC_CHECK_FUNCS([putenv setenv unsetenv])
|
||||
AC_CHECK_HEADERS([termios.h])
|
||||
|
||||
|
||||
AC_PROG_RANLIB
|
||||
|
||||
|
||||
m4_ifndef([PKG_CHECK_MODULES],
|
||||
[m4_fatal([Cannot find pkg.m4; see the INSTALL document for help])])
|
||||
|
||||
m4_ifndef([ATF_CHECK_CXX],
|
||||
[m4_fatal([Cannot find atf-c++.m4; see the INSTALL document for help])])
|
||||
ATF_CHECK_CXX([>= 0.17])
|
||||
m4_ifndef([ATF_CHECK_SH],
|
||||
[m4_fatal([Cannot find atf-sh.m4; see the INSTALL document for help])])
|
||||
ATF_CHECK_SH([>= 0.15])
|
||||
m4_ifndef([ATF_ARG_WITH],
|
||||
[m4_fatal([Cannot find atf-common.m4; see the INSTALL document for help])])
|
||||
ATF_ARG_WITH
|
||||
|
||||
PKG_CHECK_MODULES([LUTOK], [lutok >= 0.4],
|
||||
[],
|
||||
AC_MSG_ERROR([lutok (0.4 or newer) is required]))
|
||||
PKG_CHECK_MODULES([SQLITE3], [sqlite3 >= 3.6.22],
|
||||
[],
|
||||
AC_MSG_ERROR([sqlite3 (3.6.22 or newer) is required]))
|
||||
KYUA_DOXYGEN
|
||||
AC_PATH_PROG([GDB], [gdb])
|
||||
test -n "${GDB}" || GDB=gdb
|
||||
AC_PATH_PROG([GIT], [git])
|
||||
|
||||
|
||||
KYUA_UNAME_ARCHITECTURE
|
||||
KYUA_UNAME_PLATFORM
|
||||
|
||||
|
||||
AC_ARG_VAR([KYUA_CONFSUBDIR],
|
||||
[Subdirectory of sysconfdir under which to look for files])
|
||||
if test x"${KYUA_CONFSUBDIR-unset}" = x"unset"; then
|
||||
KYUA_CONFSUBDIR=kyua
|
||||
else
|
||||
case ${KYUA_CONFSUBDIR} in
|
||||
/*)
|
||||
AC_MSG_ERROR([KYUA_CONFSUBDIR must hold a relative path])
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
if test x"${KYUA_CONFSUBDIR}" = x""; then
|
||||
AC_SUBST(kyua_confdir, \${sysconfdir})
|
||||
else
|
||||
AC_SUBST(kyua_confdir, \${sysconfdir}/${KYUA_CONFSUBDIR})
|
||||
fi
|
||||
|
||||
|
||||
dnl Allow the caller of 'make check', 'make installcheck' and 'make distcheck'
|
||||
dnl on the Kyua source tree to override the configuration file passed to our
|
||||
dnl own test runs. This is for the development of Kyua only and the value of
|
||||
dnl this setting has no effect on the built product in any way. If we go
|
||||
dnl through great extents in validating the value of this setting, it is to
|
||||
dnl minimize the chance of false test run negatives later on.
|
||||
AC_ARG_VAR([KYUA_CONFIG_FILE_FOR_CHECK],
|
||||
[kyua.conf file to use at 'make (|dist|install)check' time])
|
||||
case "${KYUA_CONFIG_FILE_FOR_CHECK-none}" in
|
||||
none)
|
||||
KYUA_CONFIG_FILE_FOR_CHECK=none
|
||||
;;
|
||||
/*)
|
||||
if test -f "${KYUA_CONFIG_FILE_FOR_CHECK}"; then
|
||||
: # All good!
|
||||
else
|
||||
AC_MSG_ERROR([KYUA_CONFIG_FILE_FOR_CHECK file does not exist])
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
AC_MSG_ERROR([KYUA_CONFIG_FILE_FOR_CHECK must hold an absolute path])
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
AC_ARG_VAR([KYUA_TMPDIR],
|
||||
[Path to the directory in which to place work directories])
|
||||
case "${KYUA_TMPDIR:-unset}" in
|
||||
unset)
|
||||
KYUA_TMPDIR=/tmp
|
||||
;;
|
||||
/*)
|
||||
;;
|
||||
*)
|
||||
AC_MSG_ERROR([KYUA_TMPDIR must be an absolute path])
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
AC_SUBST(examplesdir, \${pkgdatadir}/examples)
|
||||
AC_SUBST(luadir, \${pkgdatadir}/lua)
|
||||
AC_SUBST(miscdir, \${pkgdatadir}/misc)
|
||||
AC_SUBST(pkgtestsdir, \${testsdir}/kyua)
|
||||
AC_SUBST(storedir, \${pkgdatadir}/store)
|
||||
AC_SUBST(testsdir, \${exec_prefix}/tests)
|
||||
|
||||
|
||||
dnl BSD make(1) doesn't deal with targets specified as './foo' well: they
|
||||
dnl need to be specified as 'foo'. The following hack is to workaround this
|
||||
dnl issue.
|
||||
if test "${srcdir}" = .; then
|
||||
target_srcdir=
|
||||
else
|
||||
target_srcdir="${srcdir}/"
|
||||
fi
|
||||
AM_CONDITIONAL(TARGET_SRCDIR_EMPTY, [test -z "${target_srcdir}"])
|
||||
AC_SUBST([target_srcdir])
|
||||
|
||||
|
||||
AC_OUTPUT
|
14
contrib/kyua/doc/.gitignore
vendored
Normal file
14
contrib/kyua/doc/.gitignore
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
kyua-about.1
|
||||
kyua-config.1
|
||||
kyua-db-exec.1
|
||||
kyua-db-migrate.1
|
||||
kyua-debug.1
|
||||
kyua-help.1
|
||||
kyua-list.1
|
||||
kyua-report-html.1
|
||||
kyua-report-junit.1
|
||||
kyua-report.1
|
||||
kyua-test.1
|
||||
kyua.1
|
||||
kyua.conf.5
|
||||
kyuafile.5
|
5
contrib/kyua/doc/Kyuafile
Normal file
5
contrib/kyua/doc/Kyuafile
Normal file
@ -0,0 +1,5 @@
|
||||
syntax(2)
|
||||
|
||||
test_suite("kyua")
|
||||
|
||||
atf_test_program{name="manbuild_test"}
|
152
contrib/kyua/doc/Makefile.am.inc
Normal file
152
contrib/kyua/doc/Makefile.am.inc
Normal file
@ -0,0 +1,152 @@
|
||||
# Copyright 2011 The Kyua Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
BUILD_MANPAGE = \
|
||||
$(MKDIR_P) doc; \
|
||||
$(SHELL) $(srcdir)/doc/manbuild.sh \
|
||||
-v "CONFDIR=$(kyua_confdir)" \
|
||||
-v "DOCDIR=$(docdir)" \
|
||||
-v "EGDIR=$(examplesdir)" \
|
||||
-v "MISCDIR=$(miscdir)" \
|
||||
-v "PACKAGE=$(PACKAGE_TARNAME)" \
|
||||
-v "STOREDIR=$(storedir)" \
|
||||
-v "TESTSDIR=$(testsdir)" \
|
||||
-v "VERSION=$(PACKAGE_VERSION)" \
|
||||
"$(srcdir)/doc/$${name}.in" "doc/$${name}"
|
||||
|
||||
DIST_MAN_DEPS = doc/manbuild.sh \
|
||||
doc/build-root.mdoc \
|
||||
doc/results-file-flag-read.mdoc \
|
||||
doc/results-file-flag-write.mdoc \
|
||||
doc/results-files.mdoc \
|
||||
doc/results-files-report-example.mdoc \
|
||||
doc/test-filters.mdoc \
|
||||
doc/test-isolation.mdoc
|
||||
MAN_DEPS = $(DIST_MAN_DEPS) Makefile
|
||||
EXTRA_DIST += $(DIST_MAN_DEPS)
|
||||
|
||||
man_MANS = doc/kyua-about.1
|
||||
CLEANFILES += doc/kyua-about.1
|
||||
EXTRA_DIST += doc/kyua-about.1.in
|
||||
doc/kyua-about.1: $(srcdir)/doc/kyua-about.1.in $(MAN_DEPS)
|
||||
$(AM_V_GEN)name=kyua-about.1; $(BUILD_MANPAGE)
|
||||
|
||||
man_MANS += doc/kyua-config.1
|
||||
CLEANFILES += doc/kyua-config.1
|
||||
EXTRA_DIST += doc/kyua-config.1.in
|
||||
doc/kyua-config.1: $(srcdir)/doc/kyua-config.1.in $(MAN_DEPS)
|
||||
$(AM_V_GEN)name=kyua-config.1; $(BUILD_MANPAGE)
|
||||
|
||||
man_MANS += doc/kyua-db-exec.1
|
||||
CLEANFILES += doc/kyua-db-exec.1
|
||||
EXTRA_DIST += doc/kyua-db-exec.1.in
|
||||
doc/kyua-db-exec.1: $(srcdir)/doc/kyua-db-exec.1.in $(MAN_DEPS)
|
||||
$(AM_V_GEN)name=kyua-db-exec.1; $(BUILD_MANPAGE)
|
||||
|
||||
man_MANS += doc/kyua-db-migrate.1
|
||||
CLEANFILES += doc/kyua-db-migrate.1
|
||||
EXTRA_DIST += doc/kyua-db-migrate.1.in
|
||||
doc/kyua-db-migrate.1: $(srcdir)/doc/kyua-db-migrate.1.in $(MAN_DEPS)
|
||||
$(AM_V_GEN)name=kyua-db-migrate.1; $(BUILD_MANPAGE)
|
||||
|
||||
man_MANS += doc/kyua-debug.1
|
||||
CLEANFILES += doc/kyua-debug.1
|
||||
EXTRA_DIST += doc/kyua-debug.1.in
|
||||
doc/kyua-debug.1: $(srcdir)/doc/kyua-debug.1.in $(MAN_DEPS)
|
||||
$(AM_V_GEN)name=kyua-debug.1; $(BUILD_MANPAGE)
|
||||
|
||||
man_MANS += doc/kyua-help.1
|
||||
CLEANFILES += doc/kyua-help.1
|
||||
EXTRA_DIST += doc/kyua-help.1.in
|
||||
doc/kyua-help.1: $(srcdir)/doc/kyua-help.1.in $(MAN_DEPS)
|
||||
$(AM_V_GEN)name=kyua-help.1; $(BUILD_MANPAGE)
|
||||
|
||||
man_MANS += doc/kyua-list.1
|
||||
CLEANFILES += doc/kyua-list.1
|
||||
EXTRA_DIST += doc/kyua-list.1.in
|
||||
doc/kyua-list.1: $(srcdir)/doc/kyua-list.1.in $(MAN_DEPS)
|
||||
$(AM_V_GEN)name=kyua-list.1; $(BUILD_MANPAGE)
|
||||
|
||||
man_MANS += doc/kyua-report-html.1
|
||||
CLEANFILES += doc/kyua-report-html.1
|
||||
EXTRA_DIST += doc/kyua-report-html.1.in
|
||||
doc/kyua-report-html.1: $(srcdir)/doc/kyua-report-html.1.in $(MAN_DEPS)
|
||||
$(AM_V_GEN)name=kyua-report-html.1; $(BUILD_MANPAGE)
|
||||
|
||||
man_MANS += doc/kyua-report-junit.1
|
||||
CLEANFILES += doc/kyua-report-junit.1
|
||||
EXTRA_DIST += doc/kyua-report-junit.1.in
|
||||
doc/kyua-report-junit.1: $(srcdir)/doc/kyua-report-junit.1.in $(MAN_DEPS)
|
||||
$(AM_V_GEN)name=kyua-report-junit.1; $(BUILD_MANPAGE)
|
||||
|
||||
man_MANS += doc/kyua-report.1
|
||||
CLEANFILES += doc/kyua-report.1
|
||||
EXTRA_DIST += doc/kyua-report.1.in
|
||||
doc/kyua-report.1: $(srcdir)/doc/kyua-report.1.in $(MAN_DEPS)
|
||||
$(AM_V_GEN)name=kyua-report.1; $(BUILD_MANPAGE)
|
||||
|
||||
man_MANS += doc/kyua-test.1
|
||||
CLEANFILES += doc/kyua-test.1
|
||||
EXTRA_DIST += doc/kyua-test.1.in
|
||||
doc/kyua-test.1: $(srcdir)/doc/kyua-test.1.in $(MAN_DEPS)
|
||||
$(AM_V_GEN)name=kyua-test.1; $(BUILD_MANPAGE)
|
||||
|
||||
man_MANS += doc/kyua.1
|
||||
CLEANFILES += doc/kyua.1
|
||||
EXTRA_DIST += doc/kyua.1.in
|
||||
doc/kyua.1: $(srcdir)/doc/kyua.1.in $(MAN_DEPS)
|
||||
$(AM_V_GEN)name=kyua.1; $(BUILD_MANPAGE)
|
||||
|
||||
man_MANS += doc/kyua.conf.5
|
||||
CLEANFILES += doc/kyua.conf.5
|
||||
EXTRA_DIST += doc/kyua.conf.5.in
|
||||
doc/kyua.conf.5: $(srcdir)/doc/kyua.conf.5.in $(MAN_DEPS)
|
||||
$(AM_V_GEN)name=kyua.conf.5; $(BUILD_MANPAGE)
|
||||
|
||||
man_MANS += doc/kyuafile.5
|
||||
CLEANFILES += doc/kyuafile.5
|
||||
EXTRA_DIST += doc/kyuafile.5.in
|
||||
doc/kyuafile.5: $(srcdir)/doc/kyuafile.5.in $(MAN_DEPS)
|
||||
$(AM_V_GEN)name=kyuafile.5; $(BUILD_MANPAGE)
|
||||
|
||||
if WITH_ATF
|
||||
EXTRA_DIST += doc/Kyuafile
|
||||
|
||||
noinst_SCRIPTS += doc/manbuild_test
|
||||
CLEANFILES += doc/manbuild_test
|
||||
EXTRA_DIST += doc/manbuild_test.sh
|
||||
doc/manbuild_test: $(srcdir)/doc/manbuild_test.sh Makefile
|
||||
$(AM_V_GEN)$(MKDIR_P) doc; \
|
||||
echo "#! $(ATF_SH)" >doc/manbuild_test.tmp; \
|
||||
echo "# AUTOMATICALLY GENERATED FROM Makefile" \
|
||||
>>doc/manbuild_test.tmp; \
|
||||
sed -e 's,__MANBUILD__,$(abs_srcdir)/doc/manbuild.sh,g' \
|
||||
<$(srcdir)/doc/manbuild_test.sh >>doc/manbuild_test.tmp; \
|
||||
mv doc/manbuild_test.tmp doc/manbuild_test; \
|
||||
chmod +x doc/manbuild_test
|
||||
endif
|
104
contrib/kyua/doc/build-root.mdoc
Normal file
104
contrib/kyua/doc/build-root.mdoc
Normal file
@ -0,0 +1,104 @@
|
||||
.\" Copyright 2012 The Kyua Authors.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions are
|
||||
.\" met:
|
||||
.\"
|
||||
.\" * Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" * Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" * Neither the name of Google Inc. nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.Em Build directories
|
||||
(or object directories, target directories, product directories, etc.) is
|
||||
the concept that allows a developer to keep the source tree clean from
|
||||
build products by asking the build system to place such build products
|
||||
under a separate subtree.
|
||||
.Pp
|
||||
Most build systems today support build directories.
|
||||
For example, the GNU Automake/Autoconf build system exposes such concept when
|
||||
invoked as follows:
|
||||
.Bd -literal -offset indent
|
||||
$ cd my-project-1.0
|
||||
$ mkdir build
|
||||
$ cd build
|
||||
$ ../configure
|
||||
$ make
|
||||
.Ed
|
||||
.Pp
|
||||
Under such invocation, all the results of the build are left in the
|
||||
.Pa my-project-1.0/build/
|
||||
subdirectory while maintaining the contents of
|
||||
.Pa my-project-1.0/
|
||||
intact.
|
||||
.Pp
|
||||
Because build directories are an integral part of most build systems, and
|
||||
because they are a tool that developers use frequently,
|
||||
.Nm
|
||||
supports build directories too.
|
||||
This manifests in the form of
|
||||
.Nm
|
||||
being able to run tests from build directories while reading the (often
|
||||
immutable) test suite definition from the source tree.
|
||||
.Pp
|
||||
One important property of build directories is that they follow (or need to
|
||||
follow) the exact same layout as the source tree.
|
||||
For example, consider the following directory listings:
|
||||
.Bd -literal -offset indent
|
||||
src/Kyuafile
|
||||
src/bin/ls/
|
||||
src/bin/ls/Kyuafile
|
||||
src/bin/ls/ls.c
|
||||
src/bin/ls/ls_test.c
|
||||
src/sbin/su/
|
||||
src/sbin/su/Kyuafile
|
||||
src/sbin/su/su.c
|
||||
src/sbin/su/su_test.c
|
||||
|
||||
obj/bin/ls/
|
||||
obj/bin/ls/ls*
|
||||
obj/bin/ls/ls_test*
|
||||
obj/sbin/su/
|
||||
obj/sbin/su/su*
|
||||
obj/sbin/su/su_test*
|
||||
.Ed
|
||||
.Pp
|
||||
Note how the directory layout within
|
||||
.Pa src/
|
||||
matches that of
|
||||
.Pa obj/ .
|
||||
The
|
||||
.Pa src/
|
||||
directory contains only source files and the definition of the test suite
|
||||
(the Kyuafiles), while the
|
||||
.Pa obj/
|
||||
directory contains only the binaries generated during a build.
|
||||
.Pp
|
||||
All commands that deal with the workspace support the
|
||||
.Fl -build-root Ar path
|
||||
option.
|
||||
When this option is provided, the directory specified by the
|
||||
option is considered to be the root of the build directory.
|
||||
For example, considering our previous fake tree layout, we could invoke
|
||||
.Nm
|
||||
as any of the following:
|
||||
.Bd -literal -offset indent
|
||||
$ kyua __COMMAND__ --kyuafile=src/Kyuafile --build-root=obj
|
||||
$ cd src && kyua __COMMAND__ --build-root=../obj
|
||||
.Ed
|
95
contrib/kyua/doc/kyua-about.1.in
Normal file
95
contrib/kyua/doc/kyua-about.1.in
Normal file
@ -0,0 +1,95 @@
|
||||
.\" Copyright 2012 The Kyua Authors.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions are
|
||||
.\" met:
|
||||
.\"
|
||||
.\" * Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" * Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" * Neither the name of Google Inc. nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.Dd May 20, 2015
|
||||
.Dt KYUA-ABOUT 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm "kyua about"
|
||||
.Nd Shows detailed authors, license, and version information
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Ar authors | license | version
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Sq about
|
||||
command provides generic information about the
|
||||
.Xr kyua 1
|
||||
tool.
|
||||
In the default synopsis form (no arguments), the information printed
|
||||
includes:
|
||||
.Bl -enum
|
||||
.It
|
||||
The name of the package, which is
|
||||
.Sq __PACKAGE__ .
|
||||
.It
|
||||
The version number, which is
|
||||
.Sq __VERSION__ .
|
||||
.It
|
||||
License information.
|
||||
.It
|
||||
Authors information.
|
||||
.It
|
||||
A link to the project web site.
|
||||
.El
|
||||
.Pp
|
||||
You can customize the information printed by this command by specifying
|
||||
the desired topic as the single argument to the command.
|
||||
This can be one of:
|
||||
.Bl -tag -width authorsXX
|
||||
.It Ar authors
|
||||
Displays the list of authors and contributors only.
|
||||
.It Ar license
|
||||
Displays the license information and the list of copyrights.
|
||||
.It Ar version
|
||||
Displays the package name and the version number in a format that is
|
||||
compatible with the output of GNU tools that support a
|
||||
.Fl -version
|
||||
flag.
|
||||
Use this whenever you have to query the version number of the package.
|
||||
.El
|
||||
.Sh FILES
|
||||
The following files are read by the
|
||||
.Nm
|
||||
command:
|
||||
.Bl -tag -width XX
|
||||
.It Pa __DOCDIR__/AUTHORS
|
||||
List of authors (aka copyright holders).
|
||||
.It Pa __DOCDIR__/CONTRIBUTORS
|
||||
List of contributors (aka individuals that have contributed to the project).
|
||||
.It Pa __DOCDIR__/LICENSE
|
||||
License information.
|
||||
.El
|
||||
.Sh EXIT STATUS
|
||||
The
|
||||
.Nm
|
||||
command always returns 0.
|
||||
.Pp
|
||||
Additional exit codes may be returned as described in
|
||||
.Xr kyua 1 .
|
||||
.Sh SEE ALSO
|
||||
.Xr kyua 1
|
59
contrib/kyua/doc/kyua-config.1.in
Normal file
59
contrib/kyua/doc/kyua-config.1.in
Normal file
@ -0,0 +1,59 @@
|
||||
.\" Copyright 2012 The Kyua Authors.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions are
|
||||
.\" met:
|
||||
.\"
|
||||
.\" * Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" * Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" * Neither the name of Google Inc. nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.Dd September 9, 2012
|
||||
.Dt KYUA-CONFIG 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm "kyua config"
|
||||
.Nd Inspects the values of the loaded configuration
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Ar variable1 .. variableN
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
command provides a way to list all defined configuration variables and
|
||||
their current values.
|
||||
.Pp
|
||||
This command is intended to help you in resolving the values of the
|
||||
configuration variables without having to scan over configuration files.
|
||||
.Pp
|
||||
In the default synopsis form (no arguments), the command prints all
|
||||
configuration variables.
|
||||
If any arguments are provided, the command will only print the
|
||||
requested variables.
|
||||
.Sh EXIT STATUS
|
||||
The
|
||||
.Nm
|
||||
command returns 0 on success or 1 if any of the specified configuration
|
||||
variables does not exist.
|
||||
.Pp
|
||||
Additional exit codes may be returned as described in
|
||||
.Xr kyua 1 .
|
||||
.Sh SEE ALSO
|
||||
.Xr kyua 1
|
80
contrib/kyua/doc/kyua-db-exec.1.in
Normal file
80
contrib/kyua/doc/kyua-db-exec.1.in
Normal file
@ -0,0 +1,80 @@
|
||||
.\" Copyright 2012 The Kyua Authors.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions are
|
||||
.\" met:
|
||||
.\"
|
||||
.\" * Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" * Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" * Neither the name of Google Inc. nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.Dd October 13, 2014
|
||||
.Dt KYUA-DB-EXEC 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm "kyua db-exec"
|
||||
.Nd Executes a SQL statement in a results file
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl -no-headers
|
||||
.Op Fl -results-file Ar file
|
||||
.Ar statement
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
command provides a way to execute an arbitrary SQL statement within the
|
||||
database.
|
||||
This command is mostly intended to aid in debugging, but can also be used to
|
||||
extract information from the database when the current interfaces do not
|
||||
provide the desired functionality.
|
||||
.Pp
|
||||
The input database must exist.
|
||||
It makes no sense to use
|
||||
.Nm
|
||||
on a nonexistent or empty database.
|
||||
.Pp
|
||||
The
|
||||
.Nm
|
||||
command takes one or more arguments, all of which are concatenated to form
|
||||
a single SQL statement.
|
||||
Once the statement is executed,
|
||||
.Nm
|
||||
prints the resulting table on the screen, if any.
|
||||
.Pp
|
||||
The following subcommand options are recognized:
|
||||
.Bl -tag -width XX
|
||||
.It Fl -no-headers
|
||||
Avoids printing the headers of the table in the output of the command.
|
||||
.It Fl -results-file Ar path , Fl s Ar path
|
||||
__include__ results-file-flag-read.mdoc
|
||||
.El
|
||||
.Ss Results files
|
||||
__include__ results-files.mdoc
|
||||
.Sh EXIT STATUS
|
||||
The
|
||||
.Nm
|
||||
command returns 0 on success or 1 if the SQL statement is invalid or fails
|
||||
to run.
|
||||
.Pp
|
||||
Additional exit codes may be returned as described in
|
||||
.Xr kyua 1 .
|
||||
.Sh SEE ALSO
|
||||
.Xr kyua 1 ,
|
||||
.Xr kyua-test 1
|
63
contrib/kyua/doc/kyua-db-migrate.1.in
Normal file
63
contrib/kyua/doc/kyua-db-migrate.1.in
Normal file
@ -0,0 +1,63 @@
|
||||
.\" Copyright 2013 The Kyua Authors.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions are
|
||||
.\" met:
|
||||
.\"
|
||||
.\" * Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" * Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" * Neither the name of Google Inc. nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.Dd October 13, 2014
|
||||
.Dt KYUA-DB-MIGRATE 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm "kyua db-migrate"
|
||||
.Nd Upgrades the schema of an existing results file
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl -results-file Ar file
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
command migrates the schema of an existing database to the latest
|
||||
version implemented in
|
||||
.Xr kyua 1 .
|
||||
.Pp
|
||||
This operation is not reversible.
|
||||
However, a backup of the database is created in the same directory where the
|
||||
database lives.
|
||||
.Pp
|
||||
The following subcommand options are recognized:
|
||||
.Bl -tag -width XX
|
||||
.It Fl -results-file Ar path , Fl s Ar path
|
||||
__include__ results-file-flag-read.mdoc
|
||||
.El
|
||||
.Ss Results files
|
||||
__include__ results-files.mdoc
|
||||
.Sh EXIT STATUS
|
||||
The
|
||||
.Nm
|
||||
command returns 0 on success or 1 if the migration fails.
|
||||
.Pp
|
||||
Additional exit codes may be returned as described in
|
||||
.Xr kyua 1 .
|
||||
.Sh SEE ALSO
|
||||
.Xr kyua 1
|
145
contrib/kyua/doc/kyua-debug.1.in
Normal file
145
contrib/kyua/doc/kyua-debug.1.in
Normal file
@ -0,0 +1,145 @@
|
||||
.\" Copyright 2012 The Kyua Authors.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions are
|
||||
.\" met:
|
||||
.\"
|
||||
.\" * Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" * Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" * Neither the name of Google Inc. nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.Dd October 13, 2014
|
||||
.Dt KYUA-DEBUG 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm "kyua debug"
|
||||
.Nd Executes a single test case with facilities for debugging
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl -build-root Ar path
|
||||
.Op Fl -kyuafile Ar file
|
||||
.Op Fl -stdout Ar path
|
||||
.Op Fl -stderr Ar path
|
||||
.Ar test_case
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
command provides a mechanism to execute a single test case bypassing some
|
||||
of the Kyua infrastructure and allowing the user to poke into the execution
|
||||
behavior of the test.
|
||||
.Pp
|
||||
The test case to run is selected by providing a test filter, described below in
|
||||
.Sx Test filters ,
|
||||
that matches a single test case.
|
||||
The test case is executed and its result is printed as the last line of the
|
||||
output of the tool.
|
||||
.Pp
|
||||
The test executed by
|
||||
.Nm
|
||||
is run under a controlled environment as described in
|
||||
.Sx Test isolation .
|
||||
.Pp
|
||||
At the moment, the
|
||||
.Nm
|
||||
command allows the following aspects of a test case execution to be
|
||||
tweaked:
|
||||
.Bl -bullet
|
||||
.It
|
||||
Redirection of the test case's stdout and stderr to the console (the
|
||||
default) or to arbitrary files.
|
||||
See the
|
||||
.Fl -stdout
|
||||
and
|
||||
.Fl -stderr
|
||||
options below.
|
||||
.El
|
||||
.Pp
|
||||
The following subcommand options are recognized:
|
||||
.Bl -tag -width XX
|
||||
.It Fl -build-root Ar path
|
||||
Specifies the build root in which to find the test programs referenced
|
||||
by the Kyuafile, if different from the Kyuafile's directory.
|
||||
See
|
||||
.Sx Build directories
|
||||
below for more information.
|
||||
.It Fl -kyuafile Ar file , Fl k Ar file
|
||||
Specifies the Kyuafile to process.
|
||||
Defaults to
|
||||
.Pa Kyuafile
|
||||
file in the current directory.
|
||||
.It Fl -stderr Ar path
|
||||
Specifies the file to which to send the standard error of the test
|
||||
program's body.
|
||||
The default is
|
||||
.Pa /dev/stderr ,
|
||||
which is a special character device that redirects the output to
|
||||
standard error on the console.
|
||||
.It Fl -stdout Ar path
|
||||
Specifies the file to which to send the standard output of the test
|
||||
program's body.
|
||||
The default is
|
||||
.Pa /dev/stdout ,
|
||||
which is a special character device that redirects the output to
|
||||
standard output on the console.
|
||||
.El
|
||||
.Pp
|
||||
For example, consider the following Kyua session:
|
||||
.Bd -literal -offset indent
|
||||
$ kyua test
|
||||
kernel/fs:mkdir -> passed
|
||||
kernel/fs:rmdir -> failed: Invalid argument
|
||||
|
||||
1/2 passed (1 failed)
|
||||
.Ed
|
||||
.Pp
|
||||
At this point, we do not have a lot of information regarding the
|
||||
failure of the
|
||||
.Sq kernel/fs:rmdir
|
||||
test.
|
||||
We can run this test through the
|
||||
.Nm
|
||||
command to inspect its output a bit closer, hoping that the test case is
|
||||
kind enough to log its progress:
|
||||
.Bd -literal -offset indent
|
||||
$ kyua debug kernel/fs:rmdir
|
||||
Trying rmdir('foo')
|
||||
Trying rmdir(NULL)
|
||||
kernel/fs:rmdir -> failed: Invalid argument
|
||||
.Ed
|
||||
.Pp
|
||||
Luckily, the offending test case was printing status lines as it
|
||||
progressed, so we could see the last attempted call and we can know match
|
||||
the failure message to the problem.
|
||||
.Ss Build directories
|
||||
__include__ build-root.mdoc COMMAND=debug
|
||||
.Ss Test filters
|
||||
__include__ test-filters.mdoc
|
||||
.Ss Test isolation
|
||||
__include__ test-isolation.mdoc
|
||||
.Sh EXIT STATUS
|
||||
The
|
||||
.Nm
|
||||
command returns 0 if the test case passes or 1 if the test case fails.
|
||||
.Pp
|
||||
Additional exit codes may be returned as described in
|
||||
.Xr kyua 1 .
|
||||
.Sh SEE ALSO
|
||||
.Xr kyua 1 ,
|
||||
.Xr kyuafile 5
|
64
contrib/kyua/doc/kyua-help.1.in
Normal file
64
contrib/kyua/doc/kyua-help.1.in
Normal file
@ -0,0 +1,64 @@
|
||||
.\" Copyright 2012 The Kyua Authors.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions are
|
||||
.\" met:
|
||||
.\"
|
||||
.\" * Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" * Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" * Neither the name of Google Inc. nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.Dd September 9, 2012
|
||||
.Dt KYUA-HELP 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm "kyua help"
|
||||
.Nd Shows usage information
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Ar command
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
command provides interactive help on all supported commands and options.
|
||||
If, for some reason, you happen to spot a discrepancy in the output of this
|
||||
command and this document, the command is the authoritative source of
|
||||
information.
|
||||
.Pp
|
||||
If no arguments are provided, the command prints the list of common options
|
||||
and the list of supported subcommands.
|
||||
.Pp
|
||||
If the
|
||||
.Ar command
|
||||
argument is provided to, this single argument is the name of a valid
|
||||
subcommand.
|
||||
In that case,
|
||||
.Nm
|
||||
prints a textual description of the command, the list of common options and
|
||||
the list of subcommand-specific options.
|
||||
.Sh EXIT STATUS
|
||||
The
|
||||
.Nm
|
||||
command always returns 0.
|
||||
.Pp
|
||||
Additional exit codes may be returned as described in
|
||||
.Xr kyua 1 .
|
||||
.Sh SEE ALSO
|
||||
.Xr kyua 1
|
90
contrib/kyua/doc/kyua-list.1.in
Normal file
90
contrib/kyua/doc/kyua-list.1.in
Normal file
@ -0,0 +1,90 @@
|
||||
.\" Copyright 2012 The Kyua Authors.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions are
|
||||
.\" met:
|
||||
.\"
|
||||
.\" * Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" * Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" * Neither the name of Google Inc. nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.Dd October 13, 2014
|
||||
.Dt KYUA-LIST 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm "kyua list"
|
||||
.Nd Lists test cases and their metadata
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl -build-root Ar path
|
||||
.Op Fl -kyuafile Ar file
|
||||
.Op Fl -verbose
|
||||
.Ar test_case1 Op Ar .. test_caseN
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
command scans all the test programs and test cases in a test suite (as
|
||||
defined by a
|
||||
.Xr kyuafile 5 )
|
||||
and prints a list of all their names, optionally accompanied by any metadata
|
||||
properties they have.
|
||||
.Pp
|
||||
The optional arguments to
|
||||
.Nm
|
||||
are used to select which test programs or test cases to run.
|
||||
These are filters and are described below in
|
||||
.Sx Test filters .
|
||||
.Pp
|
||||
This command must be run within a test suite or a test suite must be
|
||||
provided with the
|
||||
.Fl -kyuafile
|
||||
flag.
|
||||
.Pp
|
||||
The following subcommand options are recognized:
|
||||
.Bl -tag -width XX
|
||||
.It Fl -build-root Ar path
|
||||
Specifies the build root in which to find the test programs referenced
|
||||
by the Kyuafile, if different from the Kyuafile's directory.
|
||||
See
|
||||
.Sx Build directories
|
||||
below for more information.
|
||||
.It Fl -kyuafile Ar path , Fl k Ar path
|
||||
Specifies the Kyuafile to process.
|
||||
Defaults to a
|
||||
.Pa Kyuafile
|
||||
file in the current directory.
|
||||
.It Fl -verbose , Fl v
|
||||
Prints metadata properties for every test case.
|
||||
.El
|
||||
.Ss Build directories
|
||||
__include__ build-root.mdoc COMMAND=list
|
||||
.Ss Test filters
|
||||
__include__ test-filters.mdoc
|
||||
.Sh EXIT STATUS
|
||||
The
|
||||
.Nm
|
||||
command returns 0 on success or 1 if any of the given test case filters
|
||||
does not match any test case.
|
||||
.Pp
|
||||
Additional exit codes may be returned as described in
|
||||
.Xr kyua 1 .
|
||||
.Sh SEE ALSO
|
||||
.Xr kyua 1 ,
|
||||
.Xr kyuafile 5
|
103
contrib/kyua/doc/kyua-report-html.1.in
Normal file
103
contrib/kyua/doc/kyua-report-html.1.in
Normal file
@ -0,0 +1,103 @@
|
||||
.\" Copyright 2012 The Kyua Authors.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions are
|
||||
.\" met:
|
||||
.\"
|
||||
.\" * Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" * Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" * Neither the name of Google Inc. nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.Dd October 13, 2014
|
||||
.Dt KYUA-REPORT-HTML 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm "kyua report-html"
|
||||
.Nd Generates an HTML report with the results of a test suite run
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl -force
|
||||
.Op Fl -output Ar path
|
||||
.Op Fl -results-file Ar file
|
||||
.Op Fl -results-filter Ar types
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
command provides a simple mechanism to generate HTML reports of the
|
||||
execution of a test suite.
|
||||
The command processes a results file and then populates a directory with
|
||||
multiple HTML and supporting files to describe the results recorded in that
|
||||
results file.
|
||||
.Pp
|
||||
The HTML output is static and self-contained, so it can easily be served by
|
||||
any simple web server.
|
||||
The command expects the target directory to not exist, because it would
|
||||
overwrite any contents if not careful.
|
||||
.Pp
|
||||
The following subcommand options are recognized:
|
||||
.Bl -tag -width XX
|
||||
.It Fl -force
|
||||
Forces the deletion of the output directory if it exists.
|
||||
Use care, as this effectively means a
|
||||
.Sq rm -rf .
|
||||
.It Fl -output Ar directory
|
||||
Specifies the target directory into which to generate the HTML files.
|
||||
The directory must not exist unless the
|
||||
.Fl -force
|
||||
option is provided.
|
||||
The default is
|
||||
.Pa ./html .
|
||||
.It Fl -results-file Ar path , Fl s Ar path
|
||||
__include__ results-file-flag-read.mdoc
|
||||
.It Fl -results-filter Ar types
|
||||
Comma-separated list of the test result types to include in the report.
|
||||
The ordering of the values is respected so that you can determine how you
|
||||
want the list of tests to be shown.
|
||||
.Pp
|
||||
The valid values are:
|
||||
.Sq broken ,
|
||||
.Sq failed ,
|
||||
.Sq passed ,
|
||||
.Sq skipped
|
||||
and
|
||||
.Sq xfail .
|
||||
If the parameter supplied to the option is empty, filtering is suppressed
|
||||
and all result types are shown in the report.
|
||||
.Pp
|
||||
The default value for this flag includes all the test results except the
|
||||
passed tests.
|
||||
Showing the passed tests by default clutters the report with too much
|
||||
information, so only abnormal conditions are included.
|
||||
.El
|
||||
.Ss Results files
|
||||
__include__ results-files.mdoc
|
||||
.Sh EXIT STATUS
|
||||
The
|
||||
.Nm
|
||||
command always returns 0.
|
||||
.Pp
|
||||
Additional exit codes may be returned as described in
|
||||
.Xr kyua 1 .
|
||||
.Sh EXAMPLES
|
||||
__include__ results-files-report-example.mdoc REPORT_COMMAND=report-html
|
||||
.Sh SEE ALSO
|
||||
.Xr kyua 1 ,
|
||||
.Xr kyua-report 1 ,
|
||||
.Xr kyua-report-junit 1
|
87
contrib/kyua/doc/kyua-report-junit.1.in
Normal file
87
contrib/kyua/doc/kyua-report-junit.1.in
Normal file
@ -0,0 +1,87 @@
|
||||
.\" Copyright 2014 The Kyua Authors.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions are
|
||||
.\" met:
|
||||
.\"
|
||||
.\" * Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" * Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" * Neither the name of Google Inc. nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.Dd October 13, 2014
|
||||
.Dt KYUA-REPORT-JUNIT 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm "kyua report-junit"
|
||||
.Nd Generates a JUnit report with the results of a test suite run
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl -output Ar path
|
||||
.Op Fl -results-file Ar file
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
command provides a simple mechanism to generate JUnit reports of the
|
||||
execution of a test suite.
|
||||
The command processes a results file and then generates a single XML file
|
||||
that complies with the JUnit XSchema.
|
||||
.Pp
|
||||
The JUnit output is static and self-contained, so it can easily be plugged
|
||||
into any continuous integration system, like Jenkins.
|
||||
.Pp
|
||||
The following subcommand options are recognized:
|
||||
.Bl -tag -width XX
|
||||
.It Fl -output Ar directory
|
||||
Specifies the file into which to store the JUnit report.
|
||||
.It Fl -results-file Ar path , Fl s Ar path
|
||||
__include__ results-file-flag-read.mdoc
|
||||
.El
|
||||
.Ss Caveats
|
||||
Because of limitations in the JUnit XML schema, not all the data collected by
|
||||
Kyua can be properly represented in JUnit reports.
|
||||
However, because test data are extremely useful for debugging purposes, the
|
||||
.Nm
|
||||
command shovels these data into the JUnit output.
|
||||
In particular:
|
||||
.Bl -bullet
|
||||
.It
|
||||
The test case metadata values are prepended to the test case's standard error
|
||||
output.
|
||||
.It
|
||||
Test cases that report expected failures as their results are recorded as
|
||||
passed.
|
||||
The fact that they failed as expected is recorded in the test case's standard
|
||||
error output along with the corresponding reason.
|
||||
.El
|
||||
.Ss Results files
|
||||
__include__ results-files.mdoc
|
||||
.Sh EXIT STATUS
|
||||
The
|
||||
.Nm
|
||||
command always returns 0.
|
||||
.Pp
|
||||
Additional exit codes may be returned as described in
|
||||
.Xr kyua 1 .
|
||||
.Sh EXAMPLES
|
||||
__include__ results-files-report-example.mdoc REPORT_COMMAND=report-junit
|
||||
.Sh SEE ALSO
|
||||
.Xr kyua 1 ,
|
||||
.Xr kyua-report 1 ,
|
||||
.Xr kyua-report-html 1
|
118
contrib/kyua/doc/kyua-report.1.in
Normal file
118
contrib/kyua/doc/kyua-report.1.in
Normal file
@ -0,0 +1,118 @@
|
||||
.\" Copyright 2012 The Kyua Authors.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions are
|
||||
.\" met:
|
||||
.\"
|
||||
.\" * Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" * Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" * Neither the name of Google Inc. nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.Dd October 13, 2014
|
||||
.Dt KYUA-REPORT 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm "kyua report"
|
||||
.Nd Generates reports with the results of a test suite run
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl -output Ar path
|
||||
.Op Fl -results-file Ar file
|
||||
.Op Fl -results-filter Ar types
|
||||
.Op Fl -verbose
|
||||
.Op Ar test_filter1 .. test_filterN
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
command parses a results file and generates a user-friendly, plaintext
|
||||
report for user consumption on the terminal.
|
||||
By default, these reports only display a summary of the execution of the full
|
||||
test suite to highlight where problems may lie.
|
||||
.Pp
|
||||
The output of
|
||||
.Nm
|
||||
can be customized to display full details on all executed test cases.
|
||||
Additionally, the optional arguments to
|
||||
.Nm
|
||||
are used to select which test programs or test cases to display.
|
||||
These are filters and are described below in
|
||||
.Sx Test filters .
|
||||
.Pp
|
||||
Reports generated by
|
||||
.Nm
|
||||
are
|
||||
.Em not intended to be machine-parseable .
|
||||
.Pp
|
||||
The following subcommand options are recognized:
|
||||
.Bl -tag -width XX
|
||||
.It Fl -output Ar path
|
||||
Specifies the path to which the report should be written to.
|
||||
The special values
|
||||
.Pa /dev/stdout
|
||||
and
|
||||
.Pa /dev/stderr
|
||||
can be used to specify the standard output and the standard error,
|
||||
respectively.
|
||||
.It Fl -results-file Ar path , Fl s Ar path
|
||||
__include__ results-file-flag-read.mdoc
|
||||
.It Fl -results-filter Ar types
|
||||
Comma-separated list of the test result types to include in the report.
|
||||
The ordering of the values is respected so that you can determine how you
|
||||
want the list of tests to be shown.
|
||||
.Pp
|
||||
The valid values are:
|
||||
.Sq broken ,
|
||||
.Sq failed ,
|
||||
.Sq passed ,
|
||||
.Sq skipped
|
||||
and
|
||||
.Sq xfail .
|
||||
If the parameter supplied to the option is empty, filtering is suppressed
|
||||
and all result types are shown in the report.
|
||||
.Pp
|
||||
The default value for this flag includes all the test results except the
|
||||
passed tests.
|
||||
Showing the passed tests by default clutters the report with too much
|
||||
information, so only abnormal conditions are included.
|
||||
.It Fl -verbose
|
||||
Prints a detailed report of the execution.
|
||||
In addition to all the information printed by default, verbose reports
|
||||
include the runtime context of the test suite run, the metadata of each
|
||||
test case, and the verbatim output of the test cases.
|
||||
.El
|
||||
.Ss Results files
|
||||
__include__ results-files.mdoc
|
||||
.Ss Test filters
|
||||
__include__ test-filters.mdoc
|
||||
.Sh EXIT STATUS
|
||||
The
|
||||
.Nm
|
||||
command returns 0 if no filters were specified or if all filters match one
|
||||
or more test cases.
|
||||
If any filter fails to match any test case, the command returns 1.
|
||||
.Pp
|
||||
Additional exit codes may be returned as described in
|
||||
.Xr kyua 1 .
|
||||
.Sh EXAMPLES
|
||||
__include__ results-files-report-example.mdoc REPORT_COMMAND=report
|
||||
.Sh SEE ALSO
|
||||
.Xr kyua 1 ,
|
||||
.Xr kyua-report-html 1 ,
|
||||
.Xr kyua-report-junit 1
|
102
contrib/kyua/doc/kyua-test.1.in
Normal file
102
contrib/kyua/doc/kyua-test.1.in
Normal file
@ -0,0 +1,102 @@
|
||||
.\" Copyright 2012 The Kyua Authors.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions are
|
||||
.\" met:
|
||||
.\"
|
||||
.\" * Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" * Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" * Neither the name of Google Inc. nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.Dd October 13, 2014
|
||||
.Dt KYUA-TEST 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm "kyua test"
|
||||
.Nd Runs tests
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl -build-root Ar path
|
||||
.Op Fl -kyuafile Ar file
|
||||
.Op Fl -results-file Ar file
|
||||
.Op Ar test_filter1 .. test_filterN
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
command loads a test suite definition from a
|
||||
.Xr kyuafile 5 ,
|
||||
runs the tests defined in it, and records the results into a new results
|
||||
file.
|
||||
By default, all tests in the test suite are executed but the optional
|
||||
arguments to
|
||||
.Nm
|
||||
can be used to select which test programs or test cases to run.
|
||||
These are filters and are described below in
|
||||
.Sx Test filters .
|
||||
.Pp
|
||||
Every test executed by
|
||||
.Nm
|
||||
is run under a controlled environment as described in
|
||||
.Sx Test isolation .
|
||||
.Pp
|
||||
The following subcommand options are recognized:
|
||||
.Bl -tag -width XX
|
||||
.It Fl -build-root Ar path
|
||||
Specifies the build root in which to find the test programs referenced by
|
||||
the Kyuafile, if different from the Kyuafile's directory.
|
||||
See
|
||||
.Sx Build directories
|
||||
below for more information.
|
||||
.It Fl -kyuafile Ar path , Fl k Ar path
|
||||
Specifies the Kyuafile to process.
|
||||
Defaults to a
|
||||
.Pa Kyuafile
|
||||
file in the current directory.
|
||||
.It Fl -results-file Ar path , Fl s Ar path
|
||||
__include__ results-file-flag-write.mdoc
|
||||
.El
|
||||
.Pp
|
||||
You can later inspect the results of the test run in more detail by using
|
||||
.Xr kyua-report 1
|
||||
or you can execute a single test case with debugging functionality by using
|
||||
.Xr kyua-debug 1 .
|
||||
.Ss Build directories
|
||||
__include__ build-root.mdoc COMMAND=test
|
||||
.Ss Results files
|
||||
__include__ results-files.mdoc
|
||||
.Ss Test filters
|
||||
__include__ test-filters.mdoc
|
||||
.Ss Test isolation
|
||||
__include__ test-isolation.mdoc
|
||||
.Sh EXIT STATUS
|
||||
The
|
||||
.Nm
|
||||
command returns 0 if all executed test cases pass or 1 if any of the
|
||||
executed test cases fails or if any of the given test case filters does not
|
||||
match any test case.
|
||||
.Pp
|
||||
Additional exit codes may be returned as described in
|
||||
.Xr kyua 1 .
|
||||
.Sh EXAMPLES
|
||||
__include__ results-files-report-example.mdoc REPORT_COMMAND=report
|
||||
.Sh SEE ALSO
|
||||
.Xr kyua 1 ,
|
||||
.Xr kyua-report 1 ,
|
||||
.Xr kyuafile 5
|
400
contrib/kyua/doc/kyua.1.in
Normal file
400
contrib/kyua/doc/kyua.1.in
Normal file
@ -0,0 +1,400 @@
|
||||
.\" Copyright 2011 The Kyua Authors.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions are
|
||||
.\" met:
|
||||
.\"
|
||||
.\" * Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" * Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" * Neither the name of Google Inc. nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.Dd May 12, 2015
|
||||
.Dt KYUA 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm kyua
|
||||
.Nd Testing framework for infrastructure software
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl -config Ar file
|
||||
.Op Fl -logfile Ar file
|
||||
.Op Fl -loglevel Ar level
|
||||
.Op Fl -variable Ar name=value
|
||||
.Ar command
|
||||
.Op Ar command_options
|
||||
.Op Ar command_arguments
|
||||
.Sh DESCRIPTION
|
||||
.Em If you are here looking for details on how to run the test suite in
|
||||
.Pa /usr/tests
|
||||
.Em ( or
|
||||
.Pa __TESTSDIR__ ) ,
|
||||
.Em please start by reading the
|
||||
.Xr tests 7
|
||||
.Em manual page that should be supplied by your system .
|
||||
.Pp
|
||||
Kyua is a testing framework for infrastructure software, originally
|
||||
designed to equip BSD-based operating systems with a test suite.
|
||||
This means that Kyua is lightweight and simple, and that Kyua integrates well
|
||||
with various build systems and continuous integration frameworks.
|
||||
.Pp
|
||||
Kyua features an expressive test suite definition language, a safe
|
||||
runtime engine for test suites and a powerful report generation engine.
|
||||
.Pp
|
||||
Kyua is for both developers and users, from the developer applying a
|
||||
simple fix to a library to the system administrator deploying a new
|
||||
release on a production machine.
|
||||
.Pp
|
||||
Kyua is able to execute test programs written with a plethora of testing
|
||||
libraries and languages.
|
||||
The test program library of choice is ATF, which
|
||||
.Nm Ns 's
|
||||
design originated from.
|
||||
However, framework-less test programs and TAP-compliant test programs can also
|
||||
be executed through
|
||||
.Nm
|
||||
.Ss Overview
|
||||
As can be observed in the synopsis, the interface of
|
||||
.Nm
|
||||
implements a common subcommand-based interface.
|
||||
The arguments to the tool specify, in this order: a set of common options
|
||||
that all the commands accept, a required
|
||||
.Ar command
|
||||
name that specifies what
|
||||
.Nm
|
||||
should do, and
|
||||
a set of possibly-optional
|
||||
.Ar command_options
|
||||
and
|
||||
.Ar command_arguments
|
||||
that are specific to the chosen command.
|
||||
.Pp
|
||||
The following options are recognized by all the commands.
|
||||
Keep in mind that these must always be specified before the command name.
|
||||
.Bl -tag -width XX
|
||||
.It Fl -config Ar path , Fl c Ar path
|
||||
Specifies the configuration file to process, which must be in the format
|
||||
described in
|
||||
.Xr kyua.conf 5 .
|
||||
The special value
|
||||
.Sq none
|
||||
explicitly disables the loading of any configuration file.
|
||||
.Pp
|
||||
Defaults to
|
||||
.Pa ~/.kyua/kyua.conf
|
||||
if it exists, otherwise to
|
||||
.Pa __CONFDIR__/kyua.conf
|
||||
if it exists,
|
||||
or else to
|
||||
.Sq none .
|
||||
.It Fl -logfile Ar path
|
||||
Specifies the location of the file to which
|
||||
.Nm
|
||||
will log run time events useful for postmortem debugging.
|
||||
.Pp
|
||||
The default depends on different environment variables as described in
|
||||
.Sx Logging ,
|
||||
but typically the file will be stored within the user's home directory.
|
||||
.It Fl -loglevel Ar level
|
||||
Specifies the maximum logging level to record in the log file.
|
||||
See
|
||||
.Sx Logging
|
||||
for more details.
|
||||
.Pp
|
||||
The default is
|
||||
.Sq info .
|
||||
.It Fl -variable Ar name=value , Fl v Ar name=value
|
||||
Sets the
|
||||
.Ar name
|
||||
configuration variable to
|
||||
.Ar value .
|
||||
The values set through this option have preference over the values set in the
|
||||
configuration file.
|
||||
.Pp
|
||||
The specified variable can either be a builtin variable or a test-suite
|
||||
specific variable.
|
||||
See
|
||||
.Xr kyua.conf 5
|
||||
for more details.
|
||||
.El
|
||||
.Pp
|
||||
The following commands are generic and do not have any relation to the execution
|
||||
of tests or the inspection of their results:
|
||||
.Bl -tag -width reportXjunitXX -offset indent
|
||||
.It Ar about
|
||||
Shows general program information.
|
||||
See
|
||||
.Xr kyua-about 1 .
|
||||
.It Ar config
|
||||
Inspects the values of the configuration variables.
|
||||
See
|
||||
.Xr kyua-config 1 .
|
||||
.It Ar db-exec
|
||||
Executes an arbitrary SQL statement on a results file and prints the
|
||||
resulting table.
|
||||
See
|
||||
.Xr kyua-db-exec 1 .
|
||||
.It Ar help
|
||||
Shows usage information.
|
||||
See
|
||||
.Xr kyua-help 1 .
|
||||
.El
|
||||
.Pp
|
||||
The following commands are used to generate reports based on the data previously
|
||||
recorded in a results file:
|
||||
.Bl -tag -width reportXjunitXX -offset indent
|
||||
.It Ar report
|
||||
Generates a plaintext report.
|
||||
Combined with its
|
||||
.Fl -verbose
|
||||
flag and the ability to only display specific test cases, this command can also
|
||||
be used to debug test failures post-facto on the console.
|
||||
See
|
||||
.Xr kyua-report 1 .
|
||||
.It Ar report-html
|
||||
Generates an HTML report.
|
||||
See
|
||||
.Xr kyua-report-html 1 .
|
||||
.It Ar report-junit
|
||||
Generates a JUnit report.
|
||||
See
|
||||
.Xr kyua-report-junit 1 .
|
||||
.El
|
||||
.Pp
|
||||
The following commands are used to interact with a test suite:
|
||||
.Bl -tag -width reportXjunitXX -offset indent
|
||||
.It Ar debug
|
||||
Executes a single test case in a controlled environment for debugging purposes.
|
||||
See
|
||||
.Xr kyua-debug 1 .
|
||||
.It Ar list
|
||||
Lists test cases defined in a test suite by a
|
||||
.Xr kyuafile 5
|
||||
and, optionally, displays their metadata.
|
||||
See
|
||||
.Xr kyua-list 1 .
|
||||
.It Ar test
|
||||
Runs tests defined in a test suite by a
|
||||
.Xr kyuafile 5 .
|
||||
See
|
||||
.Xr kyua-test 1 .
|
||||
.El
|
||||
.Ss Logging
|
||||
.Nm
|
||||
has a logging facility that collects all kinds of events at run time.
|
||||
These events are always logged to a file so that the log is available when
|
||||
it is most needed: right after a non-reproducible problem happens.
|
||||
The only way to disable logging is by sending the log to
|
||||
.Pa /dev/null .
|
||||
.Pp
|
||||
The location of the log file can be manually specified with the
|
||||
.Fl -logfile
|
||||
option, which applies to all commands.
|
||||
If no file is explicitly specified, the location of the log files is chosen in
|
||||
this order:
|
||||
.Bl -enum -offset indent
|
||||
.It
|
||||
.Pa ${HOME}/.kyua/logs/
|
||||
if
|
||||
.Va HOME
|
||||
is defined.
|
||||
.It
|
||||
.Pa ${TMPDIR}/
|
||||
if
|
||||
.Va TMPDIR
|
||||
is defined.
|
||||
.It
|
||||
.Pa /tmp/ .
|
||||
.El
|
||||
.Pp
|
||||
And the default naming scheme of the log files is:
|
||||
.Sq <progname>.<timestamp>.log .
|
||||
.Pp
|
||||
The messages stored in the log file have a level (or severity) attached to
|
||||
them.
|
||||
These are:
|
||||
.Bl -tag -width warningXX -offset indent
|
||||
.It error
|
||||
Fatal error messages.
|
||||
The program generally terminates after these, either in a clean manner or by
|
||||
crashing.
|
||||
.It warning
|
||||
Non-fatal error messages.
|
||||
These generally report a condition that must be addressed but the application
|
||||
can continue to run.
|
||||
.It info
|
||||
Informational messages.
|
||||
These tell the user what the program was doing at a general level of
|
||||
operation.
|
||||
.It debug
|
||||
Detailed informational messages.
|
||||
These are often useful when debugging problems in the application, as they
|
||||
contain lots of internal details.
|
||||
.El
|
||||
.Pp
|
||||
The default log level is
|
||||
.Sq info
|
||||
unless explicitly overridden with
|
||||
.Fl -loglevel .
|
||||
.Pp
|
||||
The log file is a plain text file containing one line per log record.
|
||||
The format of each line is as follows:
|
||||
.Bd -literal -offset indent
|
||||
timestamp entry_type pid file:line: message
|
||||
.Ed
|
||||
.Pp
|
||||
.Ar entry_type
|
||||
can be one of:
|
||||
.Sq E
|
||||
for an error,
|
||||
.Sq W
|
||||
for a warning,
|
||||
.Sq I
|
||||
for an informational message and
|
||||
.Sq D
|
||||
for a debug message.
|
||||
.Ss Bug reporting
|
||||
If you think you have encountered a bug in
|
||||
.Nm ,
|
||||
please take the time to let the developers know about it.
|
||||
This will ensure that the bug is addressed and potentially fixed in the next
|
||||
Kyua release.
|
||||
.Pp
|
||||
The first step in reporting a bug is to check if there already is a similar
|
||||
bug in the database.
|
||||
You can check what issues are currently in the database by going to:
|
||||
.Bd -literal -offset indent
|
||||
https://github.com/jmmv/kyua/issues/
|
||||
.Ed
|
||||
.Pp
|
||||
If there is no existing issue that describes an issue similar to the
|
||||
one you are experiencing, you can open a new one by visiting:
|
||||
.Bd -literal -offset indent
|
||||
https://github.com/jmmv/kyua/issues/new/
|
||||
.Ed
|
||||
.Pp
|
||||
When doing so, please include as much detail as possible.
|
||||
Among other things, explain what operating system and platform you are running
|
||||
.Nm
|
||||
on, what were you trying to do, what exact messages you saw on the screen,
|
||||
how did you expect the program to behave, and any other details that you
|
||||
may find relevant.
|
||||
.Pp
|
||||
Also, please include a copy of the log file corresponding to the problem
|
||||
you are experiencing.
|
||||
Unless you have changed the location of the log files, you can most likely
|
||||
find them in
|
||||
.Pa ~/.kyua/logs/ .
|
||||
If the problem is reproducible, it is good idea to regenerate the log file
|
||||
with an increased log level so as to provide more information.
|
||||
For example:
|
||||
.Bd -literal -offset indent
|
||||
$ kyua --logfile=problem.log --loglevel=debug \\
|
||||
[rest of the command line]
|
||||
.Ed
|
||||
.Sh ENVIRONMENT
|
||||
The following variables are recognized and can be freely tuned by the end user:
|
||||
.Bl -tag -width COLUMNSXX
|
||||
.It Va COLUMNS
|
||||
The width of the screen, in number of characters.
|
||||
.Nm
|
||||
uses this to wrap long lines.
|
||||
If not present, the width of the screen is determined from the terminal
|
||||
stdout is connected to, and, if the guessing fails, this defaults to infinity.
|
||||
.It Va HOME
|
||||
Path to the user's home directory.
|
||||
.Nm
|
||||
uses this location to determine paths to configuration files and default log
|
||||
files.
|
||||
.It Va TMPDIR
|
||||
Path to the system-wide temporary directory.
|
||||
.Nm
|
||||
uses this location to place the work directory of test cases, among other
|
||||
things.
|
||||
.Pp
|
||||
The default value of this variable depends on the operating system.
|
||||
In general, it is
|
||||
.Pa /tmp .
|
||||
.El
|
||||
.Pp
|
||||
The following variables are also recognized, but you should not need to set them
|
||||
during normal operation.
|
||||
They are only provided to override the value of built-in values, which is useful
|
||||
when testing
|
||||
.Nm
|
||||
itself:
|
||||
.Bl -tag -width KYUAXCONFDIRXX
|
||||
.It Va KYUA_CONFDIR
|
||||
Path to the system-wide configuration files for
|
||||
.Nm .
|
||||
.Pp
|
||||
Defaults to
|
||||
.Pa __CONFDIR__ .
|
||||
.It Va KYUA_DOCDIR
|
||||
Path to the location of installed documentation.
|
||||
.Pp
|
||||
Defaults to
|
||||
.Pa __DOCDIR__ .
|
||||
.It Va KYUA_MISCDIR
|
||||
Path to the location of the installed miscellaneous scripts and data
|
||||
files provided by
|
||||
.Nm .
|
||||
.Pp
|
||||
Defaults to
|
||||
.Pa __MISCDIR__ .
|
||||
.It Va KYUA_STOREDIR
|
||||
Path to the location of the installed store support files; e.g., the
|
||||
directory containing the SQL database schema.
|
||||
.Pp
|
||||
Defaults to
|
||||
.Pa __STOREDIR__ .
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width XXXX
|
||||
.It Pa ~/.kyua/store/
|
||||
Default location for the results files.
|
||||
.It Pa ~/.kyua/kyua.conf
|
||||
User-specific configuration file.
|
||||
.It Pa ~/.kyua/logs/
|
||||
Default location for the collected log files.
|
||||
.It Pa __CONFDIR__/kyua.conf
|
||||
System-wide configuration file.
|
||||
.El
|
||||
.Sh EXIT STATUS
|
||||
.Nm
|
||||
returns 0 on success, 1 on a controlled error condition in the given
|
||||
subcommand, 2 on a general unexpected error and 3 on a usage error.
|
||||
.Pp
|
||||
The documentation of the subcommands in the corresponding manual pages only
|
||||
details the difference between a successful exit (0) and the detection of a
|
||||
controlled error (1).
|
||||
Even though when those manual pages do not describe any other exit statuses,
|
||||
codes above 1 can be returned.
|
||||
.Sh SEE ALSO
|
||||
.Xr kyua.conf 5 ,
|
||||
.Xr kyuafile 5 ,
|
||||
.Xr atf 7 ,
|
||||
.Xr tests 7
|
||||
.Sh AUTHORS
|
||||
For more details on the people that made
|
||||
.Nm
|
||||
possible and the license terms, run:
|
||||
.Bd -literal -offset indent
|
||||
$ kyua about
|
||||
.Ed
|
141
contrib/kyua/doc/kyua.conf.5.in
Normal file
141
contrib/kyua/doc/kyua.conf.5.in
Normal file
@ -0,0 +1,141 @@
|
||||
.\" Copyright 2012 The Kyua Authors.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions are
|
||||
.\" met:
|
||||
.\"
|
||||
.\" * Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" * Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" * Neither the name of Google Inc. nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.Dd February 20, 2015
|
||||
.Dt KYUA.CONF 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm kyua.conf
|
||||
.Nd Configuration file for the kyua tool
|
||||
.Sh SYNOPSIS
|
||||
.Fn syntax "int version"
|
||||
.Pp
|
||||
Variables:
|
||||
.Va architecture ,
|
||||
.Va platform ,
|
||||
.Va test_suites ,
|
||||
.Va unprivileged_user .
|
||||
.Sh DESCRIPTION
|
||||
The configuration of Kyua is a simple collection of key/value pairs called
|
||||
configuration variables.
|
||||
There are configuration variables that have a special meaning to the runtime
|
||||
engine implemented by
|
||||
.Xr kyua 1 ,
|
||||
and there are variables that only have meaning in the context of particular
|
||||
test suites.
|
||||
.Pp
|
||||
Configuration files are Lua scripts.
|
||||
In their most basic form, their whole purpose is to assign values to
|
||||
variables, but the user has the freedom to implement any logic he desires
|
||||
to compute such values.
|
||||
.Ss File versioning
|
||||
Every
|
||||
.Nm
|
||||
file starts with a call to
|
||||
.Fn syntax "int version" .
|
||||
This call determines the specific schema used by the file so that future
|
||||
backwards-incompatible modifications to the file can be introduced.
|
||||
.Pp
|
||||
Any new
|
||||
.Nm
|
||||
file should set
|
||||
.Fa version
|
||||
to
|
||||
.Sq 2 .
|
||||
.Ss Runtime configuration variables
|
||||
The following variables are internally recognized by
|
||||
.Xr kyua 1 :
|
||||
.Bl -tag -width XX -offset indent
|
||||
.It Va architecture
|
||||
Name of the system architecture (aka processor type).
|
||||
.It Va parallelism
|
||||
Maximum number of test cases to execute concurrently.
|
||||
.It Va platform
|
||||
Name of the system platform (aka machine type).
|
||||
.It Va unprivileged_user
|
||||
Name or UID of the unprivileged user.
|
||||
.Pp
|
||||
If set, the given user must exist in the system and his privileges will be
|
||||
used to run test cases that need regular privileges when
|
||||
.Xr kyua 1
|
||||
is executed as root.
|
||||
.El
|
||||
.Ss Test-suite configuration variables
|
||||
Each test suite is able to recognize arbitrary configuration variables, and
|
||||
their type and meaning is specific to the test suite.
|
||||
Because the existence and naming of these variables depends on every test
|
||||
suite, this manual page cannot detail them; please refer to the documentation
|
||||
of the test suite you are working with for more details on this topic.
|
||||
.Pp
|
||||
Test-suite specific configuration variables are defined inside the
|
||||
.Va test_suites
|
||||
dictionary.
|
||||
The general syntax is:
|
||||
.Bd -literal -offset indent
|
||||
test_suites.<test_suite_name>.<variable_name> = <value>
|
||||
.Ed
|
||||
.Pp
|
||||
where
|
||||
.Va test_suite_name
|
||||
is the name of the test suite,
|
||||
.Va variable_name
|
||||
is the name of the variable to set, and
|
||||
.Va value
|
||||
is a value.
|
||||
The value can be a string, an integer or a boolean.
|
||||
.Sh FILES
|
||||
.Bl -tag -width XX
|
||||
.It __EGDIR__/kyua.conf
|
||||
Sample configuration file.
|
||||
.El
|
||||
.Sh EXAMPLES
|
||||
The following
|
||||
.Nm
|
||||
shows a simple configuration file that overrides a bunch of the built-in
|
||||
.Xr kyua 1
|
||||
configuration variables:
|
||||
.Bd -literal -offset indent
|
||||
syntax(2)
|
||||
|
||||
architecture = 'x86_64'
|
||||
platform = 'amd64'
|
||||
.Ed
|
||||
.Pp
|
||||
The following is a more complex example that introduces the definition of
|
||||
per-test suite configuration variables:
|
||||
.Bd -literal -offset indent
|
||||
syntax(2)
|
||||
|
||||
-- Assign built-in variables.
|
||||
unprivileged_user = '_tests'
|
||||
|
||||
-- Assign test-suite variables. All of these must be strings.
|
||||
test_suites.NetBSD.file_systems = 'ffs ext2fs'
|
||||
test_suites.X11.graphics_driver = 'vesa'
|
||||
.Ed
|
||||
.Sh SEE ALSO
|
||||
.Xr kyua 1
|
407
contrib/kyua/doc/kyuafile.5.in
Normal file
407
contrib/kyua/doc/kyuafile.5.in
Normal file
@ -0,0 +1,407 @@
|
||||
.\" Copyright 2012 The Kyua Authors.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions are
|
||||
.\" met:
|
||||
.\"
|
||||
.\" * Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" * Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" * Neither the name of Google Inc. nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
.Dd July 3, 2015
|
||||
.Dt KYUAFILE 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm Kyuafile
|
||||
.Nd Test suite description files
|
||||
.Sh SYNOPSIS
|
||||
.Fn atf_test_program "string name" "[string metadata]"
|
||||
.Fn current_kyuafile
|
||||
.Fn fs.basename "string path"
|
||||
.Fn fs.dirname "string path"
|
||||
.Fn fs.exists "string path"
|
||||
.Fn fs.files "string path"
|
||||
.Fn fs.is_absolute "string path"
|
||||
.Fn fs.join "string path" "string path"
|
||||
.Fn include "string path"
|
||||
.Fn plain_test_program "string name" "[string metadata]"
|
||||
.Fn syntax "int version"
|
||||
.Fn tap_test_program "string name" "[string metadata]"
|
||||
.Fn test_suite "string name"
|
||||
.Sh DESCRIPTION
|
||||
A test suite is a collection of test programs and is represented by a
|
||||
hierarchical layout of test binaries on the file system.
|
||||
Any subtree of the file system can represent a test suite, provided that it
|
||||
includes one or more
|
||||
.Nm Ns s ,
|
||||
which are the test suite definition files.
|
||||
.Pp
|
||||
A
|
||||
.Nm
|
||||
is a Lua script whose purpose is to describe the structure of the test
|
||||
suite it belongs to.
|
||||
To do so, the script has access to a collection of special functions provided
|
||||
by
|
||||
.Xr kyua 1
|
||||
as described in
|
||||
.Sx Helper functions .
|
||||
.Ss File versioning
|
||||
Every
|
||||
.Nm
|
||||
file starts with a call to
|
||||
.Fn syntax "int version" .
|
||||
This call determines the specific schema used by the file so that future
|
||||
backwards-incompatible modifications to the file can be introduced.
|
||||
.Pp
|
||||
Any new
|
||||
.Nm
|
||||
file should set
|
||||
.Fa version
|
||||
to
|
||||
.Sq 2 .
|
||||
.Ss Test suite definition
|
||||
If the
|
||||
.Nm
|
||||
registers any test programs,
|
||||
the
|
||||
.Nm
|
||||
must define the name of the test suite the test programs belong to by using the
|
||||
.Fn test_suite
|
||||
function at the very beginning of the file.
|
||||
.Pp
|
||||
The test suite name provided in the
|
||||
.Fn test_suite
|
||||
call tells
|
||||
.Xr kyua 1
|
||||
which set of configuration variables from
|
||||
.Xr kyua.conf 5
|
||||
to pass to the test programs at run time.
|
||||
.Ss Test program registration
|
||||
A
|
||||
.Nm
|
||||
can register test programs by means of a variety of
|
||||
.Fn *_test_program
|
||||
functions, all of which take the name of a test program and a set of
|
||||
optional metadata properties that describe such test program.
|
||||
.Pp
|
||||
The test programs to be registered must live in the current directory; in
|
||||
other words, the various
|
||||
.Fn *_test_program
|
||||
calls cannot reference test programs in other directories.
|
||||
The rationale for this is to force all
|
||||
.Nm
|
||||
files to be self-contained, and to simplify their internal representation.
|
||||
.Pp
|
||||
.Em ATF test programs
|
||||
are those that use the
|
||||
.Xr atf 7
|
||||
libraries.
|
||||
They can be registered with the
|
||||
.Fn atf_test_program
|
||||
table constructor.
|
||||
This function takes the
|
||||
.Fa name
|
||||
of the test program and a collection of optional metadata settings for all
|
||||
the test cases in the test program.
|
||||
Any metadata properties defined by the test cases themselves override the
|
||||
metadata values defined here.
|
||||
.Pp
|
||||
.Em Plain test programs
|
||||
are those that return 0 on success and non-0 on failure; in general, most test
|
||||
programs (even those that use fancy unit-testing libraries) behave this way and
|
||||
thus also qualify as plain test programs.
|
||||
They can be registered with the
|
||||
.Fn plain_test_program
|
||||
table constructor.
|
||||
This function takes the
|
||||
.Fa name
|
||||
of the test program, an optional
|
||||
.Fa test_suite
|
||||
name that overrides the global test suite name, and a collection of optional
|
||||
metadata settings for the test program.
|
||||
.Pp
|
||||
.Em TAP test programs
|
||||
are those that implement the Test Anything Protocol.
|
||||
They can be registered with the
|
||||
.Fn tap_test_program
|
||||
table constructor.
|
||||
This function takes the
|
||||
.Fa name
|
||||
of the test program and a collection of optional metadata settings for the
|
||||
test program.
|
||||
.Pp
|
||||
The following metadata properties can be passed to any test program definition:
|
||||
.Bl -tag -width XX -offset indent
|
||||
.It Va allowed_architectures
|
||||
Whitespace-separated list of machine architecture names allowed by the test.
|
||||
If empty or not defined, the test is allowed to run on any machine
|
||||
architecture.
|
||||
.It Va allowed_platforms
|
||||
Whitespace-separated list of machine platform names allowed by the test.
|
||||
If empty or not defined, the test is allowed to run on any machine
|
||||
platform.
|
||||
.It Va custom.NAME
|
||||
Custom variable defined by the test where
|
||||
.Sq NAME
|
||||
denotes the name of the variable.
|
||||
These variables are useful to tag your tests with information specific to
|
||||
your project.
|
||||
The values of such variables are propagated all the way from the tests to the
|
||||
results files and later to any generated reports.
|
||||
.Pp
|
||||
Note that if the name happens to have dashes or any other special characters
|
||||
in it, you will have to use a special Lua syntax to define the property.
|
||||
Refer to the
|
||||
.Sx EXAMPLES
|
||||
section below for clarification.
|
||||
.It Va description
|
||||
Textual description of the test.
|
||||
.It Va is_exclusive
|
||||
If true, indicates that this test program cannot be executed along any other
|
||||
programs at the same time.
|
||||
Test programs that affect global system state, such as those that modify the
|
||||
value of a
|
||||
.Xr sysctl 8
|
||||
setting, must set themselves as exclusive to prevent failures due to race
|
||||
conditions.
|
||||
Defaults to false.
|
||||
.It Va required_configs
|
||||
Whitespace-separated list of configuration variables that the test requires
|
||||
to be defined before it can run.
|
||||
.It Va required_disk_space
|
||||
Amount of available disk space that the test needs to run successfully.
|
||||
.It Va required_files
|
||||
Whitespace-separated list of paths that the test requires to exist before
|
||||
it can run.
|
||||
.It Va required_memory
|
||||
Amount of physical memory that the test needs to run successfully.
|
||||
.It Va required_programs
|
||||
Whitespace-separated list of basenames or absolute paths pointing to executable
|
||||
binaries that the test requires to exist before it can run.
|
||||
.It Va required_user
|
||||
If empty, the test has no restrictions on the calling user for it to run.
|
||||
If set to
|
||||
.Sq unprivileged ,
|
||||
the test needs to not run as root.
|
||||
If set to
|
||||
.Sq root ,
|
||||
the test must run as root.
|
||||
.It Va timeout
|
||||
Amount of seconds that the test is allowed to execute before being killed.
|
||||
.El
|
||||
.Ss Recursion
|
||||
To reference test programs in another subdirectory, a different
|
||||
.Nm
|
||||
must be created in that directory and it must be included into the original
|
||||
.Nm
|
||||
by means of the
|
||||
.Fn include
|
||||
function.
|
||||
.Pp
|
||||
.Fn include
|
||||
may only be called with a relative path and with at most one directory
|
||||
component.
|
||||
This is by design: Kyua uses the file system structure as the layout of the
|
||||
test suite definition.
|
||||
Therefore, each subdirectory in a test suite must include its own
|
||||
.Nm
|
||||
and each
|
||||
.Nm
|
||||
can only descend into the
|
||||
.Nm Ns s
|
||||
of immediate subdirectories.
|
||||
.Pp
|
||||
If you need to source a
|
||||
.Nm
|
||||
located in disjoint parts of your file system namespace, you will have to
|
||||
create a
|
||||
.Sq shadow tree
|
||||
using symbolic links and possibly helper
|
||||
.Nm Ns s
|
||||
to plug the various subdirectories together.
|
||||
See the
|
||||
.Sx EXAMPLES
|
||||
section below for details.
|
||||
.Pp
|
||||
Note that each file is processed in its own Lua environment: there is no
|
||||
mechanism to pass state from one file to the other.
|
||||
The reason for this is that there is no such thing as a
|
||||
.Dq top-level
|
||||
.Nm
|
||||
in a test suite: the user has to be able to run the test suite from any
|
||||
directory in a given hierarchy, and this execution must not depend on files
|
||||
that live in parent directories.
|
||||
.Ss Top-level Kyuafile
|
||||
Every system has a top directory into which test suites get installed.
|
||||
The default is
|
||||
.Pa __TESTSDIR__ .
|
||||
Within this directory live test suites, each of which is in an independent
|
||||
subdirectory.
|
||||
Each subdirectory can be provided separately by independent third-party
|
||||
packages.
|
||||
.Pp
|
||||
Kyua allows running all the installed test suites at once in order to
|
||||
provide comprehensive cross-component reports.
|
||||
In order to do this, there is a special file in the top directory that knows
|
||||
how to inspect the subdirectories in search for other Kyuafiles and include
|
||||
them.
|
||||
.Pp
|
||||
The
|
||||
.Sx FILES
|
||||
section includes more details on where this file lives.
|
||||
.Ss Helper functions
|
||||
The
|
||||
.Sq base ,
|
||||
.Sq string ,
|
||||
and
|
||||
.Sq table
|
||||
Lua modules are fully available in the context of a
|
||||
.Nm .
|
||||
.Pp
|
||||
The following extra functions are provided by Kyua:
|
||||
.Bl -tag -width XX -offset indent
|
||||
.It Ft string Fn current_kyuafile
|
||||
Returns the absolute path to the current
|
||||
.Nm .
|
||||
.It Ft string Fn fs.basename "string path"
|
||||
Returns the last component of the given path.
|
||||
.It Ft string Fn fs.dirname "string path"
|
||||
Returns the given path without its last component or a dot if the path has
|
||||
a single component.
|
||||
.It Ft bool Fn fs.exists "string path"
|
||||
Checks if the given path exists.
|
||||
If the path is not absolute, it is relative to the directory containing the
|
||||
.Nm
|
||||
in which the call to this function occurs.
|
||||
.It Ft iterator Fn fs.files "string path"
|
||||
Opens a directory for scanning of its entries.
|
||||
The returned iterator yields an entry on each call, and the entry is simply
|
||||
the filename.
|
||||
If the path is not absolute, it is relative to the directory containing the
|
||||
.Nm
|
||||
in which the call to this function occurs.
|
||||
.It Ft is_absolute Fn fs.is_absolute "string path"
|
||||
Returns true if the given path is absolute; false otherwise.
|
||||
.It Ft join Fn fs.join "string path" "string path"
|
||||
Concatenates the two paths.
|
||||
The second path cannot be absolute.
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width XX
|
||||
.It Pa __TESTSDIR__/Kyuafile .
|
||||
Top-level
|
||||
.Nm
|
||||
for the current system.
|
||||
.It Pa __EGDIR__/Kyuafile.top .
|
||||
Sample file to serve as a top-level
|
||||
.Nm .
|
||||
.El
|
||||
.Sh EXAMPLES
|
||||
The following
|
||||
.Nm
|
||||
is the simplest you can define.
|
||||
It provides a test suite definition and registers a couple of different test
|
||||
programs using different interfaces:
|
||||
.Bd -literal -offset indent
|
||||
syntax(2)
|
||||
|
||||
test_suite('first')
|
||||
|
||||
atf_test_program{name='integration_test'}
|
||||
plain_test_program{name='legacy_test'}
|
||||
.Ed
|
||||
.Pp
|
||||
The following example is a bit more elaborate.
|
||||
It introduces some metadata properties to the test program definitions and
|
||||
recurses into a couple of subdirectories:
|
||||
.Bd -literal -offset indent
|
||||
syntax(2)
|
||||
|
||||
test_suite('second')
|
||||
|
||||
plain_test_program{name='legacy_test',
|
||||
allowed_architectures='amd64 i386',
|
||||
required_files='/bin/ls',
|
||||
timeout=30}
|
||||
|
||||
tap_test_program{name='privileged_test',
|
||||
required_user='root'}
|
||||
|
||||
include('module-1/Kyuafile')
|
||||
include('module-2/Kyuafile')
|
||||
.Ed
|
||||
.Pp
|
||||
The syntax to define custom properties may be not obvious if their names
|
||||
have any characters that make the property name not be a valid Lua identifier.
|
||||
Dashes are just one example.
|
||||
To set such properties, do something like this:
|
||||
.Bd -literal -offset indent
|
||||
syntax(2)
|
||||
|
||||
test_suite('FreeBSD')
|
||||
|
||||
plain_test_program{name='the_test',
|
||||
['custom.FreeBSD-Bug-Id']='category/12345'}
|
||||
.Ed
|
||||
.Ss Connecting disjoint test suites
|
||||
Now suppose you had various test suites on your file system and you would
|
||||
like to connect them together so that they could be executed and treated as
|
||||
a single unit.
|
||||
The test suites we would like to connect live under
|
||||
.Pa /usr/tests ,
|
||||
.Pa /usr/local/tests
|
||||
and
|
||||
.Pa ~/local/tests .
|
||||
.Pp
|
||||
We cannot create a
|
||||
.Nm
|
||||
that references these because the
|
||||
.Fn include
|
||||
directive does not support absolute paths.
|
||||
Instead, what we can do is create a shadow tree using symbolic links:
|
||||
.Bd -literal -offset indent
|
||||
$ mkdir ~/everything
|
||||
$ ln -s /usr/tests ~/everything/system-tests
|
||||
$ ln -s /usr/local/tests ~/everything/local-tests
|
||||
$ ln -s ~/local/tests ~/everything/home-tests
|
||||
.Ed
|
||||
.Pp
|
||||
And then we create an
|
||||
.Pa ~/everything/Kyuafile
|
||||
file to drive the execution of the integrated test suite:
|
||||
.Bd -literal -offset indent
|
||||
syntax(2)
|
||||
|
||||
test_suite('test-all-the-things')
|
||||
|
||||
include('system-tests/Kyuafile')
|
||||
include('local-tests/Kyuafile')
|
||||
include('home-tests/Kyuafile')
|
||||
.Ed
|
||||
.Pp
|
||||
Or, simply, you could reuse the sample top-level
|
||||
.Nm
|
||||
to avoid having to manually craft the list of directories into which to
|
||||
recurse:
|
||||
.Bd -literal -offset indent
|
||||
$ cp __EGDIR__/Kyuafile.top ~/everything/Kyuafile
|
||||
.Ed
|
||||
.Sh SEE ALSO
|
||||
.Xr kyua 1
|
171
contrib/kyua/doc/manbuild.sh
Executable file
171
contrib/kyua/doc/manbuild.sh
Executable file
@ -0,0 +1,171 @@
|
||||
#! /bin/sh
|
||||
# Copyright 2014 The Kyua Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
# \file doc/manbuild.sh
|
||||
# Generates a manual page from a source file.
|
||||
#
|
||||
# Input files can have __VAR__-style patterns in them that are replaced
|
||||
# with the values provided by the caller via the -v VAR=VALUE flag.
|
||||
#
|
||||
# Input files can also include other files using the __include__ directive,
|
||||
# which takes a relative path to the file to include plus an optional
|
||||
# collection of additional variables to replace in the included file.
|
||||
|
||||
|
||||
# Name of the running program for error reporting purposes.
|
||||
Prog_Name="${0##*/}"
|
||||
|
||||
|
||||
# Prints an error message and exits.
|
||||
#
|
||||
# Args:
|
||||
# ...: The error message to print. Multiple arguments are joined with a
|
||||
# single space separator.
|
||||
err() {
|
||||
echo "${Prog_Name}: ${*}" 1>&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
|
||||
# Invokes sed(1) translating input variables to expressions.
|
||||
#
|
||||
# Args:
|
||||
# ...: List of var=value pairs to replace.
|
||||
#
|
||||
# Returns:
|
||||
# True if the operation succeeds; false otherwise.
|
||||
sed_with_vars() {
|
||||
local vars="${*}"
|
||||
|
||||
set --
|
||||
for pair in ${vars}; do
|
||||
local var="$(echo "${pair}" | cut -d = -f 1)"
|
||||
local value="$(echo "${pair}" | cut -d = -f 2-)"
|
||||
set -- "${@}" -e"s&__${var}__&${value}&g"
|
||||
done
|
||||
|
||||
if [ "${#}" -gt 0 ]; then
|
||||
sed "${@}"
|
||||
else
|
||||
cat
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
# Generates the manual page reading from stdin and dumping to stdout.
|
||||
#
|
||||
# Args:
|
||||
# include_dir: Path to the directory containing the include files.
|
||||
# ...: List of var=value pairs to replace in the manpage.
|
||||
#
|
||||
# Returns:
|
||||
# True if the generation succeeds; false otherwise.
|
||||
generate() {
|
||||
local include_dir="${1}"; shift
|
||||
|
||||
while :; do
|
||||
local read_ok=yes
|
||||
local oldifs="${IFS}"
|
||||
IFS=
|
||||
read -r line || read_ok=no
|
||||
IFS="${oldifs}"
|
||||
[ "${read_ok}" = yes ] || break
|
||||
|
||||
case "${line}" in
|
||||
__include__*)
|
||||
local file="$(echo "${line}" | cut -d ' ' -f 2)"
|
||||
local extra_vars="$(echo "${line}" | cut -d ' ' -f 3-)"
|
||||
# If we fail to output the included file, just leave the line as
|
||||
# is. validate_file() will later error out.
|
||||
[ -f "${include_dir}/${file}" ] || echo "${line}"
|
||||
generate <"${include_dir}/${file}" "${include_dir}" \
|
||||
"${@}" ${extra_vars} || echo "${line}"
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "${line}"
|
||||
;;
|
||||
esac
|
||||
done | sed_with_vars "${@}"
|
||||
}
|
||||
|
||||
|
||||
# Validates that the manual page has been properly generated.
|
||||
#
|
||||
# In particular, this checks if any directives or common replacement patterns
|
||||
# have been left in place.
|
||||
#
|
||||
# Returns:
|
||||
# True if the manual page is valid; false otherwise.
|
||||
validate_file() {
|
||||
local filename="${1}"
|
||||
|
||||
if grep '__[A-Za-z0-9]*__' "${filename}" >/dev/null; then
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
# Program entry point.
|
||||
main() {
|
||||
local vars=
|
||||
|
||||
while getopts :v: arg; do
|
||||
case "${arg}" in
|
||||
v)
|
||||
vars="${vars} ${OPTARG}"
|
||||
;;
|
||||
|
||||
\?)
|
||||
err "Unknown option -${OPTARG}"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift $((${OPTIND} - 1))
|
||||
|
||||
[ ${#} -eq 2 ] || err "Must provide input and output names as arguments"
|
||||
local input="${1}"; shift
|
||||
local output="${1}"; shift
|
||||
|
||||
trap "rm -f '${output}.tmp'" EXIT HUP INT TERM
|
||||
generate "$(dirname "${input}")" ${vars} \
|
||||
<"${input}" >"${output}.tmp" \
|
||||
|| err "Failed to generate ${output}"
|
||||
if validate_file "${output}.tmp"; then
|
||||
:
|
||||
else
|
||||
err "Failed to generate ${output}; some patterns were left unreplaced"
|
||||
fi
|
||||
mv "${output}.tmp" "${output}"
|
||||
}
|
||||
|
||||
|
||||
main "${@}"
|
235
contrib/kyua/doc/manbuild_test.sh
Executable file
235
contrib/kyua/doc/manbuild_test.sh
Executable file
@ -0,0 +1,235 @@
|
||||
# Copyright 2014 The Kyua Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
# Absolute path to the uninstalled script.
|
||||
MANBUILD="__MANBUILD__"
|
||||
|
||||
|
||||
atf_test_case empty
|
||||
empty_body() {
|
||||
touch input
|
||||
atf_check "${MANBUILD}" input output
|
||||
atf_check cat output
|
||||
}
|
||||
|
||||
|
||||
atf_test_case no_replacements
|
||||
no_replacements_body() {
|
||||
cat >input <<EOF
|
||||
This is a manpage.
|
||||
|
||||
With more than one line.
|
||||
EOF
|
||||
atf_check "${MANBUILD}" input output
|
||||
atf_check -o file:input cat output
|
||||
}
|
||||
|
||||
|
||||
atf_test_case one_replacement
|
||||
one_replacement_body() {
|
||||
cat >input <<EOF
|
||||
This is a manpage.
|
||||
Where __FOO__ gets replaced.
|
||||
And nothing more.
|
||||
EOF
|
||||
atf_check "${MANBUILD}" -v FOO=this input output
|
||||
cat >expout <<EOF
|
||||
This is a manpage.
|
||||
Where this gets replaced.
|
||||
And nothing more.
|
||||
EOF
|
||||
atf_check -o file:expout cat output
|
||||
}
|
||||
|
||||
|
||||
atf_test_case some_replacements
|
||||
some_replacements_body() {
|
||||
cat >input <<EOF
|
||||
This is a manpage.
|
||||
Where __FOO__ gets __BAR__.
|
||||
And nothing more.
|
||||
EOF
|
||||
atf_check "${MANBUILD}" -v FOO=this -v BAR=replaced input output
|
||||
cat >expout <<EOF
|
||||
This is a manpage.
|
||||
Where this gets replaced.
|
||||
And nothing more.
|
||||
EOF
|
||||
atf_check -o file:expout cat output
|
||||
}
|
||||
|
||||
|
||||
atf_test_case preserve_tricky_lines
|
||||
preserve_tricky_lines_body() {
|
||||
cat >input <<EOF
|
||||
Begin
|
||||
This line is intended.
|
||||
This other \\
|
||||
continues later.
|
||||
\*(LtAnd this has strange characters\*(Gt
|
||||
End
|
||||
EOF
|
||||
atf_check "${MANBUILD}" input output
|
||||
cat >expout <<EOF
|
||||
Begin
|
||||
This line is intended.
|
||||
This other \\
|
||||
continues later.
|
||||
\*(LtAnd this has strange characters\*(Gt
|
||||
End
|
||||
EOF
|
||||
atf_check -o file:expout cat output
|
||||
}
|
||||
|
||||
|
||||
atf_test_case includes_ok
|
||||
includes_ok_body() {
|
||||
mkdir doc doc/subdir
|
||||
cat >doc/input <<EOF
|
||||
This is a manpage.
|
||||
__include__ subdir/chunk
|
||||
There is more...
|
||||
__include__ chunk
|
||||
And done!
|
||||
EOF
|
||||
cat >doc/subdir/chunk <<EOF
|
||||
This is the first inclusion
|
||||
and worked __OK__.
|
||||
EOF
|
||||
cat >doc/chunk <<EOF
|
||||
This is the second inclusion.
|
||||
EOF
|
||||
atf_check "${MANBUILD}" -v OK=ok doc/input output
|
||||
cat >expout <<EOF
|
||||
This is a manpage.
|
||||
This is the first inclusion
|
||||
and worked ok.
|
||||
There is more...
|
||||
This is the second inclusion.
|
||||
And done!
|
||||
EOF
|
||||
atf_check -o file:expout cat output
|
||||
}
|
||||
|
||||
|
||||
atf_test_case includes_parameterized
|
||||
includes_parameterized_body() {
|
||||
cat >input <<EOF
|
||||
__include__ chunk value=first
|
||||
__include__ chunk value=second
|
||||
EOF
|
||||
cat >chunk <<EOF
|
||||
This is a chunk with value: __value__.
|
||||
EOF
|
||||
atf_check "${MANBUILD}" input output
|
||||
cat >expout <<EOF
|
||||
This is a chunk with value: first.
|
||||
This is a chunk with value: second.
|
||||
EOF
|
||||
atf_check -o file:expout cat output
|
||||
}
|
||||
|
||||
|
||||
atf_test_case includes_fail
|
||||
includes_fail_body() {
|
||||
cat >input <<EOF
|
||||
This is a manpage.
|
||||
__include__ missing
|
||||
EOF
|
||||
atf_check -s exit:1 -o ignore \
|
||||
-e match:"manbuild.sh: Failed to generate output.*left unreplaced" \
|
||||
"${MANBUILD}" input output
|
||||
[ ! -f output ] || atf_fail "Output file was generated but it should" \
|
||||
"not have been"
|
||||
}
|
||||
|
||||
|
||||
atf_test_case generate_fail
|
||||
generate_fail_body() {
|
||||
touch input
|
||||
atf_check -s exit:1 -o ignore \
|
||||
-e match:"manbuild.sh: Failed to generate output" \
|
||||
"${MANBUILD}" -v 'malformed&name=value' input output
|
||||
[ ! -f output ] || atf_fail "Output file was generated but it should" \
|
||||
"not have been"
|
||||
}
|
||||
|
||||
|
||||
atf_test_case validate_fail
|
||||
validate_fail_body() {
|
||||
cat >input <<EOF
|
||||
This is a manpage.
|
||||
Where __FOO__ gets replaced.
|
||||
But where __BAR__ doesn't.
|
||||
EOF
|
||||
atf_check -s exit:1 -o ignore \
|
||||
-e match:"manbuild.sh: Failed to generate output.*left unreplaced" \
|
||||
"${MANBUILD}" -v FOO=this input output
|
||||
[ ! -f output ] || atf_fail "Output file was generated but it should" \
|
||||
"not have been"
|
||||
}
|
||||
|
||||
|
||||
atf_test_case bad_args
|
||||
bad_args_body() {
|
||||
atf_check -s exit:1 \
|
||||
-e match:'manbuild.sh: Must provide input and output names' \
|
||||
"${MANBUILD}"
|
||||
|
||||
atf_check -s exit:1 \
|
||||
-e match:'manbuild.sh: Must provide input and output names' \
|
||||
"${MANBUILD}" foo
|
||||
|
||||
atf_check -s exit:1 \
|
||||
-e match:'manbuild.sh: Must provide input and output names' \
|
||||
"${MANBUILD}" foo bar baz
|
||||
}
|
||||
|
||||
|
||||
atf_test_case bad_option
|
||||
bad_option_body() {
|
||||
atf_check -s exit:1 -e match:'manbuild.sh: Unknown option -Z' \
|
||||
"${MANBUILD}" -Z
|
||||
}
|
||||
|
||||
|
||||
atf_init_test_cases() {
|
||||
atf_add_test_case empty
|
||||
atf_add_test_case no_replacements
|
||||
atf_add_test_case one_replacement
|
||||
atf_add_test_case some_replacements
|
||||
atf_add_test_case preserve_tricky_lines
|
||||
atf_add_test_case includes_ok
|
||||
atf_add_test_case includes_parameterized
|
||||
atf_add_test_case includes_fail
|
||||
atf_add_test_case generate_fail
|
||||
atf_add_test_case validate_fail
|
||||
atf_add_test_case bad_args
|
||||
atf_add_test_case bad_option
|
||||
}
|
53
contrib/kyua/doc/results-file-flag-read.mdoc
Normal file
53
contrib/kyua/doc/results-file-flag-read.mdoc
Normal file
@ -0,0 +1,53 @@
|
||||
.\" Copyright 2014 The Kyua Authors.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions are
|
||||
.\" met:
|
||||
.\"
|
||||
.\" * Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" * Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" * Neither the name of Google Inc. nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
Specifies the results file to operate on.
|
||||
Defaults to
|
||||
.Sq LATEST ,
|
||||
which causes
|
||||
.Nm
|
||||
to automatically load the latest results file from the current test suite.
|
||||
.Pp
|
||||
The following values are accepted:
|
||||
.Bl -tag -width XX
|
||||
.It Sq LATEST
|
||||
Requests the load of the latest results file available for the test suite rooted
|
||||
at the current directory.
|
||||
.It Directory
|
||||
Requests the load of the latest results file available for the test suite rooted
|
||||
at the given directory.
|
||||
.It Test suite name
|
||||
Requests the load of the latest results file available for the given test suite.
|
||||
.It Results identifier
|
||||
Requests the load of a specific results file.
|
||||
.It Explicit file name (aka everything else)
|
||||
Load the specified results file.
|
||||
.El
|
||||
.Pp
|
||||
See
|
||||
.Sx Results files
|
||||
for more details.
|
46
contrib/kyua/doc/results-file-flag-write.mdoc
Normal file
46
contrib/kyua/doc/results-file-flag-write.mdoc
Normal file
@ -0,0 +1,46 @@
|
||||
.\" Copyright 2014 The Kyua Authors.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions are
|
||||
.\" met:
|
||||
.\"
|
||||
.\" * Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" * Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" * Neither the name of Google Inc. nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
Specifies the results file to create.
|
||||
Defaults to
|
||||
.Sq LATEST ,
|
||||
which causes
|
||||
.Nm
|
||||
to automatically generate a new results file for the test run.
|
||||
.Pp
|
||||
The following values are accepted:
|
||||
.Bl -tag -width XX
|
||||
.It Sq NEW
|
||||
Requests the automatic generation of a new results filename based on the test
|
||||
suite being run and the current time.
|
||||
.It Explicit filename (aka everything else)
|
||||
Store the results file where indicated.
|
||||
.El
|
||||
.Pp
|
||||
See
|
||||
.Sx Results files
|
||||
for more details.
|
32
contrib/kyua/doc/results-files-report-example.mdoc
Normal file
32
contrib/kyua/doc/results-files-report-example.mdoc
Normal file
@ -0,0 +1,32 @@
|
||||
.Ss Workflow with results files
|
||||
If one runs the following command twice in a row:
|
||||
.Bd -literal -offset indent
|
||||
kyua test -k /usr/tests/Kyuafile
|
||||
.Ed
|
||||
.Pp
|
||||
the two executions will generate two different files with names like:
|
||||
.Bd -literal -offset indent
|
||||
~/.kyua/store/results.usr_tests.20140731-150500-196784.db
|
||||
~/.kyua/store/results.usr_tests.20140731-151730-997451.db
|
||||
.Ed
|
||||
.Pp
|
||||
Taking advantage of the default naming scheme, the following commands would all
|
||||
generate a report for the results of the
|
||||
.Em latest
|
||||
execution of the test suite:
|
||||
.Bd -literal -offset indent
|
||||
cd /usr/tests && kyua __REPORT_COMMAND__
|
||||
cd /usr/tests && kyua __REPORT_COMMAND__ --results-file=LATEST
|
||||
kyua __REPORT_COMMAND__ --results-file=/usr/tests
|
||||
kyua __REPORT_COMMAND__ --results-file=usr_tests
|
||||
kyua __REPORT_COMMAND__ --results-file=usr_tests.20140731-151730-997451
|
||||
.Ed
|
||||
.Pp
|
||||
But it is also possible to explicitly load data for older runs or from
|
||||
explicitly-named files:
|
||||
.Bd -literal -offset indent
|
||||
kyua __REPORT_COMMAND__ \\
|
||||
--results-file=usr_tests.20140731-150500-196784
|
||||
kyua __REPORT_COMMAND__ \\
|
||||
--results-file=~/.kyua/store/results.usr_tests.20140731-150500-196784.db
|
||||
.Ed
|
68
contrib/kyua/doc/results-files.mdoc
Normal file
68
contrib/kyua/doc/results-files.mdoc
Normal file
@ -0,0 +1,68 @@
|
||||
.\" Copyright 2014 The Kyua Authors.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions are
|
||||
.\" met:
|
||||
.\"
|
||||
.\" * Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" * Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" * Neither the name of Google Inc. nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
Results files contain, as their name implies, the results of the execution of a
|
||||
test suite.
|
||||
Each test suite executed by
|
||||
.Xr kyua-test 1
|
||||
generates a new results file, and such results files can be loaded later on by
|
||||
inspection commands such as
|
||||
.Xr kyua-report 1
|
||||
to analyze their contents.
|
||||
.Pp
|
||||
Results files support identifier-based lookups and also path name lookups.
|
||||
The differences between the two are described below.
|
||||
.Pp
|
||||
The default naming scheme for the results files provides simple support for
|
||||
identifier-based lookups and historical recording of test suite runs.
|
||||
Each results file is given an identifier derived from the test suite that
|
||||
generated it and the time the test suite was run.
|
||||
Kyua can later look up results files by these fields.
|
||||
.Pp
|
||||
The identifier follows this pattern:
|
||||
.Bd -literal -offset indent
|
||||
\*(Lttest_suite\*(Gt.\*(LtYYYYMMDD\*(Gt-\*(LtHHMMSS\*(Gt-\*(Ltuuuuuu\*(Gt
|
||||
.Ed
|
||||
.Pp
|
||||
where
|
||||
.Sq test_suite
|
||||
is the path to the root of the test suite that was run with all slashes replaced
|
||||
by underscores and
|
||||
.Sq YYYYMMDD-HHMMSS-uuuuuu
|
||||
is a timestamp with microsecond resolution.
|
||||
.Pp
|
||||
When using the default naming scheme, results files are stored in the
|
||||
.Pa ~/.kyua/store/
|
||||
subdirectory and each file holds a name of the form:
|
||||
.Bd -literal -offset indent
|
||||
~/.kyua/store/results.\*(Ltidentifier\*(Gt.db
|
||||
.Ed
|
||||
.Pp
|
||||
Results files are simple SQLite databases with the schema described in the
|
||||
.Pa __STOREDIR__/schema_v?.sql
|
||||
files.
|
||||
For details on the schema, please refer to the heavily commented SQL file.
|
40
contrib/kyua/doc/test-filters.mdoc
Normal file
40
contrib/kyua/doc/test-filters.mdoc
Normal file
@ -0,0 +1,40 @@
|
||||
.\" Copyright 2012 The Kyua Authors.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions are
|
||||
.\" met:
|
||||
.\"
|
||||
.\" * Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" * Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" * Neither the name of Google Inc. nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
A
|
||||
.Em test filter
|
||||
is a string that is used to match test cases or test programs in a test suite.
|
||||
Filters have the following form:
|
||||
.Bd -literal -offset indent
|
||||
test_program_name[:test_case_name]
|
||||
.Ed
|
||||
.Pp
|
||||
Where
|
||||
.Sq test_program_name
|
||||
is the name of a test program or a subdirectory in the test suite, and
|
||||
.Sq test_case_name
|
||||
is the name of a test case.
|
112
contrib/kyua/doc/test-isolation.mdoc
Normal file
112
contrib/kyua/doc/test-isolation.mdoc
Normal file
@ -0,0 +1,112 @@
|
||||
.\" Copyright 2014 The Kyua Authors.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions are
|
||||
.\" met:
|
||||
.\"
|
||||
.\" * Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" * Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\" * Neither the name of Google Inc. nor the names of its contributors
|
||||
.\" may be used to endorse or promote products derived from this software
|
||||
.\" without specific prior written permission.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
.\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
.\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
.\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
The test programs and test cases run by
|
||||
.Nm
|
||||
are all executed in a deterministic environment.
|
||||
This known, clean environment serves to make the test execution as
|
||||
reproducible as possible and also to prevent clashes between tests that may,
|
||||
for example, create auxiliary files with overlapping names.
|
||||
.Pp
|
||||
For plain test programs and for TAP test programs, the whole test program
|
||||
is run under a single instance of the environment described in this page.
|
||||
For ATF test programs (see
|
||||
.Xr atf 7 ) ,
|
||||
each individual test case
|
||||
.Em and
|
||||
test cleanup routine are executed in separate environments.
|
||||
.Bl -tag -width XX
|
||||
.It Process space
|
||||
Each test is executed in an independent processes.
|
||||
Corollary: the test can do whatever it wants to the current process (such
|
||||
as modify global variables) without having to undo such changes.
|
||||
.It Session and process group
|
||||
The test is executed in its own session and its own process group.
|
||||
There is no controlling terminal attached to the session.
|
||||
.Pp
|
||||
Should the test spawn any children, the children should maintain the same
|
||||
session and process group.
|
||||
Modifying any of these settings prevents
|
||||
.Nm
|
||||
from being able to kill any stray subprocess as part of the cleanup phase.
|
||||
If modifying these settings is necessary, or if any subprocess started by
|
||||
the test decides to use a different process group or session, it is the
|
||||
responsibility of the test to ensure those subprocesses are forcibly
|
||||
terminated during cleanup.
|
||||
.It Work directory
|
||||
The test is executed in a temporary directory automatically created by the
|
||||
runtime engine.
|
||||
Corollary: the test can write to its current directory
|
||||
without needing to clean any files and/or directories it creates.
|
||||
The runtime engine takes care to recursively delete the temporary directories
|
||||
after the execution of a test case.
|
||||
Any file systems mounted within the temporary directory are also unmounted.
|
||||
.It Home directory
|
||||
The
|
||||
.Va HOME
|
||||
environment variable is set to the absolute path of the work directory.
|
||||
.It Umask
|
||||
The value of the umask is set to 0022.
|
||||
.It Environment
|
||||
The
|
||||
.Va LANG ,
|
||||
.Va LC_ALL ,
|
||||
.Va LC_COLLATE ,
|
||||
.Va LC_CTYPE ,
|
||||
.Va LC_MESSAGES ,
|
||||
.Va LC_MONETARY ,
|
||||
.Va LC_NUMERIC
|
||||
and
|
||||
.Va LC_TIME
|
||||
variables are unset.
|
||||
.Pp
|
||||
The
|
||||
.Va TZ
|
||||
variable is set to
|
||||
.Sq UTC .
|
||||
.Pp
|
||||
The
|
||||
.Va TMPDIR
|
||||
variable is set to the absolute path of the work directory.
|
||||
This is to prevent the test from mistakenly using a temporary directory
|
||||
outside of the automatically-managed work directory, should the test use the
|
||||
.Xr mktemp 3
|
||||
familiy of functions.
|
||||
.It Process limits
|
||||
The maximum soft core size limit is raised to its corresponding hard limit.
|
||||
This is a simple, best-effort attempt at allowing tests to dump core for
|
||||
further diagnostic purposes.
|
||||
.It Configuration varibles
|
||||
The test engine may pass run-time configuration variables to the test program
|
||||
via the environment.
|
||||
The name of the configuration variable is prefixed with
|
||||
.Sq TEST_ENV_
|
||||
so that a configuration variable of the form
|
||||
.Sq foo=bar
|
||||
becomes accessible in the environment as
|
||||
.Sq TEST_ENV_foo=bar .
|
||||
.El
|
7
contrib/kyua/drivers/Kyuafile
Normal file
7
contrib/kyua/drivers/Kyuafile
Normal file
@ -0,0 +1,7 @@
|
||||
syntax(2)
|
||||
|
||||
test_suite("kyua")
|
||||
|
||||
atf_test_program{name="list_tests_test"}
|
||||
atf_test_program{name="report_junit_test"}
|
||||
atf_test_program{name="scan_results_test"}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user