mirror of
https://github.com/openharmony/third_party_ltp.git
synced 2026-07-01 12:25:45 -04:00
@@ -1,46 +0,0 @@
|
||||
#
|
||||
# Release Makefile for LTP.
|
||||
#
|
||||
# Copyright (C) 2010, Copyrights-are-for-losers, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Invoke like:
|
||||
#
|
||||
# make -f Makefile.release release TARBALL_VERSION=FOO
|
||||
#
|
||||
# Cheers.
|
||||
#
|
||||
|
||||
top_srcdir ?= $(CURDIR)
|
||||
|
||||
include $(top_srcdir)/include/mk/env_pre.mk
|
||||
include $(top_srcdir)/include/mk/automake.mk
|
||||
|
||||
TARBALL_PREFIX ?= ltp
|
||||
|
||||
ifneq ($(wildcard $(top_srcdir)/Version),)
|
||||
TARBALL_VERSION ?= $(shell $(top_srcdir)/Version)
|
||||
endif
|
||||
|
||||
TARBALL_VERSION ?= $(error you must either make Version via make $$PWD/Version or specify an LTP version via TARBALL_VERSION)
|
||||
|
||||
TARBALL := $(TARBALL_PREFIX)-$(TARBALL_VERSION).tgz
|
||||
|
||||
clean:
|
||||
$(MAKE) -f Makefile $@
|
||||
|
||||
release: | autotools distclean
|
||||
tar -cvz --exclude "$(TARBALL)" -f $(TARBALL) .
|
||||
@@ -1,213 +0,0 @@
|
||||
Short introduction into LTP build system
|
||||
========================================
|
||||
|
||||
******************************************************************************
|
||||
The following document briefly describes the steps and methodologies used for
|
||||
the new and improved Makefile system.
|
||||
|
||||
Changelog:
|
||||
|
||||
* Initial version: Ngie Cooper <yaneurabeya@gmail.com>
|
||||
* Reformated for asciidoc: Cyril Hrubis <chrubis@suse.cz>
|
||||
******************************************************************************
|
||||
|
||||
The Problem
|
||||
-----------
|
||||
|
||||
The problem with the old Makefile system is that it was very difficult to
|
||||
maintain and it lacked any sense of formal structure, thus developing for LTP
|
||||
and including new targets was more difficult than it should have been
|
||||
(maintenance). Furthermore, proper option-based cross-compilation was
|
||||
impossible due to the fact that the Makefiles didn't support a prefixing
|
||||
system, and the appropriate implicit / static rules hadn't been configured to
|
||||
compile into multiple object directories for out-of-tree build support (ease of
|
||||
use / functionality). Finally, there wasn't a means to setup dependencies
|
||||
between components, such that if a component required libltp.a in order to
|
||||
compile, it would go off and compile libltp.a first (ease of use).
|
||||
|
||||
These items needed to be fixed to reduce maintenance nightmares for the
|
||||
development community contributing to LTP, and the project maintainers.
|
||||
|
||||
Design
|
||||
------
|
||||
|
||||
The system was designed such that including a single GNU Makefile compatible
|
||||
set in each new directory component is all that's essentially required to
|
||||
build the system.
|
||||
|
||||
Say you had a directory like the following (with .c files in them which
|
||||
directly tie into applications, e.g. baz.c -> baz):
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
.../foo/
|
||||
|--> Makefile
|
||||
|
|
||||
--> bar/
|
||||
|
|
||||
--> Makefile
|
||||
|
|
||||
--> baz.c
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Here's an example of how one would accomplish that:
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
.../foo/Makefile:
|
||||
#
|
||||
# Copyright disclaimer goes here -- please use GPLv2.
|
||||
#
|
||||
|
||||
top_srcdir ?= ..
|
||||
|
||||
include $(top_srcdir)/include/mk/env_pre.mk
|
||||
include $(top_srcdir)/include/mk/generic_trunk_target.mk
|
||||
|
||||
.../foo/bar/Makefile:
|
||||
#
|
||||
# Copyright disclaimer goes here -- please use GPLv2.
|
||||
#
|
||||
|
||||
top_srcdir ?= ..
|
||||
|
||||
include $(top_srcdir)/include/mk/env_pre.mk
|
||||
include $(top_srcdir)/include/mk/generic_leaf_target.mk
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Kernel Modules
|
||||
--------------
|
||||
|
||||
Some of the tests need to build kernel modules, happily LTP has
|
||||
infrastructure for this.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
ifneq ($(KERNELRELEASE),)
|
||||
|
||||
obj-m := module01.o
|
||||
|
||||
else
|
||||
|
||||
top_srcdir ?= ../../../..
|
||||
include $(top_srcdir)/include/mk/testcases.mk
|
||||
|
||||
REQ_VERSION_MAJOR := 2
|
||||
REQ_VERSION_PATCH := 6
|
||||
MAKE_TARGETS := test01 test02 module01.ko
|
||||
|
||||
include $(top_srcdir)/include/mk/module.mk
|
||||
include $(top_srcdir)/include/mk/generic_leaf_target.mk
|
||||
|
||||
endif
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
This is example Makefile that allows you build kernel modules inside of LTP.
|
||||
The prerequisites for the build are detected by the 'configure' script.
|
||||
|
||||
The 'REQ_VERSION_MAJOR' and 'REQ_VERSION_PATCH' describe minimal kernel
|
||||
version for which the build system tries to build the module.
|
||||
|
||||
The buildsystem is also forward compatible with changes in Linux kernel
|
||||
internal API so that if modul fails to build the failure is ignored both on
|
||||
build and installation. If the userspace counterpart of the test fails to load
|
||||
the module because the file does not exists, the test is skipped.
|
||||
|
||||
Note the 'ifneq($(KERNELRELEASE),)', the reason it's there is that the
|
||||
Makefile is executed twice, once by LTP build system and once by kernel
|
||||
kbuild, see 'Documentation/kbuild/modules.txt' in the Linux kernel tree for
|
||||
details on external module build.
|
||||
|
||||
Make Rules and Make Variables
|
||||
-----------------------------
|
||||
|
||||
When using make rules, avoid writing ad hoc rules like:
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
[prog]: [dependencies]
|
||||
cc -I../../include $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(LDLIBS) \
|
||||
-o [prog] [dependencies]
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
etc. This makes cross-compilation and determinism difficult, if not impossible.
|
||||
Besides, implicit rules are your friends and as long as you use `MAKEOPTS=;' in
|
||||
the top-level caller (or do $(subst r,$(MAKEOPTS)) to remove -r), the compile
|
||||
will complete successfully, assuming all other prerequisites have been
|
||||
fulfilled (libraries, headers, etc).
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
$(AR) : The library archiver.
|
||||
|
||||
$(CC) : The system C compiler.
|
||||
|
||||
$(CPP) : The system C preprocessor.
|
||||
|
||||
$(CFLAGS) : C compiler flags.
|
||||
|
||||
$(CPPFLAGS) : Preprocessor flags, e.g. -I arguments.
|
||||
|
||||
$(DEBUG_CFLAGS) : Debug flags to pass to $(CC), -g, etc.
|
||||
|
||||
$(LD) : The system linker (typically $(CC), but not
|
||||
necessarily).
|
||||
|
||||
$(LDFLAGS) : What to pass in to the linker, including -L arguments
|
||||
and other ld arguments, apart from -l library
|
||||
includes (see $(LDLIBS)).
|
||||
|
||||
This should be done in the $(CC) args passing style
|
||||
when LD := $(CC), e.g. `-Wl,-foo', as opposed to
|
||||
`-foo'.
|
||||
|
||||
$(LDLIBS) : Libraries to pass to the linker (e.g. -lltp, etc).
|
||||
|
||||
$(LTPLDLIBS) : LTP internal libraries i.e. these in libs/ directory.
|
||||
|
||||
$(OPT_CFLAGS) : Optimization flags to pass into the C compiler, -O2,
|
||||
etc. If you specify -O2 or higher, you should also
|
||||
specify -fno-strict-aliasing, because of gcc
|
||||
fstrict-aliasing optimization bugs in the tree
|
||||
optimizer. Search for `fstrict-aliasing optimization
|
||||
bug' with your favorite search engine.
|
||||
|
||||
Examples of more recent bugs:
|
||||
1. tree-optimization/17510
|
||||
2. tree-optimization/39100
|
||||
|
||||
Various bugs have occurred in the past due to buggy
|
||||
logic in the tree-optimization portion of the gcc
|
||||
compiler, from 3.3.x to 4.4.
|
||||
|
||||
$(RANLIB) : What to run after archiving a library.
|
||||
|
||||
$(WCFLAGS) : Warning flags to pass to $(CC), e.g. -Werror,
|
||||
-Wall, etc.
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Make System Variables
|
||||
---------------------
|
||||
|
||||
A series of variables are used within the make system that direct what actions
|
||||
need to be taken. Rather than me listing the variables here, please with their
|
||||
intended uses, please refer to the comments contained in
|
||||
+.../include/mk/env_pre.mk+.
|
||||
|
||||
Guidelines and Recommendations
|
||||
------------------------------
|
||||
|
||||
Of course, the GNU Make manual is key to understanding the Make system, but
|
||||
here are the following sections and chapters I suggest reviewing:
|
||||
|
||||
link:http://www.gnu.org/software/make/manual/make.html#Implicit-Rules[Implicit Rules]
|
||||
link:http://www.gnu.org/software/make/manual/make.html#Using-Variables[Variables and Expansion]
|
||||
link:http://www.gnu.org/software/make/manual/make.html#Origin-Function[Origin Use]
|
||||
link:http://www.gnu.org/software/make/manual/make.html#Directory-Search[VPath Use]
|
||||
|
||||
Before Committing
|
||||
-----------------
|
||||
|
||||
One should rebuild from scratch before committing. Please see INSTALL for more
|
||||
details.
|
||||
|
||||
Other Errata
|
||||
------------
|
||||
|
||||
Please see TODO for any issues related to the Makefile infrastructure, and
|
||||
build structure / source tree in general.
|
||||
-2371
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,59 +0,0 @@
|
||||
LTP Library API Writing Guidelines
|
||||
==================================
|
||||
|
||||
NOTE: See also
|
||||
https://github.com/linux-test-project/ltp/wiki/Test-Writing-Guidelines[Test Writing Guidelines],
|
||||
https://github.com/linux-test-project/ltp/wiki/C-Test-API[C Test API],
|
||||
https://github.com/linux-test-project/ltp/wiki/Shell-Test-API[Shell Test API].
|
||||
|
||||
1. General Rules
|
||||
----------------
|
||||
|
||||
For extending library API it applies the same general rules as for writing tests,
|
||||
(see https://github.com/linux-test-project/ltp/wiki/Test-Writing-Guidelines[Test Writing Guidelines],
|
||||
offline: 'doc/test-writing-guidelines.txt'),
|
||||
with strong focus on readability and simplicity.
|
||||
|
||||
Library tests are in 'lib/newlib_tests' directory.
|
||||
|
||||
Don't forget to update docs when you change the API.
|
||||
|
||||
2. C API
|
||||
--------
|
||||
|
||||
2.1 LTP-001: Sources have tst_ prefix
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
API source code is in headers `include/*.h`, `include/lapi/*.h` (backward
|
||||
compatibility for old kernel and libc) and C sources in `lib/*.c`. Files have
|
||||
'tst_' prefix.
|
||||
|
||||
2.2 LTP-002: TST_RET and TST_ERR are not modified
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The test author is guaranteed that the test API will not modify these
|
||||
variables. This prevents silent errors where the return value and
|
||||
errno are overwritten before the test has chance to check them.
|
||||
|
||||
The macros which are clearly intended to update these variables. That
|
||||
is +TEST+ and those in 'tst_test_macros.h'. Are of course allowed to
|
||||
update these variables.
|
||||
|
||||
2.3 LTP-003: Externally visible library symbols have the tst_ prefix
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Functions, types and variables in the public test API should have the
|
||||
tst_ prefix. With some exceptions for symbols already prefixed with
|
||||
safe_ or ltp_.
|
||||
|
||||
Static (private) symbols should not have the prefix.
|
||||
|
||||
|
||||
3. Shell API
|
||||
------------
|
||||
|
||||
API source code is in `tst_test.sh`, `tst_security.sh` and `tst_net.sh`
|
||||
(all in 'testcases/lib' directory).
|
||||
|
||||
Changes in the shell API should not introduce uncommon dependencies
|
||||
(use basic commands installed everywhere by default).
|
||||
@@ -1,59 +0,0 @@
|
||||
# Maintainer Patch Review Checklist
|
||||
|
||||
Patchset should be tested locally and ideally also in maintainer's fork in
|
||||
GitHub Actions on GitHub.
|
||||
|
||||
NOTE: Travis does only build testing, passing the CI means only that the
|
||||
test compiles fine on variety of different distributions and
|
||||
releases.
|
||||
|
||||
The test should be executed at least once locally and should PASS as well.
|
||||
|
||||
Commit messages should have
|
||||
|
||||
* Author's `Signed-off-by` tag
|
||||
* Committer's `Reviewed-by` or `Signed-off-by` tag
|
||||
* Check also mailing lists for other reviewers / testers tags, notes and failure reports
|
||||
* `Fixes: hash` if it fixes particular LTP commit
|
||||
* `Fixes: #N` if it fixes github issue number N, so it's automatically closed
|
||||
|
||||
After patch is accepted or rejected, set correct state and archive in
|
||||
https://patchwork.ozlabs.org/project/ltp/list/[LTP patchwork instance].
|
||||
|
||||
Also update `.github/workflows/wiki-mirror.yml` script which mirrors
|
||||
`doc/*.txt` to LTP wiki (git URL https://github.com/linux-test-project/ltp.wiki.git)
|
||||
if new wiki page is added.
|
||||
|
||||
## New tests
|
||||
New test should
|
||||
|
||||
* Have a record in runtest file
|
||||
* Test should work fine with more than one iteration
|
||||
(e.g. run with `-i 100`)
|
||||
* Have a brief description
|
||||
* License: the default license for new tests is GPL v2 or later, use
|
||||
GPL-2.0-or-later; the licence for test (e.g. GPL-2.0) should not change
|
||||
unless test is completely rewritten
|
||||
* Old copyrights should be kept unless test is completely rewritten
|
||||
|
||||
### C tests
|
||||
* Use new https://github.com/linux-test-project/ltp/wiki/Test-Writing-Guidelines#22-writing-a-test-in-c[C API]
|
||||
* Test binaries are added into corresponding '.gitignore' files
|
||||
* Check coding style with `make check`
|
||||
(more in https://github.com/linux-test-project/ltp/wiki/Test-Writing-Guidelines#21-c-coding-style[C coding style])
|
||||
* Docparse documentation
|
||||
* If a test is a regression test it should include tags
|
||||
(more in https://github.com/linux-test-project/ltp/wiki/Test-Writing-Guidelines#2238-test-tags[Test tags])
|
||||
* When rewriting old tests, https://en.wikipedia.org/wiki/%CE%9CClinux[uClinux]
|
||||
support should be removed (project has been discontinued).
|
||||
E.g. remove `#ifdef UCLINUX`, replace `FORK_OR_VFORK()` with simple `fork()` or `SAFE_FORK()`.
|
||||
|
||||
### Shell tests
|
||||
* Use new https://github.com/linux-test-project/ltp/wiki/Test-Writing-Guidelines#23-writing-a-testcase-in-shell[shell API]
|
||||
* Check coding style with `make check`
|
||||
(more in https://github.com/linux-test-project/ltp/wiki/Test-Writing-Guidelines#132-shell-coding-style[Shell coding style])
|
||||
* If a test is a regression test it should include related kernel or glibc commits as a comment
|
||||
|
||||
## LTP library
|
||||
For patchset touching library please check also
|
||||
https://github.com/linux-test-project/ltp/wiki/LTP-Library-API-Writing-Guidelines[LTP Library API Writing Guidelines].
|
||||
@@ -1,62 +0,0 @@
|
||||
Mini-Howto: Building LTP from Git
|
||||
=================================
|
||||
|
||||
******************************************************************************
|
||||
The following document briefly describes the single steps to build LTP from
|
||||
the Git repository located at GitHub.
|
||||
The instructions here were tested on a Ubuntu/precise Linux system (feel free
|
||||
to adapt to your distribution).
|
||||
|
||||
Changelog:
|
||||
* Initial version: Sedat Dilek <sedat.dilek@gmail.com>
|
||||
* Embedded comments from Cyril Hrubis <chrubis@suse.cz>
|
||||
******************************************************************************
|
||||
|
||||
# Export language settings
|
||||
|
||||
export LANG=C
|
||||
export LC_ALL=C
|
||||
|
||||
# Set some useful variables (adapt if you dislike)
|
||||
|
||||
WORKING_DIR="$HOME/src/ltp"
|
||||
|
||||
PREFIX="/opt/ltp"
|
||||
|
||||
GIT_URL="https://github.com/linux-test-project/ltp.git"
|
||||
|
||||
MAKE_JOBS=$(getconf _NPROCESSORS_ONLN)
|
||||
|
||||
BUILD_LOG_FILE="build-log.txt"
|
||||
INSTALL_LOG_FILE="install-log.txt"
|
||||
|
||||
# PREREQS on Ubuntu (package-list is incomplete and may vary for other distros)
|
||||
|
||||
sudo apt-get install build-essential
|
||||
sudo apt-get install autoconf automake autotools-dev m4
|
||||
sudo apt-get install git
|
||||
sudo apt-get install linux-headers-$(uname -r)
|
||||
sudo apt-get install libaio-dev libattr1-dev libcap-dev
|
||||
|
||||
# Working directory
|
||||
|
||||
mkdir -p $WORKING_DIR
|
||||
cd $WORKING_DIR
|
||||
|
||||
# Get the LTP source
|
||||
|
||||
git clone $GIT_URL ltp-git
|
||||
|
||||
# Configure LTP
|
||||
|
||||
cd ltp-git/
|
||||
make autotools
|
||||
./configure --prefix=$PREFIX
|
||||
|
||||
# Start building LTP
|
||||
|
||||
make -j$MAKE_JOBS 2>&1 | tee ../$BUILD_LOG_FILE
|
||||
|
||||
# Install LTP (requires superuser privileges)
|
||||
|
||||
sudo make install 2>&1 | tee ../$INSTALL_LOG_FILE
|
||||
@@ -1,476 +0,0 @@
|
||||
LTP C Test Network API
|
||||
======================
|
||||
|
||||
NOTE: See also
|
||||
https://github.com/linux-test-project/ltp/wiki/Test-Writing-Guidelines[Test Writing Guidelines],
|
||||
https://github.com/linux-test-project/ltp/wiki/C-Test-Case-Tutorial[C Test Case Tutorial],
|
||||
https://github.com/linux-test-project/ltp/wiki/C-Test-API[C Test API],
|
||||
https://github.com/linux-test-project/ltp/wiki/Shell-Test-API[Shell Test API].
|
||||
|
||||
LTP library includes helper functions for configuring sockets and setting up
|
||||
network devices.
|
||||
|
||||
1 Configuring sockets
|
||||
---------------------
|
||||
|
||||
1.1 Safe syscall variants
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
+#include "tst_safe_net.h"+
|
||||
|
||||
Most common standard syscalls and libc functions for configuring sockets have a
|
||||
"safe" variant in LTP library which will call +tst_brk()+ if the underlying
|
||||
system function fails. See
|
||||
https://github.com/linux-test-project/ltp/wiki/C-Test-API[C Test API]. The
|
||||
safe function names are in uppercase with the +SAFE_+ prefix (e.g. the safe
|
||||
variant of +socket()+ is called +SAFE_SOCKET()+). For most safe functions, the
|
||||
parameters and return type are identical to the standard system function:
|
||||
|
||||
- +SAFE_SOCKET()+
|
||||
- +SAFE_SOCKETPAIR()+
|
||||
- +SAFE_GETSOCKOPT()+
|
||||
- +SAFE_SETSOCKOPT()+
|
||||
- +SAFE_BIND()+
|
||||
- +SAFE_LISTEN()+
|
||||
- +SAFE_ACCEPT()+
|
||||
- +SAFE_CONNECT()+
|
||||
- +SAFE_GETSOCKNAME()+
|
||||
- +SAFE_GETHOSTNAME()+
|
||||
- +SAFE_GETADDRINFO()+
|
||||
|
||||
A few safe functions have extra parameters for quick return value validation.
|
||||
The ellipsis (+...+) represents the standard parameters of the underlying system
|
||||
function:
|
||||
|
||||
* +SAFE_SEND(char strict, ...)+
|
||||
* +SAFE_SENDTO(char strict, ...)+
|
||||
** If +strict+ is non-zero, the return value must be equal to the data length
|
||||
argument. Otherwise the test will fail and exit.
|
||||
|
||||
* +SAFE_SENDMSG(size_t msg_len, ...)+
|
||||
* +SAFE_RECV(size_t msg_len, ...)+
|
||||
* +SAFE_RECVMSG(size_t msg_len, ...)+
|
||||
** If +msg_len+ is non-zero, the return value must be equal to the +msg_len+
|
||||
argument. Otherwise the test will fail and exit.
|
||||
|
||||
There are also some custom functions for simpler configuration and queries:
|
||||
|
||||
- +int SAFE_SETSOCKOPT_INT(int sockfd, int level, int optname, int value)+ –
|
||||
Simple setsockopt() variant for passing integers by value.
|
||||
|
||||
- +int TST_GETSOCKPORT(int sockfd)+ – Get port number (in host byte order) of a
|
||||
bound socket.
|
||||
|
||||
- +unsigned short TST_GET_UNUSED_PORT(int family, int type)+ – Get a random
|
||||
port number (in network byte order) which is currently closed for the given
|
||||
socket family and type. Note that another application may open the port while
|
||||
the test is still running. The test user is responsible for setting up test
|
||||
environment without such interference.
|
||||
|
||||
1.2 Address conversion functions
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
+#include "tst_net.h"+
|
||||
|
||||
LTP library also provides helper functions for quick initialization of socket
|
||||
address structures:
|
||||
|
||||
- +void tst_get_in_addr(const char *ip_str, struct in_addr *ip)+ – Convert
|
||||
human-readable IPv4 address string +ip_str+ to binary representation in
|
||||
network byte order. The converted value will be stored in the second argument.
|
||||
|
||||
- +void tst_get_in6_addr(const char *ip_str, struct in6_addr *ip6)+ – Convert
|
||||
human-readable IPv6 address string +ip_str+ to binary representation in
|
||||
network byte order. The converted value will be stored in the second argument.
|
||||
|
||||
- +socklen_t tst_get_connect_address(int sock, struct sockaddr_storage *addr)+ –
|
||||
Find the address which can be used to send data to bound socket +sock+ from
|
||||
another socket. The address will be stored in the second argument. This
|
||||
function automatically converts wildcard bind address to localhost. Returns
|
||||
size of the address in bytes.
|
||||
|
||||
- +void tst_init_sockaddr_inet(struct sockaddr_in *sa, const char *ip_str,
|
||||
uint16_t port)+ – Initialize socket address structure +sa+ using
|
||||
human-readable IPv4 address +ip_str+ and port number +port+ in host byte
|
||||
order.
|
||||
|
||||
- +void tst_init_sockaddr_inet_bin(struct sockaddr_in *sa, uint32_t ip_val,
|
||||
uint16_t port)+ – Initialize socket address structure +sa+ using binary IPv4
|
||||
address +ip_val+ and port number +port+, both in host byte order.
|
||||
|
||||
- +void tst_init_sockaddr_inet6(struct sockaddr_in6 *sa, const char *ip_str,
|
||||
uint16_t port)+ – Initialize socket address structure +sa+ using
|
||||
human-readable IPv6 address +ip_str+ and port number +port+ in host byte
|
||||
order.
|
||||
|
||||
- +void tst_init_sockaddr_inet6_bin(struct sockaddr_in6 *sa, const struct
|
||||
in6_addr *ip_val, uint16_t port)+ – Initialize socket address structure +sa+
|
||||
using binary IPv6 address +ip_val+ and port number +port+, both in host byte
|
||||
order.
|
||||
|
||||
.Example Usage
|
||||
[source,c]
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include "tst_test.h"
|
||||
#include "tst_safe_net.h"
|
||||
#include "tst_net.h"
|
||||
|
||||
static int sockfd = -1;
|
||||
|
||||
static void setup(void)
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
|
||||
tst_init_sockaddr_inet_bin(&addr, INADDR_ANY, 0);
|
||||
sockfd = SAFE_SOCKET(AF_INET, SOCK_STREAM, 0);
|
||||
SAFE_SETSOCKOPT_INT(sockfd, SOL_SOCKET, SO_SNDBUF, 4096);
|
||||
SAFE_BIND(sockfd, (struct sockaddr *)&addr, sizeof(addr));
|
||||
SAFE_LISTEN(sockfd, 8);
|
||||
}
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
2 Configuring network devices
|
||||
-----------------------------
|
||||
|
||||
+#include "tst_netdevice.h"+
|
||||
|
||||
When opening a localhost socket isn't enough and the test needs special device
|
||||
or routing configuration, the netdevice library can create the required network
|
||||
setup without calling external programs. Internally, the netdevice functions
|
||||
use a rtnetlink socket to communicate with the kernel.
|
||||
|
||||
All of these functions will call +tst_brk()+ on failure, unless stated
|
||||
otherwise. Error values described below are returned only during test cleanup
|
||||
stage.
|
||||
|
||||
2.1 Network device management
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- +int NETDEV_INDEX_BY_NAME(const char *ifname)+ – Returns the device index for
|
||||
the given device name, or -1 on error.
|
||||
|
||||
- +int NETDEV_SET_STATE(const char *ifname, int up)+ – Enable or disable a
|
||||
network device +ifname+. Returns 0 on success, -1 on error.
|
||||
|
||||
- +int CREATE_VETH_PAIR(const char *ifname1, const char *ifname2)+ – Creates a
|
||||
connected pair of virtual network devices with given device names. Returns 1
|
||||
on success, 0 on error. Add +"CONFIG_VETH"+ to +test.needs_kconfigs+ if your
|
||||
test calls this function.
|
||||
|
||||
- +int NETDEV_ADD_DEVICE(const char *ifname, const char *devtype)+ - Creates
|
||||
a new network device named +ifname+ of specified device type. Returns 1 on
|
||||
success, 0 on error.
|
||||
|
||||
- +int NETDEV_REMOVE_DEVICE(const char *ifname)+ – Removes network device
|
||||
+ifname+. Returns 1 on success, 0 on error.
|
||||
|
||||
2.2 Network address management
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- +int NETDEV_ADD_ADDRESS(const char \*ifname, unsigned int family, const void
|
||||
*address, unsigned int prefix, size_t addrlen, unsigned int flags)+ – Adds
|
||||
new address to network device +ifname+. This is a low-level function which
|
||||
allows setting any type of address. You must specify the protocol +family+,
|
||||
address length in bytes (+addrlen+) and network prefix length (+prefix+). The
|
||||
+address+ itself must be in binary representation in network byte order. You
|
||||
can also pass rtnetlink flags from the +IFA_F_*+ group. Returns 1 on success,
|
||||
0 on error.
|
||||
|
||||
- +int NETDEV_ADD_ADDRESS_INET(const char *ifname, in_addr_t address, unsigned
|
||||
int prefix, unsigned int flags)+ – Adds new IPv4 address to network device
|
||||
+ifname+. Parameters have the same meaning as in +NETDEV_ADD_ADDRESS()+.
|
||||
Returns 1 on success, 0 on error.
|
||||
|
||||
- +int NETDEV_REMOVE_ADDRESS(const char *ifname, unsigned int family, const
|
||||
void *address, size_t addrlen)+ – Removes the specified address from network
|
||||
device +ifname+. Parameters have the same meaning as in
|
||||
+NETDEV_ADD_ADDRESS()+. Returns 1 on success, 0 on error.
|
||||
|
||||
- +int NETDEV_REMOVE_ADDRESS_INET(const char *ifname, in_addr_t address)+ –
|
||||
Removes specified IPv4 +address+ (in network byte order) from network device
|
||||
+ifname+. Returns 1 on success, 0 on error.
|
||||
|
||||
2.3 Network namespace device assignment
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
WARNING: Moving a network device to another namespace will erase previous
|
||||
configuration. Move the device to the correct namespace first, then
|
||||
configure it.
|
||||
|
||||
- +int NETDEV_CHANGE_NS_FD(const char *ifname, int nsfd)+ – Moves network
|
||||
device +ifname+ to network namespace designated by open file descriptor
|
||||
+nsfd+. Returns 1 on success, 0 on error.
|
||||
|
||||
- +int NETDEV_CHANGE_NS_PID(const char *ifname, pid_t nspid)+ – Moves network
|
||||
device +ifname+ to the network namespace currently used by process +nspid+.
|
||||
Returns 1 on success, 0 on error.
|
||||
|
||||
2.4 Routing table management
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- +int NETDEV_ADD_ROUTE(const char *ifname, unsigned int family, const void
|
||||
*srcaddr, unsigned int srcprefix, size_t srclen, const void *dstaddr,
|
||||
unsigned int dstprefix, size_t dstlen, const void *gateway, size_t
|
||||
gatewaylen)+ – Adds new route to the main routing table. This is a low-level
|
||||
function which allows creating routes for any protocol. You must specify the
|
||||
protocol +family+ and either network device name +ifname+ or +gateway+
|
||||
address. Both packet source address +srcaddr+ and destination address
|
||||
+dstaddr+ are optional. You must also specify the corresponding length
|
||||
and prefix argument for any address which is not +NULL+. All addresses must
|
||||
be in binary representation in network byte order. Returns 1 on success,
|
||||
0 on error.
|
||||
|
||||
- +int NETDEV_ADD_ROUTE_INET(const char *ifname, in_addr_t srcaddr, unsigned
|
||||
int srcprefix, in_addr_t dstaddr, unsigned int dstprefix, in_addr_t
|
||||
gateway)+ – Adds new IPv4 route to the main routing table. Parameters have
|
||||
the same meaning as in +NETDEV_ADD_ROUTE()+. If you do not want to set
|
||||
explicit +gateway+ address, set it to 0. If the routing rule should ignore
|
||||
the source or destination address, set the corresponding prefix argument
|
||||
to 0. Returns 1 on success, 0 on error.
|
||||
|
||||
- +int NETDEV_REMOVE_ROUTE(const char *ifname, unsigned int family, const void
|
||||
*srcaddr, unsigned int srcprefix, size_t srclen, const void *dstaddr,
|
||||
unsigned int dstprefix, size_t dstlen, const void *gateway, size_t
|
||||
gatewaylen)+ – Removes a route from the main routing table. Parameters have
|
||||
the same meaning as in +NETDEV_ADD_ROUTE()+. Returns 1 on success, 0 on
|
||||
error.
|
||||
|
||||
- +int NETDEV_REMOVE_ROUTE_INET(const char *ifname, in_addr_t srcaddr,
|
||||
unsigned int srcprefix, in_addr_t dstaddr, unsigned int dstprefix, in_addr_t
|
||||
gateway)+ – Removes IPv4 route from the main routing table. Parameters have
|
||||
the same meaning as in +NETDEV_ADD_ROUTE_INET()+. Returns 1 on success,
|
||||
0 on error.
|
||||
|
||||
.Example Usage
|
||||
[source,c]
|
||||
-------------------------------------------------------------------------------
|
||||
#include <arpa/inet.h>
|
||||
#include <linux/if_addr.h>
|
||||
#include "tst_test.h"
|
||||
#include "tst_netdevice.h"
|
||||
|
||||
...
|
||||
|
||||
static void setup(void)
|
||||
{
|
||||
CREATE_VETH_PAIR("ltp_veth1", "ltp_veth2");
|
||||
NETDEV_ADD_ADDRESS_INET("ltp_veth2", htonl(DSTADDR), NETMASK,
|
||||
IFA_F_NOPREFIXROUTE);
|
||||
NETDEV_SET_STATE("ltp_veth2", 1);
|
||||
NETDEV_ADD_ROUTE_INET("ltp_veth2", 0, 0, htonl(SRCNET), NETMASK, 0);
|
||||
|
||||
NETDEV_ADD_ADDRESS_INET("ltp_veth1", htonl(SRCADDR), NETMASK,
|
||||
IFA_F_NOPREFIXROUTE);
|
||||
NETDEV_SET_STATE("ltp_veth1", 1);
|
||||
NETDEV_ADD_ROUTE_INET("ltp_veth1", 0, 0, htonl(DSTNET), NETMASK, 0);
|
||||
...
|
||||
}
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
3 rtnetlink API
|
||||
---------------
|
||||
|
||||
+#include "tst_rtnetlink.h"+
|
||||
|
||||
The rtnetlink library provides helper functions for constructing and sending
|
||||
arbitrary messages and parsing kernel responses.
|
||||
|
||||
All of the functions below will call +tst_brk()+ on failure, unless stated
|
||||
otherwise. Error values described below are returned only during test cleanup
|
||||
stage.
|
||||
|
||||
3.1 Data structures
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
[source,c]
|
||||
-------------------------------------------------------------------------------
|
||||
struct tst_rtnl_context;
|
||||
|
||||
struct tst_rtnl_attr_list {
|
||||
unsigned short type;
|
||||
const void *data;
|
||||
ssize_t len;
|
||||
const struct tst_rtnl_attr_list *sublist;
|
||||
};
|
||||
|
||||
struct tst_rtnl_message {
|
||||
struct nlmsghdr *header;
|
||||
struct nlmsgerr *err;
|
||||
void *payload;
|
||||
size_t payload_size;
|
||||
};
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
+struct tst_rtnl_context+ is an opaque rtnetlink socket with buffer for
|
||||
constructing and sending arbitrary messages using the functions described
|
||||
below. Create a new context using +RTNL_CREATE_CONTEXT()+, then free it using
|
||||
+RTNL_DESTROY_CONTEXT()+ when you're done with it.
|
||||
|
||||
+struct tst_rtnl_attr_list+ is a helper structure for defining complex
|
||||
rtnetlink message attribute payloads, including nested attribute lists. Every
|
||||
list and sublist defined using this structure is terminated by item with
|
||||
negative +len+.
|
||||
|
||||
- +type+ is the attribute type that will be stored in +struct rtattr.rta_type+.
|
||||
|
||||
- +data+ contains arbitrary attribute payload.
|
||||
|
||||
- +len+ contains length of the +data+ attribute in bytes. If +data+ is +NULL+,
|
||||
set +len+ to 0. The last item in a list or sublist must have negative length.
|
||||
|
||||
- +sublist+ contains a nested attribute list which will be appended after
|
||||
+data+ as part of the attribute payload. +struct rtattr.rta_len+ will be
|
||||
calculated automatically with proper alignment, do _not_ add the sublist size
|
||||
to the +len+ field. If you do not want to add nested attributes, set
|
||||
+sublist+ to +NULL+.
|
||||
|
||||
+struct tst_rtnl_message+ is a structure holding partially parsed rtnetlink
|
||||
messages received from the kernel. +RTNL_RECV()+ returns an array of these
|
||||
structures with the last item having +NULL+ in the +header+ field. Call
|
||||
+RTNL_FREE_MESSAGE()+ to free a message list returned by +RTNL_RECV()+.
|
||||
|
||||
- +header+ is the netlink header structure of the message. +NULL+ in the header
|
||||
field terminates a list of messages.
|
||||
|
||||
- +err+ points to the payload of +NLMSG_ERROR+ messages. It is set to +NULL+
|
||||
for all other message types.
|
||||
|
||||
- +payload+ is a pointer to message data.
|
||||
|
||||
- +payload_size+ is the length of +payload+ data in bytes.
|
||||
|
||||
3.2 Sending and receiving messages
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- +struct tst_rtnl_context *RTNL_CREATE_CONTEXT(void)+ – Creates a new
|
||||
rtnetlink communication context for use with the functions described below.
|
||||
Returns +NULL+ on error.
|
||||
|
||||
- +void RTNL_FREE_MESSAGE(struct tst_rtnl_message *msg)+ – Frees an array of
|
||||
messages returned by +RTNL_RECV()+.
|
||||
|
||||
- +void RTNL_DESTROY_CONTEXT(struct tst_rtnl_context *ctx)+ – Closes a
|
||||
communication context created by +RTNL_CREATE_CONTEXT()+.
|
||||
|
||||
- +int RTNL_SEND(struct tst_rtnl_context *ctx)+ – Sends all messages waiting
|
||||
in +ctx+ buffer to the kernel. If there are multiple messages to send, a new
|
||||
+NLMSG_DONE+ message will be added automatically. Returns the number of
|
||||
bytes sent on success. Return 0 or negative value on error.
|
||||
|
||||
- +int RTNL_SEND_VALIDATE(struct tst_rtnl_context *ctx)+ – Sends all messages
|
||||
just like +RTNL_SEND()+, then receives the response from the kernel and
|
||||
validates results of requests sent with the +NLM_F_ACK+ flag. This function
|
||||
calls +tst_brk()+ as usual if communication fails but it will return error
|
||||
status without terminating the test if one of the received messages contains
|
||||
error code. See +RTNL_CHECK_ACKS()+ below for explanation of the return
|
||||
value.
|
||||
|
||||
- +int RTNL_WAIT(struct tst_rtnl_context *ctx)+ – Waits until data becomes
|
||||
available to read from the rtnetlink socket (timeout: 1 second). Returns 1
|
||||
if there is data to read, 0 on timeout or -1 on error.
|
||||
|
||||
- +struct tst_rtnl_message *RTNL_RECV(struct tst_rtnl_context *ctx)+ – Receives
|
||||
rtnetlink messages from the kernel. The messages are received in non-blocking
|
||||
mode so calling +RTNL_WAIT()+ first is recommended. Returns an array of
|
||||
partially parsed messages terminated by an item with +NULL+ in the +header+
|
||||
field. On error or when there are no messages to receive, returns +NULL+.
|
||||
Call +RTNL_FREE_MESSAGE()+ to free the returned data.
|
||||
|
||||
- +int RTNL_CHECK_ACKS(struct tst_rtnl_context *ctx, struct tst_rtnl_message
|
||||
*response)+ – Validate results of requests sent with the +NLM_F_ACK+ flag.
|
||||
Do not call +RTNL_ADD_MESSAGE()+ between +RTNL_SEND()+ and
|
||||
+RTNL_CHECK_ACKS()+ because it will reset the state of +ctx+ and prevent
|
||||
result validation. Returns 1 if all messages sent with the +NLM_F_ACK+ flag
|
||||
have a corresponding message in +response+ and the error code is 0. If any
|
||||
of the expected response messages is missing, this function will call
|
||||
+tst_brk()+ (or return 0 during test cleanup phase). If any of the response
|
||||
messages has non-zero error code, this function will return 0 and store the
|
||||
first non-zero error code in global variable +tst_rtnl_errno+ (sign-flipped
|
||||
just like regular libc +errno+).
|
||||
|
||||
3.3 Creating messages
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- +int RTNL_ADD_MESSAGE(struct tst_rtnl_context *ctx, const struct nlmsghdr
|
||||
*header, const void *payload, size_t payload_size)+ – Adds new rtnetlink
|
||||
message to +ctx+ buffer. You need to provide message +header+ and optional
|
||||
+payload+. +payload_size+ is the size of +payload+ data in bytes. If you
|
||||
don't want to add any payload data, set +payload+ to +NULL+ and
|
||||
+payload_size+ to 0. This function will automatically fill the +nlmsg_len+,
|
||||
+nlmsg_seq+ and +nlmsg_pid+ fields of the new message header. You don't need
|
||||
to set those. It'll also automatically add +NLM_F_MULTI+ flag when needed.
|
||||
Returns 1 on success, 0 on error. Note that the first call of
|
||||
+RTNL_ADD_MESSAGE()+ after +RTNL_SEND()+ will reset the state of +ctx+
|
||||
and +RTNL_CHECK_ACKS()+ will not work correctly until the next +RTNL_SEND()+.
|
||||
|
||||
- +int RTNL_ADD_ATTR(struct tst_rtnl_context *ctx, unsigned short type, const
|
||||
void *data, unsigned short len)+ – Adds new attribute to the last message
|
||||
in +ctx+ buffer. See +RTNL_ADD_MESSAGE()+. You need to provide attribute
|
||||
+type+ which will be stored in +struct rtattr.rta_type+, optional payload
|
||||
+data+ and payload size +len+ in bytes. If you don't want to add any payload,
|
||||
set +data+ to +NULL+ and +len+ to 0. Returns 1 on success, 0 on error.
|
||||
|
||||
- +int RTNL_ADD_ATTR_STRING(struct tst_rtnl_context *ctx, unsigned short type,
|
||||
const char *data)+ – Adds new string attribute to the last message in +ctx+
|
||||
buffer. Parameters and return value are the same as for +RTNL_ADD_ATTR()+,
|
||||
except the payload length is calculated using +strlen()+.
|
||||
|
||||
- +int RTNL_ADD_ATTR_LIST(struct tst_rtnl_context *ctx, const struct
|
||||
tst_rtnl_attr_list *list)+ – Adds a list of attributes to the last message
|
||||
in +ctx+ buffer. See description of +struct tst_rtnl_attr_list+ and
|
||||
+RTNL_ADD_MESSAGE()+ above. Returns the number of added attributes on
|
||||
success (nested attributes are not counted), -1 on error.
|
||||
|
||||
.Example Usage
|
||||
[source,c]
|
||||
-------------------------------------------------------------------------------
|
||||
#include <asm/types.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "tst_test.h"
|
||||
#include "tst_rtnetlink.h"
|
||||
#include "tst_netdevice.h"
|
||||
|
||||
...
|
||||
|
||||
void setup(void)
|
||||
{
|
||||
struct tst_rtnl_context *ctx;
|
||||
int index, ret;
|
||||
in_addr_t addr;
|
||||
|
||||
struct nlmsghdr header = {
|
||||
.nlmsg_type = RTM_NEWADDR,
|
||||
.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE |
|
||||
NLM_F_EXCL
|
||||
};
|
||||
|
||||
struct ifaddrmsg info = {
|
||||
.ifa_family = AF_INET,
|
||||
.ifa_prefixlen = 24
|
||||
};
|
||||
|
||||
index = NETDEV_INDEX_BY_NAME("ltp_veth1");
|
||||
info.ifa_index = index;
|
||||
|
||||
ctx = RTNL_CREATE_CONTEXT();
|
||||
RTNL_ADD_MESSAGE(ctx, &header, &info, sizeof(info));
|
||||
addr = inet_addr("192.168.123.45");
|
||||
RTNL_ADD_ATTR(ctx, IFA_LOCAL, &addr, sizeof(addr));
|
||||
ret = RTNL_SEND_VALIDATE(ctx);
|
||||
RTNL_DESTROY_CONTEXT(ctx);
|
||||
|
||||
if (!ret) {
|
||||
tst_brk(TBROK, "Failed to set ltp_veth1 address");
|
||||
}
|
||||
}
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -1,763 +0,0 @@
|
||||
LTP Shell Test API
|
||||
==================
|
||||
|
||||
NOTE: See also
|
||||
https://github.com/linux-test-project/ltp/wiki/Test-Writing-Guidelines[Test Writing Guidelines],
|
||||
https://github.com/linux-test-project/ltp/wiki/C-Test-API[C Test API].
|
||||
|
||||
1 Writing a testcase in shell
|
||||
-----------------------------
|
||||
|
||||
LTP supports testcases to be written in a portable shell too.
|
||||
|
||||
There is a shell library modeled closely to the C interface at
|
||||
'testcases/lib/tst_test.sh'.
|
||||
|
||||
WARNING: All identifiers starting with 'TST_' or 'tst_' are reserved for the
|
||||
test library.
|
||||
|
||||
1.1 Basic test interface
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
[source,sh]
|
||||
-------------------------------------------------------------------------------
|
||||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
# This is a basic test for true shell builtin
|
||||
|
||||
TST_TESTFUNC=do_test
|
||||
. tst_test.sh
|
||||
|
||||
do_test()
|
||||
{
|
||||
true
|
||||
ret=$?
|
||||
|
||||
if [ $ret -eq 0 ]; then
|
||||
tst_res TPASS "true returned 0"
|
||||
else
|
||||
tst_res TFAIL "true returned $ret"
|
||||
fi
|
||||
}
|
||||
|
||||
tst_run
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
TIP: To execute this test the 'tst_test.sh' library must be in '$PATH'. If you
|
||||
are executing the test from a git checkout you can run it as
|
||||
'PATH="$PATH:../../lib" ./foo01.sh'
|
||||
|
||||
The shell library expects test setup, cleanup and the test function executing
|
||||
the test in the '$TST_SETUP', '$TST_CLEANUP' and '$TST_TESTFUNC' variables.
|
||||
|
||||
Both '$TST_SETUP' and '$TST_CLEANUP' are optional.
|
||||
|
||||
The '$TST_TESTFUNC' may be called several times if more than one test
|
||||
iteration was requested by passing right command line options to the test.
|
||||
|
||||
The '$TST_CLEANUP' may be called even in the middle of the setup and must be
|
||||
able to clean up correctly even in this situation. The easiest solution for
|
||||
this is to keep track of what was initialized and act accordingly in the
|
||||
cleanup.
|
||||
|
||||
WARNING: Similar to the C library, calling 'tst_brk' in the $TST_CLEANUP does
|
||||
not exit the test and 'TBROK' is converted to 'TWARN'.
|
||||
|
||||
Notice also the 'tst_run' shell API function called at the end of the test that
|
||||
actually starts the test.
|
||||
|
||||
WARNING: cleanup function is called only after 'tst_run' has been started.
|
||||
Calling 'tst_brk' in shell libraries, e.g. 'tst_test.sh' or 'tst_net.sh' does
|
||||
not trigger calling it.
|
||||
|
||||
[source,sh]
|
||||
-------------------------------------------------------------------------------
|
||||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
# Example test with tests in separate functions
|
||||
|
||||
TST_TESTFUNC=test
|
||||
TST_CNT=2
|
||||
. tst_test.sh
|
||||
|
||||
test1()
|
||||
{
|
||||
tst_res TPASS "Test $1 passed"
|
||||
}
|
||||
|
||||
test2()
|
||||
{
|
||||
tst_res TPASS "Test $1 passed"
|
||||
}
|
||||
|
||||
tst_run
|
||||
# output:
|
||||
# foo 1 TPASS: Test 1 passed
|
||||
# foo 2 TPASS: Test 2 passed
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
If '$TST_CNT' is set, the test library looks if there are functions named
|
||||
'$\{TST_TESTFUNC\}1', ..., '$\{TST_TESTFUNC\}$\{TST_CNT\}' and if these are
|
||||
found they are executed one by one. The test number is passed to it in the '$1'.
|
||||
|
||||
[source,sh]
|
||||
-------------------------------------------------------------------------------
|
||||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
# Example test with tests in a single function
|
||||
|
||||
TST_TESTFUNC=do_test
|
||||
TST_CNT=2
|
||||
. tst_test.sh
|
||||
|
||||
do_test()
|
||||
{
|
||||
case $1 in
|
||||
1) tst_res TPASS "Test $1 passed";;
|
||||
2) tst_res TPASS "Test $1 passed";;
|
||||
esac
|
||||
}
|
||||
|
||||
tst_run
|
||||
# output:
|
||||
# foo 1 TPASS: Test 1 passed
|
||||
# foo 2 TPASS: Test 2 passed
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Otherwise, if '$TST_CNT' is set but there is no '$\{TST_TESTFUNC\}1', etc.,
|
||||
the '$TST_TESTFUNC' is executed '$TST_CNT' times and the test number is passed
|
||||
to it in the '$1'.
|
||||
|
||||
[source,sh]
|
||||
-------------------------------------------------------------------------------
|
||||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
# Example test with tests in a single function, using $TST_TEST_DATA and
|
||||
# $TST_TEST_DATA_IFS
|
||||
|
||||
TST_TESTFUNC=do_test
|
||||
TST_TEST_DATA="foo:bar:d dd"
|
||||
TST_TEST_DATA_IFS=":"
|
||||
. tst_test.sh
|
||||
|
||||
do_test()
|
||||
{
|
||||
tst_res TPASS "Test $1 passed with data '$2'"
|
||||
}
|
||||
|
||||
tst_run
|
||||
# output:
|
||||
# foo 1 TPASS: Test 1 passed with data 'foo'
|
||||
# foo 2 TPASS: Test 1 passed with data 'bar'
|
||||
# foo 3 TPASS: Test 1 passed with data 'd dd'
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
It's possible to pass data for function with '$TST_TEST_DATA'. Optional
|
||||
'$TST_TEST_DATA_IFS' is used for splitting, default value is space.
|
||||
|
||||
[source,sh]
|
||||
-------------------------------------------------------------------------------
|
||||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
# Example test with tests in a single function, using $TST_TEST_DATA and $TST_CNT
|
||||
|
||||
TST_TESTFUNC=do_test
|
||||
TST_CNT=2
|
||||
TST_TEST_DATA="foo bar"
|
||||
. tst_test.sh
|
||||
|
||||
do_test()
|
||||
{
|
||||
case $1 in
|
||||
1) tst_res TPASS "Test $1 passed with data '$2'";;
|
||||
2) tst_res TPASS "Test $1 passed with data '$2'";;
|
||||
esac
|
||||
}
|
||||
|
||||
tst_run
|
||||
# output:
|
||||
# foo 1 TPASS: Test 1 passed with data 'foo'
|
||||
# foo 2 TPASS: Test 2 passed with data 'foo'
|
||||
# foo 3 TPASS: Test 1 passed with data 'bar'
|
||||
# foo 4 TPASS: Test 2 passed with data 'bar'
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
'$TST_TEST_DATA' can be used with '$TST_CNT'. If '$TST_TEST_DATA_IFS' not specified,
|
||||
space as default value is used. Of course, it's possible to use separate functions.
|
||||
|
||||
1.2 Library environment variables and functions for shell
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Similarily to the C library various checks and preparations can be requested
|
||||
simply by setting right '$TST_NEEDS_FOO'.
|
||||
|
||||
[options="header"]
|
||||
|=============================================================================
|
||||
| Variable name | Action done
|
||||
| 'TST_NEEDS_ROOT' | Exit the test with 'TCONF' unless executed under root.
|
||||
| | Alternatively the 'tst_require_root' command can be used.
|
||||
| 'TST_NEEDS_TMPDIR' | Create test temporary directory and cd into it.
|
||||
| 'TST_NEEDS_DEVICE' | Prepare test temporary device, the path to testing
|
||||
device is stored in '$TST_DEVICE' variable.
|
||||
The option implies 'TST_NEEDS_TMPDIR'.
|
||||
| 'TST_NEEDS_CMDS' | String with command names that has to be present for
|
||||
the test (see below).
|
||||
| 'TST_NEEDS_MODULE' | Test module name needed for the test (see below).
|
||||
| 'TST_NEEDS_DRIVERS' | Checks kernel drivers support for the test.
|
||||
| 'TST_NEEDS_KCONFIGS' | Checks kernel kconfigs support for the test (see below).
|
||||
| 'TST_NEEDS_KCONFIGS_IFS' | Used for splitting '$TST_NEEDS_KCONFIGS' variable,
|
||||
default value is comma, it only supports single character.
|
||||
| 'TST_TIMEOUT' | Maximum timeout set for the test in sec. Must be int >= 1,
|
||||
or -1 (special value to disable timeout), default is 300.
|
||||
Variable is meant be set in tests, not by user.
|
||||
It's an equivalent of `tst_test.timeout` in C, can be set
|
||||
via 'tst_set_timeout(timeout)' after test has started.
|
||||
|=============================================================================
|
||||
|
||||
[options="header"]
|
||||
|=============================================================================
|
||||
| Function name | Action done
|
||||
| 'tst_set_timeout(timeout)' | Maximum timeout set for the test in sec.
|
||||
See 'TST_TIMEOUT' variable.
|
||||
|=============================================================================
|
||||
|
||||
NOTE: Network tests (see testcases/network/README.md) use additional variables
|
||||
and functions in 'tst_net.sh'.
|
||||
|
||||
Checking for presence of commands
|
||||
+++++++++++++++++++++++++++++++++
|
||||
|
||||
[source,sh]
|
||||
-------------------------------------------------------------------------------
|
||||
#!/bin/sh
|
||||
|
||||
...
|
||||
|
||||
TST_NEEDS_CMDS="modinfo modprobe"
|
||||
. tst_test.sh
|
||||
|
||||
...
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Setting '$TST_NEEDS_CMDS' to a string listing required commands will check for
|
||||
existence each of them and exits the test with 'TCONF' on first missing.
|
||||
|
||||
Alternatively the 'tst_require_cmds()' function can be used to do the same on
|
||||
runtime, since sometimes we need to the check at runtime too.
|
||||
|
||||
'tst_check_cmds()' can be used for requirements just for a particular test
|
||||
as it doesn't exit (it issues 'tst_res TCONF'). Expected usage is:
|
||||
|
||||
[source,sh]
|
||||
-------------------------------------------------------------------------------
|
||||
#!/bin/sh
|
||||
|
||||
TST_TESTFUNC=do_test
|
||||
. tst_test.sh
|
||||
|
||||
do_test()
|
||||
{
|
||||
tst_check_cmds cmd || return
|
||||
cmd --foo
|
||||
...
|
||||
}
|
||||
|
||||
tst_run
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Locating kernel modules
|
||||
+++++++++++++++++++++++
|
||||
|
||||
The LTP build system can build kernel modules as well, setting
|
||||
'$TST_NEEDS_MODULE' to module name will cause the library to look for the
|
||||
module in a few possible paths.
|
||||
|
||||
If module was found the path to it will be stored into '$TST_MODPATH'
|
||||
variable, if module wasn't found the test will exit with 'TCONF'.
|
||||
|
||||
Alternatively the 'tst_require_module()' function can be used to do the same
|
||||
at runtime.
|
||||
|
||||
1.3 Optional command line parameters
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
[source,sh]
|
||||
-------------------------------------------------------------------------------
|
||||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
# Optional test command line parameters
|
||||
|
||||
TST_OPTS="af:"
|
||||
TST_USAGE=usage
|
||||
TST_PARSE_ARGS=parse_args
|
||||
TST_TESTFUNC=do_test
|
||||
|
||||
. tst_test.sh
|
||||
|
||||
ALTERNATIVE=0
|
||||
MODE="foo"
|
||||
|
||||
usage()
|
||||
{
|
||||
cat << EOF
|
||||
usage: $0 [-a] [-f <foo|bar>]
|
||||
|
||||
OPTIONS
|
||||
-a Enable support for alternative foo
|
||||
-f Specify foo or bar mode
|
||||
EOF
|
||||
}
|
||||
|
||||
parse_args()
|
||||
{
|
||||
case $1 in
|
||||
a) ALTERNATIVE=1;;
|
||||
f) MODE="$2";;
|
||||
esac
|
||||
}
|
||||
|
||||
do_test()
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
tst_run
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
The 'getopts' string for optional parameters is passed in the '$TST_OPTS'
|
||||
variable. There are a few default parameters that cannot be used by a test,
|
||||
these can be listed with passing help '-h' option to any test.
|
||||
|
||||
The function that prints the usage is passed in '$TST_USAGE', the help for
|
||||
the options implemented in the library is appended when usage is printed.
|
||||
|
||||
Lastly the function '$PARSE_ARGS' is called with the option name in the '$1'
|
||||
and, if option has argument, its value in the '$2'.
|
||||
|
||||
[source,sh]
|
||||
-------------------------------------------------------------------------------
|
||||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
# Optional test positional parameters
|
||||
|
||||
TST_POS_ARGS=3
|
||||
TST_USAGE=usage
|
||||
TST_TESTFUNC=do_test
|
||||
|
||||
. tst_test.sh
|
||||
|
||||
usage()
|
||||
{
|
||||
cat << EOF
|
||||
usage: $0 [min] [max] [size]
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
min="$1"
|
||||
max="$2"
|
||||
size="$3"
|
||||
|
||||
do_test()
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
tst_run
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
You can also request a number of positional parameters by setting the
|
||||
'$TST_POS_ARGS' variable. If you do, these will be available as they were
|
||||
passed directly to the script in '$1', '$2', ..., '$n'.
|
||||
|
||||
1.4 Useful library functions
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Retrieving configuration variables
|
||||
++++++++++++++++++++++++++++++++++
|
||||
|
||||
You may need to retrieve configuration values such as PAGESIZE, there is
|
||||
'getconf' but as some system may not have it, you are advised to use
|
||||
'tst_getconf' instead. Note that it implements subset of 'getconf'
|
||||
system variables used by the testcases only.
|
||||
|
||||
[source,sh]
|
||||
-------------------------------------------------------------------------------
|
||||
# retrieve PAGESIZE
|
||||
pagesize=`tst_getconf PAGESIZE`
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Sleeping for subsecond intervals
|
||||
++++++++++++++++++++++++++++++++
|
||||
|
||||
Albeit there is a sleep command available basically everywhere not all
|
||||
implementations can support sleeping for less than one second. And most of the
|
||||
time sleeping for a second is too much. Therefore LTP includes 'tst_sleep'
|
||||
that can sleep for defined amount of seconds, milliseconds or microseconds.
|
||||
|
||||
[source,sh]
|
||||
-------------------------------------------------------------------------------
|
||||
# sleep for 100 milliseconds
|
||||
tst_sleep 100ms
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Retry a function call multiple times
|
||||
++++++++++++++++++++++++++++++++++++
|
||||
|
||||
Sometimes an LTP test needs to retry a function call multiple times because
|
||||
the system is not ready to process it successfully on the first try. The LTP
|
||||
library has useful tools to handle the call retry automatically.
|
||||
'TST_RETRY_FUNC()' will keep retrying for up to 1 second. If you want a custom
|
||||
time limit use 'TST_RETRY_FN_EXP_BACKOFF()'. Both methods return the value
|
||||
returned by the last 'FUNC' call.
|
||||
|
||||
The delay between retries starts at 1 microsecond and doubles after each call.
|
||||
The retry loop ends when the function call succeeds or when the next delay
|
||||
exceeds the specified time (1 second for 'TST_RETRY_FUNC()'). The maximum
|
||||
delay is multiplied by TST_TIMEOUT_MUL. The total cumulative delay may be up
|
||||
to twice as long as the adjusted maximum delay.
|
||||
|
||||
The C version of 'TST_RETRY_FUNC()' is a macro which takes two arguments:
|
||||
|
||||
* 'FUNC' is the complete function call with arguments which should be retried
|
||||
multiple times.
|
||||
* 'SUCCESS_CHECK' is a macro or function which will validate 'FUNC' return
|
||||
value. 'FUNC' call was successful if 'SUCCESS_CHECK(ret)' evaluates to
|
||||
non-zero.
|
||||
|
||||
Both retry methods clear 'errno' before every 'FUNC' call so your
|
||||
'SUCCESS_CHECK' can look for specific error codes as well. The LTP library
|
||||
also includes predefined 'SUCCESS_CHECK' macros for the most common call
|
||||
conventions:
|
||||
|
||||
* 'TST_RETVAL_EQ0()' - The call was successful if 'FUNC' returned 0 or NULL
|
||||
* 'TST_RETVAL_NOTNULL()' - The call was successful if 'FUNC' returned any
|
||||
value other than 0 or NULL.
|
||||
* 'TST_RETVAL_GE0()' - The call was successful if 'FUNC' returned value >= 0.
|
||||
|
||||
[source,c]
|
||||
-------------------------------------------------------------------------------
|
||||
/* Keep trying for 1 second */
|
||||
TST_RETRY_FUNC(FUNC, SUCCESS_CHECK)
|
||||
|
||||
/* Keep trying for up to 2*N seconds */
|
||||
TST_RETRY_FN_EXP_BACKOFF(FUNC, SUCCESS_CHECK, N)
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
The shell version of 'TST_RETRY_FUNC()' is simpler and takes slightly
|
||||
different arguments:
|
||||
|
||||
* 'FUNC' is a string containing the complete function or program call with
|
||||
arguments.
|
||||
* 'EXPECTED_RET' is a single expected return value. 'FUNC' call was successful
|
||||
if the return value is equal to EXPECTED_RET.
|
||||
|
||||
[source,sh]
|
||||
-------------------------------------------------------------------------------
|
||||
# Keep trying for 1 second
|
||||
TST_RETRY_FUNC "FUNC arg1 arg2 ..." "EXPECTED_RET"
|
||||
|
||||
# Keep trying for up to 2*N seconds
|
||||
TST_RETRY_FN_EXP_BACKOFF "FUNC arg1 arg2 ..." "EXPECTED_RET" "N"
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Checking for integers
|
||||
+++++++++++++++++++++
|
||||
|
||||
[source,sh]
|
||||
-------------------------------------------------------------------------------
|
||||
# returns zero if passed an integer parameter, non-zero otherwise
|
||||
tst_is_int "$FOO"
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Checking for integers and floating point numbers
|
||||
++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
[source,sh]
|
||||
-------------------------------------------------------------------------------
|
||||
# returns zero if passed an integer or floating point number parameter,
|
||||
# non-zero otherwise
|
||||
tst_is_num "$FOO"
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Obtaining random numbers
|
||||
++++++++++++++++++++++++
|
||||
|
||||
There is no '$RANDOM' in portable shell, use 'tst_random' instead.
|
||||
|
||||
[source,sh]
|
||||
-------------------------------------------------------------------------------
|
||||
# get random integer between 0 and 1000 (including 0 and 1000)
|
||||
tst_random 0 1000
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Formatting device with a filesystem
|
||||
+++++++++++++++++++++++++++++++++++
|
||||
|
||||
The 'tst_mkfs' helper will format device with the filesystem.
|
||||
|
||||
[source,sh]
|
||||
-------------------------------------------------------------------------------
|
||||
# format test device with ext2
|
||||
tst_mkfs ext2 $TST_DEVICE
|
||||
# default params are $TST_FS_TYPE $TST_DEVICE
|
||||
tst_mkfs
|
||||
# optional parameters
|
||||
tst_mkfs ext4 /dev/device -T largefile
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Mounting and unmounting filesystems
|
||||
+++++++++++++++++++++++++++++++++++
|
||||
|
||||
The 'tst_mount' and 'tst_umount' helpers are a safe way to mount/umount
|
||||
a filesystem.
|
||||
|
||||
The 'tst_mount' mounts '$TST_DEVICE' of '$TST_FS_TYPE' (optional) to
|
||||
'$TST_MNTPOINT' (defaults to mntpoint), optionally using the
|
||||
'$TST_MNT_PARAMS'. The '$TST_MNTPOINT' directory is created if it didn't
|
||||
exist prior to the function call.
|
||||
|
||||
If the path passed (optional, must be absolute path, defaults to '$TST_MNTPOINT')
|
||||
to the 'tst_umount' is not mounted (present in '/proc/mounts') it's noop.
|
||||
Otherwise it retries to umount the filesystem a few times on failure.
|
||||
This is a workaround since there are daemons dumb enough to probe all newly
|
||||
mounted filesystems, and prevents them from being umounted shortly after they
|
||||
were mounted.
|
||||
|
||||
ROD and ROD_SILENT
|
||||
++++++++++++++++++
|
||||
|
||||
These functions supply the 'SAFE_MACROS' used in C although they work and are
|
||||
named differently.
|
||||
|
||||
[source,sh]
|
||||
-------------------------------------------------------------------------------
|
||||
ROD_SILENT command arg1 arg2 ...
|
||||
|
||||
# is shorthand for:
|
||||
|
||||
command arg1 arg2 ... > /dev/null 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
tst_brk TBROK "..."
|
||||
fi
|
||||
|
||||
|
||||
ROD command arg1 arg2 ...
|
||||
|
||||
# is shorthand for:
|
||||
|
||||
ROD arg1 arg2 ...
|
||||
if [ $? -ne 0 ]; then
|
||||
tst_brk TBROK "..."
|
||||
fi
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
WARNING: Keep in mind that output redirection (to a file) happens in the
|
||||
caller rather than in the ROD function and cannot be checked for
|
||||
write errors by the ROD function.
|
||||
|
||||
As a matter of a fact doing +ROD echo a > /proc/cpuinfo+ would work just fine
|
||||
since the 'ROD' function will only get the +echo a+ part that will run just
|
||||
fine.
|
||||
|
||||
[source,sh]
|
||||
-------------------------------------------------------------------------------
|
||||
# Redirect output to a file with ROD
|
||||
ROD echo foo \> bar
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Note the '>' is escaped with '\', this causes that the '>' and filename are
|
||||
passed to the 'ROD' function as parameters and the 'ROD' function contains
|
||||
code to split '$@' on '>' and redirects the output to the file.
|
||||
|
||||
EXPECT_PASS{,_BRK} and EXPECT_FAIL{,_BRK}
|
||||
+++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
[source,sh]
|
||||
-------------------------------------------------------------------------------
|
||||
EXPECT_PASS command arg1 arg2 ... [ \> file ]
|
||||
EXPECT_FAIL command arg1 arg2 ... [ \> file ]
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
'EXPECT_PASS' calls 'tst_res TPASS' if the command exited with 0 exit code,
|
||||
and 'tst_res TFAIL' otherwise. 'EXPECT_FAIL' does vice versa.
|
||||
|
||||
Output redirection rules are the same as for the 'ROD' function. In addition
|
||||
to that, 'EXPECT_FAIL' always redirects the command's stderr to '/dev/null'.
|
||||
|
||||
There are also 'EXPECT_PASS_BRK' and 'EXPECT_FAIL_BRK', which works the same way
|
||||
except breaking a test when unexpected action happen.
|
||||
|
||||
It's possible to detect whether expected value happened:
|
||||
[source,sh]
|
||||
-------------------------------------------------------------------------------
|
||||
if ! EXPECT_PASS command arg1 2\> /dev/null; then
|
||||
continue
|
||||
fi
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
tst_kvcmp
|
||||
+++++++++
|
||||
|
||||
This command compares the currently running kernel version given conditions
|
||||
with syntax similar to the shell test command.
|
||||
|
||||
[source,sh]
|
||||
-------------------------------------------------------------------------------
|
||||
# Exit the test if kernel version is older or equal to 2.6.8
|
||||
if tst_kvcmp -le 2.6.8; then
|
||||
tst_brk TCONF "Kernel newer than 2.6.8 is needed"
|
||||
fi
|
||||
|
||||
# Exit the test if kernel is newer than 3.8 and older than 4.0.1
|
||||
if tst_kvcmp -gt 3.8 -a -lt 4.0.1; then
|
||||
tst_brk TCONF "Kernel must be older than 3.8 or newer than 4.0.1"
|
||||
fi
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
[options="header"]
|
||||
|=======================================================================
|
||||
| expression | description
|
||||
| -eq kver | Returns true if kernel version is equal
|
||||
| -ne kver | Returns true if kernel version is not equal
|
||||
| -gt kver | Returns true if kernel version is greater
|
||||
| -ge kver | Returns true if kernel version is greater or equal
|
||||
| -lt kver | Returns true if kernel version is lesser
|
||||
| -le kver | Returns true if kernel version is lesser or equal
|
||||
| -a | Does logical and between two expressions
|
||||
| -o | Does logical or between two expressions
|
||||
|=======================================================================
|
||||
|
||||
The format for kernel version has to either be with one dot e.g. '2.6' or with
|
||||
two dots e.g. '4.8.1'.
|
||||
|
||||
.tst_fs_has_free
|
||||
[source,sh]
|
||||
-------------------------------------------------------------------------------
|
||||
#!/bin/sh
|
||||
|
||||
...
|
||||
|
||||
# whether current directory has 100MB free space at least.
|
||||
if ! tst_fs_has_free . 100MB; then
|
||||
tst_brkm TCONF "Not enough free space"
|
||||
fi
|
||||
|
||||
...
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
The 'tst_fs_has_free' shell interface returns 0 if the specified free space is
|
||||
satisfied, 1 if not, and 2 on error.
|
||||
|
||||
The second argument supports suffixes kB, MB and GB, the default unit is Byte.
|
||||
|
||||
.tst_retry
|
||||
[source,sh]
|
||||
-------------------------------------------------------------------------------
|
||||
#!/bin/sh
|
||||
|
||||
...
|
||||
|
||||
# Retry ping command three times
|
||||
tst_retry "ping -c 1 127.0.0.1"
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
tst_resm TFAIL "Failed to ping 127.0.0.1"
|
||||
else
|
||||
tst_resm TPASS "Successfully pinged 127.0.0.1"
|
||||
fi
|
||||
|
||||
...
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
The 'tst_retry' function allows you to retry a command after waiting small
|
||||
amount of time until it succeeds or until given amount of retries has been
|
||||
reached (default is three attempts).
|
||||
|
||||
1.5 Restarting daemons
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Restarting system daemons is a complicated task for two reasons.
|
||||
|
||||
* There are different init systems
|
||||
(SysV init, systemd, etc...)
|
||||
|
||||
* Daemon names are not unified between distributions
|
||||
(apache vs httpd, cron vs crond, various syslog variations)
|
||||
|
||||
To solve these problems LTP has 'testcases/lib/daemonlib.sh' library that
|
||||
provides functions to start/stop/query daemons as well as variables that store
|
||||
correct daemon name.
|
||||
|
||||
.Supported operations
|
||||
|==============================================================================
|
||||
| start_daemon() | Starts daemon, name is passed as first parameter.
|
||||
| stop_daemon() | Stops daemon, name is passed as first parameter.
|
||||
| restart_daemon() | Restarts daemon, name is passed as first parameter.
|
||||
| status_daemon() | Detect daemon status (exit code: 0: running, 1: not running).
|
||||
|==============================================================================
|
||||
|
||||
.Variables with detected names
|
||||
|==============================================================================
|
||||
| CROND_DAEMON | Cron daemon name (cron, crond).
|
||||
| SYSLOG_DAEMON | Syslog daemon name (syslog, syslog-ng, rsyslog).
|
||||
|==============================================================================
|
||||
|
||||
.Cron daemon restart example
|
||||
[source,sh]
|
||||
-------------------------------------------------------------------------------
|
||||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
# Cron daemon restart example
|
||||
|
||||
TCID=cron01
|
||||
TST_COUNT=1
|
||||
. test.sh
|
||||
. daemonlib.sh
|
||||
|
||||
...
|
||||
|
||||
restart_daemon $CROND_DAEMON
|
||||
|
||||
...
|
||||
|
||||
tst_exit
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
1.6 Access to the checkpoint interface
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The shell library provides an implementation of the checkpoint interface
|
||||
compatible with the C version. All 'TST_CHECKPOINT_*' functions are available.
|
||||
|
||||
In order to initialize checkpoints '$TST_NEEDS_CHECKPOINTS' must be set to '1'
|
||||
before the inclusion of 'tst_test.sh':
|
||||
|
||||
[source,sh]
|
||||
-------------------------------------------------------------------------------
|
||||
#!/bin/sh
|
||||
|
||||
TST_NEEDS_CHECKPOINTS=1
|
||||
. tst_test.sh
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Since both the implementations are compatible, it's also possible to start
|
||||
a child binary process from a shell test and synchronize with it. This process
|
||||
must have checkpoints initialized by calling 'tst_reinit()'.
|
||||
|
||||
1.7 Parsing kernel .config
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
The shell library provides an implementation of the kconfig parsing interface
|
||||
compatible with the C version.
|
||||
|
||||
It's possible to pass kernel kconfig list for tst_require_kconfigs API with
|
||||
'$TST_NEEDS_KCONFIGS'.
|
||||
Optional '$TST_NEEDS_KCONFIGS_IFS' is used for splitting, default value is comma.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
#!/bin/sh
|
||||
TST_NEEDS_KCONFIGS="CONFIG_EXT4_FS, CONFIG_QUOTACTL=y"
|
||||
|
||||
. tst_test.sh
|
||||
-------------------------------------------------------------------------------
|
||||
@@ -1,66 +0,0 @@
|
||||
Supported kernel, libc, toolchain versions
|
||||
==========================================
|
||||
|
||||
1. Build testing with GitHub Actions
|
||||
------------------------------------
|
||||
|
||||
We test master branch in https://github.com/linux-test-project/ltp/actions[GitHub Actions]
|
||||
to ensure LTP builds on various distributions including old, current and bleeding edge.
|
||||
We test both gcc and clang toolchains, various architectures with cross-compilation.
|
||||
For list of tested distros see
|
||||
https://github.com/linux-test-project/ltp/blob/master/.github/workflows/ci.yml[.github/workflows/ci.yml].
|
||||
|
||||
|
||||
NOTE: GitHub Actions does only build testing, passing the CI means only that
|
||||
the test compiles fine on variety of different distributions and releases.
|
||||
GitHub Actions also uses the latest distribution image of a particular release.
|
||||
|
||||
1.1 Oldest tested distributions
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
[align="center",options="header"]
|
||||
|==============================================================
|
||||
| Distro | kernel | glibc | gcc | clang
|
||||
| CentOS 7 | 3.10 | 2.17 | 4.8.5 | -
|
||||
| Ubuntu 16.04 LTS xenial | 4.4 | 2.23 | 5.3.1 | -
|
||||
| Debian 9 stretch (oldstable) | 4.9.30 | 2.24 | 6.3.0 | 3.8
|
||||
|==============================================================
|
||||
|
||||
Older distributions are not officially supported, which means that it
|
||||
may or may not work. It all depends on your luck. It should be possible
|
||||
to compile latest LTP even on slightly older distributions than we
|
||||
support with a few manual tweaks, e.g. disabling manually tests for
|
||||
newly added syscalls, etc. Trivial fixes/workarounds may be accepted,
|
||||
but users are encouraged to move to a newer distro.
|
||||
|
||||
If latest LTP cannot be compiled even with some amount of workarounds,
|
||||
you may result to older LTP releases, however these are _not_ supported
|
||||
in any way. Also if you are trying to run LTP on more than 10 years old
|
||||
distribution you may as well reconsider you life choices.
|
||||
|
||||
1.2 Tested architectures
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
[align="center",options="header"]
|
||||
|==================================
|
||||
| arch | build
|
||||
| x86_64 | native
|
||||
| x86 emulation | native
|
||||
| aarch64 | cross compilation
|
||||
| ppc64le | cross compilation
|
||||
| s390x | cross compilation
|
||||
|==================================
|
||||
|
||||
1.3 Supported libc
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
[align="center",options="header"]
|
||||
|==================================
|
||||
| Libc | Note
|
||||
| https://www.gnu.org/software/libc/[GNU C Library (glibc)] | Targetted libc, tested both compilation and actual test results.
|
||||
| https://uclibc-ng.org/[uClibc-ng] | Although not being tested it should work as well as it attempt to maintain a glibc compatible interface.
|
||||
| https://www.uclibc.org/[uClibc] | Older https://www.uclibc.org/[uClibc] might have problems.
|
||||
| https://musl.libc.org/[musl] | Not yet fully supported (see
|
||||
https://github.com/linux-test-project/ltp/blob/master/ci/alpine.sh[CI script]
|
||||
for list of files which need to be deleted in order to compile under musl).
|
||||
| binder (Android) | Please use https://android.googlesource.com/platform/external/ltp/[AOSP fork].
|
||||
@@ -1,336 +0,0 @@
|
||||
LTP Test Writing Guidelines
|
||||
===========================
|
||||
|
||||
This document describes LTP guidelines and is intended for anybody who want to
|
||||
write or modify a LTP testcase. It's not a definitive guide and it's not, by
|
||||
any means, a substitute for common sense.
|
||||
|
||||
NOTE: See also
|
||||
https://github.com/linux-test-project/ltp/wiki/C-Test-API[C Test API],
|
||||
https://github.com/linux-test-project/ltp/wiki/Shell-Test-API[Shell Test API],
|
||||
https://github.com/linux-test-project/ltp/wiki/LTP-Library-API-Writing-Guidelines[LTP Library API Writing Guidelines].
|
||||
|
||||
Rules and recommendations which are "machine checkable" should be
|
||||
tagged with an ID like +LTP-XXX+. There will be a corresponding entry
|
||||
in
|
||||
https://github.com/linux-test-project/ltp/tree/master/doc/rules.tsv[doc/rules.tsv]. When
|
||||
you run 'make check' or 'make check-test' it will display these IDs as
|
||||
a reference.
|
||||
|
||||
1. Guide to clean and understandable code
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
For testcases it's required that the source code is as easy to follow as
|
||||
possible. When a test starts to fail the failure has to be analyzed, clean
|
||||
test codebase makes this task much easier and quicker.
|
||||
|
||||
Here are some hints on how to write clean and understandable code, a few of
|
||||
these points are further discussed below:
|
||||
|
||||
* First of all *Keep things simple*
|
||||
|
||||
* Keep function and variable names short but descriptive
|
||||
|
||||
* Keep functions reasonably short and focused on a single task
|
||||
|
||||
* Do not overcomment
|
||||
|
||||
* Be consistent
|
||||
|
||||
* Avoid deep nesting
|
||||
|
||||
* DRY
|
||||
|
||||
1.1 Keep things simple
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
For all it's worth keep the testcases simple or better as simple as possible.
|
||||
|
||||
The kernel and libc are tricky beasts and the complexity imposed by their
|
||||
interfaces is quite high. Concentrate on the interface you want to test and
|
||||
follow the UNIX philosophy.
|
||||
|
||||
It's a good idea to make the test as self-contained as possible too, ideally
|
||||
tests should not depend on tools or libraries that are not widely available.
|
||||
|
||||
Do not reinvent the wheel!
|
||||
|
||||
* Use LTP standard interface
|
||||
|
||||
* Do not add custom PASS/FAIL reporting functions
|
||||
|
||||
* Do not write Makefiles from scratch, use LTP build system instead
|
||||
|
||||
* Etc.
|
||||
|
||||
1.2 Keep functions and variable names short
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Choosing a good name for an API functions or even variables is a difficult
|
||||
task do not underestimate it.
|
||||
|
||||
There are a couple of customary names for different things that help people to
|
||||
understand code, for example:
|
||||
|
||||
* For loop variables are usually named with a single letter 'i', 'j', ...
|
||||
|
||||
* File descriptors 'fd' or 'fd_foo'.
|
||||
|
||||
* Number of bytes stored in file are usually named as 'size' or 'len'
|
||||
|
||||
* Etc.
|
||||
|
||||
1.3 Do not overcomment
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Comments can sometimes save you day but they can easily do more harm than
|
||||
good. There has been several cases where comments and actual implementation
|
||||
drifted slowly apart which yielded into API misuses and hard to find bugs.
|
||||
Remember there is only one thing worse than no documentation, wrong
|
||||
documentation.
|
||||
|
||||
Ideally everybody should write code that is obvious, which unfortunately isn't
|
||||
always possible. If there is a code that requires to be commented keep it
|
||||
short and to the point. These comments should explain *why* and not *how*
|
||||
things are done.
|
||||
|
||||
Never ever comment the obvious.
|
||||
|
||||
In case of LTP testcases it's customary to add an asciidoc formatted comment
|
||||
paragraph with highlevel test description at the beginning of the file right
|
||||
under the GPL SPDX header. This helps other people to understand the overall
|
||||
goal of the test before they dive into the technical details. It's also
|
||||
exported into generated documentation hence it should mostly explain what is
|
||||
tested.
|
||||
|
||||
1.4 DRY (Code duplication)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Copy & paste is a good servant but very poor master. If you are about to copy a
|
||||
large part of the code from one testcase to another, think what would happen if
|
||||
you find bug in the code that has been copied all around the tree. What about
|
||||
moving it to a library instead?
|
||||
|
||||
The same goes for short but complicated parts, whenever you are about to copy &
|
||||
paste a syscall wrapper that packs arguments accordingly to machine
|
||||
architecture or similarly complicated code, put it into a header instead.
|
||||
|
||||
2 Coding style
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
2.1 C coding style
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
LTP adopted Linux kernel coding style:
|
||||
https://www.kernel.org/doc/html/latest/process/coding-style.html
|
||||
|
||||
If you aren't familiar with its rules please read it, it's a well written
|
||||
introduction.
|
||||
|
||||
Run `make check` in the test's directory and/or use `make check-$TCID`,
|
||||
it uses (among other checks) our vendored version of
|
||||
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/scripts/checkpatch.pl[checkpatch.pl]
|
||||
script from kernel git tree.
|
||||
|
||||
NOTE: If `make check` does not report any problems, the code still may be wrong
|
||||
as all tools used for checking only look for common mistakes.
|
||||
|
||||
2.1.1 LTP-004: Test executable symbols are marked static
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Test executables should not export symbols unnecessarily. This means
|
||||
that all top-level variables and functions should be marked with the
|
||||
static keyword. The only visible symbols should be those included from
|
||||
shared object files.
|
||||
|
||||
2.2 Shell coding style
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
When writing testcases in shell write in *portable shell* only, it's a good
|
||||
idea to try to run the test using alternative shell (alternative to bash, for
|
||||
example dash) too.
|
||||
|
||||
*Portable shell* means Shell Command Language as defined by POSIX with a
|
||||
exception of few widely used extensions, namely 'local' keyword used inside of
|
||||
functions and '-o' and '-a' test parameters (that are marked as obsolete in
|
||||
POSIX).
|
||||
|
||||
You can either try to run the testcases on Debian which has '/bin/sh' pointing
|
||||
to 'dash' by default or install 'dash' on your favorite distribution and use
|
||||
it to run the tests. If your distribution lacks 'dash' package you can always
|
||||
compile it from http://gondor.apana.org.au/~herbert/dash/files/[source].
|
||||
|
||||
Run `make check` in the test's directory and/or use `make check-$TCID.sh`,
|
||||
it uses (among other checks) our vendored version of
|
||||
https://salsa.debian.org/debian/devscripts/raw/master/scripts/checkbashisms.pl[checkbashism.pl]
|
||||
from Debian, that is used to check for non-portable shell code.
|
||||
|
||||
NOTE: If `make check` does not report any problems, the code still may be wrong
|
||||
as `checkbashisms.pl` used for checking only looks for common mistakes.
|
||||
|
||||
Here are some common sense style rules for shell
|
||||
|
||||
* Keep lines under 80 chars
|
||||
|
||||
* Use tabs for indentation
|
||||
|
||||
* Keep things simple, avoid unnecessary subshells
|
||||
|
||||
* Don't do confusing things (i.e. don't name your functions like common shell
|
||||
commands, etc.)
|
||||
|
||||
* Quote variables
|
||||
|
||||
* Be consistent
|
||||
|
||||
3 Backwards compatibility
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
LTP test should be as backward compatible as possible. Think of an enterprise
|
||||
distributions with long term support (more than five years since the initial
|
||||
release) or of an embedded platform that needs to use several years old
|
||||
toolchain supplied by the manufacturer.
|
||||
|
||||
Therefore LTP test for more current features should be able to cope with older
|
||||
systems. It should at least compile fine and if it's not appropriate for the
|
||||
configuration it should return 'TCONF'.
|
||||
|
||||
There are several types of checks we use:
|
||||
|
||||
The *configure script* is usually used to detect availability of a function
|
||||
declarations in system headers. It's used to disable tests at compile time or
|
||||
to enable fallback definitions.
|
||||
|
||||
Checking the *errno* value is another type of runtime check. Most of the
|
||||
syscalls returns either 'EINVAL' or 'ENOSYS' when syscall was not implemented
|
||||
or was disabled upon kernel compilation.
|
||||
|
||||
LTP has kernel version detection that can be used to disable tests at runtime,
|
||||
unfortunately kernel version does not always corresponds to a well defined
|
||||
feature set as distributions tend to backport hundreds of patches while the
|
||||
kernel version stays the same. Use with caution.
|
||||
|
||||
Lately we added kernel '.config' parser, a test can define a boolean
|
||||
expression of kernel config variables that has to be satisfied in order for a
|
||||
test to run. This is mostly used for kernel namespaces at the moment.
|
||||
|
||||
Sometimes it also makes sense to define a few macros instead of creating
|
||||
configure test. One example are Linux specific POSIX clock ids in
|
||||
'include/lapi/posix_clocks.h'.
|
||||
|
||||
3.1 Dealing with messed up legacy code
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
LTP still contains a lot of old and messy code and we are cleaning it up as
|
||||
fast as we can but despite the decade of efforts there is still a lot. If you
|
||||
start modifying old or a messy testcase and your changes are more complicated
|
||||
than simple typo fixes you should convert the test into a new library first.
|
||||
|
||||
It's also much easier to review the changes if you split them into a smaller
|
||||
logical groups. The same goes for moving files. If you need a rename or move
|
||||
file do it in a separate patch.
|
||||
|
||||
4 License
|
||||
~~~~~~~~~
|
||||
|
||||
Code contributed to LTP should be licensed under GPLv2+ (GNU GPL version 2 or
|
||||
any later version).
|
||||
|
||||
Use `SPDX-License-Identifier: GPL-2.0-or-later`
|
||||
|
||||
5 LTP Structure
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
The structure of LTP is quite simple. Each test is a binary written either in
|
||||
portable shell or C. The test gets a configuration via environment variables
|
||||
and/or command line parameters, it prints additional information into the
|
||||
stdout and reports overall success/failure via the exit value.
|
||||
|
||||
Tests are generally placed under the 'testcases/' directory. Everything that
|
||||
is a syscall or (slightly confusingly) libc syscall wrapper goes under
|
||||
'testcases/kernel/syscalls/'.
|
||||
|
||||
Then there is 'testcases/open_posix_testsuite/' which is a well maintained fork
|
||||
of the upstream project that has been dead since 2005 and also a number of
|
||||
directories with tests for more specific features.
|
||||
|
||||
5.1 Runtest Files
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
The list of tests to be executed is stored in runtest files under the
|
||||
'runtest/' directory. The default set of runtest files to be executed is
|
||||
stored in 'scenario_groups/default'. When you add a test you should add
|
||||
corresponding entries into some runtest file(s) as well.
|
||||
|
||||
For syscall tests (these placed under 'testcases/kernel/syscalls/') use
|
||||
'runtest/syscalls' file, for kernel related tests for memory management we
|
||||
have 'runtest/mm', etc.
|
||||
|
||||
IMPORTANT: The runtest files should have one entry per a test. Creating a
|
||||
wrapper that runs all your tests and adding it as a single test
|
||||
into runtest file is strongly discouraged.
|
||||
|
||||
5.2 Datafiles
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
If your test needs datafiles to work, these should be put into a subdirectory
|
||||
named 'datafiles' and installed into the 'testcases/data/$TCID' directory (to
|
||||
do that you have to add 'INSTALL_DIR := testcases/data/TCID' into the
|
||||
'datafiles/Makefile').
|
||||
|
||||
You can obtain path to datafiles via $TST_DATAROOT provided by test.sh
|
||||
'$TST_DATAROOT/...'
|
||||
or via C function 'tst_dataroot()' provided by libltp:
|
||||
|
||||
[source,c]
|
||||
-------------------------------------------------------------------------------
|
||||
const char *dataroot = tst_dataroot();
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Datafiles can also be accessed as '$LTPROOT/testcases/data/$TCID/...',
|
||||
but '$TST_DATAROOT' and 'tst_dataroot()' are preferred as these can be used
|
||||
when running testcases directly in git tree as well as from install
|
||||
location.
|
||||
|
||||
The path is constructed according to these rules:
|
||||
|
||||
1. if '$LTPROOT' is set, return '$LTPROOT/testcases/data/$TCID'
|
||||
2. else if 'tst_tmpdir()' was called return '$STARTWD/datafiles'
|
||||
(where '$STARTWD' is initial working directory as recorded by 'tst_tmpdir()')
|
||||
3. else return '$CWD/datafiles'
|
||||
|
||||
See 'testcases/commands/file/' for example.
|
||||
|
||||
5.3 Subexecutables
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If you test needs to execute a binary, place it in the same directory as the
|
||||
testcase and name the file starting with '${test_binary_name}_'. Once the
|
||||
test is executed by the framework, the path to the directory with all LTP
|
||||
binaries is added to the '$PATH' and you can execute it just by its name.
|
||||
|
||||
TIP: If you need to execute such test from the LTP tree, you can add path to
|
||||
current directory to '$PATH' manually with: 'PATH="$PATH:$PWD" ./foo01'.
|
||||
|
||||
6 Test Contribution Checklist
|
||||
------------------------------
|
||||
|
||||
NOTE: See also
|
||||
https://github.com/linux-test-project/ltp/wiki/Maintainer-Patch-Review-Checklist[Maintainer Patch Review Checklist].
|
||||
|
||||
1. Test compiles and runs fine (check with `-i 10` too)
|
||||
2. `make check` does not emit any warnings for the test you are working on
|
||||
(hint: run it in the test's directory and/or use `make check-$TCID`)
|
||||
3. The runtest entries are in place
|
||||
4. Test binaries are added into corresponding '.gitignore' files
|
||||
5. Patches apply over the latest git
|
||||
|
||||
6.1 About .gitignore files
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
There are numerous '.gitignore' files in the LTP tree. Usually there is a
|
||||
'.gitignore' file per a group of tests. The reason for this setup is simple.
|
||||
It's easier to maintain a '.gitignore' file per directory with tests, rather
|
||||
than having single file in the project root directory. This way, we don't have
|
||||
to update all the gitignore files when moving directories, and they get deleted
|
||||
automatically when a directory with tests is removed.
|
||||
@@ -1,41 +0,0 @@
|
||||
LTP User Guidelines
|
||||
===================
|
||||
|
||||
For compiling, installing and running the tests see `README.md`.
|
||||
For running LTP network tests see `testcases/network/README.md`.
|
||||
|
||||
1. Library environment variables
|
||||
--------------------------------
|
||||
|
||||
|==============================================================================
|
||||
| 'KCONFIG_PATH' | The path to the kernel config file, (if not set, it tries
|
||||
the usual paths '/boot/config-RELEASE' or '/proc/config.gz').
|
||||
| 'KCONFIG_SKIP_CHECK' | Skip kernel config check if variable set (not set by default).
|
||||
| 'LTPROOT' | Prefix for installed LTP, the default is '/opt/ltp'.
|
||||
| 'LTP_COLORIZE_OUTPUT' | Force colorized output behaviour. 'y' or '1': always colorize
|
||||
'n' or '0': never colorize.
|
||||
| 'LTP_DEV' | Path to the block device to be used
|
||||
(C: '.needs_device = 1', shell: 'TST_NEEDS_DEVICE=1').
|
||||
| 'LTP_SINGLE_FS_TYPE' | Testing only - specifies filesystem instead all
|
||||
supported (for tests with '.all_filesystems').
|
||||
| 'LTP_DEV_FS_TYPE' | Filesystem used for testing (default: 'ext2').
|
||||
| 'LTP_TIMEOUT_MUL' | Multiply timeout, must be number >= 1 (> 1 is useful for
|
||||
slow machines to avoid unexpected timeout).
|
||||
Variable is also used in shell tests, but ceiled to int.
|
||||
| 'LTP_VIRT_OVERRIDE' | Overrides virtual machine detection in the test
|
||||
library. Setting it to empty string tell the library
|
||||
that system is not a virtual machine. Other possible
|
||||
values are 'kvm', 'xen', 'zvm' and 'microsoft' that
|
||||
describe different types supervisors.
|
||||
| 'PATH' | It's required to addjust path:
|
||||
`PATH="$PATH:$LTPROOT/testcases/bin"`
|
||||
| 'TMPDIR' | Base directory for template directory (C: '.needs_tmpdir = 1'
|
||||
and others, which imply it, shell: 'TST_NEEDS_TMPDIR=1').
|
||||
| 'TST_NO_CLEANUP' | Disable running test cleanup (defined in 'TST_CLEANUP').
|
||||
|==============================================================================
|
||||
|
||||
2. Colorized output
|
||||
-------------------
|
||||
|
||||
By default LTP colorizes it's output unless using pipe or redirect to file.
|
||||
It's possible to force behaviour with 'LTP_COLORIZE_OUTPUT' environment variable.
|
||||
-474
@@ -1,474 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
An LTP [execution and] parsing wrapper.
|
||||
|
||||
Used as a second layer for ease-of-use with users as many developers
|
||||
complain about complexity involved with trying to use LTP in my
|
||||
organization -_-.
|
||||
|
||||
Copyright (C) 2009-2012, Ngie Cooper
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
"""
|
||||
|
||||
|
||||
from optparse import OptionGroup, OptionParser
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
|
||||
class ResultsParseException(Exception):
|
||||
""" Extended class for parsing LTP results. """
|
||||
|
||||
|
||||
def parse_ltp_results(exec_log, output_log, verbose=0):
|
||||
"""Function for parsing LTP results.
|
||||
|
||||
1. The exec log is the log with the results in summary form.
|
||||
|
||||
And now a note from our sponsors about exec logs...
|
||||
|
||||
startup='Thu Oct 1 06:42:07 2009'
|
||||
tag=abort01 stime=1254379327 dur=2 exit=exited stat=0 core=no cu=0 cs=16
|
||||
tag=accept01 stime=1254379329 dur=0 exit=exited stat=0 core=no cu=1 cs=0
|
||||
tag=access01 stime=1254379329 dur=0 exit=exited stat=0 core=no cu=0 cs=0
|
||||
tag=access02 stime=1254379329 dur=0 exit=exited stat=0 core=no cu=0 cs=0
|
||||
tag=access03 stime=1254379329 dur=1 exit=exited stat=0 core=no cu=0 cs=1
|
||||
|
||||
[...]
|
||||
|
||||
a. tag is the test tag name.
|
||||
b. stime is the system time at the start of the exec.
|
||||
c. dur is the total duration of the test.
|
||||
d. exit tells you what the result was. Valid values are:
|
||||
- exited
|
||||
- signaled
|
||||
- stopped
|
||||
- unknown
|
||||
See run_child in pan.c.
|
||||
e. stat is the exit status.
|
||||
f. core answers the question: `did I dump core?'.
|
||||
g. cu is the cutime (cumulative user time).
|
||||
h. cs is the cstime (cumulative system time).
|
||||
|
||||
2. The output log is the log with all of the terse results.
|
||||
3. verbose tells us whether or not we need to include the passed results.
|
||||
"""
|
||||
|
||||
if not os.access(exec_log, os.R_OK):
|
||||
raise ResultsParseException("Exec log - %s - specified doesn't exist"
|
||||
% exec_log)
|
||||
elif 1 < verbose and not os.access(output_log, os.R_OK):
|
||||
# Need the output log for context to the end user.
|
||||
raise ResultsParseException("Output log - %s - specified doesn't exist"
|
||||
% output_log)
|
||||
|
||||
context = None
|
||||
|
||||
failed = []
|
||||
passed = 0
|
||||
|
||||
if 2 <= verbose:
|
||||
passed = []
|
||||
|
||||
target_vals = ('exited', '0', 'no')
|
||||
|
||||
fd = open(exec_log, 'r')
|
||||
|
||||
try:
|
||||
content = fd.read()
|
||||
matches = re.finditer('tag=(?P<tag>\w+).+exit=(?P<exit>\w+) '
|
||||
'stat=(?P<stat>\d+) core=(?P<core>\w+)', content)
|
||||
finally:
|
||||
content = None
|
||||
fd.close()
|
||||
|
||||
if not matches:
|
||||
raise ResultsParseException("No parseable results were found in the "
|
||||
"exec log - `%s'." % exec_log)
|
||||
|
||||
for match in matches:
|
||||
|
||||
if ((match.group('exit'), match.group('stat'), match.group('core')) !=
|
||||
target_vals):
|
||||
failed.append(match.group('tag'))
|
||||
elif 2 <= verbose:
|
||||
passed.append(match.group('tag'))
|
||||
else:
|
||||
passed += 1
|
||||
|
||||
# Save memory on large files because lists can eat up a fair amount of
|
||||
# memory.
|
||||
matches = None
|
||||
|
||||
if 1 <= verbose:
|
||||
|
||||
context = {}
|
||||
|
||||
search_tags = failed[:]
|
||||
|
||||
if 2 <= verbose:
|
||||
search_tags += passed
|
||||
|
||||
search_tags.sort()
|
||||
|
||||
fd = open(output_log, 'r')
|
||||
|
||||
try:
|
||||
|
||||
line_iterator = getattr(fd, 'xreadlines', getattr(fd, 'readlines'))
|
||||
|
||||
end_output = '<<<execution_status>>>'
|
||||
output_start = '<<<test_output>>>'
|
||||
|
||||
tag_re = re.compile('tag=(\w+)')
|
||||
|
||||
grab_output = False
|
||||
|
||||
local_context = ''
|
||||
|
||||
search_tag = None
|
||||
|
||||
try:
|
||||
|
||||
while True:
|
||||
|
||||
line = next(line_iterator)
|
||||
|
||||
if line.startswith(end_output):
|
||||
|
||||
if search_tag:
|
||||
context[search_tag] = local_context
|
||||
|
||||
grab_output = False
|
||||
local_context = ''
|
||||
search_tag = None
|
||||
|
||||
if not search_tag:
|
||||
|
||||
while True:
|
||||
|
||||
line = next(line_iterator)
|
||||
|
||||
match = tag_re.match(line)
|
||||
|
||||
if match and match.group(1) in search_tags:
|
||||
search_tag = match.group(1)
|
||||
break
|
||||
|
||||
elif line.startswith(output_start):
|
||||
grab_output = True
|
||||
elif grab_output:
|
||||
local_context += line
|
||||
|
||||
except StopIteration:
|
||||
pass
|
||||
|
||||
for k in list(context.keys()):
|
||||
if k not in search_tags:
|
||||
raise ResultsParseException('Leftover token in search '
|
||||
'keys: %s' % k)
|
||||
|
||||
except Exception as exc:
|
||||
# XXX (garrcoop): change from Exception to soft error and print
|
||||
# out warning with logging module.
|
||||
raise ResultsParseException('Encountered exception reading output '
|
||||
'for context: %s' % str(exc))
|
||||
finally:
|
||||
fd.close()
|
||||
|
||||
return failed, passed, context
|
||||
|
||||
|
||||
def determine_context(output_log, testsuite, test_set, context):
|
||||
"""Return a set of context values mapping test_set -> context."""
|
||||
|
||||
test_set_context = {}
|
||||
|
||||
for test in test_set:
|
||||
|
||||
if test in context:
|
||||
test_context = context[test]
|
||||
del context[test]
|
||||
else:
|
||||
test_context = ('Could not determine context for %s; please see '
|
||||
'output log - %s' % (test, output_log))
|
||||
|
||||
test_set_context['%s : %s' % (testsuite, test)] = test_context
|
||||
|
||||
return test_set_context
|
||||
|
||||
|
||||
def print_context(output_dest, header, testsuite_context):
|
||||
"""Print out testsuite_context to output_dest, heading it up with
|
||||
header.
|
||||
"""
|
||||
|
||||
output_dest.write('\n'.join(['', '=' * 40, header, '-' * 40, '']))
|
||||
|
||||
for test, context in list(testsuite_context.items()):
|
||||
output_dest.write('<output test="%s">\n%s\n</output>\n' %
|
||||
(test, context.strip()))
|
||||
|
||||
|
||||
def main():
|
||||
"""main"""
|
||||
|
||||
parser = OptionParser(prog=os.path.basename(sys.argv[0]),
|
||||
usage='usage: %prog [options] test ...',
|
||||
version='0.0.2')
|
||||
|
||||
ltpdir = os.getenv('LTPROOT', '@prefix@')
|
||||
|
||||
parser.add_option('-l', '--ltp-dir', dest='ltp_dir',
|
||||
default=ltpdir, help='LTP directory [default: %default]')
|
||||
parser.add_option('-L', '--log-dir', dest='log_dir',
|
||||
default=None,
|
||||
help=('directory for [storing and] retrieving logs '
|
||||
'[default: %s/output]' % ltpdir),
|
||||
metavar='DIR')
|
||||
parser.add_option('-p', '--postprocess-only', dest='postprocess_only',
|
||||
default=False, action='store_true',
|
||||
help=("Don't execute runltp; just postprocess logs "
|
||||
"[default: %default]."))
|
||||
parser.add_option('-o', '--output-file', dest='output_file',
|
||||
default=None,
|
||||
help='File to output results')
|
||||
parser.add_option('-r', '--runltp-opts', dest='runltp_opts',
|
||||
default='',
|
||||
help=('options to pass directly to runltp (will '
|
||||
'suppress -q).'))
|
||||
|
||||
group = OptionGroup(parser, 'Logging',
|
||||
'If --summary-mode is 0, then the summary output is '
|
||||
'suppressed. '
|
||||
'If --summary-mode is 1 [the default], then summary '
|
||||
'output will be displayed for test execution'
|
||||
'If --summary-mode is 2, then summary output will be '
|
||||
'provided on a per-test suite basis. If only '
|
||||
'one test suite is specified, this has the same net '
|
||||
"effect as `--summary-mode 1'"
|
||||
'If --verbose is specified once, prints out failed '
|
||||
'test information with additional context. '
|
||||
'If --verbose is specified twice, prints out the '
|
||||
'failed and passed test context, as well as the '
|
||||
'summary.')
|
||||
|
||||
parser.add_option('-s', '--summary-mode', dest='summary_mode', default=1,
|
||||
type='int',
|
||||
help='See Logging.')
|
||||
|
||||
parser.add_option('-v', '--verbose', dest='verbose', default=0,
|
||||
action='count',
|
||||
help=('Increases context verbosity from tests. See '
|
||||
'Verbosity for more details.'))
|
||||
parser.add_option_group(group)
|
||||
|
||||
group = OptionGroup(parser, 'Copyright',
|
||||
'%(prog)s version %(version)s, Copyright (C) '
|
||||
'2009-2012, Ngie Cooper %(prog)s comes with '
|
||||
'ABSOLUTELY NO WARRANTY; '
|
||||
'This is free software, and you are welcome to '
|
||||
'redistribute it under certain conditions (See the '
|
||||
'license tort in %(file)s for more details).'
|
||||
% { 'file' : os.path.abspath(__file__),
|
||||
'prog' : parser.prog,
|
||||
'version' : parser.version })
|
||||
|
||||
parser.add_option_group(group)
|
||||
|
||||
opts, args = parser.parse_args()
|
||||
|
||||
# Remove -q from the opts string, as long as it's a standalone option.
|
||||
runltp_opts = re.sub('^((?<!\S)+\-q\s+|\-q|\s+\-q(?!\S))$', '',
|
||||
opts.runltp_opts)
|
||||
|
||||
if not opts.log_dir:
|
||||
opts.log_dir = os.path.join(opts.ltp_dir, 'output')
|
||||
|
||||
if not opts.summary_mode and not opts.verbose:
|
||||
parser.error('You cannot suppress summary output and disable '
|
||||
'verbosity.')
|
||||
elif opts.summary_mode not in list(range(3)):
|
||||
parser.error('--summary-mode must be a value between 0 and 2.')
|
||||
|
||||
if len(args) == 0:
|
||||
# Default to scenarios also used by runltp.
|
||||
fd = open(os.path.join(ltpdir, 'scenario_groups/default'), 'r')
|
||||
try:
|
||||
args = [l.strip() for l in fd.readlines()]
|
||||
finally:
|
||||
fd.close()
|
||||
|
||||
if opts.output_file:
|
||||
|
||||
output_dir = os.path.dirname(opts.output_file)
|
||||
|
||||
if output_dir:
|
||||
# Not cwd; let's check to make sure that the directory does or
|
||||
# does not exist.
|
||||
|
||||
if not os.path.exists(output_dir):
|
||||
# We need to make the directory.
|
||||
os.makedirs(os.path.dirname(opts.output_file))
|
||||
elif not os.path.isdir(os.path.abspath(output_dir)):
|
||||
# Path exists, but isn't a file. Oops!
|
||||
parser.error('Dirname for path specified - %s - is not valid'
|
||||
% output_dir)
|
||||
|
||||
else:
|
||||
# Current path (cwd)
|
||||
opts.output_file = os.path.join(os.getcwd(), opts.output_file)
|
||||
|
||||
output_dest = open(opts.output_file, 'w')
|
||||
|
||||
else:
|
||||
|
||||
output_dest = sys.stdout
|
||||
|
||||
try:
|
||||
|
||||
failed_context = {}
|
||||
passed_context = {}
|
||||
|
||||
failed_count = 0
|
||||
passed_count = 0
|
||||
|
||||
if opts.summary_mode == 2 and len(args) == 1:
|
||||
opts.summary_mode = 1
|
||||
|
||||
for testsuite in args:
|
||||
|
||||
# Iterate over the provided test list
|
||||
|
||||
context = {}
|
||||
exec_log = os.path.join(opts.log_dir, '%s-exec.log' % testsuite)
|
||||
output_log = os.path.join(opts.log_dir, ('%s-output.log'
|
||||
% testsuite))
|
||||
|
||||
failed_subset = {}
|
||||
|
||||
runtest_file = os.path.join(opts.ltp_dir, 'runtest', testsuite)
|
||||
|
||||
if not opts.postprocess_only:
|
||||
|
||||
for log in [exec_log, output_log]:
|
||||
if os.path.isfile(log):
|
||||
os.remove(log)
|
||||
|
||||
if not os.access(runtest_file, os.R_OK):
|
||||
output_dest.write("%s doesn't exist; skipping "
|
||||
"test\n" % runtest_file)
|
||||
continue
|
||||
|
||||
os.system(' '.join([os.path.join(opts.ltp_dir, 'runltp'),
|
||||
runltp_opts, '-f', testsuite,
|
||||
'-l', exec_log, '-o', output_log]))
|
||||
|
||||
try:
|
||||
|
||||
failed_subset, passed_css, context = \
|
||||
parse_ltp_results(exec_log, output_log,
|
||||
verbose=opts.verbose)
|
||||
|
||||
except ResultsParseException as rpe:
|
||||
output_dest.write('Error encountered when parsing results for '
|
||||
'test - %s: %s\n' % (testsuite, str(rpe)))
|
||||
continue
|
||||
|
||||
failed_count += len(failed_subset)
|
||||
|
||||
failed_subset_context = {}
|
||||
passed_subset_context = {}
|
||||
|
||||
if opts.verbose:
|
||||
failed_subset_context = determine_context(output_log,
|
||||
testsuite,
|
||||
failed_subset,
|
||||
context)
|
||||
if type(passed_css) == list:
|
||||
|
||||
passed_count += len(passed_css)
|
||||
|
||||
if opts.verbose == 2:
|
||||
passed_subset_context = determine_context(output_log,
|
||||
testsuite,
|
||||
passed_css,
|
||||
context)
|
||||
|
||||
else:
|
||||
|
||||
passed_count += passed_css
|
||||
|
||||
if opts.summary_mode == 1:
|
||||
|
||||
failed_context.update(failed_subset_context)
|
||||
passed_context.update(passed_subset_context)
|
||||
|
||||
else:
|
||||
|
||||
if 1 <= opts.verbose:
|
||||
# Print out failed testcases.
|
||||
print_context(output_dest,
|
||||
'FAILED TESTCASES for %s' % testsuite,
|
||||
failed_subset_context)
|
||||
|
||||
if opts.verbose == 2:
|
||||
# Print out passed testcases with context.
|
||||
print_context(output_dest,
|
||||
'PASSED TESTCASES for %s' % testsuite,
|
||||
passed_subset_context)
|
||||
|
||||
if opts.summary_mode == 2:
|
||||
output_dest.write("""
|
||||
========================================
|
||||
SUMMARY for: %s
|
||||
----------------------------------------
|
||||
PASS - %d
|
||||
FAIL - %d
|
||||
----------------------------------------
|
||||
""" % (testsuite, passed_count, len(failed_subset)))
|
||||
|
||||
if opts.summary_mode == 1:
|
||||
|
||||
# Print out overall results.
|
||||
|
||||
if 1 <= opts.verbose:
|
||||
# Print out failed testcases with context.
|
||||
print_context(output_dest, "FAILED TESTCASES", failed_context)
|
||||
|
||||
if opts.verbose == 2:
|
||||
# Print out passed testcases with context.
|
||||
print_context(output_dest, "PASSED TESTCASES", passed_context)
|
||||
|
||||
output_dest.write("""
|
||||
========================================
|
||||
SUMMARY for tests:
|
||||
%s
|
||||
----------------------------------------
|
||||
PASS - %d
|
||||
FAIL - %d
|
||||
----------------------------------------
|
||||
""" % (' '.join(args), passed_count, failed_count))
|
||||
|
||||
finally:
|
||||
|
||||
if output_dest != sys.stdout:
|
||||
|
||||
output_dest.close()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) International Business Machines Corp., 2001
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
|
||||
* the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* ipcshm.h - common definitions for the IPC shared memory tests
|
||||
*/
|
||||
|
||||
#ifndef __IPCSHM_H
|
||||
#define __IPCSHM_H
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
|
||||
#include "test.h"
|
||||
|
||||
void cleanup(void);
|
||||
void setup(void);
|
||||
|
||||
#define SHM_RD 0400
|
||||
#define SHM_WR 0200
|
||||
#define SHM_RW SHM_RD | SHM_WR
|
||||
|
||||
#define SHM_SIZE 2048 /* a resonable size for a memory segment */
|
||||
#define INT_SIZE 4 /* instead of sizeof(int) */
|
||||
|
||||
#define MODE_MASK 0x01FF /* to get the lower nine permission bits */
|
||||
/* from shmid_ds.ipc_perm.mode */
|
||||
|
||||
key_t shmkey; /* an IPC key generated by ftok() */
|
||||
|
||||
void rm_shm(int shm_id);
|
||||
|
||||
int getipckey();
|
||||
int getuserid(char*);
|
||||
|
||||
#endif /* ipcshm.h */
|
||||
@@ -1,56 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (c) 2020 Linaro Limited. All rights reserved.
|
||||
* Author: Viresh Kumar <viresh.kumar@linaro.org>
|
||||
*/
|
||||
|
||||
#ifndef LAPI_CLONE_H__
|
||||
#define LAPI_CLONE_H__
|
||||
|
||||
#include <sys/syscall.h>
|
||||
#include <linux/types.h>
|
||||
#include <sched.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "lapi/syscalls.h"
|
||||
|
||||
#ifndef HAVE_CLONE3
|
||||
struct clone_args {
|
||||
uint64_t __attribute__((aligned(8))) flags;
|
||||
uint64_t __attribute__((aligned(8))) pidfd;
|
||||
uint64_t __attribute__((aligned(8))) child_tid;
|
||||
uint64_t __attribute__((aligned(8))) parent_tid;
|
||||
uint64_t __attribute__((aligned(8))) exit_signal;
|
||||
uint64_t __attribute__((aligned(8))) stack;
|
||||
uint64_t __attribute__((aligned(8))) stack_size;
|
||||
uint64_t __attribute__((aligned(8))) tls;
|
||||
};
|
||||
|
||||
static inline int clone3(struct clone_args *args, size_t size)
|
||||
{
|
||||
return tst_syscall(__NR_clone3, args, size);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef CLONE_PIDFD
|
||||
#define CLONE_PIDFD 0x00001000 /* set if a pidfd should be placed in parent */
|
||||
#endif
|
||||
|
||||
#ifndef CLONE_NEWUSER
|
||||
# define CLONE_NEWUSER 0x10000000
|
||||
#endif
|
||||
|
||||
static inline void clone3_supported_by_kernel(void)
|
||||
{
|
||||
long ret;
|
||||
|
||||
if ((tst_kvercmp(5, 3, 0)) < 0) {
|
||||
/* Check if the syscall is backported on an older kernel */
|
||||
ret = syscall(__NR_clone3, NULL, 0);
|
||||
if (ret == -1 && errno == ENOSYS)
|
||||
tst_brk(TCONF, "Test not supported on kernel version < v5.3");
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* LAPI_CLONE_H__ */
|
||||
@@ -1,31 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (c) 2015 Red Hat, Inc.
|
||||
*/
|
||||
|
||||
#ifndef LAPI_NAMESPACES_CONSTANTS_H__
|
||||
#define LAPI_NAMESPACES_CONSTANTS_H__
|
||||
|
||||
#ifndef CLONE_NEWIPC
|
||||
# define CLONE_NEWIPC 0x08000000
|
||||
#endif
|
||||
#ifndef CLONE_NEWNS
|
||||
# define CLONE_NEWNS 0x00020000
|
||||
#endif
|
||||
#ifndef CLONE_NEWNET
|
||||
# define CLONE_NEWNET 0x40000000
|
||||
#endif
|
||||
#ifndef CLONE_NEWPID
|
||||
# define CLONE_NEWPID 0x20000000
|
||||
#endif
|
||||
#ifndef CLONE_NEWUSER
|
||||
# define CLONE_NEWUSER 0x10000000
|
||||
#endif
|
||||
#ifndef CLONE_NEWUTS
|
||||
# define CLONE_NEWUTS 0x04000000
|
||||
#endif
|
||||
#ifndef CLONE_NEWTIME
|
||||
# define CLONE_NEWTIME 0x00000080
|
||||
#endif
|
||||
|
||||
#endif /* LAPI_NAMESPACES_CONSTANTS_H__ */
|
||||
@@ -1,24 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (c) 2020 Linaro Limited. All rights reserved.
|
||||
* Author: Viresh Kumar <viresh.kumar@linaro.org>
|
||||
*/
|
||||
|
||||
#ifndef LAPI_PIDFD_OPEN_H__
|
||||
#define LAPI_PIDFD_OPEN_H__
|
||||
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "lapi/syscalls.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef HAVE_PIDFD_OPEN
|
||||
static inline int pidfd_open(pid_t pid, unsigned int flags)
|
||||
{
|
||||
return tst_syscall(__NR_pidfd_open, pid, flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LAPI_PIDFD_OPEN_H__ */
|
||||
@@ -1,27 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (c) 2019 SUSE LLC
|
||||
* Author: Christian Amann <camann@suse.com>
|
||||
*/
|
||||
|
||||
#ifndef LAPI_PIDFD_SEND_SIGNAL_H__
|
||||
#define LAPI_PIDFD_SEND_SIGNAL_H__
|
||||
|
||||
#include "tst_test.h"
|
||||
#include "lapi/syscalls.h"
|
||||
|
||||
static inline void pidfd_send_signal_supported(void)
|
||||
{
|
||||
/* allow the tests to fail early */
|
||||
tst_syscall(__NR_pidfd_send_signal);
|
||||
}
|
||||
|
||||
#ifndef HAVE_PIDFD_SEND_SIGNAL
|
||||
static inline int pidfd_send_signal(int pidfd, int sig, siginfo_t *info,
|
||||
unsigned int flags)
|
||||
{
|
||||
return tst_syscall(__NR_pidfd_send_signal, pidfd, sig, info, flags);
|
||||
}
|
||||
#endif /* HAVE_PIDFD_SEND_SIGNAL */
|
||||
|
||||
#endif /* LAPI_PIDFD_SEND_SIGNAL_H__ */
|
||||
@@ -1,22 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (c) 2016 Linux Test Project
|
||||
*/
|
||||
|
||||
/*
|
||||
* Test for watchdog timeout.
|
||||
*/
|
||||
|
||||
#include "tst_test.h"
|
||||
|
||||
|
||||
static void do_test(void)
|
||||
{
|
||||
sleep(2);
|
||||
tst_res(TPASS, "Not reached");
|
||||
}
|
||||
|
||||
static struct tst_test test = {
|
||||
.test_all = do_test,
|
||||
.timeout = 1,
|
||||
};
|
||||
@@ -1,21 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (c) 2016 Linux Test Project
|
||||
*/
|
||||
|
||||
/*
|
||||
* Test for timeout override.
|
||||
*/
|
||||
|
||||
#include "tst_test.h"
|
||||
|
||||
static void do_test(void)
|
||||
{
|
||||
sleep(1);
|
||||
tst_res(TPASS, "Passed!");
|
||||
}
|
||||
|
||||
static struct tst_test test = {
|
||||
.timeout = 2,
|
||||
.test_all = do_test,
|
||||
};
|
||||
@@ -1,22 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (c) 2018, Linux Test Project
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include "tst_test.h"
|
||||
|
||||
static void run(void)
|
||||
{
|
||||
do {
|
||||
sleep(1);
|
||||
} while (tst_timeout_remaining() >= 4);
|
||||
|
||||
tst_res(TPASS, "Timeout remaining: %d", tst_timeout_remaining());
|
||||
}
|
||||
|
||||
static struct tst_test test = {
|
||||
.test_all = run,
|
||||
.timeout = 5
|
||||
};
|
||||
@@ -1,17 +0,0 @@
|
||||
dnl SPDX-License-Identifier: GPL-2.0-or-later
|
||||
dnl Copyright (c) Linux Test Project, 2014
|
||||
|
||||
AC_DEFUN([LTP_CHECK_CLONE_SUPPORTS_7_ARGS],[
|
||||
AH_TEMPLATE(CLONE_SUPPORTS_7_ARGS,
|
||||
[Define to 1 if clone() supports 7 arguments.])
|
||||
AC_MSG_CHECKING([if clone() supports 7 args])
|
||||
AC_TRY_LINK([#define _GNU_SOURCE
|
||||
#include <sched.h>
|
||||
#include <stdlib.h>],
|
||||
[
|
||||
#ifndef __ia64__
|
||||
clone(NULL, NULL, 0, NULL, NULL, NULL, NULL);
|
||||
#endif
|
||||
],
|
||||
AC_DEFINE(CLONE_SUPPORTS_7_ARGS) AC_MSG_RESULT(yes), AC_MSG_RESULT(no))
|
||||
])
|
||||
@@ -1,12 +0,0 @@
|
||||
dnl SPDX-License-Identifier: GPL-2.0-or-later
|
||||
dnl Copyright (c) Linux Test Project, 2012
|
||||
dnl Author: Cyril Hrubis <chrubis@suse.cz>
|
||||
|
||||
AC_DEFUN([LTP_CHECK_MREMAP_FIXED],[
|
||||
AH_TEMPLATE(HAVE_MREMAP_FIXED,
|
||||
[Define to 1 if you have MREMAP_FIXED in <sys/mman.h>.])
|
||||
AC_MSG_CHECKING([for MREMAP_FIXED in <sys/mman.h>])
|
||||
AC_TRY_COMPILE([#define _GNU_SOURCE
|
||||
#include <sys/mman.h>], [int flags = MREMAP_FIXED;],
|
||||
AC_DEFINE(HAVE_MREMAP_FIXED) AC_MSG_RESULT(yes), AC_MSG_RESULT(no))
|
||||
])
|
||||
@@ -1,16 +0,0 @@
|
||||
dnl SPDX-License-Identifier: GPL-2.0-or-later
|
||||
dnl Copyright (c) 2014 Fujitsu Ltd.
|
||||
dnl Copyright (c) 2014 Cyril Hrubis <chrubis@suse.cz>
|
||||
dnl Author: Xiaoguang Wang <wangxg.fnst@cn.fujitsu.com>
|
||||
|
||||
AC_DEFUN([LTP_CHECK_SYSCALL_PERF_EVENT_OPEN],[
|
||||
AH_TEMPLATE(HAVE_PERF_EVENT_ATTR,
|
||||
[Define to 1 if you have struct perf_event_attr])
|
||||
AC_MSG_CHECKING([for perf_event_attr in linux/perf_event.h])
|
||||
AC_TRY_COMPILE([#include <unistd.h>
|
||||
#include <linux/perf_event.h>],
|
||||
[
|
||||
struct perf_event_attr pe;
|
||||
],
|
||||
AC_DEFINE(HAVE_PERF_EVENT_ATTR) AC_MSG_RESULT(yes), AC_MSG_RESULT(no))
|
||||
])
|
||||
-84
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it would be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* Further, this software is distributed without any warranty that it is
|
||||
* free of the rightful claim of any third person regarding infringement
|
||||
* or the like. Any license provided herein, whether implied or
|
||||
* otherwise, applies only to this software file. Patent licenses, if
|
||||
* any, provided herein do not apply to combinations of this program with
|
||||
* other software, or any other product whatsoever.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
|
||||
* Mountain View, CA 94043, or:
|
||||
*
|
||||
* http://www.sgi.com
|
||||
*
|
||||
* For further information regarding this notice, see:
|
||||
*
|
||||
* http://oss.sgi.com/projects/GenInfo/NoticeExplan/
|
||||
*
|
||||
*/
|
||||
/* $Id: debug.c,v 1.1 2000/09/21 21:35:06 alaffin Exp $ */
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "reporter.h"
|
||||
|
||||
#ifdef DEBUGGING
|
||||
int Debug[MAXDEBUG]; /* Debug level in their areas */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* set debug areas & levels
|
||||
*
|
||||
* Syntax: area[,area]:level[,area[,area]:level]...
|
||||
*/
|
||||
int set_debug(char *optarg)
|
||||
{
|
||||
#ifdef DEBUGGING
|
||||
/* pointers to the debug area and level in the option's arguments */
|
||||
char *d_area, *d_level;
|
||||
/* debug area and level after converted to integers */
|
||||
int db_area, db_level;
|
||||
|
||||
d_area = optarg;
|
||||
|
||||
while (*d_area) {
|
||||
d_level = strchr(d_area, ':');
|
||||
*d_level++ = '\0';
|
||||
db_level = atoi(d_level);
|
||||
db_area = atoi(d_area);
|
||||
|
||||
if (db_area > MAXDEBUG) {
|
||||
printf("Error - Debug area %s > maximum of %d\n",
|
||||
d_area, MAXDEBUG);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
while (d_area != NULL) {
|
||||
db_area = atoi(d_area);
|
||||
printf("Debug area %d set to %d\n", db_area, db_level);
|
||||
Debug[db_area] = db_level;
|
||||
if ((d_area = strchr(d_area, ',')) != NULL)
|
||||
d_area++;
|
||||
}
|
||||
if ((d_area = strchr(d_level, ',')) == NULL)
|
||||
break;
|
||||
}
|
||||
#else
|
||||
printf("Debugging is not enabled. -D has been ignored\n");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
-67
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it would be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* Further, this software is distributed without any warranty that it is
|
||||
* free of the rightful claim of any third person regarding infringement
|
||||
* or the like. Any license provided herein, whether implied or
|
||||
* otherwise, applies only to this software file. Patent licenses, if
|
||||
* any, provided herein do not apply to combinations of this program with
|
||||
* other software, or any other product whatsoever.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
|
||||
* Mountain View, CA 94043, or:
|
||||
*
|
||||
* http://www.sgi.com
|
||||
*
|
||||
* For further information regarding this notice, see:
|
||||
*
|
||||
* http://oss.sgi.com/projects/GenInfo/NoticeExplan/
|
||||
*
|
||||
*/
|
||||
/* $Id: debug.h,v 1.1 2000/09/21 21:35:06 alaffin Exp $ */
|
||||
#ifndef _DEBUG_H_
|
||||
#define _DEBUG_H_
|
||||
|
||||
int set_debug( char * );
|
||||
|
||||
/*
|
||||
* DEBUG support
|
||||
*
|
||||
* use -DDEBUGGING with cc to enable debugging
|
||||
*/
|
||||
#ifdef DEBUGGING
|
||||
|
||||
extern int Debug[];
|
||||
#define MAXDEBUG 30
|
||||
#define DEBUG(a,l) if (Debug[a] >= l)
|
||||
#define DEBUGO(a,l,c) if (Debug[a] >= l || c)
|
||||
|
||||
#else
|
||||
|
||||
#define DEBUG(a,l) if (0)
|
||||
#define DEBUGO(a,l,c) if (0)
|
||||
|
||||
#endif
|
||||
|
||||
#define D_INIT 1
|
||||
#define D_SCAN 2
|
||||
#define D_SCAN_LEX 3
|
||||
#define D_SCAN_CUTS 4
|
||||
#define D_REPORT 5
|
||||
#define D_REP_H 6
|
||||
#define D_REP_CUTS 7
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,175 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it would be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* Further, this software is distributed without any warranty that it is
|
||||
* free of the rightful claim of any third person regarding infringement
|
||||
* or the like. Any license provided herein, whether implied or
|
||||
* otherwise, applies only to this software file. Patent licenses, if
|
||||
* any, provided herein do not apply to combinations of this program with
|
||||
* other software, or any other product whatsoever.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
|
||||
* Mountain View, CA 94043, or:
|
||||
*
|
||||
* http://www.sgi.com
|
||||
*
|
||||
* For further information regarding this notice, see:
|
||||
*
|
||||
* http://oss.sgi.com/projects/GenInfo/NoticeExplan/
|
||||
*
|
||||
*/
|
||||
/* $Id: ltp-scanner.c,v 1.1 2009/05/19 09:39:11 subrata_modak Exp $ */
|
||||
/*
|
||||
* An RTS/pan driver output processing program.
|
||||
*
|
||||
* This program reads an RTS/pan driver output format file, parses it using lex
|
||||
* and saves the information into an in-memory hierarchical keyword table.
|
||||
*
|
||||
* The reporting segment of the program reads that keyword table to produce
|
||||
* it's reports.
|
||||
*
|
||||
* Synopsis:
|
||||
* ltp-scanner [ -e ] [ -D area:level ] [ -h ]
|
||||
*
|
||||
* Description:
|
||||
* Scanner is part of the RTS 2.0 reporting mechanism or pan.
|
||||
* It processes RTS/pan driver format output and produces a single simple report
|
||||
* of each test tag executed, the TCIDs it executed, and their testcases.
|
||||
*
|
||||
* Options:
|
||||
* -e
|
||||
* use an "extended" output format
|
||||
*
|
||||
* -D
|
||||
* enable debug statements. Areas are listed in report2.h and levels
|
||||
* are in the code. Must be compiled with "-DDEBUGGING"
|
||||
*
|
||||
* -h
|
||||
* print out a command usage statement and exit.
|
||||
*
|
||||
* INPUT
|
||||
* The input must conform to the RTS/pan driver format.
|
||||
*
|
||||
* Report Format
|
||||
* A single report style is used. It consists of a header made of all
|
||||
* keywords in the rts_keywords fields of the driver output, and the test
|
||||
* information.
|
||||
* interpretation of CUTS "number of testcases" field when there are
|
||||
* multiple TCIDs. It must be the sum of all TCIDs' testcases.
|
||||
*
|
||||
* System Configuration:
|
||||
* ARCHITECTURE IOS_MODEL_E CRAY_YMP YMP7XX
|
||||
* CONFIG JOBCNTL AVL BMD EMA HPM SECURE TFM_UDB_6 SDS SSD
|
||||
* RELEASE 82
|
||||
* UNAME sn1703c cool 8.2.0ae d82.25
|
||||
* date 03/24/94
|
||||
*
|
||||
* tag tcid testcase status contact
|
||||
* ------------------------------------------------------------------------
|
||||
*
|
||||
* When a report is made for only a tag, the TCID and Testcase fields
|
||||
* contain a dash ( "-" ). The intention is that the output be usable
|
||||
* by other Unix programs.
|
||||
*
|
||||
* When a report is made for all TCIDs and Testcases, a star ( "*" ) is used.
|
||||
*
|
||||
* When in extended mode, an additional output line is produced for each
|
||||
* tag.
|
||||
*
|
||||
* This line is identified with a "!" in the TCID and Testcase fields.
|
||||
*
|
||||
* It has no minimum and maximum field widths, so the output does not
|
||||
* line up in columns
|
||||
*
|
||||
* the "status" field contains the initiation status
|
||||
*
|
||||
* the "contact" field does not expand multiple comma-separated contacts
|
||||
*
|
||||
* fields:
|
||||
* tag, tcid, testcase, status, contact,
|
||||
* start time, duration, termination type, termination id,
|
||||
* output starting line, output ending line
|
||||
*
|
||||
* RELATED DOCUMENTS
|
||||
* Regression Test System Phase 2 Test Result Reporting System
|
||||
*
|
||||
* AUTHOR
|
||||
* Glen Overby wrote the code.
|
||||
*
|
||||
* Internal Data Format
|
||||
* All data is maintained in a hierarchical key database. While there are
|
||||
* many available databases, this impliments a simple ASCII comma-separated
|
||||
* keyed database.
|
||||
*
|
||||
* Key Naming
|
||||
* - The top-level keys are named after the RTS or pan test tags.
|
||||
* - The top-level key named "_RTS" contains the RTS Keywords
|
||||
* - Each tag has a "_keys" tag that contains the key fields from
|
||||
* the TEST_START and EXECUTION_STATUS fields.
|
||||
*/
|
||||
|
||||
#include <getopt.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "scan.h"
|
||||
#include "debug.h"
|
||||
#include "reporter.h"
|
||||
#include "symbol.h"
|
||||
|
||||
char *cnf; /* current filename */
|
||||
int extended = 0; /* -e option */
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
SYM tags; /* tag data */
|
||||
int c;
|
||||
|
||||
while ((c = getopt(argc, argv, "D:ehi")) != -1) {
|
||||
switch (c) {
|
||||
case 'i':
|
||||
set_iscanner();
|
||||
break;
|
||||
case 'D':
|
||||
set_debug(optarg);
|
||||
break;
|
||||
case 'e':
|
||||
extended++;
|
||||
break;
|
||||
case 'h':
|
||||
fprintf(stderr,
|
||||
"%s [-e] [-i] [ -D area, level ] input-filenames\n",
|
||||
argv[0]);
|
||||
exit(0);
|
||||
default:
|
||||
fprintf(stderr, "invalid argument, %c\n", c);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
lex_files(&argv[optind]); /* I hope that argv[argc+1] == NULL */
|
||||
tags = sym_open(0, 0, 0);
|
||||
|
||||
scanner(tags);
|
||||
#ifdef DEBUGGING
|
||||
DEBUG(D_INIT, 1)
|
||||
sym_dump_s(tags, 0);
|
||||
#endif
|
||||
reporter(tags);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
-270
@@ -1,270 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it would be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* Further, this software is distributed without any warranty that it is
|
||||
* free of the rightful claim of any third person regarding infringement
|
||||
* or the like. Any license provided herein, whether implied or
|
||||
* otherwise, applies only to this software file. Patent licenses, if
|
||||
* any, provided herein do not apply to combinations of this program with
|
||||
* other software, or any other product whatsoever.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
|
||||
* Mountain View, CA 94043, or:
|
||||
*
|
||||
* http://www.sgi.com
|
||||
*
|
||||
* For further information regarding this notice, see:
|
||||
*
|
||||
* http://oss.sgi.com/projects/GenInfo/NoticeExplan/
|
||||
*
|
||||
*/
|
||||
/* $Id: reporter.c,v 1.1 2000/09/21 21:35:06 alaffin Exp $ */
|
||||
/*
|
||||
* This is the report generator half of the scanner program.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include "reporter.h"
|
||||
#include "symbol.h"
|
||||
#include "tag_report.h"
|
||||
#include "splitstr.h"
|
||||
|
||||
/************************************************************************
|
||||
* Report Generation *
|
||||
************************************************************************/
|
||||
|
||||
static int scanner_reporter(SYM);
|
||||
static int iscanner_reporter(SYM);
|
||||
static int scanner_test_end(SYM, SYM, SYM);
|
||||
static int iscanner_test_end(SYM, SYM, SYM);
|
||||
|
||||
static int (*reporter_func) (SYM) = scanner_reporter;
|
||||
static int (*test_end_func) (SYM, SYM, SYM) = scanner_test_end;
|
||||
|
||||
/*
|
||||
* Do the report generation.
|
||||
*
|
||||
* A problem: I really need multiple cursors. I'd rather not look into
|
||||
* the depths of the current symbol table implimentation (there are the
|
||||
* cursors there that I could use) so that a different (faster!) symbol
|
||||
* table can be used in the future.
|
||||
*
|
||||
* I could get a key (tag), get it's sub-keys (TCIDs), then get the key
|
||||
* again to reset to the top level, _then_ get the next key. That would
|
||||
* be very inefficient.
|
||||
*
|
||||
* The solution I chose is to extract all tags into a list (char array),
|
||||
* then go thru that list with the cursor free for other levels to use.
|
||||
*
|
||||
* (1) make a list (2d char array) of all Tags
|
||||
* (2) search for the first tag that has a "stime" record, and use that as
|
||||
* the date (MMDDYY) that the tests were run.
|
||||
* (3) print the report header
|
||||
* (4) go thru all tags and report each as described at the beginning of
|
||||
* this file
|
||||
*/
|
||||
static int scanner_reporter(SYM tags)
|
||||
{
|
||||
DBT Key, Data;
|
||||
SYM Tag, Keys;
|
||||
|
||||
time_t clock;
|
||||
struct tm *tm;
|
||||
|
||||
/* a list of tags, a count of the number of tags allocated to the list,
|
||||
and a pointer to go thru the list */
|
||||
char **taglist, **tl;
|
||||
int ntags;
|
||||
int tagcount; /* how many tags used */
|
||||
|
||||
char key_get[KEYSIZE];
|
||||
char *info;
|
||||
|
||||
/*
|
||||
* extract tag names from data
|
||||
*/
|
||||
ntags = NTAGS_START;
|
||||
taglist = malloc(sizeof(char *) * ntags);
|
||||
tagcount = 0;
|
||||
|
||||
tl = taglist;
|
||||
sym_seq(tags, &Key, &Data, R_FIRST);
|
||||
do {
|
||||
if (tagcount == ntags) {
|
||||
/* exceeded tag array size -- realloc */
|
||||
ntags += NTAGS_START;
|
||||
taglist =
|
||||
(char **)realloc(taglist, sizeof(char *) * ntags);
|
||||
tl = taglist + tagcount;
|
||||
}
|
||||
|
||||
*tl++ = Key.data;
|
||||
tagcount++;
|
||||
} while (sym_seq(tags, &Key, &Data, R_NEXT) == 0);
|
||||
|
||||
if (tagcount == ntags) {
|
||||
/* exceeded tag array size -- realloc */
|
||||
ntags += NTAGS_START;
|
||||
taglist = (char **)realloc(taglist, sizeof(char *) * ntags);
|
||||
tl = taglist + tagcount;
|
||||
}
|
||||
|
||||
*tl++ = NULL;
|
||||
ntags = tagcount;
|
||||
/* Retrieve one "stime" to get the date. */
|
||||
for (tl = taglist; *tl != NULL; tl++) {
|
||||
strcpy(key_get, *tl);
|
||||
strcat(key_get, ",_keys,stime");
|
||||
if ((info = (char *)sym_get(tags, key_get)) != NULL) {
|
||||
clock = atoi(info);
|
||||
tm = gmtime(&clock);
|
||||
strftime(key_get, KEYSIZE, "%x", tm);
|
||||
sym_put(tags, strdup("_RTS,date"), strdup(key_get), 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
print_header(tags);
|
||||
|
||||
/*
|
||||
* The way that I am using 'Keys' and 'Tag' makes assumptions about the
|
||||
* internals of the sym_* data structure.
|
||||
*/
|
||||
/* dump 'em all */
|
||||
for (tl = taglist; *tl != NULL; tl++) {
|
||||
if (!strcmp(*tl, "_RTS"))
|
||||
continue;
|
||||
|
||||
strcpy(key_get, *tl);
|
||||
strcat(key_get, ",_keys");
|
||||
if ((Keys = sym_get(tags, key_get)) == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
strcpy(key_get, *tl);
|
||||
if ((Tag = sym_get(tags, key_get)) != NULL) {
|
||||
tag_report(NULL, Tag, Keys);
|
||||
}
|
||||
}
|
||||
free(taglist);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* End-Of-Test seen, insert this tag into the global tag data.
|
||||
* (1) Get the test's tag
|
||||
* (2) insert the keywords in the "_keys" tag
|
||||
* (3) insert it into the global data under this tag, replacing any existing
|
||||
* data.
|
||||
*
|
||||
* a "feature" of the key implimentation: I can insert a key tree
|
||||
* under another key tree with almost zero brainwork because a SYM
|
||||
* is what the DATA area points to.
|
||||
*/
|
||||
static int scanner_test_end(SYM alltags, SYM ctag, SYM keys)
|
||||
{
|
||||
static int notag = 0; /* counter for records with no tag (error) */
|
||||
char tagname[KEYSIZE]; /* used when creating name (see above) */
|
||||
char *tag; /* tag name to look things up in */
|
||||
char *status; /* initiation status of old tag */
|
||||
SYM rm; /* pointer to old tag -- to remove it */
|
||||
|
||||
if (alltags == NULL || keys == NULL || ctag == NULL)
|
||||
return -1; /* for really messed up test output */
|
||||
|
||||
/* insert keys into tag */
|
||||
sym_put(ctag, "_keys", (void *)keys, 0);
|
||||
|
||||
/* get the tag, or build a new one */
|
||||
if ((tag = (char *)sym_get(keys, "tag")) == NULL) {
|
||||
/* this is an "impossible" situation: test_output checks for this
|
||||
* and creates a dummy tag. */
|
||||
sprintf(tagname, "no_tag_%d", notag++);
|
||||
fprintf(stderr, "No TAG key! Using %s\n", tagname);
|
||||
sym_put(keys, "tag", strdup(tagname), 0);
|
||||
tag = strdup(tagname);
|
||||
}
|
||||
|
||||
/*
|
||||
* Special case: duplicate tag that has an initiation_status failure
|
||||
* is thrown away.
|
||||
*/
|
||||
if ((rm = (SYM) sym_get(alltags, tag)) != NULL) {
|
||||
if ((status =
|
||||
(char *)sym_get(keys, "initiation_status")) != NULL) {
|
||||
if (strcmp(status, "ok")) {
|
||||
/* do not take new data. remove new data */
|
||||
sym_rm(ctag, RM_KEY | RM_DATA);
|
||||
return 1;
|
||||
} else {
|
||||
/* remove old data in alltags */
|
||||
sym_rm(rm, RM_KEY | RM_DATA);
|
||||
}
|
||||
} else {
|
||||
/* new data does not have an initiation_status -- throw it away */
|
||||
sym_rm(ctag, RM_KEY | RM_DATA);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* put new data.. replaces existing "tag" key if it exists
|
||||
* (it's data should have been removed above) */
|
||||
sym_put(alltags, tag, ctag, PUT_REPLACE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iscanner_reporter(SYM tags)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iscanner_test_end(SYM alltags, SYM ctag, SYM keys)
|
||||
{
|
||||
if (alltags == NULL || keys == NULL || ctag == NULL)
|
||||
return -1; /* for really messed up test output */
|
||||
|
||||
/* insert keys into tag */
|
||||
sym_put(ctag, "_keys", (void *)keys, 0);
|
||||
|
||||
return tag_report(alltags, ctag, keys);
|
||||
}
|
||||
|
||||
int reporter(SYM s)
|
||||
{
|
||||
return reporter_func(s);
|
||||
}
|
||||
|
||||
int test_end(SYM a, SYM b, SYM c)
|
||||
{
|
||||
return test_end_func(a, b, c);
|
||||
}
|
||||
|
||||
void set_scanner(void)
|
||||
{
|
||||
reporter_func = scanner_reporter;
|
||||
test_end_func = scanner_test_end;
|
||||
}
|
||||
|
||||
void set_iscanner(void)
|
||||
{
|
||||
reporter_func = iscanner_reporter;
|
||||
test_end_func = iscanner_test_end;
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it would be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* Further, this software is distributed without any warranty that it is
|
||||
* free of the rightful claim of any third person regarding infringement
|
||||
* or the like. Any license provided herein, whether implied or
|
||||
* otherwise, applies only to this software file. Patent licenses, if
|
||||
* any, provided herein do not apply to combinations of this program with
|
||||
* other software, or any other product whatsoever.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
|
||||
* Mountain View, CA 94043, or:
|
||||
*
|
||||
* http://www.sgi.com
|
||||
*
|
||||
* For further information regarding this notice, see:
|
||||
*
|
||||
* http://oss.sgi.com/projects/GenInfo/NoticeExplan/
|
||||
*
|
||||
*/
|
||||
/* $Id: reporter.h,v 1.1 2000/09/21 21:35:06 alaffin Exp $ */
|
||||
#ifndef _REPORT_H_
|
||||
#define _REPORT_H_
|
||||
#include "symbol.h"
|
||||
|
||||
void set_scanner(void);
|
||||
void set_iscanner(void);
|
||||
|
||||
int reporter( SYM );
|
||||
int test_end( SYM, SYM, SYM );
|
||||
|
||||
/*
|
||||
* how much TCID space to start with (table)
|
||||
*/
|
||||
#define NTCID_START 5
|
||||
|
||||
/*
|
||||
* how much tag space to start with (table)
|
||||
*/
|
||||
#define NTAGS_START 500
|
||||
|
||||
/* Return Tokens (from lex) */
|
||||
#define KW_START 100
|
||||
#define KW_END 101
|
||||
#define TEST_START 102
|
||||
#define TEST_OUTPUT 103
|
||||
#define EXEC_STATUS 104
|
||||
#define TEST_END 105
|
||||
#define TEXT_LINE 106
|
||||
#define KEYWORD 107
|
||||
#define KEYWORD_QUOTED 108
|
||||
#define CUTS_RESULT 109
|
||||
#define CUTS_RESULT_R 110
|
||||
#define SPACE 999
|
||||
|
||||
/* Scan Modes (above and beyond what I use lex for) */
|
||||
#define SCAN_OUTSIDE 10 /* not in anything */
|
||||
#define SCAN_RTSKEY 20 /* keywords: rts_keyword */
|
||||
#define SCAN_TSTKEY 21 /* keywords: either test_start or
|
||||
execution_status */
|
||||
#define SCAN_OUTPUT 30 /* test_output */
|
||||
|
||||
/*
|
||||
* Configuration type things
|
||||
*/
|
||||
#define KEYSIZE 255 /* maximum key size */
|
||||
|
||||
#endif
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it would be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* Further, this software is distributed without any warranty that it is
|
||||
* free of the rightful claim of any third person regarding infringement
|
||||
* or the like. Any license provided herein, whether implied or
|
||||
* otherwise, applies only to this software file. Patent licenses, if
|
||||
* any, provided herein do not apply to combinations of this program with
|
||||
* other software, or any other product whatsoever.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
|
||||
* Mountain View, CA 94043, or:
|
||||
*
|
||||
* http://www.sgi.com
|
||||
*
|
||||
* For further information regarding this notice, see:
|
||||
*
|
||||
* http://oss.sgi.com/projects/GenInfo/NoticeExplan/
|
||||
*
|
||||
*/
|
||||
/* $Id: scan.h,v 1.1 2000/09/21 21:35:06 alaffin Exp $ */
|
||||
#ifndef _SCAN_H_
|
||||
#define _SCAN_H_
|
||||
#include "symbol.h"
|
||||
|
||||
int scanner ( SYM );
|
||||
int sym_dump_s ( SYM, int );
|
||||
int lex_files( char ** );
|
||||
|
||||
#endif
|
||||
-456
@@ -1,456 +0,0 @@
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it would be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* Further, this software is distributed without any warranty that it is
|
||||
* free of the rightful claim of any third person regarding infringement
|
||||
* or the like. Any license provided herein, whether implied or
|
||||
* otherwise, applies only to this software file. Patent licenses, if
|
||||
* any, provided herein do not apply to combinations of this program with
|
||||
* other software, or any other product whatsoever.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
|
||||
* Mountain View, CA 94043, or:
|
||||
*
|
||||
* http://www.sgi.com
|
||||
*
|
||||
* For further information regarding this notice, see:
|
||||
*
|
||||
* http://oss.sgi.com/projects/GenInfo/NoticeExplan/
|
||||
*
|
||||
*/
|
||||
/* $Id: scan.l,v 1.1 2000/09/21 21:35:06 alaffin Exp $ */
|
||||
/*
|
||||
* Lex rules for input processing.
|
||||
*
|
||||
* This handles all of the input parsing. The rules liste here properly
|
||||
* store or process the pertenant input data in the proper ways. The rules
|
||||
* for the various patterns maintains a "state" to determine if corrupted
|
||||
* input is seen (%Start keys + internal ones that only flag errors).
|
||||
*
|
||||
* See scanner.c for routines called from the actions.
|
||||
*
|
||||
* States:
|
||||
* SCAN_OUTSIDE
|
||||
* start-up state, inbetween tests
|
||||
* SCAN_RTSKEY valid from SCAN_OUTSIDE
|
||||
* from rts_keyword_start to _end
|
||||
* accompanied by lex KEY state.
|
||||
* SCAN_TSTKEY valid from SCAN_OUTSIDE
|
||||
* test_start to test_output or test_end,
|
||||
* execution_status to test_end
|
||||
* accompanied by lex KEY state.
|
||||
* SCAN_OUTPUT
|
||||
* test_output to execution_status.
|
||||
* accompanied by lex OUT or CUTS states.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "scan.h"
|
||||
#include "reporter.h"
|
||||
#include "symbol.h"
|
||||
#include "tag_report.h"
|
||||
|
||||
int scan_mode = SCAN_OUTSIDE; /* current mode */
|
||||
char *key, *cont; /* keyword pieces */
|
||||
SYM keys=NULL; /* stored keywords */
|
||||
SYM ctag=NULL; /* temporary - for storing current tag's info */
|
||||
SYM alltags; /* entire tag database. set to scanner 'tags' param.*/
|
||||
SYM k; /* temporary sym pointer -- for key removal */
|
||||
char info[KEYSIZE]; /* tmp string for inserting line numbers */
|
||||
static int test_output( SYM, SYM);
|
||||
static int check_mode(int, int, ...);
|
||||
|
||||
/*
|
||||
* Lex Definitions:
|
||||
* UI Unsigned Integer
|
||||
* A Alphabetic
|
||||
* W "Word" characters (Alpha, Numeric, Hyphens, Underscores)
|
||||
* S Space characters
|
||||
*/
|
||||
%}
|
||||
|
||||
%option noc++
|
||||
%option noinput
|
||||
%option nolex-compat
|
||||
%option nounput
|
||||
%option yylineno
|
||||
|
||||
UI [0-9]+
|
||||
A [a-zA-Z]+
|
||||
W [a-zA-Z0-9_-]+
|
||||
S [ \t]+
|
||||
|
||||
%Start KEY OUT CUTS
|
||||
%%
|
||||
^<<<rts_keyword_start>>>$ {
|
||||
BEGIN KEY;
|
||||
check_mode(scan_mode, SCAN_OUTSIDE, 0);
|
||||
scan_mode = SCAN_RTSKEY;
|
||||
|
||||
/* remove any keys that exist right now */
|
||||
if(keys != NULL)
|
||||
sym_rm(keys, RM_KEY | RM_DATA);
|
||||
/* start a new table of keys */
|
||||
keys = sym_open(0, 0, 0);
|
||||
return(KW_START);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
^<<<rts_keyword_end>>>$ {
|
||||
BEGIN 0;
|
||||
check_mode(scan_mode, SCAN_RTSKEY, 0);
|
||||
scan_mode = SCAN_OUTSIDE;
|
||||
#ifdef DEBUGGING
|
||||
DEBUG(D_SCAN_LEX, 10) {
|
||||
printf("RTS Keywords:\n");
|
||||
sym_dump_s(keys, 0);
|
||||
}
|
||||
#endif
|
||||
/* remove _RTS key, if it exists, before replacing it */
|
||||
if( (k=(SYM)sym_get(alltags, "_RTS")) != NULL) {
|
||||
sym_rm(k, RM_KEY | RM_DATA);
|
||||
}
|
||||
|
||||
sym_put(alltags, "_RTS", (void *)keys, PUT_REPLACE);
|
||||
keys = NULL;
|
||||
|
||||
return(KW_END);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
^<<<test_start>>>$ {
|
||||
BEGIN KEY;
|
||||
check_mode(scan_mode, SCAN_OUTSIDE, 0);
|
||||
scan_mode = SCAN_TSTKEY;
|
||||
|
||||
/*
|
||||
* set up new "tag" and "keys" tables
|
||||
* to put the new data into.
|
||||
*/
|
||||
|
||||
/* remove any keys that exist right now */
|
||||
if(keys != NULL)
|
||||
sym_rm(keys, RM_KEY | RM_DATA);
|
||||
keys = sym_open(0, 0, 0);
|
||||
|
||||
sprintf(info, "%d", yylineno);
|
||||
sym_put(keys, "_Start_line", strdup(info), 0);
|
||||
|
||||
/* remove any tag info that exists right now */
|
||||
if(ctag != NULL)
|
||||
sym_rm(ctag, RM_KEY | RM_DATA);
|
||||
ctag = sym_open(0, 0, 0);
|
||||
|
||||
return(TEST_START);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
^<<<test_output>>>$ {
|
||||
BEGIN OUT;
|
||||
check_mode(scan_mode, SCAN_TSTKEY, 0);
|
||||
scan_mode = SCAN_OUTPUT;
|
||||
|
||||
test_output(ctag, keys);
|
||||
|
||||
return(TEST_OUTPUT);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
^<<<execution_status>>>$ {
|
||||
BEGIN KEY;
|
||||
check_mode(scan_mode, SCAN_TSTKEY, SCAN_OUTPUT, 0);
|
||||
scan_mode = SCAN_TSTKEY;
|
||||
return(EXEC_STATUS);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
^<<<test_end>>>$ {
|
||||
BEGIN 0;
|
||||
check_mode(scan_mode, SCAN_TSTKEY, 0);
|
||||
scan_mode = SCAN_OUTSIDE;
|
||||
|
||||
sprintf(info, "%d", yylineno);
|
||||
|
||||
sym_put(keys, "_End_line", strdup(info), 0);
|
||||
#ifdef DEBUGGING
|
||||
DEBUG(D_SCAN_LEX, 10) {
|
||||
printf("Tag's Keywords:\n");
|
||||
sym_dump_s(keys, 0);
|
||||
}
|
||||
#endif
|
||||
test_end(alltags, ctag, keys);
|
||||
ctag = keys = NULL;
|
||||
|
||||
return(TEST_END);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
<KEY>[a-zA-Z_-]+=\"[^\"\n]+\" {
|
||||
key = yytext;
|
||||
cont = strchr(yytext, '=');
|
||||
*cont++ = '\0';
|
||||
if(*cont == '"') cont++;
|
||||
if(yytext[yyleng-1] == '"')
|
||||
yytext[yyleng-1] = '\0';
|
||||
#ifdef DEBUGGING
|
||||
DEBUG(D_SCAN_LEX, 5)
|
||||
printf("A quoted keyword: %s = %s\n", key, cont);
|
||||
#endif
|
||||
sym_put(keys, key, strdup(cont), 0);
|
||||
|
||||
return(KEYWORD_QUOTED);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
<KEY>[a-zA-Z_-]+=[^\t \n]+ {
|
||||
key = yytext;
|
||||
cont = strchr(yytext, '=');
|
||||
*cont++ = '\0';
|
||||
#ifdef DEBUGGING
|
||||
DEBUG(D_SCAN_LEX, 5)
|
||||
printf("A keyword: %s = %s\n", key, cont);
|
||||
#endif
|
||||
sym_put(keys, key, strdup(cont), 0);
|
||||
|
||||
return(KEYWORD);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
<KEY>[ \t\n]* {
|
||||
return(SPACE);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
<OUT>^.+$ {
|
||||
#ifdef DEBUGGING
|
||||
DEBUG(D_SCAN_LEX, 5)
|
||||
printf("TEXT_LINE: %s\n", yytext);
|
||||
#endif
|
||||
|
||||
return(TEXT_LINE);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
<CUTS>^{W}{S}{UI}{S}{A}{S}":" {
|
||||
#ifdef DEBUGGING
|
||||
DEBUG(D_SCAN_LEX, 5)
|
||||
printf("CUTS Result: %s\n", yytext);
|
||||
#endif
|
||||
cuts_testcase(ctag, keys);
|
||||
|
||||
return(CUTS_RESULT);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
<CUTS>^{W}{S}{UI}-{UI}{S}{A}{S}":" {
|
||||
#ifdef DEBUGGING
|
||||
DEBUG(D_SCAN_LEX, 5)
|
||||
printf("CUTS Result: %s\n", yytext);
|
||||
#endif
|
||||
cuts_testcase(ctag, keys);
|
||||
|
||||
return(CUTS_RESULT_R);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
. {
|
||||
return(SPACE);
|
||||
/* NOTREACHED */
|
||||
|
||||
}
|
||||
"\n" {
|
||||
return(SPACE);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
%%
|
||||
/*
|
||||
* the BEGIN macro only exists in the lex file, so define a routine to
|
||||
* BEGIN the CUTS state.
|
||||
*/
|
||||
int
|
||||
begin_cuts(void)
|
||||
{
|
||||
BEGIN CUTS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calls lex repeatedly until all input is seen.
|
||||
*/
|
||||
int
|
||||
scanner(SYM tags)
|
||||
{
|
||||
alltags = tags; /* move into global scope for lex actions */
|
||||
|
||||
while(yylex())
|
||||
;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test-Output record
|
||||
* check if this is a CUTS test; if so, enter the lex "cuts" state;
|
||||
* otherwise do nothing and lex will be in a "data" mode that will just
|
||||
* toss all the output.
|
||||
*/
|
||||
static int
|
||||
test_output(SYM tag, SYM keys)
|
||||
{
|
||||
char *at;
|
||||
|
||||
if((at=(char *)sym_get(keys, "analysis")) != NULL) {
|
||||
/* CUTS:number_of_testcases || CUTS-1:number_of_testcases */
|
||||
if(strncasecmp("cuts", at, 4) == 0) {
|
||||
begin_cuts();
|
||||
/*printf("CUTS output expected\n");*/
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Input Data State Check
|
||||
* RTS driver output goes thru specific
|
||||
* phases; this is used to verify that the new state is a legal state
|
||||
* to change to from the current state.
|
||||
* This accepts a variable number of arguments (valid states to be
|
||||
* in). The last argument MUST be zero
|
||||
*/
|
||||
struct parse_states {
|
||||
char *name;
|
||||
int bits;
|
||||
} parse_states[] = {
|
||||
{ "outside", SCAN_OUTSIDE },
|
||||
{ "rts_keyword_start", SCAN_RTSKEY },
|
||||
{ "test_start | execution_status", SCAN_TSTKEY },
|
||||
{ "test_output", SCAN_OUTPUT },
|
||||
{ "unknown", 0 }, /*end sentinel: bits = 0 */
|
||||
};
|
||||
|
||||
static int
|
||||
check_mode(int scan_mode, int fst, ...)
|
||||
{
|
||||
va_list ap; /* used for variable argument functions*/
|
||||
int found=0; /* set to true if a valid state was found */
|
||||
int ckm; /* Check Mode: the mode to look for */
|
||||
register struct parse_states *ps; /* for looking thru parse_states */
|
||||
char exp_mode[KEYSIZE]; /* expected mode list (for error message) */
|
||||
|
||||
extern int yylineno; /* Line number from Lex */
|
||||
|
||||
/* look thru parse_states; end sentinel is "bits" = 0 */
|
||||
for(ps=parse_states; ps->bits && (ps->bits != fst);ps++)
|
||||
;
|
||||
strcpy(exp_mode, ps->name);
|
||||
|
||||
/* look at first variable argument */
|
||||
if(fst == scan_mode)
|
||||
found++;
|
||||
else {
|
||||
/* not first... look at variable args */
|
||||
va_start(ap, fst);
|
||||
while(((ckm = va_arg(ap, int)) != 0) && (ckm != scan_mode)) {
|
||||
for(ps=parse_states; ps->bits && (ps->bits != ckm);ps++)
|
||||
;
|
||||
strcat(exp_mode, ", ");
|
||||
strcat(exp_mode, ps->name);
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
if(ckm == scan_mode)
|
||||
found++;
|
||||
}
|
||||
|
||||
if(!found) {
|
||||
for(ps=parse_states; ps->bits && (ps->bits != scan_mode);ps++)
|
||||
;
|
||||
|
||||
fprintf(stderr, "PARSE ERROR -- Line %d found %s in mode %s[%d] expected { %s }\n",
|
||||
yylineno, yytext, ps->name, scan_mode, exp_mode);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This part of the file contains subroutines called by a lex scanner which
|
||||
* is parsing rts-driver-format input and putting it into a multi-level
|
||||
* symbol table.
|
||||
*/
|
||||
|
||||
/*
|
||||
* References to lex variables
|
||||
*/
|
||||
/*extern char yytext[]; / * text matched by last pattern */
|
||||
/*extern long yyleng; / * length of above */
|
||||
|
||||
char **filenames;
|
||||
|
||||
int
|
||||
lex_files(char **names)
|
||||
{
|
||||
/* lex */
|
||||
extern FILE *yyin;
|
||||
|
||||
filenames = names;
|
||||
|
||||
if(*filenames != NULL) {
|
||||
#ifdef DEBUGGING
|
||||
DEBUG(D_SCAN, 1)
|
||||
printf("lex_files: first file is %s\n", *filenames);
|
||||
#endif
|
||||
if((yyin = fopen(*filenames, "r")) == NULL) {
|
||||
printf("Error opening %s for reading\n", *filenames);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called by lex's end-of-file processing.
|
||||
* Open the next file on the command line. If there is no next file,
|
||||
* return "-1" and lex will end.
|
||||
*/
|
||||
int
|
||||
yywrap(void)
|
||||
{
|
||||
extern FILE *yyin;
|
||||
extern int yylineno; /* Line number from Lex */
|
||||
|
||||
if(*filenames != NULL)
|
||||
if(*++filenames != NULL) {
|
||||
#ifdef DEBUGGING
|
||||
DEBUG(D_SCAN, 1)
|
||||
printf("yywrap: next file is %s\n", *filenames);
|
||||
#endif
|
||||
yylineno=1;
|
||||
if((yyin = fopen(*filenames, "r")) != NULL)
|
||||
return(0);
|
||||
else {
|
||||
printf("Error opening %s for reading\n", *filenames);
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
|
||||
return(-1);
|
||||
}
|
||||
|
||||
-467
@@ -1,467 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it would be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* Further, this software is distributed without any warranty that it is
|
||||
* free of the rightful claim of any third person regarding infringement
|
||||
* or the like. Any license provided herein, whether implied or
|
||||
* otherwise, applies only to this software file. Patent licenses, if
|
||||
* any, provided herein do not apply to combinations of this program with
|
||||
* other software, or any other product whatsoever.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
|
||||
* Mountain View, CA 94043, or:
|
||||
*
|
||||
* http://www.sgi.com
|
||||
*
|
||||
* For further information regarding this notice, see:
|
||||
*
|
||||
* http://oss.sgi.com/projects/GenInfo/NoticeExplan/
|
||||
*
|
||||
*/
|
||||
/* $Id: symbol.c,v 1.4 2002/05/28 16:26:16 robbiew Exp $ */
|
||||
/*
|
||||
* Generic Symbol Table
|
||||
*
|
||||
* This is intended to look a lot like ndbm, except that all information
|
||||
* is kept in memory, and a multi-key, hierarchical access mode is provided.
|
||||
* This is largely patterned after the Berkeley "DB" package.
|
||||
*
|
||||
* Requirements
|
||||
*
|
||||
* - "key" is ASCII (a C string, in fact)
|
||||
*
|
||||
* Symbol Table Structure
|
||||
*
|
||||
* Two data structures:
|
||||
* Symbol Table Header
|
||||
* Symbol Table Node
|
||||
*
|
||||
* A symbol table header consists of a magic number, a pointer to
|
||||
* the first node in the symbol table, and a cursor that is used
|
||||
* when sequentialy stepping thru the entire list.
|
||||
*
|
||||
* Symbol table nodes contain a pointer to a key, a pointer to this
|
||||
* key's data, and a pointer to the next node in the chain.
|
||||
* Note that to create a hierarchical symbol table, a node is created
|
||||
* whose data points to a symbol table header.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "symbol.h"
|
||||
#include "splitstr.h"
|
||||
|
||||
#define SYM_MAGIC 0xbadc0de
|
||||
|
||||
/*
|
||||
* Some functions can report an error message by assigning it to this
|
||||
* string.
|
||||
*/
|
||||
|
||||
static char *sym_error = NULL;
|
||||
|
||||
/*
|
||||
* Memory Allocators
|
||||
*
|
||||
* newsym() allocates a new symbol table header node
|
||||
* mknode(...) allocates a new symbol table entry
|
||||
*/
|
||||
|
||||
SYM newsym(void)
|
||||
{
|
||||
SYM h;
|
||||
|
||||
if ((h = malloc(sizeof(struct symh))) == NULL) {
|
||||
sym_error = "sym header malloc failed!";
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
h->magic = SYM_MAGIC;
|
||||
h->sym = NULL;
|
||||
h->cursor = NULL;
|
||||
return (h);
|
||||
}
|
||||
|
||||
static struct sym *mknode(struct sym *next, char *key, void *data)
|
||||
{
|
||||
struct sym *n;
|
||||
|
||||
if ((n = malloc(sizeof(struct sym))) == NULL) {
|
||||
sym_error = "sym node malloc failed!";
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
n->next = next;
|
||||
n->key = strdup(key);
|
||||
n->data = data;
|
||||
|
||||
if (n->key == NULL) {
|
||||
sym_error = "sym node strdup(key) failed!";
|
||||
free(n);
|
||||
return (NULL);
|
||||
}
|
||||
return (n);
|
||||
}
|
||||
|
||||
/*
|
||||
* Search for a key in a single-level symbol table hierarchy.
|
||||
*/
|
||||
static struct sym *find_key1(struct sym *sym, char *key)
|
||||
{
|
||||
while (sym != NULL)
|
||||
if (strcmp(sym->key, key) == 0)
|
||||
return (sym);
|
||||
else
|
||||
sym = sym->next;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new key node, add it to the *end* of this list
|
||||
*/
|
||||
static int add_key(SYM sym, char *key, void *data)
|
||||
{
|
||||
register struct sym *sn;
|
||||
|
||||
if (sym->sym == NULL) {
|
||||
sym->sym = mknode(NULL, key, data);
|
||||
if (sym->sym == NULL) {
|
||||
return (-1);
|
||||
}
|
||||
} else {
|
||||
for (sn = sym->sym; sn != NULL && sn->next != NULL;
|
||||
sn = sn->next) ;
|
||||
sn->next = mknode(NULL, key, data);
|
||||
assert(sn->next != NULL);
|
||||
if (sn->next == NULL)
|
||||
return (-1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new symbol table
|
||||
*/
|
||||
SYM sym_open(int flags, int mode, int openinfo)
|
||||
{
|
||||
return (newsym());
|
||||
}
|
||||
|
||||
/*
|
||||
* Add (key, data) to an existing symbol table
|
||||
*
|
||||
* If the key does not exist, a new key is added to the end of the list.
|
||||
* If the key exists and the PUT_REPLACE flag is not supplied, return EEXIST.
|
||||
* If a symbol table entry in a multi-part key is not a symbol table (i.e.
|
||||
* element two of a three or more element key), return ENOTDIR.
|
||||
*
|
||||
* "data" is not duplicated and must not point to a static area that could
|
||||
* go away before the element is deleted (such as a local string in a
|
||||
* function)
|
||||
*
|
||||
* "key" is duplicated as needed, and is not modified.
|
||||
*
|
||||
* Code:
|
||||
* chop up key on commas
|
||||
*
|
||||
* search until a key element isn't found in the key tree, the key list is
|
||||
* exhausted, or a key's data element is not a sub-tree
|
||||
*
|
||||
* if the key list is exhausted, return a "duplicate entry" error
|
||||
*
|
||||
* if the last found key's data element is not a sub-tree, return
|
||||
* something like "ENOTDIR".
|
||||
*
|
||||
* add new keys for sub-trees until key list is exhausted;
|
||||
* last node gets 'data'.
|
||||
*
|
||||
*/
|
||||
int sym_put(SYM sym, char *key, void *data, int flags)
|
||||
{
|
||||
const char **keys; /* key split into a 2d string array */
|
||||
char **kk;
|
||||
char *nkey; /* copy of 'key' -- before split */
|
||||
SYM csym, ncsym; /* search: current symbol table */
|
||||
struct sym *nsym = NULL; /* search: found symbol entry */
|
||||
|
||||
if (sym == NULL)
|
||||
return (EINVAL);
|
||||
|
||||
nkey = strdup(key);
|
||||
keys = splitstr(key, ",", NULL);
|
||||
|
||||
if (keys == NULL) {
|
||||
free(nkey);
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
for (kk = (char **)keys, csym = sym;
|
||||
*kk != NULL && (nsym = find_key1(csym->sym, *kk)) != NULL;
|
||||
csym = nsym->data) {
|
||||
|
||||
if (*++kk == NULL)
|
||||
break;
|
||||
|
||||
if (nsym->data == NULL) { /* fatal error */
|
||||
free(nkey);
|
||||
splitstr_free(keys);
|
||||
return (ENOTDIR);
|
||||
}
|
||||
if (((SYM) (nsym->data))->magic != SYM_MAGIC) {
|
||||
free(nkey);
|
||||
splitstr_free(keys);
|
||||
return (ENOTDIR);
|
||||
}
|
||||
}
|
||||
|
||||
if (*kk == NULL) { /* found a complete match */
|
||||
free(nkey);
|
||||
splitstr_free(keys);
|
||||
|
||||
if (flags == PUT_REPLACE) {
|
||||
nsym->data = data;
|
||||
return (0);
|
||||
} else {
|
||||
return (EEXIST);
|
||||
}
|
||||
}
|
||||
|
||||
/* csym is a ptr to a list */
|
||||
for (; *kk != NULL; kk++) {
|
||||
if (*(kk + 1) != NULL) {
|
||||
add_key(csym, *kk, (void *)(ncsym = newsym()));
|
||||
csym = ncsym;
|
||||
} else {
|
||||
add_key(csym, *kk, data); /* last key */
|
||||
}
|
||||
}
|
||||
|
||||
free(nkey);
|
||||
splitstr_free(keys);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieve a Symbol's Contents
|
||||
*
|
||||
* "key" is not modified.
|
||||
* If the key cannot be found, NULL is returned
|
||||
*/
|
||||
void *sym_get(SYM sym, char *key)
|
||||
{
|
||||
char *nkey;
|
||||
const char **keys; /* key split into a 2d string array */
|
||||
char **kk;
|
||||
SYM csym; /* search: current symbol table */
|
||||
struct sym *nsym = NULL; /* search: found symbol entry */
|
||||
|
||||
if (sym == NULL)
|
||||
return (NULL);
|
||||
|
||||
nkey = strdup(key);
|
||||
keys = splitstr(nkey, ",", NULL);
|
||||
if (keys == NULL)
|
||||
return (NULL);
|
||||
|
||||
for (kk = (char **)keys, csym = sym;
|
||||
*kk != NULL && (nsym = find_key1(csym->sym, *kk)) != NULL;
|
||||
csym = nsym->data) {
|
||||
|
||||
if (*++kk == NULL)
|
||||
break;
|
||||
|
||||
if (nsym->data == NULL) { /* fatal error */
|
||||
free(nkey);
|
||||
splitstr_free(keys);
|
||||
return (NULL);
|
||||
}
|
||||
if (((SYM) (nsym->data))->magic != SYM_MAGIC) {
|
||||
free(nkey);
|
||||
splitstr_free(keys);
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (*kk == NULL) { /* found a complete match */
|
||||
splitstr_free(keys);
|
||||
free(nkey);
|
||||
return (nsym->data);
|
||||
} else {
|
||||
splitstr_free(keys);
|
||||
free(nkey);
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Step thru a symbol table list
|
||||
*
|
||||
* The cursor must be set by R_CURSOR, R_FIRST before using R_NEXT.
|
||||
* NULL is returned when no more items are available.
|
||||
*/
|
||||
int sym_seq(SYM sym, DBT * key, DBT * data, int flags)
|
||||
{
|
||||
SYM csym;
|
||||
|
||||
switch (flags) {
|
||||
/*
|
||||
* A number of ways to do this:
|
||||
* specificly: sym_seq( .., "key,key") sets to Nth element of the 2nd
|
||||
* level symbol table
|
||||
* sym_seq(.., "key,key,") sets to the first element of the 3rd
|
||||
* level symbol table
|
||||
*
|
||||
* sym_seq(.., "key,key") where both must be complete keys, sets
|
||||
* cursor to the first element of the 3rd level symbol table;
|
||||
* if there is no 3rd level, return an error.
|
||||
*/
|
||||
case R_CURSOR:
|
||||
csym = (SYM) sym_get(sym, (char *)key->data);
|
||||
if (csym == NULL || csym->magic != SYM_MAGIC) {
|
||||
return (2);
|
||||
}
|
||||
sym->cursor = csym->sym;
|
||||
if (sym->cursor == NULL)
|
||||
return (1);
|
||||
key->data = sym->cursor->key;
|
||||
data->data = sym->cursor->data;
|
||||
|
||||
return (0);
|
||||
|
||||
case R_FIRST:
|
||||
sym->cursor = sym->sym;
|
||||
if (sym->cursor == NULL)
|
||||
return (1);
|
||||
key->data = sym->cursor->key;
|
||||
data->data = sym->cursor->data;
|
||||
|
||||
return (0);
|
||||
|
||||
case R_NEXT:
|
||||
if (sym->cursor == NULL)
|
||||
return (1);
|
||||
sym->cursor = sym->cursor->next;
|
||||
|
||||
if (sym->cursor == NULL)
|
||||
return (1);
|
||||
|
||||
key->data = sym->cursor->key;
|
||||
data->data = sym->cursor->data;
|
||||
|
||||
return (0);
|
||||
|
||||
case R_LAST:
|
||||
case R_PREV:
|
||||
default:
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Dump a symbol table's keys.
|
||||
* Handles hierarchies, using a double quote to indicate depth, one
|
||||
* double quote for each level.
|
||||
*/
|
||||
int sym_dump(SYM sym, int depth)
|
||||
{
|
||||
|
||||
register struct sym *se; /* symbol entry */
|
||||
register int d;
|
||||
|
||||
if (sym == NULL || sym->magic != SYM_MAGIC)
|
||||
return -1;
|
||||
|
||||
for (se = sym->sym; se != NULL; se = se->next) {
|
||||
for (d = 0; d < depth; d++) {
|
||||
putchar('"');
|
||||
putchar(' ');
|
||||
}
|
||||
printf("%s\n", se->key);
|
||||
sym_dump((SYM) se->data, depth + 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* sym dump, but data is _always_ a string (print it)
|
||||
*/
|
||||
int sym_dump_s(SYM sym, int depth)
|
||||
{
|
||||
|
||||
register struct sym *se; /* symbol entry */
|
||||
register int d;
|
||||
|
||||
if (sym == NULL)
|
||||
return 0;
|
||||
|
||||
if (sym->magic != SYM_MAGIC) {
|
||||
for (d = 0; d < depth; d++) {
|
||||
putchar('"');
|
||||
putchar(' ');
|
||||
}
|
||||
printf(" = %s\n", (char *)sym);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (se = sym->sym; se != NULL; se = se->next) {
|
||||
for (d = 0; d < depth; d++) {
|
||||
putchar('"');
|
||||
putchar(' ');
|
||||
}
|
||||
printf("%s", se->key);
|
||||
if (((SYM) se->data)->magic == SYM_MAGIC) {
|
||||
putchar('\n');
|
||||
sym_dump_s((SYM) se->data, depth + 1);
|
||||
} else {
|
||||
printf("(%p) = %s (%p)\n", se->key, (char *)se->data,
|
||||
se->data);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove an entire symbol table (done bottom up)
|
||||
*/
|
||||
int sym_rm(SYM sym, int flags)
|
||||
{
|
||||
register struct sym *se, *nse; /* symbol entry */
|
||||
|
||||
if (sym == NULL)
|
||||
return 0;
|
||||
|
||||
if (sym->magic != SYM_MAGIC) {
|
||||
if (!(flags & RM_DATA))
|
||||
free(sym);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (se = sym->sym; se != NULL;) {
|
||||
sym_rm((SYM) se->data, flags);
|
||||
nse = se->next;
|
||||
if (flags & RM_KEY)
|
||||
free(se->key);
|
||||
if (flags & RM_DATA)
|
||||
free(se->data);
|
||||
free(se);
|
||||
se = nse;
|
||||
}
|
||||
if (!(flags & RM_DATA))
|
||||
free(sym);
|
||||
return 0;
|
||||
}
|
||||
-104
@@ -1,104 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it would be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* Further, this software is distributed without any warranty that it is
|
||||
* free of the rightful claim of any third person regarding infringement
|
||||
* or the like. Any license provided herein, whether implied or
|
||||
* otherwise, applies only to this software file. Patent licenses, if
|
||||
* any, provided herein do not apply to combinations of this program with
|
||||
* other software, or any other product whatsoever.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
|
||||
* Mountain View, CA 94043, or:
|
||||
*
|
||||
* http://www.sgi.com
|
||||
*
|
||||
* For further information regarding this notice, see:
|
||||
*
|
||||
* http://oss.sgi.com/projects/GenInfo/NoticeExplan/
|
||||
*
|
||||
*/
|
||||
/* $Id: symbol.h,v 1.1 2000/09/21 21:35:06 alaffin Exp $ */
|
||||
#ifndef _SYMBOL_H_
|
||||
#define _SYMBOL_H_
|
||||
|
||||
/*
|
||||
* "Generic" Symbol Table
|
||||
*
|
||||
* These data structures are the internal part of a library providing
|
||||
* an in-memory dbm-like (key, content) database with hierarchical
|
||||
* key names.
|
||||
*/
|
||||
struct sym {
|
||||
struct sym *next;
|
||||
char *key;
|
||||
void *data;
|
||||
};
|
||||
|
||||
/*
|
||||
* Symbol Table Header
|
||||
*/
|
||||
struct symh {
|
||||
int magic;
|
||||
struct sym *sym;
|
||||
struct sym *cursor;
|
||||
};
|
||||
|
||||
/*
|
||||
* The "SYM" typedef is the only external data type.
|
||||
*/
|
||||
typedef struct symh *SYM;
|
||||
|
||||
/*
|
||||
* Data for keys and contents (lifted from dbopen(3))
|
||||
* dbopen(3) uses this for all functions, but I'm hard-wired into chars
|
||||
* for keys and the like; I just need this for sym_get
|
||||
*/
|
||||
typedef struct {
|
||||
void *data;
|
||||
int size;
|
||||
} DBT;
|
||||
|
||||
/*
|
||||
* Prototypes
|
||||
*/
|
||||
|
||||
SYM sym_open(int flags, int mode, int openinfo );
|
||||
int sym_put (SYM sym, char *key, void *data, int flags );
|
||||
void *sym_get (SYM sym, char *key );
|
||||
int sym_seq (SYM sym, DBT *key, DBT *data, int flags );
|
||||
int sym_rm (SYM sym, int flags );
|
||||
|
||||
/*
|
||||
* Flags for sym_put
|
||||
*/
|
||||
#define PUT_REPLACE 1 /* replace data on a put */
|
||||
|
||||
/*
|
||||
* Flags for sym_rm
|
||||
*/
|
||||
#define RM_KEY 001 /* free() on key pointer */
|
||||
#define RM_DATA 002 /* free() on data pointer */
|
||||
|
||||
/*
|
||||
* Flags for sym_seq (clones of 44BSD dbopen(3))
|
||||
*/
|
||||
#define R_CURSOR 1 /* set "cursor" to where "data" key is */
|
||||
#define R_FIRST 2 /* set "cursor" to first item */
|
||||
#define R_NEXT 4 /* set "cursor" to next item */
|
||||
#define R_LAST 3 /* set "cursor" to last item (UNIMP) */
|
||||
#define R_PREV 5 /* set "cursor" to previous item (UNIMP) */
|
||||
|
||||
#endif
|
||||
@@ -1,478 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it would be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* Further, this software is distributed without any warranty that it is
|
||||
* free of the rightful claim of any third person regarding infringement
|
||||
* or the like. Any license provided herein, whether implied or
|
||||
* otherwise, applies only to this software file. Patent licenses, if
|
||||
* any, provided herein do not apply to combinations of this program with
|
||||
* other software, or any other product whatsoever.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
|
||||
* Mountain View, CA 94043, or:
|
||||
*
|
||||
* http://www.sgi.com
|
||||
*
|
||||
* For further information regarding this notice, see:
|
||||
*
|
||||
* http://oss.sgi.com/projects/GenInfo/NoticeExplan/
|
||||
*
|
||||
*/
|
||||
/* $Id: tag_report.c,v 1.2 2006/12/13 22:55:22 vapier Exp $ */
|
||||
#include "tag_report.h"
|
||||
#include "debug.h"
|
||||
#include "reporter.h"
|
||||
#include "splitstr.h"
|
||||
|
||||
static char *worst_case(char *, char *);
|
||||
|
||||
/************************************************************************
|
||||
* Report Generation *
|
||||
************************************************************************/
|
||||
|
||||
/*
|
||||
* printf format statement for standard reports
|
||||
* 5 fields with max/min widths
|
||||
*/
|
||||
#define FORMAT "%-20.20s %-15.15s %10.10s %-20.20s %s\n"
|
||||
|
||||
/*
|
||||
* This is the central results reporting function. All standard report
|
||||
* format results are printed thru test_result.
|
||||
*/
|
||||
int test_result(char *tag, char *tcid, char *tc, char *result, SYM tags)
|
||||
{
|
||||
char *expert, expkey[KEYSIZE];
|
||||
register char *c;
|
||||
char **cont;
|
||||
const char **cont_save;
|
||||
|
||||
if (tcid == NULL)
|
||||
tcid = "-";
|
||||
if (tc == NULL)
|
||||
tc = "-";
|
||||
if (tag == NULL)
|
||||
tag = "test_result: no tag";
|
||||
if (result == NULL)
|
||||
result = "(RESULT IS NULL)";
|
||||
|
||||
strcpy(expkey, "contacts");
|
||||
/* note: the sym_get here does _not_ change the "cursor" */
|
||||
if ((expert = (char *)sym_get(tags, expkey)) == NULL) {
|
||||
expert = "UNKNOWN";
|
||||
}
|
||||
|
||||
/* ' tr " " "_" ' */
|
||||
for (c = result; *c; c++) {
|
||||
if (*c == ' ') {
|
||||
*c = '_';
|
||||
}
|
||||
}
|
||||
if (*result == '\0')
|
||||
result = "?";
|
||||
|
||||
/* split contacts on "," and print out a line for each */
|
||||
cont_save = splitstr(expert, ",", NULL);
|
||||
for (cont = (char **)cont_save; *cont != NULL; cont++) {
|
||||
printf(FORMAT, tag, tcid, tc, result, *cont);
|
||||
}
|
||||
splitstr_free(cont_save);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* CUTS test reporting.
|
||||
*
|
||||
* (1) make a list (2d char array) of all TCIDs (see above for why)
|
||||
* (2) look thru the list:
|
||||
* (a) keep track of the "worst case" in this *TAG*
|
||||
* (b) report each testcase's results
|
||||
* (c) if the testcase number is != 0, count it
|
||||
* (3) report tag's results
|
||||
* (4) check the number of expected results with the actual results,
|
||||
* report an error if they don't match.
|
||||
*/
|
||||
|
||||
int cuts_report(SYM tags, SYM keys, char *at, char *tag)
|
||||
{
|
||||
DBT Key, Data;
|
||||
|
||||
/* analysis type: count of CUTS test cases */
|
||||
const char **ant;
|
||||
char *dat; /* strdup(at) */
|
||||
int tccount; /* expected count of testcases */
|
||||
int tcnum; /* seen count of testcases */
|
||||
|
||||
/* a list of tcids */
|
||||
char **taglist, **tl;
|
||||
int ntags, tagcount;
|
||||
|
||||
char key_get[255];
|
||||
|
||||
char *result = "", *worst_case(); /* overall result */
|
||||
|
||||
/* parse analysis type: cuts:tc-count */
|
||||
ant = splitstr((dat = strdup(at)), ":", NULL);
|
||||
if (ant[1] != NULL)
|
||||
tccount = atoi(ant[1]);
|
||||
else
|
||||
tccount = 0;
|
||||
free(dat);
|
||||
splitstr_free(ant);
|
||||
|
||||
/* extract tcids */
|
||||
ntags = NTCID_START;
|
||||
taglist = (char **)malloc(sizeof(char *) * ntags);
|
||||
tagcount = 0;
|
||||
|
||||
tl = taglist;
|
||||
sym_seq(tags, &Key, &Data, R_FIRST);
|
||||
do {
|
||||
if (tagcount == ntags) {
|
||||
/* exceeded tag array size -- realloc */
|
||||
ntags += NTCID_START;
|
||||
taglist =
|
||||
(char **)realloc(taglist, sizeof(char *) * ntags);
|
||||
tl = taglist + tagcount;
|
||||
}
|
||||
|
||||
if (strcmp((char *)Key.data, "_keys") == 0)
|
||||
continue;
|
||||
DEBUG(D_REPORT, 10)
|
||||
printf("cuts_report: tcid %s\n", (char *)Key.data);
|
||||
*tl++ = Key.data;
|
||||
tagcount++;
|
||||
} while (sym_seq(tags, &Key, &Data, R_NEXT) == 0);
|
||||
|
||||
if (tagcount == ntags) {
|
||||
/* exceeded tag array size -- realloc */
|
||||
ntags++; /* need just one more */
|
||||
taglist = (char **)realloc(taglist, sizeof(char *) * ntags);
|
||||
tl = taglist + tagcount;
|
||||
}
|
||||
|
||||
*tl++ = NULL;
|
||||
|
||||
ntags = tagcount;
|
||||
|
||||
/* dump all found records */
|
||||
tcnum = 0;
|
||||
for (tl = taglist; *tl != NULL; tl++) {
|
||||
|
||||
strcpy(key_get, *tl);
|
||||
Key.data = (void *)key_get;
|
||||
|
||||
/*sym_dump_s(sym_get(tags, key_get), 0); */
|
||||
|
||||
sym_seq(tags, &Key, &Data, R_CURSOR);
|
||||
do {
|
||||
DEBUG(D_REPORT, 10)
|
||||
printf("cuts_report: tc %s = %s\n",
|
||||
(char *)Key.data, (char *)Data.data);
|
||||
result = worst_case(result, (char *)Data.data);
|
||||
test_result(tag, *tl, (char *)Key.data,
|
||||
(char *)Data.data, keys);
|
||||
if (atoi((char *)Key.data))
|
||||
tcnum++;
|
||||
} while (sym_seq(tags, &Key, &Data, R_NEXT) == 0);
|
||||
}
|
||||
|
||||
test_result(tag, "*", "*", result, keys);
|
||||
|
||||
if (tccount != 0 && tccount != tcnum)
|
||||
test_result(tag, "-", "-", "TC count wrong", keys);
|
||||
|
||||
free(taglist);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do the report generation.
|
||||
*
|
||||
* A problem: I really need multiple cursors. I'd rather not look into
|
||||
* the depths of the current symbol table implimentation (there are the
|
||||
* cursors there that I could use) so that a different (faster!) symbol
|
||||
* table can be used in the future.
|
||||
*
|
||||
* I could get a key (tag), get it's sub-keys (TCIDs), then get the key
|
||||
* again to reset to the top level, _then_ get the next key. That would
|
||||
* be very inefficient.
|
||||
*
|
||||
* The solution I chose is to extract all tags into a list (char array),
|
||||
* then go thru that list with the cursor free for other levels to use.
|
||||
*
|
||||
* (1) make a list (2d char array) of all Tags
|
||||
* (2) search for the first tag that has a "stime" record, and use that as
|
||||
* the date (MMDDYY) that the tests were run.
|
||||
* (3) print the report header
|
||||
* (4) go thru all tags and report each as described at the beginning of
|
||||
* this file
|
||||
*/
|
||||
int tag_report(SYM alltags, SYM ctag, SYM keys)
|
||||
{
|
||||
|
||||
extern int extended;
|
||||
|
||||
char key_get[KEYSIZE];
|
||||
char *info;
|
||||
|
||||
/* retrieved _keys values: initation status, start time, duration,
|
||||
* termination type, termination id, start line, end line. */
|
||||
char *tag, *contact, *is, *mystime, *duration, *tt, *ti, *sl, *el;
|
||||
|
||||
/* Check all driver-level status first */
|
||||
strcpy(key_get, "tag");
|
||||
if ((tag = (char *)sym_get(keys, key_get)) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check all driver-level status first */
|
||||
strcpy(key_get, "initiation_status");
|
||||
if ((is = (char *)sym_get(keys, key_get)) == NULL) {
|
||||
test_result(tag, NULL, NULL, "no init status", keys);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strcmp(is, "ok")) {
|
||||
test_result(tag, NULL, NULL, is, keys);
|
||||
} else {
|
||||
|
||||
strcpy(key_get, "corefile");
|
||||
if ((info = (char *)sym_get(keys, key_get)) != NULL)
|
||||
if (strcmp(info, "no") != 0) {
|
||||
test_result(tag, NULL, NULL, "coredump", keys);
|
||||
}
|
||||
|
||||
strcpy(key_get, "termination_type");
|
||||
if ((tt = (char *)sym_get(keys, key_get)) == NULL) {
|
||||
test_result(tag, NULL, NULL, "no Term Type", keys);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strcmp(tt, "exited")) {
|
||||
test_result(tag, NULL, NULL, tt, keys);
|
||||
}
|
||||
|
||||
strcpy(key_get, "analysis");
|
||||
if ((info = (char *)sym_get(keys, key_get)) == NULL) {
|
||||
test_result(tag, NULL, NULL, "no Analysis Type", keys);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Getting here indicates that there were no fatal driver-level
|
||||
* errors. Do the kind of reporting requested by the test.
|
||||
*/
|
||||
|
||||
if (strncmp(info, "none", 4) == 0) {
|
||||
/*
|
||||
* If analysis is 'none', alway report the test as
|
||||
* a pass regardless of output or exit status.
|
||||
*/
|
||||
test_result(tag, NULL, NULL, "pass", keys);
|
||||
|
||||
} else if (strncmp(info, "cuts", 4)) {
|
||||
|
||||
/*
|
||||
* If analysis is not cuts, assume it is 'exit', thus
|
||||
* the termination_id is used to determine pass/fail result.
|
||||
*/
|
||||
if (strcmp(tt, "timeout")) {
|
||||
strcpy(key_get, "termination_id");
|
||||
if ((info =
|
||||
(char *)sym_get(keys, key_get)) == NULL) {
|
||||
test_result(tag, NULL, NULL,
|
||||
"no_Term_Id", keys);
|
||||
} else {
|
||||
if (strcmp(info, "0")) {
|
||||
test_result(tag, NULL, NULL,
|
||||
"fail", keys);
|
||||
} else {
|
||||
test_result(tag, NULL, NULL,
|
||||
"pass", keys);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cuts_report(ctag, keys, info, tag);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Extended Format:
|
||||
* - tcid+tc = "!"
|
||||
* - tab separated fields
|
||||
* - no field widths
|
||||
* - fields 6 - ~ are:
|
||||
* start-time (time_t)
|
||||
* duration
|
||||
* termination_id
|
||||
* termination_type
|
||||
* Start Line (of test results in output file)
|
||||
* End Line
|
||||
*/
|
||||
|
||||
if (extended) {
|
||||
|
||||
strcpy(key_get, "termination_id");
|
||||
if ((ti = (char *)sym_get(keys, key_get)) == NULL) {
|
||||
ti = "No_Termination_ID";
|
||||
}
|
||||
|
||||
strcpy(key_get, "termination_type");
|
||||
if ((tt = (char *)sym_get(keys, key_get)) == NULL) {
|
||||
tt = "No_Termination_Type";
|
||||
}
|
||||
|
||||
strcpy(key_get, "duration");
|
||||
if ((duration = (char *)sym_get(keys, key_get)) == NULL) {
|
||||
duration = "No_Duration";
|
||||
}
|
||||
|
||||
strcpy(key_get, "_Start_line");
|
||||
if ((sl = (char *)sym_get(keys, key_get)) == NULL) {
|
||||
sl = "No_Start_line";
|
||||
}
|
||||
|
||||
strcpy(key_get, "_End_line");
|
||||
if ((el = (char *)sym_get(keys, key_get)) == NULL) {
|
||||
el = "No_End_line";
|
||||
}
|
||||
|
||||
strcpy(key_get, "contacts");
|
||||
if ((contact = (char *)sym_get(keys, key_get)) == NULL) {
|
||||
contact = "No_Contacts";
|
||||
}
|
||||
|
||||
strcpy(key_get, "stime");
|
||||
if ((mystime = (char *)sym_get(keys, key_get)) == NULL) {
|
||||
mystime = "No_stime";
|
||||
}
|
||||
|
||||
printf("%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t\n",
|
||||
tag, "!", "!", is, contact, mystime, duration,
|
||||
ti, tt, sl, el);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Print a header made up of the RTS keywords
|
||||
* In "extended" mode, print the header to stderr.
|
||||
*/
|
||||
int print_header(SYM tags)
|
||||
{
|
||||
DBT Key, Data;
|
||||
char key_get[255];
|
||||
|
||||
FILE *out;
|
||||
|
||||
extern int extended;
|
||||
|
||||
if (extended)
|
||||
out = stderr;
|
||||
else
|
||||
out = stdout;
|
||||
|
||||
fprintf(out, "System Configuration:\n");
|
||||
/* build header out of RTS keywords */
|
||||
sprintf(key_get, "_RTS");
|
||||
Key.data = (void *)key_get;
|
||||
if (sym_seq(tags, &Key, &Data, R_CURSOR) == 0) {
|
||||
do {
|
||||
if (strcmp((char *)Key.data, "PATH") == 0)
|
||||
continue;
|
||||
fprintf(out, "%-20.20s %s\n", (char *)Key.data,
|
||||
(char *)Data.data);
|
||||
} while (sym_seq(tags, &Key, &Data, R_NEXT) == 0);
|
||||
}
|
||||
|
||||
fprintf(out, "\n");
|
||||
fprintf(out, FORMAT, "tag", "tcid", "testcase", "status", "contact");
|
||||
fprintf(out,
|
||||
"-------------------------------------------------------------------------------\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* CUTS testcase record
|
||||
*
|
||||
* This is passed s SYM for the current tag and the initiation keys.
|
||||
* The text seen by lex is in yytext (global).
|
||||
*/
|
||||
int cuts_testcase(SYM tag, SYM keys)
|
||||
{
|
||||
char *cuts_info[6];
|
||||
char key[KEYSIZE];
|
||||
char *oldresult, *newresult, *worst_case();
|
||||
int tok_num = 0;
|
||||
extern char yytext[];
|
||||
|
||||
cuts_info[tok_num] = strtok(yytext, "\t ");
|
||||
while (tok_num < 5 &&
|
||||
(cuts_info[++tok_num] = strtok(NULL, "\t ")) != NULL) ;
|
||||
|
||||
strcpy(key, cuts_info[0]);
|
||||
strcat(key, ",");
|
||||
strcat(key, cuts_info[1]);
|
||||
|
||||
#ifdef DEBUGGING
|
||||
DEBUG(D_SCAN_CUTS, 1) {
|
||||
printf("cuts_testcase: TCID=%s TC=%s Result=%s\n", cuts_info[0],
|
||||
cuts_info[1], cuts_info[2]);
|
||||
printf("cuts_testcase: %d %s\n", tok_num, key);
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((oldresult = (char *)sym_get(tag, key)) != NULL) {
|
||||
/* Duplicate -- assume mulitple runs */
|
||||
/* keep "worst case" */
|
||||
newresult = worst_case(oldresult, cuts_info[2]);
|
||||
sym_put(tag, key, strdup(newresult), PUT_REPLACE);
|
||||
free(oldresult); /* remove the "data" portion of the key */
|
||||
} else {
|
||||
sym_put(tag, key, strdup(cuts_info[2]), 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine a "worst case" status from two given statuses.
|
||||
*/
|
||||
static char *worst_case(char *t1, char *t2)
|
||||
{
|
||||
/* NULL-terminated table, ordered from worst-case to best-case */
|
||||
static char *worst[] = {
|
||||
"FAIL", "BROK", "PASS", "CONF",
|
||||
"WARN", "INFO", NULL,
|
||||
};
|
||||
|
||||
char **w1, **w2;
|
||||
|
||||
/* Search the table for each status, then use the index to determine
|
||||
which has a lower precedence */
|
||||
for (w1 = worst; *w1 != NULL && strcmp(t1, *w1); w1++) ;
|
||||
|
||||
for (w2 = worst; *w2 != NULL && strcmp(t2, *w2); w2++) ;
|
||||
|
||||
if (w1 < w2)
|
||||
return (t1);
|
||||
else
|
||||
return (t2);
|
||||
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
#DESCRIPTION:ltp A-sync IO Stress IO tests
|
||||
#
|
||||
# aio-stress [-s size] [-r size] [-a size] [-d num] [-b num]
|
||||
# [-i num] [-t num] [-c num] [-C size] [-nxhlvOS ]
|
||||
# file1 [file2 ...]
|
||||
# -a size in KB at which to align buffers
|
||||
# -b max number of iocbs to give io_submit at once
|
||||
# -c number of io contexts per file
|
||||
# -C offset between contexts, default 2MB
|
||||
# -s size in MB of the test file(s), default 1024MB
|
||||
# -r record size in KB used for each io, default 64KB
|
||||
# -d number of pending aio requests for each file, default 64
|
||||
# -i number of ios per file sent before switching
|
||||
# to the next file, default 8
|
||||
# -O Use O_DIRECT (not available in 2.4 kernels),
|
||||
# -S Use O_SYNC for writes
|
||||
# -o add an operation to the list: write=0, read=1,
|
||||
# random write=2, random read=3.
|
||||
# repeat -o to specify multiple ops: -o 0 -o 1 etc.
|
||||
# -m shm use ipc shared memory for io buffers instead of malloc
|
||||
# -m shmfs mmap a file in /dev/shm for io buffers
|
||||
# -n no fsyncs between write stage and read stage
|
||||
# -l print io_submit latencies after each stage
|
||||
# -t number of threads to run
|
||||
# -v verification of bytes written
|
||||
# -x turn off thread stonewalling
|
||||
# -h this message
|
||||
#
|
||||
ADS1000 aio-stress -I500 -o2 -S -r4 $TMPDIR/file1
|
||||
ADS1001 aio-stress -I500 -o2 -S -r8 $TMPDIR/file1
|
||||
ADS1002 aio-stress -I500 -o2 -S -r16 $TMPDIR/file1
|
||||
ADS1003 aio-stress -I500 -o2 -S -r32 -t2 $TMPDIR/junkfile $TMPDIR/file2
|
||||
ADS1004 aio-stress -I500 -o2 -S -r64 $TMPDIR/junkfile $TMPDIR/file2
|
||||
ADS1005 aio-stress -I500 -o3 -S -r4 $TMPDIR/junkfile $TMPDIR/file2
|
||||
ADS1006 aio-stress -I500 -o3 -S -r8 -t2 $TMPDIR/junkfile $TMPDIR/file2
|
||||
ADS1007 aio-stress -I500 -o3 -S -r16 -t2 $TMPDIR/junkfile $TMPDIR/file2
|
||||
ADS1008 aio-stress -I500 -o3 -S -r32 -t4 $TMPDIR/junkfile $TMPDIR/file2 $TMPDIR/file3 $TMPDIR/file4
|
||||
ADS1009 aio-stress -I500 -o3 -S -r64 -t4 $TMPDIR/junkfile $TMPDIR/file2 $TMPDIR/file3 $TMPDIR/file4
|
||||
ADS1010 aio-stress -I500 -o3 -S -r128 -t4 $TMPDIR/junkfile $TMPDIR/file2 $TMPDIR/file3 $TMPDIR/file4
|
||||
ADS1011 aio-stress -I500 -o3 -S -r256 -t8 $TMPDIR/junkfile $TMPDIR/file2 $TMPDIR/file3 $TMPDIR/file4 $TMPDIR/file5 $TMPDIR/file6 $TMPDIR/file7 $TMPDIR/file8
|
||||
ADS1012 aio-stress -I500 -o3 -S -r512 -t8 $TMPDIR/junkfile $TMPDIR/file2 $TMPDIR/file3 $TMPDIR/file4 $TMPDIR/file5 $TMPDIR/file6 $TMPDIR/file7 $TMPDIR/file8
|
||||
ADS1013 aio-stress -I500 -o2 -O -r4 -t8 $TMPDIR/junkfile $TMPDIR/file2 $TMPDIR/file3 $TMPDIR/file4 $TMPDIR/file5 $TMPDIR/file6 $TMPDIR/file7 $TMPDIR/file8
|
||||
ADS1014 aio-stress -I500 -o2 -O -r8 $TMPDIR/file1 $TMPDIR/file2
|
||||
ADS1015 aio-stress -I500 -o2 -O -r16 $TMPDIR/file1 $TMPDIR/file2
|
||||
ADS1016 aio-stress -I500 -o2 -O -r32 -t2 $TMPDIR/junkfile $TMPDIR/file2
|
||||
ADS1017 aio-stress -I500 -o2 -O -r64 -t2 $TMPDIR/junkfile $TMPDIR/file2
|
||||
ADS1018 aio-stress -I500 -o3 -O -r4 -t2 $TMPDIR/junkfile $TMPDIR/file2
|
||||
ADS1019 aio-stress -I500 -o3 -O -r8 -t2 $TMPDIR/junkfile $TMPDIR/file2
|
||||
ADS1020 aio-stress -I500 -o3 -O -r16 -t2 $TMPDIR/junkfile $TMPDIR/file2
|
||||
ADS1021 aio-stress -I500 -o3 -O -r32 -t4 $TMPDIR/junkfile $TMPDIR/file2 $TMPDIR/file7 $TMPDIR/file8
|
||||
ADS1022 aio-stress -I500 -o3 -O -r64 -t4 $TMPDIR/junkfile $TMPDIR/file2 $TMPDIR/file7 $TMPDIR/file8
|
||||
ADS1023 aio-stress -I500 -o3 -O -r128 -t4 $TMPDIR/junkfile $TMPDIR/file2 $TMPDIR/file7 $TMPDIR/file8
|
||||
ADS1024 aio-stress -I500 -o3 -O -r256 -t8 $TMPDIR/junkfile $TMPDIR/file2 $TMPDIR/file7 $TMPDIR/file8 $TMPDIR/file4 $TMPDIR/file3 $TMPDIR/file5 $TMPDIR/file6
|
||||
ADS1025 aio-stress -I500 -o3 -O -r512 -t8 $TMPDIR/junkfile $TMPDIR/file2 $TMPDIR/file7 $TMPDIR/file8 $TMPDIR/file3 $TMPDIR/file4 $TMPDIR/file5 $TMPDIR/file6
|
||||
ADS1026 aio-stress -I500 -o0 -S -r4 -t8 $TMPDIR/junkfile $TMPDIR/file2 $TMPDIR/file7 $TMPDIR/file8 $TMPDIR/file3 $TMPDIR/file4 $TMPDIR/file5 $TMPDIR/file6
|
||||
ADS1027 aio-stress -I500 -o0 -S -r8 $TMPDIR/file2
|
||||
ADS1028 aio-stress -I500 -o0 -S -r16 $TMPDIR/file2
|
||||
ADS1029 aio-stress -I500 -o0 -S -r32 -t2 $TMPDIR/junkfile $TMPDIR/file2
|
||||
ADS1030 aio-stress -I500 -o0 -S -r64 -t2 $TMPDIR/junkfile $TMPDIR/file2
|
||||
ADS1031 aio-stress -I500 -o1 -S -r4 -t2 $TMPDIR/junkfile $TMPDIR/file2
|
||||
ADS1032 aio-stress -I500 -o1 -S -r8 -t2 $TMPDIR/junkfile $TMPDIR/file2
|
||||
ADS1033 aio-stress -I500 -o1 -S -r16 -t2 $TMPDIR/junkfile $TMPDIR/file2
|
||||
ADS1034 aio-stress -I500 -o1 -S -r32 -t4 $TMPDIR/junkfile $TMPDIR/file2 $TMPDIR/file7 $TMPDIR/file8
|
||||
ADS1035 aio-stress -I500 -o1 -S -r64 -t4 $TMPDIR/junkfile $TMPDIR/file2 $TMPDIR/file7 $TMPDIR/file8
|
||||
ADS1036 aio-stress -I500 -o1 -S -r128 -t4 $TMPDIR/junkfile $TMPDIR/file2 $TMPDIR/file7 $TMPDIR/file8
|
||||
ADS1037 aio-stress -I500 -o1 -S -r256 -t8 $TMPDIR/junkfile $TMPDIR/file2 $TMPDIR/file7 $TMPDIR/file8 $TMPDIR/file4 $TMPDIR/file3 $TMPDIR/file5 $TMPDIR/file6
|
||||
ADS1038 aio-stress -I500 -o1 -S -r512 -t8 -x $TMPDIR/junkfile $TMPDIR/file2 $TMPDIR/file7 $TMPDIR/file8 $TMPDIR/file3 $TMPDIR/file4 $TMPDIR/file5 $TMPDIR/file6
|
||||
ADS1039 aio-stress -I500 -o1 -O -r4 -t8 -x $TMPDIR/junkfile $TMPDIR/file2 $TMPDIR/file7 $TMPDIR/file8 $TMPDIR/file3 $TMPDIR/file4 $TMPDIR/file5 $TMPDIR/file6
|
||||
ADS1040 aio-stress -I500 -o1 -O -r8 -t2 -x $TMPDIR/junkfile $TMPDIR/file2
|
||||
ADS1041 aio-stress -I500 -o1 -O -r16 -t2 -x $TMPDIR/junkfile $TMPDIR/file2
|
||||
ADS1042 aio-stress -I500 -o1 -O -r32 -t2 $TMPDIR/junkfile $TMPDIR/file2
|
||||
ADS1043 aio-stress -I500 -o1 -O -r64 -t2 $TMPDIR/junkfile $TMPDIR/file2
|
||||
ADS1044 aio-stress -I500 -o1 -O -r4 -t4 $TMPDIR/junkfile $TMPDIR/file2 $TMPDIR/file7 $TMPDIR/file8
|
||||
ADS1045 aio-stress -I500 -o1 -O -r8 -t4 $TMPDIR/junkfile $TMPDIR/file2 $TMPDIR/file7 $TMPDIR/file8
|
||||
ADS1046 aio-stress -I500 -o1 -O -r16 -t4 $TMPDIR/junkfile $TMPDIR/file2 $TMPDIR/file7 $TMPDIR/file8
|
||||
ADS1047 aio-stress -I500 -o1 -O -r32 -t8 $TMPDIR/junkfile $TMPDIR/file2 $TMPDIR/file7 $TMPDIR/file8 $TMPDIR/file4 $TMPDIR/file3 $TMPDIR/file5 $TMPDIR/file6
|
||||
ADS1048 aio-stress -I500 -o1 -O -r64 -t8 $TMPDIR/junkfile $TMPDIR/file2 $TMPDIR/file7 $TMPDIR/file8 $TMPDIR/file3 $TMPDIR/file4 $TMPDIR/file5 $TMPDIR/file6
|
||||
ADS1049 aio-stress -I500 -o1 -O -r128 -t8 $TMPDIR/junkfile $TMPDIR/file2 $TMPDIR/file7 $TMPDIR/file8 $TMPDIR/file3 $TMPDIR/file4 $TMPDIR/file5 $TMPDIR/file6
|
||||
ADS1050 aio-stress -I500 -o1 -O -r256 -t2 $TMPDIR/junkfile $TMPDIR/file2
|
||||
@@ -1,38 +0,0 @@
|
||||
#DESCRIPTION:ltp A-sync IO Stress IO tests
|
||||
#
|
||||
# aio-stress [-s size] [-r size] [-a size] [-d num] [-b num]
|
||||
# [-i num] [-t num] [-c num] [-C size] [-nxhlvOS ]
|
||||
# file1 [file2 ...]
|
||||
# -a size in KB at which to align buffers
|
||||
# -b max number of iocbs to give io_submit at once
|
||||
# -c number of io contexts per file
|
||||
# -C offset between contexts, default 2MB
|
||||
# -s size in MB of the test file(s), default 1024MB
|
||||
# -r record size in KB used for each io, default 64KB
|
||||
# -d number of pending aio requests for each file, default 64
|
||||
# -i number of ios per file sent before switching
|
||||
# to the next file, default 8
|
||||
# -O Use O_DIRECT (not available in 2.4 kernels),
|
||||
# -S Use O_SYNC for writes
|
||||
# -o add an operation to the list: write=0, read=1,
|
||||
# random write=2, random read=3.
|
||||
# repeat -o to specify multiple ops: -o 0 -o 1 etc.
|
||||
# -m shm use ipc shared memory for io buffers instead of malloc
|
||||
# -m shmfs mmap a file in /dev/shm for io buffers
|
||||
# -n no fsyncs between write stage and read stage
|
||||
# -l print io_submit latencies after each stage
|
||||
# -t number of threads to run
|
||||
# -v verification of bytes written
|
||||
# -x turn off thread stonewalling
|
||||
# -h this message
|
||||
#
|
||||
ADS2001 aio-stress -I500 -o2 -S -r32 -t2 $TMPDIR/junkfile $TMPDIR/file2
|
||||
ADS2002 aio-stress -I500 -o3 -S -r8 -t2 $TMPDIR/junkfile $TMPDIR/file2
|
||||
ADS2003 aio-stress -I500 -o3 -S -r16 -t2 $TMPDIR/junkfile $TMPDIR/file2
|
||||
ADS2004 aio-stress -I500 -o3 -S -r32 -t4 $TMPDIR/junkfile $TMPDIR/file2 $TMPDIR/file3 $TMPDIR/file4
|
||||
ADS2005 aio-stress -I500 -o3 -S -r64 -t4 $TMPDIR/junkfile $TMPDIR/file2 $TMPDIR/file3 $TMPDIR/file4
|
||||
ADS2006 aio-stress -I500 -o2 -O -r32 -t2 $TMPDIR/junkfile $TMPDIR/file2
|
||||
ADS2007 aio-stress -I500 -o3 -O -r8 -t2 $TMPDIR/junkfile $TMPDIR/file2
|
||||
ADS2008 aio-stress -I500 -o3 -O -r16 -t2 $TMPDIR/junkfile $TMPDIR/file2
|
||||
ADS2009 aio-stress -I500 -o3 -O -r32 -t4 $TMPDIR/junkfile $TMPDIR/file2 $TMPDIR/file3 $TMPDIR/file4
|
||||
ADS2010 aio-stress -I500 -o3 -O -r64 -t4 $TMPDIR/junkfile $TMPDIR/file2 $TMPDIR/file3 $TMPDIR/file4
|
||||
@@ -1,8 +0,0 @@
|
||||
#DESCRIPTION:Remote Procedure Call
|
||||
#
|
||||
# PLEASE READ THE README FILE IN /rpc BEFORE RUNNING THESE.
|
||||
#
|
||||
rpc01 rpc01.sh
|
||||
rpcinfo rpcinfo01.sh
|
||||
rup rup01.sh
|
||||
rusers rusers01.sh
|
||||
@@ -1,4 +0,0 @@
|
||||
#! /bin/csh
|
||||
|
||||
echo "this is a shell script"
|
||||
echo "used to test file command"
|
||||
@@ -1,4 +0,0 @@
|
||||
#! /bin/ksh
|
||||
|
||||
echo "this is a shell script"
|
||||
echo "used to test file command"
|
||||
@@ -1,14 +0,0 @@
|
||||
/check_for_unshare
|
||||
mountns/mountns01
|
||||
mountns/mountns02
|
||||
mountns/mountns03
|
||||
mountns/mountns04
|
||||
userns/userns01
|
||||
userns/userns02
|
||||
userns/userns03
|
||||
userns/userns04
|
||||
userns/userns05
|
||||
userns/userns06_capcheck
|
||||
userns/userns06
|
||||
userns/userns07
|
||||
userns/userns08
|
||||
@@ -1,45 +0,0 @@
|
||||
#
|
||||
# kernel/containers testcase suite common definitions Makefile.
|
||||
#
|
||||
# Copyright (C) 2009, Cisco Systems Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Ngie Cooper, July 2009
|
||||
#
|
||||
|
||||
# DO NOT USE THIS FILE FOR containers / libclone!!!
|
||||
|
||||
LIBDIR := ../libclone
|
||||
|
||||
LIBS := $(LIBDIR)/libclone.a
|
||||
|
||||
CPPFLAGS += -I$(abs_srcdir)/$(LIBDIR)
|
||||
|
||||
LDFLAGS += -L$(abs_builddir)/$(LIBDIR)
|
||||
|
||||
$(LIBDIR):
|
||||
mkdir -p "$@"
|
||||
|
||||
# Make the target the real lib so we don't have to deal with rebuilding this
|
||||
# every time the dependency is evaluated, like with PHONY rules.
|
||||
$(LIBS): $(LIBDIR)
|
||||
$(MAKE) -C $^ -f "$(abs_srcdir)/$^/Makefile" all
|
||||
|
||||
INSTALL_TARGETS ?= *.sh
|
||||
|
||||
MAKE_DEPS := $(LIBS)
|
||||
|
||||
# vim: syntax=make
|
||||
@@ -1,50 +0,0 @@
|
||||
################################################################################
|
||||
## ##
|
||||
## Copyright (c) International Business Machines Corp., 2007 ##
|
||||
## ##
|
||||
## This program is free software; you can redistribute it and#or modify ##
|
||||
## it under the terms of the GNU General Public License as published by ##
|
||||
## the Free Software Foundation; either version 2 of the License, or ##
|
||||
## (at your option) any later version. ##
|
||||
## ##
|
||||
## This program is distributed in the hope that it will be useful, but ##
|
||||
## WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ##
|
||||
## or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ##
|
||||
## for more details. ##
|
||||
## ##
|
||||
## You should have received a copy of the GNU General Public License ##
|
||||
## along with this program; if not, write to the Free Software ##
|
||||
## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ##
|
||||
## ##
|
||||
################################################################################
|
||||
|
||||
CONTAINER TESTS AUTOMATION SUITE
|
||||
----------------------------
|
||||
The tests requires the Kernel to be compiled with the following configs
|
||||
|
||||
CONFIG_DUMMY=y(or =m)
|
||||
CONFIG_NAMESPACES=y
|
||||
CONFIG_UTS_NS=y
|
||||
CONFIG_IPC_NS=y
|
||||
CONFIG_USER_NS=y
|
||||
CONFIG_PID_NS=y
|
||||
CONFIG_NET_NS=y
|
||||
CONFIG_VETH=y(or =m)
|
||||
CONFIG_MACVLAN=y(optional)
|
||||
|
||||
The container test automation suite helps run the container functionality
|
||||
(e.g: utsname etc..) tests and report results. Please refer the following
|
||||
each functionality README file for detail:
|
||||
|
||||
sysvipc/*
|
||||
Contains all the testcases related to IPC NS tests.
|
||||
posixmq/*
|
||||
Contains all the testcases related to POSIX MQ NS tests. These
|
||||
are strictly speaking a part of the ipc namespaces, but can be
|
||||
enabled in the kernel without SYSV IPC support.
|
||||
utsname/*
|
||||
Contains all the testcases related to utsname tests.
|
||||
libclone/*
|
||||
Contains the library API for clone() .
|
||||
netns/*
|
||||
Contains the testcases related to the network NS tests.
|
||||
@@ -1,27 +0,0 @@
|
||||
################################################################################
|
||||
## Copyright (c) International Business Machines Corp., 2007
|
||||
##
|
||||
## This program is free software; you can redistribute it and#or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2 of the License, or
|
||||
## (at your option) any later version.
|
||||
## This program is distributed in the hope that it will be useful, but
|
||||
## WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
## or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
## for more details.
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, write to the Free Software
|
||||
## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
################################################################################
|
||||
|
||||
Following are tentative Testcases to be included into LTP-Containers in future:
|
||||
|
||||
NAME TENTATIVE-TIME
|
||||
=================================================================================
|
||||
PID NAMESPACES (NEAR FUTURE)
|
||||
NETWORK NAMESPACES (NEAR FUTURE)
|
||||
POSIX IPC NAMESPACES (NEAR FUTURE)
|
||||
TTY+CONSOLE+DEVPTS NAMESPACES (NEAR FUTURE)
|
||||
PROC+SYSFS ISOLATION (NEAR FUTURE)
|
||||
PER-CONTAINER CAPABILITY/SECURITY TESTS (NEAR FUTURE)
|
||||
=================================================================================
|
||||
@@ -1,27 +0,0 @@
|
||||
################################################################################
|
||||
## ##
|
||||
## Copyright (c) International Business Machines Corp., 2007 ##
|
||||
## ##
|
||||
## This program is free software; you can redistribute it and#or modify ##
|
||||
## it under the terms of the GNU General Public License as published by ##
|
||||
## the Free Software Foundation; either version 2 of the License, or ##
|
||||
## (at your option) any later version. ##
|
||||
## ##
|
||||
## This program is distributed in the hope that it will be useful, but ##
|
||||
## WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ##
|
||||
## or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ##
|
||||
## for more details. ##
|
||||
## ##
|
||||
## You should have received a copy of the GNU General Public License ##
|
||||
## along with this program; if not, write to the Free Software ##
|
||||
## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ##
|
||||
## ##
|
||||
################################################################################
|
||||
|
||||
top_srcdir ?= ../../../..
|
||||
|
||||
include $(top_srcdir)/include/mk/testcases.mk
|
||||
|
||||
INTERNAL_LIB := libclone.a
|
||||
|
||||
include $(top_srcdir)/include/mk/lib.mk
|
||||
@@ -1,142 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) International Business Machines Corp., 2007
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
|
||||
* the GNU General Public License for more details.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
***************************************************************************/
|
||||
#include "libclone.h"
|
||||
|
||||
int do_clone_tests(unsigned long clone_flags,
|
||||
int (*fn1) (void *arg), void *arg1,
|
||||
int (*fn2) (void *arg), void *arg2)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ltp_clone_quick(clone_flags | SIGCHLD, fn1, arg1);
|
||||
|
||||
if (ret == -1) {
|
||||
return -1;
|
||||
}
|
||||
if (fn2)
|
||||
ret = fn2(arg2);
|
||||
else
|
||||
ret = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int do_unshare_tests(unsigned long clone_flags,
|
||||
int (*fn1) (void *arg), void *arg1,
|
||||
int (*fn2) (void *arg), void *arg2)
|
||||
{
|
||||
int pid, ret = 0;
|
||||
int retpipe[2];
|
||||
char buf[2];
|
||||
|
||||
if (pipe(retpipe) == -1) {
|
||||
perror("pipe");
|
||||
return -1;
|
||||
}
|
||||
pid = fork();
|
||||
if (pid == -1) {
|
||||
perror("fork");
|
||||
close(retpipe[0]);
|
||||
close(retpipe[1]);
|
||||
return -1;
|
||||
}
|
||||
if (pid == 0) {
|
||||
close(retpipe[0]);
|
||||
ret = ltp_syscall(SYS_unshare, clone_flags);
|
||||
if (ret == -1) {
|
||||
if (write(retpipe[1], "0", 2) < 0) {
|
||||
perror("unshare:write(retpipe[1], ..)");
|
||||
}
|
||||
close(retpipe[1]);
|
||||
exit(1);
|
||||
} else {
|
||||
if (write(retpipe[1], "1", 2) < 0) {
|
||||
perror("unshare:write(retpipe[1], ..)");
|
||||
}
|
||||
}
|
||||
close(retpipe[1]);
|
||||
ret = fn1(arg1);
|
||||
exit(ret);
|
||||
} else {
|
||||
close(retpipe[1]);
|
||||
if (read(retpipe[0], &buf, 2) < 0) {
|
||||
perror("unshare:read(retpipe[0], ..)");
|
||||
}
|
||||
close(retpipe[0]);
|
||||
if (*buf == '0')
|
||||
return -1;
|
||||
if (fn2)
|
||||
ret = fn2(arg2);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int do_plain_tests(int (*fn1) (void *arg), void *arg1,
|
||||
int (*fn2) (void *arg), void *arg2)
|
||||
{
|
||||
int ret = 0, pid;
|
||||
|
||||
pid = fork();
|
||||
if (pid == -1) {
|
||||
perror("fork");
|
||||
return -1;
|
||||
}
|
||||
if (pid == 0)
|
||||
exit(fn1(arg1));
|
||||
if (fn2)
|
||||
ret = fn2(arg2);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int do_clone_unshare_test(int use_clone, unsigned long clone_flags,
|
||||
int (*fn1) (void *arg), void *arg1)
|
||||
{
|
||||
switch (use_clone) {
|
||||
case T_NONE:
|
||||
return do_plain_tests(fn1, arg1, NULL, NULL);
|
||||
case T_CLONE:
|
||||
return do_clone_tests(clone_flags, fn1, arg1, NULL, NULL);
|
||||
case T_UNSHARE:
|
||||
return do_unshare_tests(clone_flags, fn1, arg1, NULL, NULL);
|
||||
default:
|
||||
printf("%s: bad use_clone option: %d\n", __FUNCTION__,
|
||||
use_clone);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Run fn1 in a unshared environmnent, and fn2 in the original context
|
||||
*/
|
||||
int do_clone_unshare_tests(int use_clone, unsigned long clone_flags,
|
||||
int (*fn1) (void *arg), void *arg1,
|
||||
int (*fn2) (void *arg), void *arg2)
|
||||
{
|
||||
switch (use_clone) {
|
||||
case T_NONE:
|
||||
return do_plain_tests(fn1, arg1, fn2, arg2);
|
||||
case T_CLONE:
|
||||
return do_clone_tests(clone_flags, fn1, arg1, fn2, arg2);
|
||||
case T_UNSHARE:
|
||||
return do_unshare_tests(clone_flags, fn1, arg1, fn2, arg2);
|
||||
default:
|
||||
printf("%s: bad use_clone option: %d\n", __FUNCTION__,
|
||||
use_clone);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) International Business Machines Corp., 2007
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
|
||||
* the GNU General Public License for more details.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
***************************************************************************/
|
||||
#ifndef __LIBCLONE_H
|
||||
#define __LIBCLONE_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sched.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <libgen.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <signal.h>
|
||||
#include "lapi/syscalls.h"
|
||||
#include "test.h"
|
||||
#include "lapi/namespaces_constants.h"
|
||||
|
||||
#define T_UNSHARE 0
|
||||
#define T_CLONE 1
|
||||
#define T_NONE 2
|
||||
|
||||
#ifndef SYS_unshare
|
||||
#ifdef __NR_unshare
|
||||
#define SYS_unshare __NR_unshare
|
||||
#elif __i386__
|
||||
#define SYS_unshare 310
|
||||
#elif __ia64__
|
||||
#define SYS_unshare 1296
|
||||
#elif __x86_64__
|
||||
#define SYS_unshare 272
|
||||
#elif __s390x__ || __s390__
|
||||
#define SYS_unshare 303
|
||||
#elif __powerpc__
|
||||
#define SYS_unshare 282
|
||||
#else
|
||||
#error "unshare not supported on this architecure."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef __NR_unshare
|
||||
#define __NR_unshare SYS_unshare
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Run fn1 in a unshared environmnent, and fn2 in the original context
|
||||
* Fn2 may be NULL.
|
||||
*/
|
||||
|
||||
int do_clone_tests(unsigned long clone_flags,
|
||||
int(*fn1)(void *arg), void *arg1,
|
||||
int(*fn2)(void *arg), void *arg2);
|
||||
|
||||
int do_unshare_tests(unsigned long clone_flags,
|
||||
int (*fn1)(void *arg), void *arg1,
|
||||
int (*fn2)(void *arg), void *arg2);
|
||||
|
||||
int do_fork_tests(int (*fn1)(void *arg), void *arg1,
|
||||
int (*fn2)(void *arg), void *arg2);
|
||||
|
||||
int do_clone_unshare_test(int use_clone, unsigned long clone_flags,
|
||||
int (*fn1)(void *arg), void *arg1);
|
||||
|
||||
int do_clone_unshare_tests(int use_clone, unsigned long clone_flags,
|
||||
int (*fn1)(void *arg), void *arg1,
|
||||
int (*fn2)(void *arg), void *arg2);
|
||||
|
||||
#endif
|
||||
@@ -1,61 +0,0 @@
|
||||
/* Copyright (c) 2014 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of version 2 the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "libclone.h"
|
||||
#include "test.h"
|
||||
#include "safe_macros.h"
|
||||
|
||||
#define DIRA "A"
|
||||
#define DIRB "B"
|
||||
|
||||
static int dummy_child(void *v)
|
||||
{
|
||||
(void) v;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_newns(void)
|
||||
{
|
||||
int pid, status;
|
||||
|
||||
if (tst_kvercmp(2, 4, 19) < 0)
|
||||
tst_brkm(TCONF, NULL, "CLONE_NEWNS not supported");
|
||||
|
||||
pid = do_clone_unshare_test(T_CLONE, CLONE_NEWNS, dummy_child, NULL);
|
||||
if (pid == -1)
|
||||
tst_brkm(TCONF | TERRNO, NULL, "CLONE_NEWNS not supported");
|
||||
SAFE_WAIT(NULL, &status);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cleanup(void)
|
||||
{
|
||||
umount(DIRA);
|
||||
umount(DIRB);
|
||||
tst_rmdir();
|
||||
}
|
||||
|
||||
static void setup(void)
|
||||
{
|
||||
tst_require_root();
|
||||
check_newns();
|
||||
tst_tmpdir();
|
||||
TST_CHECKPOINT_INIT(tst_rmdir);
|
||||
SAFE_MKDIR(cleanup, DIRA, 0777);
|
||||
SAFE_MKDIR(cleanup, DIRB, 0777);
|
||||
SAFE_TOUCH(cleanup, DIRA"/A", 0, NULL);
|
||||
SAFE_TOUCH(cleanup, DIRB"/B", 0, NULL);
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
#ifndef __MQNS_H
|
||||
#define __MQNS_H
|
||||
|
||||
#define DEV_MQUEUE "/dev/mqueue"
|
||||
#define DEV_MQUEUE2 "/dev/mqueue2"
|
||||
#define SLASH_MQ1 "/MQ1"
|
||||
#define NOSLASH_MQ1 "MQ1"
|
||||
#define SLASH_MQ2 "/MQ2"
|
||||
#define NOSLASH_MQ2 "MQ2"
|
||||
|
||||
#endif /* __MQNS_H */
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) International Business Machines Corp., 2009
|
||||
* Copyright (c) Nadia Derbey, 2009
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
|
||||
* the GNU General Public License for more details.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Author: Serge Hallyn <serue@us.ibm.com>
|
||||
***************************************************************************/
|
||||
#include <sys/mount.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <mqueue.h>
|
||||
#include "../libclone/libclone.h"
|
||||
#include "lapi/syscalls.h"
|
||||
#include "safe_macros.h"
|
||||
#include "test.h"
|
||||
|
||||
static int dummy_child(void *v)
|
||||
{
|
||||
(void) v;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void check_mqns(void)
|
||||
{
|
||||
int pid, status;
|
||||
mqd_t mqd;
|
||||
|
||||
if (tst_kvercmp(2, 6, 30) < 0)
|
||||
tst_brkm(TCONF, NULL, "Kernel version is lower than expected");
|
||||
|
||||
mq_unlink("/checkmqnsenabled");
|
||||
mqd =
|
||||
mq_open("/checkmqnsenabled", O_RDWR | O_CREAT | O_EXCL, 0777, NULL);
|
||||
if (mqd == -1)
|
||||
tst_brkm(TCONF, NULL, "mq_open check failed");
|
||||
|
||||
mq_close(mqd);
|
||||
mq_unlink("/checkmqnsenabled");
|
||||
|
||||
pid = do_clone_unshare_test(T_CLONE, CLONE_NEWIPC, dummy_child, NULL);
|
||||
if (pid == -1)
|
||||
tst_brkm(TCONF | TERRNO, NULL, "CLONE_NEWIPC not supported");
|
||||
|
||||
SAFE_WAIT(NULL, &status);
|
||||
}
|
||||
@@ -1,278 +0,0 @@
|
||||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
# Copyright (c) Linux Test Project, 2014-2021
|
||||
# Copyright (c) 2015 Red Hat, Inc.
|
||||
|
||||
TST_CLEANUP=netns_ns_exec_cleanup
|
||||
TST_NEEDS_ROOT=1
|
||||
TST_NEEDS_CMDS="ip ping"
|
||||
TST_NEEDS_DRIVERS="veth"
|
||||
. tst_test.sh
|
||||
|
||||
# Set to 1 only for test cases using ifconfig (ioctl).
|
||||
USE_IFCONFIG=0
|
||||
|
||||
# Variables which can be used in test cases (set by netns_setup() function):
|
||||
|
||||
# Use in test cases to execute commands inside a namespace. Set to 'ns_exec' or
|
||||
# 'ip netns exec' command according to NS_EXEC_PROGRAM argument specified in
|
||||
# netns_setup() function call.
|
||||
NS_EXEC=
|
||||
|
||||
# Set to "net" for ns_create/ns_exec as their options requires
|
||||
# to specify a namespace type. Empty for ip command.
|
||||
NS_TYPE=
|
||||
|
||||
# IP addresses of veth0 (IP0) and veth1 (IP1) devices (ipv4/ipv6 variant
|
||||
# is determined according to the IP_VERSION argument specified in netns_setup()
|
||||
# function call.
|
||||
IP0=
|
||||
IP1=
|
||||
NETMASK=
|
||||
|
||||
# 'ping' or 'ping6' according to the IP_VERSION argument specified
|
||||
# in netns_setup() function call.
|
||||
tping=
|
||||
|
||||
# Network namespaces handles for manipulating and executing commands inside
|
||||
# namespaces. For 'ns_exec' handles are PIDs of daemonized processes running
|
||||
# in namespaces.
|
||||
NS_HANDLE0=
|
||||
NS_HANDLE1=
|
||||
|
||||
# Adds "inet6 add" to the 'ifconfig' arguments which is required for the ipv6
|
||||
# version. Always use with 'ifconfig', even if ipv4 version of a test case is
|
||||
# used, in which case IFCONF_IN6_ARG will be empty string. Usage:
|
||||
# ifconfig <device> $IFCONF_IN6_ARG IP/NETMASK
|
||||
IFCONF_IN6_ARG=
|
||||
|
||||
# Sets up global variables which can be used in test cases (documented above),
|
||||
# creates two network namespaces and a pair of virtual ethernet devices, each
|
||||
# device in one namespace. Each device is then enabled and assigned an IP
|
||||
# address according to the function parameters. IFCONF_IN6_ARG variable is set
|
||||
# only if ipv6 variant of test case is used (determined by IP_VERSION argument).
|
||||
#
|
||||
# SYNOPSIS:
|
||||
# netns_setup <NS_EXEC_PROGRAM> <IP_VERSION> <COMM_TYPE> <IP4_VETH0>
|
||||
# <IP4_VETH1> <IP6_VETH0> <IP6_VETH1>
|
||||
#
|
||||
# OPTIONS:
|
||||
# * NS_EXEC_PROGRAM (ns_exec|ip)
|
||||
# Program which will be used to enter and run other commands
|
||||
# inside a network namespace.
|
||||
# * IP_VERSION (ipv4|ipv6)
|
||||
# Version of IP. (ipv4|ipv6)
|
||||
# * COMM_TYPE (netlink|ioctl)
|
||||
# Communication type between kernel and user space
|
||||
# for enabling and assigning IP addresses to the virtual
|
||||
# ethernet devices. Uses 'ip' command for netlink and 'ifconfig'
|
||||
# for ioctl. (If set to ioctl, function also checks the existance
|
||||
# of the 'ifconfig' command.)
|
||||
# * IP4_VETH0, IP4_VETH1
|
||||
# IPv4 addresses for veth0 and veth1 devices.
|
||||
# * IP6_VETH0, IP6_VETH1
|
||||
# IPv6 addresses for veth0 and veth1 devices.
|
||||
#
|
||||
# On success function returns, on error tst_brk is called and TC is terminated.
|
||||
netns_setup()
|
||||
{
|
||||
case "$1" in
|
||||
ns_exec)
|
||||
setns_check
|
||||
[ $? -eq 32 ] && tst_brk TCONF "setns not supported"
|
||||
|
||||
NS_TYPE="net"
|
||||
netns_ns_exec_setup
|
||||
TST_CLEANUP=netns_ns_exec_cleanup
|
||||
;;
|
||||
ip)
|
||||
netns_ip_setup
|
||||
TST_CLEANUP=netns_ip_cleanup
|
||||
;;
|
||||
*)
|
||||
tst_brk TBROK \
|
||||
"first argument must be a program used to enter a network namespace (ns_exec|ip)"
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$3" in
|
||||
netlink)
|
||||
;;
|
||||
ioctl)
|
||||
USE_IFCONFIG=1
|
||||
tst_require_cmds ifconfig
|
||||
;;
|
||||
*)
|
||||
tst_brk TBROK \
|
||||
"third argument must be a comm. type between kernel and user space (netlink|ioctl)"
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "$4" ]; then
|
||||
tst_brk TBROK "fourth argument must be the IPv4 address for veth0"
|
||||
fi
|
||||
if [ -z "$5" ]; then
|
||||
tst_brk TBROK "fifth argument must be the IPv4 address for veth1"
|
||||
fi
|
||||
if [ -z "$6" ]; then
|
||||
tst_brk TBROK "sixth argument must be the IPv6 address for veth0"
|
||||
fi
|
||||
if [ -z "$7" ]; then
|
||||
tst_brk TBROK "seventh argument must be the IPv6 address for veth1"
|
||||
fi
|
||||
|
||||
case "$2" in
|
||||
ipv4)
|
||||
IP0=$4
|
||||
IP1=$5
|
||||
tping="ping"
|
||||
NETMASK=24
|
||||
;;
|
||||
ipv6)
|
||||
IFCONF_IN6_ARG="inet6 add"
|
||||
IP0=$6
|
||||
IP1=$7
|
||||
|
||||
if tst_cmd_available ping6; then
|
||||
tping="ping6"
|
||||
else
|
||||
tping="ping -6"
|
||||
tst_res_ TINFO "ping6 binary/symlink is missing, using workaround. Please, report missing ping6 to your distribution."
|
||||
fi
|
||||
NETMASK=64
|
||||
;;
|
||||
*)
|
||||
tst_brk TBROK "second argument must be an ip version (ipv4|ipv6)"
|
||||
;;
|
||||
esac
|
||||
|
||||
netns_set_ip
|
||||
}
|
||||
|
||||
# Sets up NS_EXEC to use 'ns_exec', creates two network namespaces and stores
|
||||
# their handles into NS_HANDLE0 and NS_HANDLE1 variables (in this case handles
|
||||
# are PIDs of daemonized processes running in these namespaces). Virtual
|
||||
# ethernet device is then created for each namespace.
|
||||
netns_ns_exec_setup()
|
||||
{
|
||||
local ret
|
||||
|
||||
NS_EXEC="ns_exec"
|
||||
|
||||
NS_HANDLE0=$(ns_create $NS_TYPE)
|
||||
if [ $? -eq 1 ]; then
|
||||
tst_res TINFO "$NS_HANDLE0"
|
||||
tst_brk TBROK "unable to create a new network namespace"
|
||||
fi
|
||||
|
||||
NS_HANDLE1=$(ns_create $NS_TYPE)
|
||||
if [ $? -eq 1 ]; then
|
||||
tst_res TINFO "$NS_HANDLE1"
|
||||
tst_brk TBROK "unable to create a new network namespace"
|
||||
fi
|
||||
|
||||
$NS_EXEC $NS_HANDLE0 $NS_TYPE ip link add veth0 type veth peer name veth1 || \
|
||||
tst_brk TBROK "unable to create veth pair devices"
|
||||
|
||||
$NS_EXEC $NS_HANDLE0 $NS_TYPE ns_ifmove veth1 $NS_HANDLE1
|
||||
ret=$?
|
||||
[ $ret -eq 0 ] && return
|
||||
[ $ret -eq 32 ] && tst_brk TCONF "IFLA_NET_NS_PID not supported"
|
||||
|
||||
tst_brk TBROK "unable to add device veth1 to the separate network namespace"
|
||||
}
|
||||
|
||||
# Sets up NS_EXEC to use 'ip netns exec', creates two network namespaces
|
||||
# and stores their handles into NS_HANDLE0 and NS_HANDLE1 variables. Virtual
|
||||
# ethernet device is then created for each namespace.
|
||||
netns_ip_setup()
|
||||
{
|
||||
ip netns > /dev/null || \
|
||||
tst_brk TCONF "ip without netns support (required iproute2 >= ss111010 - v3.0.0)"
|
||||
|
||||
NS_EXEC="ip netns exec"
|
||||
|
||||
NS_HANDLE0=tst_net_ns0
|
||||
NS_HANDLE1=tst_net_ns1
|
||||
|
||||
ip netns del $NS_HANDLE0 2>/dev/null
|
||||
ip netns del $NS_HANDLE1 2>/dev/null
|
||||
|
||||
ip netns add $NS_HANDLE0 || \
|
||||
tst_brk TBROK "unable to create a new network namespace"
|
||||
ip netns add $NS_HANDLE1 || \
|
||||
tst_brk TBROK "unable to create a new network namespace"
|
||||
|
||||
$NS_EXEC $NS_HANDLE0 ip link add veth0 type veth peer name veth1 || \
|
||||
tst_brk TBROK "unable to create veth pair devices"
|
||||
|
||||
$NS_EXEC $NS_HANDLE0 ip link set veth1 netns $NS_HANDLE1 || \
|
||||
tst_brk TBROK "unable to add device veth1 to the separate network namespace"
|
||||
}
|
||||
|
||||
# Enables virtual ethernet devices and assigns IP addresses for both
|
||||
# of them (IPv4/IPv6 variant is decided by netns_setup() function).
|
||||
netns_set_ip()
|
||||
{
|
||||
[ "$NS_EXEC" ] || tst_brk TBROK "netns_setup() function must be called first"
|
||||
|
||||
# This applies only for ipv6 variant:
|
||||
# Do not accept Router Advertisements (accept_ra) and do not use
|
||||
# Duplicate Address Detection (accept_dad) which uses Neighbor
|
||||
# Discovery Protocol - the problem is that until DAD can confirm that
|
||||
# there is no other host with the same address, the address is
|
||||
# considered to be "tentative" (attempts to bind() to the address fail
|
||||
# with EADDRNOTAVAIL) which may cause problems for tests using ipv6.
|
||||
echo 0 | $NS_EXEC $NS_HANDLE0 $NS_TYPE \
|
||||
tee /proc/sys/net/ipv6/conf/veth0/accept_dad \
|
||||
/proc/sys/net/ipv6/conf/veth0/accept_ra >/dev/null
|
||||
echo 0 | $NS_EXEC $NS_HANDLE1 $NS_TYPE \
|
||||
tee /proc/sys/net/ipv6/conf/veth1/accept_dad \
|
||||
/proc/sys/net/ipv6/conf/veth1/accept_ra >/dev/null
|
||||
|
||||
case $USE_IFCONFIG in
|
||||
1)
|
||||
$NS_EXEC $NS_HANDLE0 $NS_TYPE ifconfig veth0 $IFCONF_IN6_ARG $IP0/$NETMASK ||
|
||||
tst_brk TBROK "adding address to veth0 failed"
|
||||
$NS_EXEC $NS_HANDLE1 $NS_TYPE ifconfig veth1 $IFCONF_IN6_ARG $IP1/$NETMASK ||
|
||||
tst_brk TBROK "adding address to veth1 failed"
|
||||
$NS_EXEC $NS_HANDLE0 $NS_TYPE ifconfig veth0 up ||
|
||||
tst_brk TBROK "enabling veth0 device failed"
|
||||
$NS_EXEC $NS_HANDLE1 $NS_TYPE ifconfig veth1 up ||
|
||||
tst_brk TBROK "enabling veth1 device failed"
|
||||
;;
|
||||
*)
|
||||
$NS_EXEC $NS_HANDLE0 $NS_TYPE ip address add $IP0/$NETMASK dev veth0 ||
|
||||
tst_brk TBROK "adding address to veth0 failed"
|
||||
$NS_EXEC $NS_HANDLE1 $NS_TYPE ip address add $IP1/$NETMASK dev veth1 ||
|
||||
tst_brk TBROK "adding address to veth1 failed"
|
||||
$NS_EXEC $NS_HANDLE0 $NS_TYPE ip link set veth0 up ||
|
||||
tst_brk TBROK "enabling veth0 device failed"
|
||||
$NS_EXEC $NS_HANDLE1 $NS_TYPE ip link set veth1 up ||
|
||||
tst_brk TBROK "enabling veth1 device failed"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
netns_ns_exec_cleanup()
|
||||
{
|
||||
[ "$NS_EXEC" ] || return
|
||||
|
||||
# removes veth0 device (which also removes the paired veth1 device)
|
||||
$NS_EXEC $NS_HANDLE0 $NS_TYPE ip link delete veth0
|
||||
|
||||
kill -9 $NS_HANDLE0 2>/dev/null
|
||||
kill -9 $NS_HANDLE1 2>/dev/null
|
||||
}
|
||||
|
||||
|
||||
netns_ip_cleanup()
|
||||
{
|
||||
[ "$NS_EXEC" ] || return
|
||||
|
||||
# removes veth0 device (which also removes the paired veth1 device)
|
||||
$NS_EXEC $NS_HANDLE0 ip link delete veth0
|
||||
|
||||
ip netns del $NS_HANDLE0 2>/dev/null
|
||||
ip netns del $NS_HANDLE1 2>/dev/null
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) International Business Machines Corp., 2007
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
|
||||
* the GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "../libclone/libclone.h"
|
||||
#include "test.h"
|
||||
#include "safe_macros.h"
|
||||
|
||||
static int dummy_child(void *v)
|
||||
{
|
||||
(void) v;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_newpid(void)
|
||||
{
|
||||
int pid, status;
|
||||
|
||||
if (tst_kvercmp(2, 6, 24) < 0)
|
||||
tst_brkm(TCONF, NULL, "CLONE_NEWPID not supported");
|
||||
|
||||
pid = do_clone_unshare_test(T_CLONE, CLONE_NEWPID, dummy_child, NULL);
|
||||
if (pid == -1)
|
||||
tst_brkm(TCONF | TERRNO, NULL, "CLONE_NEWPID not supported");
|
||||
SAFE_WAIT(NULL, &status);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
/ns_ifmove
|
||||
/ns_create
|
||||
/ns_exec
|
||||
/setns_check
|
||||
@@ -1,22 +0,0 @@
|
||||
# Copyright (c) 2015 Red Hat, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of version 2 the GNU General Public License as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
##############################################################################
|
||||
top_srcdir ?= ../../../..
|
||||
|
||||
include $(top_srcdir)/include/mk/testcases.mk
|
||||
include $(abs_srcdir)/../Makefile.inc
|
||||
|
||||
LDLIBS := -lltp
|
||||
|
||||
include $(top_srcdir)/include/mk/generic_leaf_target.mk
|
||||
@@ -1,55 +0,0 @@
|
||||
/* Copyright (c) 2015 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of version 2 the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
#ifndef __NS_COMMON_H__
|
||||
#define __NS_COMMON_H__
|
||||
#include <sched.h>
|
||||
#include "lapi/namespaces_constants.h"
|
||||
|
||||
#define PROC_PATH "/proc"
|
||||
#define NS_TOTAL 6
|
||||
|
||||
|
||||
struct param {
|
||||
const char *name;
|
||||
int flag;
|
||||
};
|
||||
|
||||
struct param params[] = {
|
||||
{"ipc", CLONE_NEWIPC},
|
||||
{"mnt", CLONE_NEWNS},
|
||||
{"net", CLONE_NEWNET},
|
||||
{"pid", CLONE_NEWPID},
|
||||
{"user", CLONE_NEWUSER},
|
||||
{"uts", CLONE_NEWUTS},
|
||||
{NULL, 0}
|
||||
};
|
||||
|
||||
|
||||
struct param *get_param(const char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; params[i].name; i++) {
|
||||
if (!strcasecmp(params[i].name, name))
|
||||
return params + i;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,109 +0,0 @@
|
||||
/* Copyright (c) 2015 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of version 2 the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Written by Matus Marhefka <mmarhefk@redhat.com>
|
||||
*
|
||||
***********************************************************************
|
||||
* Creates a child process in the new specified namespace(s), child is then
|
||||
* daemonized and is running in the background. PID of the daemonized child
|
||||
* process is printed on the stdout. As the new namespace(s) is(are) maintained
|
||||
* by the daemonized child process it(they) can be removed by killing this
|
||||
* process.
|
||||
*
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <sched.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "test.h"
|
||||
#include "lapi/namespaces_constants.h"
|
||||
#include "ns_common.h"
|
||||
|
||||
char *TCID = "ns_create";
|
||||
|
||||
|
||||
void print_help(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("usage: ns_create <%s", params[0].name);
|
||||
|
||||
for (i = 1; params[i].name; i++)
|
||||
printf("|,%s", params[i].name);
|
||||
printf(">\nThe only argument is a comma separated list "
|
||||
"of namespaces to create.\nExample: ns_create net,ipc\n");
|
||||
}
|
||||
|
||||
static int child_fn(void *arg LTP_ATTRIBUTE_UNUSED)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (setsid() == -1) {
|
||||
tst_resm(TINFO | TERRNO, "setsid");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (chdir("/") == -1) {
|
||||
tst_resm(TINFO | TERRNO, "chdir");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* close all inherrited file descriptors */
|
||||
for (i = 0; i < sysconf(_SC_OPEN_MAX); i++)
|
||||
close(i);
|
||||
|
||||
pause();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ./ns_create <ipc,mnt,net,pid,user,uts>
|
||||
*/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int pid, flags;
|
||||
char *token;
|
||||
|
||||
if (argc < 2) {
|
||||
print_help();
|
||||
return 1;
|
||||
}
|
||||
|
||||
flags = 0;
|
||||
while ((token = strsep(&argv[1], ","))) {
|
||||
struct param *p = get_param(token);
|
||||
|
||||
if (!p) {
|
||||
tst_resm(TINFO, "Unknown namespace: %s", token);
|
||||
print_help();
|
||||
return 1;
|
||||
}
|
||||
|
||||
flags |= p->flag;
|
||||
}
|
||||
|
||||
pid = ltp_clone_quick(flags | SIGCHLD, child_fn, NULL);
|
||||
if (pid == -1) {
|
||||
tst_resm(TINFO | TERRNO, "ltp_clone_quick");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("%d", pid);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,158 +0,0 @@
|
||||
/* Copyright (c) 2015 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of version 2 the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Written by Matus Marhefka <mmarhefk@redhat.com>
|
||||
*
|
||||
***********************************************************************
|
||||
* Enters the namespace(s) of a process specified by a PID and then executes
|
||||
* the indicated program inside that namespace(s).
|
||||
*
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <sched.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "test.h"
|
||||
#include "lapi/syscalls.h"
|
||||
#include "lapi/namespaces_constants.h"
|
||||
#include "ns_common.h"
|
||||
|
||||
char *TCID = "ns_exec";
|
||||
int ns_fd[NS_TOTAL];
|
||||
int ns_fds;
|
||||
|
||||
|
||||
void print_help(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("usage: ns_exec <NS_PID> <%s", params[0].name);
|
||||
|
||||
for (i = 1; params[i].name; i++)
|
||||
printf("|,%s", params[i].name);
|
||||
printf("> <PROGRAM> [ARGS]\nSecond argument indicates the types"
|
||||
" of a namespaces maintained by NS_PID\nand is specified"
|
||||
" as a comma separated list.\nExample: ns_exec 1234 net,ipc"
|
||||
" ip a\n");
|
||||
}
|
||||
|
||||
static int open_ns_fd(const char *pid, const char *ns)
|
||||
{
|
||||
int fd;
|
||||
char file_buf[30];
|
||||
|
||||
sprintf(file_buf, "%s/%s/ns/%s", PROC_PATH, pid, ns);
|
||||
|
||||
fd = open(file_buf, O_RDONLY);
|
||||
if (fd > 0) {
|
||||
ns_fd[ns_fds] = fd;
|
||||
++ns_fds;
|
||||
return 0;
|
||||
} else if (fd == -1 && errno != ENOENT) {
|
||||
tst_resm(TINFO | TERRNO, "open");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void close_ns_fd(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ns_fds; i++)
|
||||
close(ns_fd[i]);
|
||||
}
|
||||
|
||||
static int child_fn(void *arg)
|
||||
{
|
||||
char **args = (char **)arg;
|
||||
|
||||
execvp(args[3], args+3);
|
||||
tst_resm(TINFO | TERRNO, "execvp");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* ./ns_exec <NS_PID> <ipc,mnt,net,pid,user,uts> <PROGRAM> [ARGS]
|
||||
*/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int i, rv, pid;
|
||||
char *token;
|
||||
|
||||
rv = syscall(__NR_setns, -1, 0);
|
||||
if (rv == -1 && errno == ENOSYS) {
|
||||
tst_resm(TINFO, "setns is not supported in the kernel");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (argc < 4) {
|
||||
print_help();
|
||||
return 1;
|
||||
}
|
||||
|
||||
memset(ns_fd, 0, sizeof(ns_fd));
|
||||
while ((token = strsep(&argv[2], ","))) {
|
||||
struct param *p = get_param(token);
|
||||
|
||||
if (!p) {
|
||||
tst_resm(TINFO, "Unknown namespace: %s", token);
|
||||
print_help();
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (open_ns_fd(argv[1], token) != 0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ns_fds == 0) {
|
||||
tst_resm(TINFO, "no namespace entries in /proc/%s/ns/",
|
||||
argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 0; i < ns_fds; i++) {
|
||||
if (syscall(__NR_setns, ns_fd[i], 0) == -1) {
|
||||
tst_resm(TINFO | TERRNO, "setns");
|
||||
close_ns_fd();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
pid = ltp_clone_quick(SIGCHLD, (void *)child_fn, (void *)argv);
|
||||
if (pid == -1) {
|
||||
tst_resm(TINFO | TERRNO, "ltp_clone_quick");
|
||||
close_ns_fd();
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (waitpid(pid, &rv, 0) == -1) {
|
||||
tst_resm(TINFO | TERRNO, "waitpid");
|
||||
return 1;
|
||||
}
|
||||
|
||||
close_ns_fd();
|
||||
|
||||
if (WIFEXITED(rv))
|
||||
return WEXITSTATUS(rv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,134 +0,0 @@
|
||||
/* Copyright (c) 2015 Red Hat, Inc.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of version 2 the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Written by Matus Marhefka <mmarhefk@redhat.com>
|
||||
*
|
||||
***********************************************************************
|
||||
* Moves a network interface to the namespace of a process specified by a PID.
|
||||
*
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <asm/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/if.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <arpa/inet.h>
|
||||
#include "test.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
char *TCID = "ns_ifmove";
|
||||
|
||||
#if HAVE_DECL_IFLA_NET_NS_PID
|
||||
|
||||
struct {
|
||||
struct nlmsghdr nh;
|
||||
struct ifinfomsg ifi;
|
||||
char attrbuf[512];
|
||||
} req;
|
||||
|
||||
|
||||
int get_intf_index_from_name(const char *intf_name)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
int sock_fd;
|
||||
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
strncpy(ifr.ifr_name, intf_name, sizeof(ifr.ifr_name) - 1);
|
||||
ifr.ifr_name[sizeof(ifr.ifr_name)-1] = '\0';
|
||||
|
||||
sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
|
||||
if (sock_fd == -1) {
|
||||
tst_resm(TINFO | TERRNO, "socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* gets interface index */
|
||||
if (ioctl(sock_fd, SIOCGIFINDEX, &ifr) == -1) {
|
||||
tst_resm(TINFO | TERRNO, "ioctl");
|
||||
close(sock_fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
close(sock_fd);
|
||||
return ifr.ifr_ifindex;
|
||||
}
|
||||
|
||||
/*
|
||||
* ./ns_ifmove <INTERFACE_NAME> <NAMESPACE_PID>
|
||||
*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct rtattr *rta;
|
||||
int intf_index, pid, rtnetlink_socket;
|
||||
|
||||
if (argc != 3) {
|
||||
tst_resm(TINFO, "%s <INTERFACE_NAME> <NAMESPACE_PID>",
|
||||
argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
intf_index = get_intf_index_from_name(argv[1]);
|
||||
if (intf_index == -1) {
|
||||
tst_resm(TINFO , "unable to get interface index");
|
||||
return 1;
|
||||
}
|
||||
|
||||
pid = atoi(argv[2]);
|
||||
|
||||
rtnetlink_socket = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
|
||||
if (rtnetlink_socket == -1) {
|
||||
tst_resm(TINFO | TERRNO, "socket");
|
||||
return 1;
|
||||
}
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.nh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
|
||||
req.nh.nlmsg_flags = NLM_F_REQUEST;
|
||||
req.nh.nlmsg_type = RTM_NEWLINK;
|
||||
req.ifi.ifi_family = AF_UNSPEC;
|
||||
req.ifi.ifi_index = intf_index;
|
||||
req.ifi.ifi_change = 0xffffffff;
|
||||
rta = (struct rtattr *)(((char *) &req) +
|
||||
NLMSG_ALIGN(req.nh.nlmsg_len));
|
||||
rta->rta_type = IFLA_NET_NS_PID;
|
||||
rta->rta_len = RTA_LENGTH(sizeof(int));
|
||||
req.nh.nlmsg_len = NLMSG_ALIGN(req.nh.nlmsg_len) +
|
||||
RTA_LENGTH(sizeof(pid));
|
||||
memcpy(RTA_DATA(rta), &pid, sizeof(pid));
|
||||
|
||||
if (send(rtnetlink_socket, &req, req.nh.nlmsg_len, 0) == -1) {
|
||||
tst_resm(TINFO | TERRNO, "send");
|
||||
return 1;
|
||||
}
|
||||
|
||||
close(rtnetlink_socket);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int main(void)
|
||||
{
|
||||
tst_brkm(TCONF, NULL, "IFLA_NET_NS_PID not defined in linux/if_link.h");
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,32 +0,0 @@
|
||||
/* Copyright (c) 2015 Fujitsu Ltd.
|
||||
* Author: Guangwen Feng <fenggw-fnst@cn.fujitsu.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of version 2 the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
***********************************************************************
|
||||
* Check for setns() availability, should be called before ns_exec.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "test.h"
|
||||
#include "lapi/syscalls.h"
|
||||
|
||||
char *TCID = "setns_check";
|
||||
|
||||
int main(void)
|
||||
{
|
||||
if (syscall(__NR_setns, -1, 0) == -1 && errno == ENOSYS)
|
||||
tst_brkm(TCONF, NULL, "setns is not supported in the kernel");
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) International Business Machines Corp., 2007
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
|
||||
* the GNU General Public License for more details.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Author: Rishikesh K Rajak <risrajak@in.ibm.com>
|
||||
***************************************************************************/
|
||||
#include <sched.h>
|
||||
#include "../libclone/libclone.h"
|
||||
#include "test.h"
|
||||
#include "safe_macros.h"
|
||||
|
||||
static int dummy_child(void *v)
|
||||
{
|
||||
(void) v;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void check_newipc(void)
|
||||
{
|
||||
int pid, status;
|
||||
|
||||
if (tst_kvercmp(2, 6, 19) < 0)
|
||||
tst_brkm(TCONF, NULL, "CLONE_NEWIPC not supported");
|
||||
|
||||
pid = do_clone_unshare_test(T_CLONE, CLONE_NEWIPC, dummy_child, NULL);
|
||||
if (pid == -1)
|
||||
tst_brkm(TCONF | TERRNO, NULL, "CLONE_NEWIPC not supported");
|
||||
|
||||
SAFE_WAIT(NULL, &status);
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Huawei Technologies Co., Ltd., 2015
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
|
||||
* the GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include "../libclone/libclone.h"
|
||||
#include "test.h"
|
||||
#include "safe_macros.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#define UID_MAP 0
|
||||
#define GID_MAP 1
|
||||
|
||||
static int dummy_child(void *v)
|
||||
{
|
||||
(void) v;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_newuser(void)
|
||||
{
|
||||
int pid, status;
|
||||
|
||||
if (tst_kvercmp(3, 8, 0) < 0)
|
||||
tst_brkm(TCONF, NULL, "CLONE_NEWUSER not supported");
|
||||
|
||||
pid = do_clone_unshare_test(T_CLONE, CLONE_NEWUSER, dummy_child, NULL);
|
||||
if (pid == -1)
|
||||
tst_brkm(TCONF | TERRNO, NULL, "CLONE_NEWUSER not supported");
|
||||
SAFE_WAIT(NULL, &status);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
LTP_ATTRIBUTE_UNUSED static int updatemap(int cpid, bool type, int idnum,
|
||||
int parentmappid, void (*cleanup)(void))
|
||||
{
|
||||
char path[BUFSIZ];
|
||||
char content[BUFSIZ];
|
||||
int fd;
|
||||
|
||||
if (type == UID_MAP)
|
||||
sprintf(path, "/proc/%d/uid_map", cpid);
|
||||
else if (type == GID_MAP)
|
||||
sprintf(path, "/proc/%d/gid_map", cpid);
|
||||
else
|
||||
tst_brkm(TBROK, cleanup, "invalid type parameter");
|
||||
|
||||
sprintf(content, "%d %d 1", idnum, parentmappid);
|
||||
fd = SAFE_OPEN(cleanup, path, O_WRONLY, 0644);
|
||||
SAFE_WRITE(cleanup, 1, fd, content, strlen(content));
|
||||
SAFE_CLOSE(cleanup, fd);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
#!/bin/sh
|
||||
################################################################################
|
||||
## ##
|
||||
## Copyright (c) International Business Machines Corp., 2007 ##
|
||||
## ##
|
||||
## This program is free software; you can redistribute it and#or modify ##
|
||||
## it under the terms of the GNU General Public License as published by ##
|
||||
## the Free Software Foundation; either version 2 of the License, or ##
|
||||
## (at your option) any later version. ##
|
||||
## ##
|
||||
## This program is distributed in the hope that it will be useful, but ##
|
||||
## WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ##
|
||||
## or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ##
|
||||
## for more details. ##
|
||||
## ##
|
||||
## You should have received a copy of the GNU General Public License ##
|
||||
## along with this program; if not, write to the Free Software ##
|
||||
## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ##
|
||||
## ##
|
||||
################################################################################
|
||||
|
||||
oldhostname=`hostname`
|
||||
exit_code=0
|
||||
echo "unshare tests"
|
||||
for i in `seq 1 5`; do
|
||||
echo "test $i (unshare)"
|
||||
./utstest_noltp unshare $i
|
||||
if [ $? -ne 0 ]; then
|
||||
exit_code=$?
|
||||
fi
|
||||
done
|
||||
echo "clone tests"
|
||||
for i in `seq 1 5`; do
|
||||
echo "test $i (clone)"
|
||||
./utstest_noltp clone $i
|
||||
if [ $? -ne 0 ]; then
|
||||
exit_code=$?
|
||||
fi
|
||||
done
|
||||
hostname "$oldhostname"
|
||||
exit $exit_code
|
||||
@@ -1,356 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) International Business Machines Corp., 2007
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
|
||||
* the GNU General Public License for more details.
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
***************************************************************************
|
||||
* Copyright 2007 IBM
|
||||
* Author: Serge Hallyn <serue@us.ibm.com>
|
||||
*
|
||||
* test1:
|
||||
P1: A=gethostname
|
||||
P2: B=gethostname
|
||||
Ensure(A==B)
|
||||
|
||||
* test2:
|
||||
P1: sethostname(A);
|
||||
P2: (wait); B=gethostname
|
||||
Ensure (A==B)
|
||||
|
||||
* test3:
|
||||
P1: A=gethostname; unshare(utsname); sethostname(newname); C=gethostname
|
||||
P2: B=gethostname; (wait); (wait); D=gethostname
|
||||
Ensure (A==B && A==D && C!=D)
|
||||
|
||||
* test4:
|
||||
P1: A=gethostname; unshare(utsname); (wait); C=gethostname
|
||||
P2: B=gethostname; (wait); sethostname(newname); D=gethostname
|
||||
Ensure (A==B && A==C && C!=D)
|
||||
|
||||
* test5:
|
||||
P1: drop_privs(); unshare(utsname); (wait); C=gethostname
|
||||
P2: (wait); sethostname(B); D=gethostname
|
||||
Ensure (B==C==D) and state is ok.
|
||||
*
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE 1
|
||||
#include <sys/wait.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "libclone.h"
|
||||
#include "test.h"
|
||||
#include "safe_macros.h"
|
||||
|
||||
char *TCID = "uts_namespace";
|
||||
int TST_TOTAL = 1;
|
||||
|
||||
static int dummy_child(void *v)
|
||||
{
|
||||
(void) v;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void check_newuts(void)
|
||||
{
|
||||
int pid, status;
|
||||
|
||||
if (tst_kvercmp(2, 6, 19) < 0)
|
||||
tst_brkm(TCONF, NULL, "CLONE_NEWUTS not supported");
|
||||
|
||||
pid = do_clone_unshare_test(T_CLONE, CLONE_NEWUTS, dummy_child, NULL);
|
||||
if (pid == -1)
|
||||
tst_brkm(TCONF | TERRNO, NULL, "CLONE_NEWUTS not supported");
|
||||
|
||||
SAFE_WAIT(NULL, &status);
|
||||
}
|
||||
|
||||
int drop_root(void)
|
||||
{
|
||||
int ret;
|
||||
ret = setresuid(1000, 1000, 1000);
|
||||
if (ret) {
|
||||
perror("setresuid");
|
||||
exit(4);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define HLEN 100
|
||||
#define NAME1 "serge1"
|
||||
#define NAME2 "serge2"
|
||||
|
||||
int p1fd[2], p2fd[2];
|
||||
static char oldhost[HLEN];
|
||||
pid_t cpid;
|
||||
|
||||
void picknewhostname(char *orig, char *new)
|
||||
{
|
||||
memset(new, 0, HLEN);
|
||||
if (strcmp(orig, NAME1) == 0)
|
||||
strcpy(new, NAME2);
|
||||
else
|
||||
strcpy(new, NAME1);
|
||||
}
|
||||
|
||||
void zeroize(char *s)
|
||||
{
|
||||
memset(s, 0, HLEN);
|
||||
}
|
||||
|
||||
char *tsttype;
|
||||
int P1(void *vtest)
|
||||
{
|
||||
char hostname[HLEN], newhostname[HLEN], rhostname[HLEN];
|
||||
int err;
|
||||
int len;
|
||||
int testnum;
|
||||
|
||||
testnum = atoi((char *)vtest);
|
||||
|
||||
close(p1fd[1]);
|
||||
close(p2fd[0]);
|
||||
|
||||
switch (testnum) {
|
||||
case 1:
|
||||
gethostname(hostname, HLEN);
|
||||
zeroize(rhostname);
|
||||
len = read(p1fd[0], rhostname, HLEN);
|
||||
if (strcmp(hostname, rhostname) == 0) {
|
||||
tst_resm(TPASS, "test 1 (%s): success", tsttype);
|
||||
tst_exit();
|
||||
}
|
||||
tst_brkm(TFAIL, NULL,
|
||||
"test 1 (%s): hostname 1 %s, hostname 2 %s",
|
||||
tsttype, hostname, rhostname);
|
||||
case 2:
|
||||
gethostname(hostname, HLEN);
|
||||
picknewhostname(hostname, newhostname);
|
||||
err = sethostname(newhostname, strlen(newhostname));
|
||||
write(p2fd[1], "1", 1);
|
||||
if (err == -1) {
|
||||
tst_brkm(TFAIL, NULL,
|
||||
"test 2 (%s): failed to sethostname",
|
||||
tsttype);
|
||||
}
|
||||
zeroize(rhostname);
|
||||
len = read(p1fd[0], rhostname, HLEN);
|
||||
if (strcmp(newhostname, rhostname) == 0) {
|
||||
tst_resm(TPASS, "test 2 (%s): success", tsttype);
|
||||
tst_exit();
|
||||
}
|
||||
tst_brkm(TFAIL, NULL,
|
||||
"test 2 (%s) hostname 1 %s, hostname 2 %s",
|
||||
tsttype, newhostname, rhostname);
|
||||
case 3:
|
||||
gethostname(hostname, HLEN);
|
||||
picknewhostname(hostname, newhostname);
|
||||
err = sethostname(newhostname, strlen(newhostname));
|
||||
write(p2fd[1], "1", 1);
|
||||
if (err == -1) {
|
||||
tst_brkm(TFAIL, NULL,
|
||||
"test 3 (%s): failed to sethostname",
|
||||
tsttype);
|
||||
}
|
||||
|
||||
zeroize(rhostname);
|
||||
len = read(p1fd[0], rhostname, HLEN);
|
||||
if (strcmp(newhostname, rhostname) == 0) {
|
||||
tst_brkm(TFAIL,
|
||||
NULL,
|
||||
"test 3 (%s): hostname 1 %s, hostname 2 %s, these should have been different",
|
||||
tsttype, newhostname, rhostname);
|
||||
}
|
||||
if (strcmp(hostname, rhostname) == 0) {
|
||||
tst_resm(TPASS, "test 3 (%s): success", tsttype);
|
||||
tst_exit();
|
||||
}
|
||||
tst_brkm(TFAIL,
|
||||
NULL,
|
||||
"test 3 (%s): hostname 1 %s, hostname 2 %s, should have been same",
|
||||
tsttype, hostname, rhostname);
|
||||
|
||||
case 4:
|
||||
gethostname(hostname, HLEN);
|
||||
write(p2fd[1], "1", 1); /* tell p2 to go ahead and sethostname */
|
||||
zeroize(rhostname);
|
||||
len = read(p1fd[0], rhostname, HLEN);
|
||||
gethostname(newhostname, HLEN);
|
||||
if (strcmp(hostname, newhostname) != 0) {
|
||||
tst_brkm(TFAIL,
|
||||
NULL,
|
||||
"test 4 (%s): hostname 1 %s, hostname 2 %s, should be same",
|
||||
tsttype, hostname, newhostname);
|
||||
}
|
||||
if (strcmp(hostname, rhostname) == 0) {
|
||||
tst_brkm(TFAIL,
|
||||
NULL,
|
||||
"test 4 (%s): hostname 1 %s, hostname 2 %s, should be different",
|
||||
tsttype, hostname, rhostname);
|
||||
}
|
||||
tst_resm(TPASS, "test 4 (%s): successful", tsttype);
|
||||
tst_exit();
|
||||
case 5:
|
||||
write(p2fd[1], "1", 1); /* tell p2 to go ahead and sethostname */
|
||||
zeroize(rhostname);
|
||||
len = read(p1fd[0], rhostname, HLEN);
|
||||
gethostname(newhostname, HLEN);
|
||||
if (strcmp(rhostname, newhostname) != 0) {
|
||||
tst_brkm(TFAIL,
|
||||
NULL,
|
||||
"test 5 (%s): hostnames %s and %s should be same",
|
||||
tsttype, rhostname, newhostname);
|
||||
}
|
||||
tst_resm(TPASS, "test 5 (%s): successful", tsttype);
|
||||
tst_exit();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
tst_exit();
|
||||
}
|
||||
|
||||
int P2(void *vtest)
|
||||
{
|
||||
char hostname[HLEN], newhostname[HLEN];
|
||||
int len;
|
||||
int testnum;
|
||||
|
||||
testnum = atoi((char *)vtest);
|
||||
|
||||
close(p1fd[0]);
|
||||
close(p2fd[1]);
|
||||
|
||||
switch (testnum) {
|
||||
case 1:
|
||||
gethostname(hostname, HLEN);
|
||||
write(p1fd[1], hostname, strlen(hostname));
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
len = 0;
|
||||
while (!len) {
|
||||
len = read(p2fd[0], hostname, 1);
|
||||
}
|
||||
gethostname(hostname, HLEN);
|
||||
write(p1fd[1], hostname, strlen(hostname));
|
||||
break;
|
||||
case 4:
|
||||
case 5:
|
||||
len = 0;
|
||||
while (!len) {
|
||||
len = read(p2fd[0], hostname, 1);
|
||||
}
|
||||
if (hostname[0] == '0') {
|
||||
tst_resm(TPASS, "P2: P1 claims error");
|
||||
return 0;
|
||||
}
|
||||
gethostname(hostname, HLEN);
|
||||
picknewhostname(hostname, newhostname);
|
||||
sethostname(newhostname, strlen(newhostname));
|
||||
write(p1fd[1], newhostname, strlen(newhostname));
|
||||
break;
|
||||
default:
|
||||
tst_resm(TFAIL, "undefined test: %d", testnum);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void setup(void)
|
||||
{
|
||||
gethostname(oldhost, HLEN);
|
||||
tst_require_root();
|
||||
check_newuts();
|
||||
}
|
||||
|
||||
static void cleanup(void)
|
||||
{
|
||||
sethostname(oldhost, strlen(oldhost));
|
||||
}
|
||||
|
||||
#define UNSHARESTR "unshare"
|
||||
#define CLONESTR "clone"
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int r, pid, use_clone = T_UNSHARE;
|
||||
int testnum;
|
||||
void *vtest;
|
||||
|
||||
setup();
|
||||
if (argc != 3) {
|
||||
tst_resm(TFAIL, "Usage: %s <clone|unshare> <testnum>",
|
||||
argv[0]);
|
||||
tst_resm(TFAIL,
|
||||
" where clone or unshare specifies unshare method,");
|
||||
tst_resm(TFAIL, " and testnum is between 1 and 5 inclusive");
|
||||
exit(2);
|
||||
}
|
||||
if (pipe(p1fd) == -1) {
|
||||
perror("pipe");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if (pipe(p2fd) == -1) {
|
||||
perror("pipe");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
tsttype = UNSHARESTR;
|
||||
if (strcmp(argv[1], "clone") == 0) {
|
||||
use_clone = T_CLONE;
|
||||
tsttype = CLONESTR;
|
||||
}
|
||||
|
||||
testnum = atoi(argv[2]);
|
||||
|
||||
vtest = (void *)argv[2];
|
||||
switch (testnum) {
|
||||
case 1:
|
||||
case 2:
|
||||
r = do_clone_unshare_tests(T_NONE, 0, P1, vtest, P2, vtest);
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
r = do_clone_unshare_tests(use_clone, CLONE_NEWUTS,
|
||||
P1, vtest, P2, vtest);
|
||||
break;
|
||||
case 5:
|
||||
pid = fork();
|
||||
if (pid == -1) {
|
||||
perror("fork");
|
||||
exit(2);
|
||||
}
|
||||
if (pid == 0) {
|
||||
if (!drop_root()) {
|
||||
tst_brkm(TFAIL, NULL, "failed to drop root.");
|
||||
}
|
||||
r = do_clone_unshare_test(use_clone, CLONE_NEWUTS,
|
||||
P1, vtest);
|
||||
write(p2fd[1], "0", 1); /* don't let p2 hang */
|
||||
exit(0);
|
||||
} else {
|
||||
P2(vtest);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
tst_resm(TFAIL,
|
||||
"testnum should be between 1 and 5 inclusive.");
|
||||
break;
|
||||
}
|
||||
|
||||
cleanup();
|
||||
tst_exit();
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (c) 2009 FUJITSU LIMITED
|
||||
* Author: Li Zefan <lizf@cn.fujitsu.com>
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <sched.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include "test.h"
|
||||
|
||||
#define DEFAULT_USEC 30000
|
||||
|
||||
int foo(void __attribute__ ((unused)) * arg)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int usec;
|
||||
|
||||
if (argc == 2)
|
||||
usec = atoi(argv[1]);
|
||||
else
|
||||
usec = DEFAULT_USEC;
|
||||
|
||||
while (1) {
|
||||
usleep(usec);
|
||||
ltp_clone_quick(CLONE_NEWNS, foo, NULL);
|
||||
}
|
||||
|
||||
tst_exit();
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
# Copyright (c) 2009 FUJITSU LIMITED
|
||||
# Author: Li Zefan <lizf@cn.fujitsu.com>
|
||||
|
||||
trap exit USR1
|
||||
|
||||
while true; do
|
||||
mount -t cgroup xxx cgroup/ > /dev/null 2>&1
|
||||
cat cgroup/release_agent > /dev/null 2>&1
|
||||
umount cgroup/ > /dev/null 2>&1
|
||||
done
|
||||
@@ -1,11 +0,0 @@
|
||||
#!/bin/sh
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
# Copyright (c) 2009 FUJITSU LIMITED
|
||||
# Author: Li Zefan <lizf@cn.fujitsu.com>
|
||||
|
||||
trap exit USR1
|
||||
|
||||
while true; do
|
||||
mount -t cgroup xxx cgroup/ > /dev/null 2>&1
|
||||
umount cgroup/ > /dev/null 2>&1
|
||||
done
|
||||
@@ -1,3 +0,0 @@
|
||||
/create-files
|
||||
/random-access
|
||||
/random-access-del-create
|
||||
@@ -1,41 +0,0 @@
|
||||
#
|
||||
# kernel/fs/fs-bench testcases Makefile.
|
||||
#
|
||||
# Copyright (C) 2009, Cisco Systems Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Ngie Cooper, July 2009
|
||||
#
|
||||
|
||||
top_srcdir ?= ../../../..
|
||||
|
||||
include $(top_srcdir)/include/mk/env_pre.mk
|
||||
|
||||
INSTALL_TARGETS := modaltr.sh fs-bench-test.sh fs-bench-test2.sh
|
||||
|
||||
LDLIBS += -lm
|
||||
|
||||
create-files: boxmuler.o create-files.o
|
||||
|
||||
random-access-del-create: boxmuler.o random-access-del-create.o
|
||||
|
||||
MAKE_TARGETS := create-files random-access\
|
||||
random-access-del-create
|
||||
|
||||
dist: clean
|
||||
(cd $(abs_srcdir); tar zcvf fs-bench.tar.gz $(abs_srcdir))
|
||||
|
||||
include $(top_srcdir)/include/mk/generic_leaf_target.mk
|
||||
@@ -1,45 +0,0 @@
|
||||
Programs for File system stress test.
|
||||
|
||||
All of programs are distributed under GPL 2 license
|
||||
by Hironobu SUZUKI <hironobu@h2np.net>
|
||||
|
||||
HOW TO TEST
|
||||
------------
|
||||
|
||||
1: Type "make"
|
||||
|
||||
# cd
|
||||
# tar zxvf fs-bench.tar.gz
|
||||
# cd fs-bench
|
||||
# make
|
||||
|
||||
2: Change directory to terget file system and do-it!
|
||||
(I always use one-HDD/one-partition for fs stress test.)
|
||||
|
||||
# mount -t jfs /dev/hdc1 /jfs
|
||||
# cd /jfs
|
||||
# ~/fs-bench/test.sh 2>&1 | tee ~/fs-bench/jfs-test
|
||||
|
||||
|
||||
NOTE
|
||||
-----
|
||||
|
||||
The size of files that are created for stress test is not fixed. The
|
||||
file size are determined by probabilistic algorithm, box-muler
|
||||
algorithm.
|
||||
|
||||
number
|
||||
of files
|
||||
^
|
||||
| ****
|
||||
| * *
|
||||
| * *
|
||||
| * *
|
||||
| ** **
|
||||
|** **
|
||||
+-------------------> file size
|
||||
min max
|
||||
|
||||
|
||||
------
|
||||
$Id: README,v 1.1 2004/11/18 20:23:05 robbiew Exp $
|
||||
@@ -1,28 +0,0 @@
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define M_2PI (M_PI*2)
|
||||
|
||||
int box_muler(int min, int max)
|
||||
{
|
||||
double u1, u2, z;
|
||||
int i;
|
||||
int ave;
|
||||
int range;
|
||||
int ZZ;
|
||||
if (min >= max) {
|
||||
return (-1);
|
||||
}
|
||||
range = max - min;
|
||||
ave = range / 2;
|
||||
for (i = 0; i < 10; i++) {
|
||||
u1 = ((double)(random() % 1000000)) / 1000000;
|
||||
u2 = ((double)(random() % 1000000)) / 1000000;
|
||||
z = sqrt(-2.0 * log(u1)) * cos(M_2PI * u2);
|
||||
ZZ = min + (ave + (z * (ave / 4)));
|
||||
if (ZZ >= min && ZZ < max) {
|
||||
return (ZZ);
|
||||
}
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
/* create.c (GPL)*/
|
||||
/* Hironobu SUZUKI <hironobu@h2np.net> */
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define MAXN 4096
|
||||
|
||||
#define MAXFSIZE 1024 * 192
|
||||
|
||||
char wbuf[MAXFSIZE];
|
||||
static int filecount = 0;
|
||||
|
||||
void makedir(char *dir1);
|
||||
void changedir(char *dir);
|
||||
void create_file(char *filename);
|
||||
|
||||
extern int box_muler(int, int);
|
||||
|
||||
int startc = 0;
|
||||
int main(int ac, char *av[])
|
||||
{
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
int k = 0;
|
||||
int l = 0;
|
||||
char dir1[MAXN];
|
||||
char dir2[MAXN];
|
||||
char dir3[MAXN];
|
||||
char filename[MAXN];
|
||||
time_t t;
|
||||
int maxfiles = 0xFFFFFF;
|
||||
int createfiles = 0;
|
||||
|
||||
if (ac > 1) {
|
||||
sscanf(av[1], "%x", &maxfiles);
|
||||
if (maxfiles == 0) {
|
||||
printf("maxfile argument error (0 value)\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
time(&t);
|
||||
srandom((unsigned int)getpid() ^
|
||||
(((unsigned int)t << 16) | (unsigned int)t >> 16));
|
||||
printf("Create files\n");
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
sprintf(dir1, "%2.2x", i);
|
||||
makedir(dir1);
|
||||
changedir(dir1);
|
||||
for (j = 0; j < 0xFF; j++) {
|
||||
sprintf(dir2, "%2.2x", j);
|
||||
makedir(dir2);
|
||||
changedir(dir2);
|
||||
for (k = 0; k < 0xFF; k++) {
|
||||
sprintf(dir3, "%2.2x", k);
|
||||
makedir(dir3);
|
||||
changedir(dir3);
|
||||
for (l = 0; l < 0xFF; l++) {
|
||||
sprintf(filename, "%s%s%s%2.2x", dir1,
|
||||
dir2, dir3, l);
|
||||
create_file(filename);
|
||||
if (maxfiles < createfiles++) {
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
changedir("../");
|
||||
}
|
||||
changedir("../");
|
||||
}
|
||||
changedir("../");
|
||||
}
|
||||
end:
|
||||
fprintf(stderr, "\nTotal create files: %d\n", filecount);
|
||||
printf("Done\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int showchar[] = { 124, 47, 45, 92, 124, 47, 45, 92 };
|
||||
|
||||
void makedir(char *dir1)
|
||||
{
|
||||
if (mkdir(dir1, S_IRWXU) < 0) {
|
||||
perror(dir1);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void changedir(char *dir)
|
||||
{
|
||||
if (chdir(dir) < 0) {
|
||||
perror(dir);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void create_file(char *filename)
|
||||
{
|
||||
int fd;
|
||||
int randomsize;
|
||||
if ((fd = creat(filename, S_IRWXU)) < 0) {
|
||||
fprintf(stderr, "\nTotal create files: %d\n", filecount);
|
||||
perror(filename);
|
||||
exit(1);
|
||||
}
|
||||
if ((randomsize = box_muler(0, MAXFSIZE)) < 0) {
|
||||
randomsize = MAXFSIZE;
|
||||
}
|
||||
if (write(fd, wbuf, randomsize) < 0) {
|
||||
fprintf(stderr, "\nTotal create files: %d\n", filecount);
|
||||
perror(filename);
|
||||
exit(1);
|
||||
}
|
||||
filecount++;
|
||||
close(fd);
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
#! /bin/bash
|
||||
|
||||
echo "## Start Test"
|
||||
date
|
||||
if [ -d ./00 ] ; then
|
||||
echo -n "Clear old files..."
|
||||
/bin/rm -fr ./00 >& /dev/null
|
||||
echo "done"
|
||||
fi
|
||||
STARTT=`date +%s`
|
||||
echo $STARTT
|
||||
echo ""
|
||||
echo "## Create files "
|
||||
time ~/fs-bench/cr
|
||||
|
||||
echo ""
|
||||
echo "## tar all "
|
||||
MAXFILE=`tar cBf - 00 | tar tvBf - 2>&1 | tail -n 1 | awk '{print $6;}'| awk -F'/' '{print $4;}'`
|
||||
|
||||
echo ""
|
||||
echo "## Change owner"
|
||||
time chown -R $USER ./00
|
||||
|
||||
echo ""
|
||||
echo "## random access"
|
||||
time ~/fs-bench/ra $MAXFILE
|
||||
|
||||
echo ""
|
||||
echo "## Change mode "
|
||||
time chmod -R go+rw ./00
|
||||
|
||||
echo ""
|
||||
echo "## Random delete and create"
|
||||
time ~/fs-bench/radc $MAXFILE
|
||||
|
||||
echo ""
|
||||
echo "## Change mode again"
|
||||
time chmod -R go-rw ./00
|
||||
|
||||
echo ""
|
||||
echo "## Remove all files and directories"
|
||||
time /bin/rm -fr ./00
|
||||
echo ""
|
||||
echo "## Finish test"
|
||||
ENDT=`date +%s`
|
||||
echo $ENDT
|
||||
date
|
||||
|
||||
echo -n 'TOTAL(seconds): '
|
||||
expr $ENDT - $STARTT
|
||||
@@ -1,63 +0,0 @@
|
||||
#! /bin/bash
|
||||
|
||||
echo "## Start Test"
|
||||
date
|
||||
date +%s
|
||||
if [ -d ./00 ] ; then
|
||||
/bin/rm -fr ./00 >& /dev/null
|
||||
fi
|
||||
STARTT=`date +%s`
|
||||
echo $STARTT
|
||||
|
||||
echo ""
|
||||
echo "## Create files "
|
||||
time ~/fs-bench/cr
|
||||
|
||||
echo ""
|
||||
echo "## tar all "
|
||||
MAXFILE=`tar cBf - 00 | tar tvBf - 2>&1 | tail -n 1 | awk '{print $6;}'| awk -F'/' '{print $4;}'`
|
||||
HALFFILE=`echo "obase=F;ibase=F;$MAXFILE/2" | bc`
|
||||
|
||||
echo ""
|
||||
echo "## Remove all files and directories"
|
||||
/bin/rm -fr ./00 >& /dev/null
|
||||
|
||||
echo ""
|
||||
echo "## Create half files"
|
||||
echo create half files
|
||||
time ~/fs-bench/cr $HALFFILE
|
||||
|
||||
echo ""
|
||||
echo "## Change owner"
|
||||
time chown -R $USER ./00
|
||||
|
||||
echo ""
|
||||
echo "## random access"
|
||||
time ~/fs-bench/ra $HALFFILE
|
||||
|
||||
|
||||
echo ""
|
||||
echo "## Change mode "
|
||||
time chmod -R go+rw ./00
|
||||
|
||||
echo ""
|
||||
echo "## Random delete and create"
|
||||
time ~/fs-bench/radc $HALFFILE
|
||||
|
||||
echo ""
|
||||
echo "## Change mode again"
|
||||
time chmod -R go-rw ./00
|
||||
|
||||
echo ""
|
||||
echo "## Remove all files and directories"
|
||||
time /bin/rm -fr ./00
|
||||
|
||||
echo ""
|
||||
echo "## Finish test"
|
||||
date
|
||||
ENDT=`date +%s`
|
||||
echo $ENDT
|
||||
echo -n 'TOTAL(seconds): '
|
||||
expr $ENDT - $STARTT
|
||||
|
||||
|
||||
@@ -1,124 +0,0 @@
|
||||
#!/bin/sh
|
||||
#To run this script the following is necessary
|
||||
# 1.kernel should mtd support as module.
|
||||
# 2.kernel should hsve jffs2 support as module.
|
||||
# 3.kernel should have loopback device support .
|
||||
# 4.you should have fs-bench utility (http://h2np.net/tools/fs-bench-0.2.tar.gz)
|
||||
# 5.results will be copied to /tmp/log and /tmp/log1 files
|
||||
|
||||
#DESCRIPTION: This testscript creates a jffs2 file system type and tests the filesystem test
|
||||
#and places the log in the log directory.The file system test actually creates a tree of large
|
||||
#directories and performs the delete and random delete operations as per the filesystem stress
|
||||
#algorithim and gives a report of real time ,user time,system time taken to perform the file
|
||||
#operations.
|
||||
|
||||
#script created G.BANU PRAKASH (mailto:prakash.banu@wipro.com).
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
|
||||
# the GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
|
||||
MTD_RAM=mtdram
|
||||
MTD_BLOCK=mtdblock
|
||||
JFFS2=jffs2
|
||||
LOOP=loop
|
||||
MTD_BLKDEVS=mtd_blkdevs
|
||||
ZLIB_DEFLATE=zlib_deflate
|
||||
ZLIB_INFLATE=zlib_inflate
|
||||
MTD_CORE=mtdcore
|
||||
MOUNT_DIR=/mnt
|
||||
LOG_DIR=/tmp/log
|
||||
LOG_DIR1=/tmp/log1
|
||||
HOME_DIR=/home
|
||||
BLOCK_DIR=/dev/mtdblock
|
||||
export PATH=$PATH:/sbin
|
||||
if [ $(id -ru) -ne 0 ];
|
||||
then
|
||||
echo "must be root to run this"
|
||||
exit
|
||||
fi
|
||||
|
||||
|
||||
|
||||
lsmod |grep $MTD_RAM
|
||||
|
||||
if [ $? -ne 0 ];
|
||||
then
|
||||
echo "inserting mtd ram and its dependencies"
|
||||
fi
|
||||
modprobe $MTD_RAM total_size=32768 erase_size=256
|
||||
if [ $? -ne 0 ];
|
||||
then
|
||||
echo "check wheather MTD -mtdram is been compiled in the kernel"
|
||||
fi
|
||||
lsmod |grep $MTD_BLOCK
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "inserting mtdblock and its dependencies"
|
||||
fi
|
||||
modprobe $MTD_BLOCK
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "check wheather mtdblock is been compiled in the kernel"
|
||||
fi
|
||||
|
||||
lsmod |grep $JFFS2
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "inserting jffs2 and its dependencies"
|
||||
fi
|
||||
modprobe $JFFS2
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "check wheather jffs2 is been compiled in the kernel"
|
||||
fi
|
||||
|
||||
lsmod |grep $LOOP
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "inserting loopback device module"
|
||||
fi
|
||||
modprobe $LOOP
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "check wheather loopback device option is been compiled in the kernel"
|
||||
fi
|
||||
mkdir -p $BLOCK_DIR
|
||||
mknod $BLOCK_DIR/0 b 31 0 >/dev/null 2>&1
|
||||
mount -t jffs2 $BLOCK_DIR/0 $MOUNT_DIR
|
||||
mount|grep $JFFS2
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "jffs2 mounted sucessfully"
|
||||
else
|
||||
echo "mount unsucessfull"
|
||||
fi
|
||||
cd $MOUNT_DIR
|
||||
echo "This is will take long time "
|
||||
./test.sh >log 2>&1
|
||||
./test2.sh >log1 2>&1
|
||||
|
||||
mv log $LOG_DIR
|
||||
mv log1 $LOG_DIR1
|
||||
cd $HOME_DIR
|
||||
|
||||
|
||||
#cleanup
|
||||
echo "unmounting $MOUNT_DIR "
|
||||
umount $MOUNT_DIR
|
||||
echo "removing the modules inserted"
|
||||
rmmod $MTD_BLOCK
|
||||
rmmod $MTD_BLKDEVS
|
||||
rmmod $LOOP
|
||||
rmmod $JFFS2
|
||||
rmmod $ZLIB_DEFLATE
|
||||
rmmod $ZLIB_INFLATE
|
||||
rmmod $MTD_RAM
|
||||
rmmod $MTD_CORE
|
||||
rm -rf /dev/mtdblock
|
||||
echo "TEST COMPLETE"
|
||||
echo "RESULTS LOGGED IN FILE /tmp/log and /tmp/log1 "
|
||||
@@ -1,138 +0,0 @@
|
||||
/* random-del-create.c (GPL)*/
|
||||
/* Hironobu SUZUKI <hironobu@h2np.net> */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#define FAIL 0
|
||||
#define SUCCESS 1
|
||||
|
||||
int openlog[2] = { 0, 0 };
|
||||
|
||||
#define MAXNUM 0x100000
|
||||
|
||||
#define MAXERROR 1024
|
||||
|
||||
extern int box_muler(int, int);
|
||||
extern void create_or_delete(char *);
|
||||
|
||||
int delete_file(char *filename);
|
||||
int create_file(char *filename);
|
||||
|
||||
int cfilecount = 0;
|
||||
int dfilecount = 0;
|
||||
int errorcount = 0;
|
||||
|
||||
int main(int ac, char **av)
|
||||
{
|
||||
int r;
|
||||
char fname[1024];
|
||||
time_t t;
|
||||
int i;
|
||||
int m;
|
||||
|
||||
if (ac != 2) {
|
||||
printf("%s hex-style-filename \n", av[0]);
|
||||
printf("ex) %s 00022300\n", av[0]);
|
||||
exit(1);
|
||||
}
|
||||
sscanf(av[1], "%x", &m);
|
||||
if (m < 1 || m > MAXNUM) {
|
||||
printf("out of size %d\n", m);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
time(&t);
|
||||
srandom((unsigned int)getpid() ^
|
||||
(((unsigned int)t << 16) | (unsigned int)t >> 16));
|
||||
|
||||
/* 00/00/00/00 */
|
||||
for (i = 0; i < m; i++) {
|
||||
r = random() % m;
|
||||
sprintf(fname, "00/%2.2x/%2.2x/00%2.2x%2.2x%2.2x",
|
||||
((r >> 16) & 0xFF),
|
||||
((r >> 8) & 0xFF),
|
||||
((r >> 16) & 0xFF), ((r >> 8) & 0xFF), (r & 0xFF));
|
||||
create_or_delete(fname);
|
||||
}
|
||||
fprintf(stderr, "Total create files: %d\n", cfilecount);
|
||||
fprintf(stderr, "Total delete files: %d\n", dfilecount);
|
||||
fprintf(stderr, "Total error : %d\n", errorcount);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
#define MAXFSIZE (192*1024)
|
||||
#define AVEFSIZE (MAXFSIZE/2)
|
||||
#define POOLDISKSPACE (AVEFSIZE*128)
|
||||
|
||||
static int disk_space_pool = 0;
|
||||
void create_or_delete(char *fname)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = (random() & 1);
|
||||
if (r && disk_space_pool > POOLDISKSPACE) {
|
||||
/* create */
|
||||
create_file(fname);
|
||||
} else {
|
||||
delete_file(fname);
|
||||
}
|
||||
if ((errorcount > dfilecount || errorcount > cfilecount)
|
||||
&& (errorcount > MAXERROR)) {
|
||||
fprintf(stderr, "too much error -- stop\n");
|
||||
fprintf(stderr, "Total create files: %d\n", cfilecount);
|
||||
fprintf(stderr, "Total delete files: %d\n", dfilecount);
|
||||
fprintf(stderr, "Total error : %d\n", errorcount);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int create_file(char *filename)
|
||||
{
|
||||
int fd;
|
||||
int randomsize;
|
||||
char wbuf[MAXFSIZE];
|
||||
if ((fd = creat(filename, S_IRWXU)) < 0) {
|
||||
errorcount++;
|
||||
return (-1);
|
||||
}
|
||||
if ((randomsize = box_muler(0, MAXFSIZE)) < 0) {
|
||||
randomsize = MAXFSIZE;
|
||||
}
|
||||
if (write(fd, wbuf, randomsize) < 0) {
|
||||
errorcount++;
|
||||
close(fd);
|
||||
return (-1);
|
||||
}
|
||||
cfilecount++;
|
||||
disk_space_pool -= randomsize;
|
||||
close(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int delete_file(char *filename)
|
||||
{
|
||||
struct stat buf;
|
||||
int st;
|
||||
st = stat(filename, &buf);
|
||||
if (st < 0) {
|
||||
errorcount++;
|
||||
return (-1);
|
||||
}
|
||||
disk_space_pool += buf.st_size;
|
||||
if (unlink(filename) < 0) {
|
||||
errorcount++;
|
||||
return (-1);
|
||||
}
|
||||
dfilecount++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
/* random-access.c (GPL)*/
|
||||
/* Hironobu SUZUKI <hironobu@h2np.net> */
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#define FAIL 0
|
||||
#define SUCCESS 1
|
||||
|
||||
int openlog[2] = { 0, 0 };
|
||||
|
||||
#define MAXNUM 0x100000
|
||||
|
||||
void open_read_close(char *fname);
|
||||
|
||||
int nullfd;
|
||||
|
||||
int main(int ac, char **av)
|
||||
{
|
||||
int r;
|
||||
char fname[1024];
|
||||
time_t t;
|
||||
int i;
|
||||
int m;
|
||||
|
||||
if (ac != 2) {
|
||||
printf("%s hex-style-filename \n", av[0]);
|
||||
printf("ex) %s 00022300\n", av[0]);
|
||||
exit(1);
|
||||
}
|
||||
sscanf(av[1], "%x", &m);
|
||||
if (m < 1 || m > MAXNUM) {
|
||||
printf("out of size %d\n", m);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
time(&t);
|
||||
srandom((unsigned int)getpid() ^
|
||||
(((unsigned int)t << 16) | (unsigned int)t >> 16));
|
||||
|
||||
if ((nullfd = open("/dev/null", O_WRONLY)) < 0) {
|
||||
perror("/dev/null");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* 00/00/00/00 */
|
||||
for (i = 0; i < m; i++) {
|
||||
r = random() % m;
|
||||
sprintf(fname, "00/%2.2x/%2.2x/00%2.2x%2.2x%2.2x",
|
||||
((r >> 16) & 0xFF),
|
||||
((r >> 8) & 0xFF),
|
||||
((r >> 16) & 0xFF), ((r >> 8) & 0xFF), (r & 0xFF));
|
||||
open_read_close(fname);
|
||||
}
|
||||
close(nullfd);
|
||||
printf("Success:\t%d\nFail:\t%d\n", openlog[SUCCESS], openlog[FAIL]);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
#define BUFS 8192
|
||||
void open_read_close(char *fname)
|
||||
{
|
||||
int fd;
|
||||
char buf[BUFS];
|
||||
int c;
|
||||
|
||||
if ((fd = open(fname, O_RDONLY)) < 0) {
|
||||
openlog[FAIL]++;
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
openlog[SUCCESS]++;
|
||||
while ((c = read(fd, buf, BUFS)) > 0) {
|
||||
if (write(nullfd, buf, c) < 0) {
|
||||
perror("/dev/null");
|
||||
printf("Opened\t %d\nUnopend:\t%d\n", openlog[SUCCESS],
|
||||
openlog[FAIL]);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (c < 0) {
|
||||
perror(fname);
|
||||
printf("Opened\t %d\nUnopend:\t%d\n", openlog[SUCCESS],
|
||||
openlog[FAIL]);
|
||||
exit(1);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
@@ -1,134 +0,0 @@
|
||||
/* random-del-create.c (GPL)*/
|
||||
/* Hironobu SUZUKI <hironobu@h2np.net> */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#define FAIL 0
|
||||
#define SUCCESS 1
|
||||
|
||||
int openlog[2] = { 0, 0 };
|
||||
|
||||
#define MAXNUM 0x100000
|
||||
|
||||
#define MAXERROR 1024
|
||||
|
||||
extern int box_muler(int, int);
|
||||
extern void create_or_delete(char *);
|
||||
|
||||
int cfilecount = 0;
|
||||
int dfilecount = 0;
|
||||
int errorcount = 0;
|
||||
|
||||
int main(int ac, char **av)
|
||||
{
|
||||
int r;
|
||||
char fname[1024];
|
||||
time_t t;
|
||||
int i;
|
||||
int m;
|
||||
|
||||
if (ac != 2) {
|
||||
printf("%s hex-style-filename \n", av[0]);
|
||||
printf("ex) %s 00022300\n", av[0]);
|
||||
exit(1);
|
||||
}
|
||||
sscanf(av[1], "%x", &m);
|
||||
if (m < 1 || m > MAXNUM) {
|
||||
printf("out of size %d\n", m);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
time(&t);
|
||||
srandom((unsigned int)getpid() ^
|
||||
(((unsigned int)t << 16) | (unsigned int)t >> 16));
|
||||
|
||||
/* 00/00/00/00 */
|
||||
for (i = 0; i < m; i++) {
|
||||
r = random() % m;
|
||||
sprintf(fname, "00/%2.2x/%2.2x/00%2.2x%2.2x%2.2x",
|
||||
((r >> 16) & 0xFF),
|
||||
((r >> 8) & 0xFF),
|
||||
((r >> 16) & 0xFF), ((r >> 8) & 0xFF), (r & 0xFF));
|
||||
create_or_delete(fname);
|
||||
}
|
||||
fprintf(stderr, "Total create files: %d\n", cfilecount);
|
||||
fprintf(stderr, "Total delete files: %d\n", dfilecount);
|
||||
fprintf(stderr, "Total error : %d\n", errorcount);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
#define MAXFSIZE (192*1024)
|
||||
#define AVEFSIZE (MAXFSIZE/2)
|
||||
#define POOLDISKSPACE (AVEFSIZE*128)
|
||||
|
||||
static int disk_space_pool = 0;
|
||||
void create_or_delete(char *fname)
|
||||
{
|
||||
int r;
|
||||
int fsize;
|
||||
|
||||
r = (random() & 1);
|
||||
if (r && disk_space_pool > POOLDISKSPACE) {
|
||||
/* create */
|
||||
create_file(fname);
|
||||
} else {
|
||||
delete_file(fname);
|
||||
}
|
||||
if ((errorcount > dfilecount || errorcount > cfilecount)
|
||||
&& (errorcount > MAXERROR)) {
|
||||
fprintf(stderr, "too much error -- stop\n");
|
||||
fprintf(stderr, "Total create files: %d\n", cfilecount);
|
||||
fprintf(stderr, "Total delete files: %d\n", dfilecount);
|
||||
fprintf(stderr, "Total error : %d\n", errorcount);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int create_file(char *filename)
|
||||
{
|
||||
int fd;
|
||||
int randomsize;
|
||||
char wbuf[MAXFSIZE];
|
||||
if ((fd = creat(filename, S_IRWXU)) < 0) {
|
||||
errorcount++;
|
||||
return (-1);
|
||||
}
|
||||
if ((randomsize = box_muler(0, MAXFSIZE)) < 0) {
|
||||
randomsize = MAXFSIZE;
|
||||
}
|
||||
if (write(fd, wbuf, randomsize) < 0) {
|
||||
errorcount++;
|
||||
close(fd);
|
||||
return (-1);
|
||||
}
|
||||
cfilecount++;
|
||||
disk_space_pool -= randomsize;
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int delete_file(char *filename)
|
||||
{
|
||||
struct stat buf;
|
||||
int st;
|
||||
st = stat(filename, &buf);
|
||||
if (st < 0) {
|
||||
errorcount++;
|
||||
return (-1);
|
||||
}
|
||||
disk_space_pool += buf.st_size;
|
||||
if (unlink(filename) < 0) {
|
||||
errorcount++;
|
||||
return (-1);
|
||||
}
|
||||
dfilecount++;
|
||||
return 0;
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004 Daniel McNeil <daniel@osdl.org>
|
||||
* 2004 Open Source Development Lab
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
|
||||
* the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Module: .c
|
||||
*/
|
||||
|
||||
/*
|
||||
* Change History:
|
||||
*
|
||||
* 2/2004 Marty Ridgeway (mridge@us.ibm.com) Changes to adapt to LTP
|
||||
*
|
||||
*/
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "common_checkzero.h"
|
||||
|
||||
int read_eof(char *filename)
|
||||
{
|
||||
int fd;
|
||||
int i;
|
||||
int r;
|
||||
char buf[4096];
|
||||
|
||||
if ((fd = open(filename, O_RDWR)) < 0) {
|
||||
fprintf(stderr, "can't open file %s \n", filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (i = 0; i < 100000; i++) {
|
||||
off_t offset;
|
||||
char *bufoff;
|
||||
|
||||
offset = lseek(fd, 4096, SEEK_END);
|
||||
r = write(fd, "A", 1);
|
||||
|
||||
offset = lseek(fd, offset - 4096, SEEK_SET);
|
||||
|
||||
r = read(fd, buf, 4096);
|
||||
if (r > 0) {
|
||||
if ((bufoff = check_zero(buf, r))) {
|
||||
fprintf(stderr, "non-zero read at offset %p\n",
|
||||
offset + bufoff);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "read_checkzero done\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc < 2) {
|
||||
printf("You must pass a filename to the test \n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *filename = argv[1];
|
||||
|
||||
read_eof(filename);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
/sem01
|
||||
/sem02
|
||||
@@ -1,30 +0,0 @@
|
||||
#
|
||||
# testcases/kernel/ipc/semaphore Makefile.
|
||||
#
|
||||
# Copyright (C) 2009, Cisco Systems Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Ngie Cooper, July 2009
|
||||
#
|
||||
|
||||
top_srcdir ?= ../../../..
|
||||
|
||||
include $(top_srcdir)/include/mk/testcases.mk
|
||||
|
||||
CPPFLAGS += -I../include
|
||||
LDLIBS += -lpthread
|
||||
|
||||
include $(top_srcdir)/include/mk/generic_leaf_target.mk
|
||||
@@ -1,164 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) International Business Machines Corp., 2001
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
|
||||
* the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* FILE : sem01.c
|
||||
* DESCRIPTION : Creates a semaphore and two processes. The processes
|
||||
* each go through a loop where they semdown, delay for a
|
||||
* random amount of time, and semup, so they will almost
|
||||
* always be fighting for control of the semaphore.
|
||||
* HISTORY:
|
||||
* 01/15/2001 Paul Larson (plars@us.ibm.com)
|
||||
* -written
|
||||
* 11/09/2001 Manoj Iyer (manjo@ausin.ibm.com)
|
||||
* Modified.
|
||||
* - Removed compiler warnings.
|
||||
* added exit to the end of function main()
|
||||
*
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/ipc.h>
|
||||
#include "lapi/sem.h"
|
||||
|
||||
int verbose = 0;
|
||||
int loops = 100;
|
||||
int errors = 0;
|
||||
|
||||
int semup(int semid)
|
||||
{
|
||||
struct sembuf semops;
|
||||
semops.sem_num = 0;
|
||||
semops.sem_op = 1;
|
||||
semops.sem_flg = SEM_UNDO;
|
||||
if (semop(semid, &semops, 1) == -1) {
|
||||
perror("semup");
|
||||
errors++;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int semdown(int semid)
|
||||
{
|
||||
struct sembuf semops;
|
||||
semops.sem_num = 0;
|
||||
semops.sem_op = -1;
|
||||
semops.sem_flg = SEM_UNDO;
|
||||
if (semop(semid, &semops, 1) == -1) {
|
||||
perror("semdown");
|
||||
errors++;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void delayloop()
|
||||
{
|
||||
int delay;
|
||||
delay = 1 + ((100.0 * rand()) / RAND_MAX);
|
||||
if (verbose)
|
||||
printf("in delay function for %d microseconds\n", delay);
|
||||
usleep(delay);
|
||||
}
|
||||
|
||||
void mainloop(int semid)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < loops; i++) {
|
||||
if (semdown(semid)) {
|
||||
printf("semdown failed\n");
|
||||
}
|
||||
if (verbose)
|
||||
printf("sem is down\n");
|
||||
delayloop();
|
||||
if (semup(semid)) {
|
||||
printf("semup failed\n");
|
||||
}
|
||||
if (verbose)
|
||||
printf("sem is up\n");
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int semid, opt;
|
||||
union semun semunion;
|
||||
extern char *optarg;
|
||||
pid_t pid;
|
||||
int chstat;
|
||||
|
||||
while ((opt = getopt(argc, argv, "l:vh")) != EOF) {
|
||||
switch ((char)opt) {
|
||||
case 'l':
|
||||
loops = atoi(optarg);
|
||||
break;
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
case 'h':
|
||||
default:
|
||||
printf("Usage: -l loops [-v]\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* set up the semaphore */
|
||||
if ((semid = semget((key_t) 9142, 1, 0666 | IPC_CREAT)) < 0) {
|
||||
printf("error in semget()\n");
|
||||
exit(-1);
|
||||
}
|
||||
semunion.val = 1;
|
||||
if (semctl(semid, 0, SETVAL, semunion) == -1) {
|
||||
printf("error in semctl\n");
|
||||
}
|
||||
|
||||
if ((pid = fork()) < 0) {
|
||||
printf("fork error\n");
|
||||
exit(-1);
|
||||
}
|
||||
if (pid) {
|
||||
/* parent */
|
||||
srand(pid);
|
||||
mainloop(semid);
|
||||
waitpid(pid, &chstat, 0);
|
||||
if (!WIFEXITED(chstat)) {
|
||||
printf("child exited with status\n");
|
||||
exit(-1);
|
||||
}
|
||||
if (semctl(semid, 0, IPC_RMID, semunion) == -1) {
|
||||
printf("error in semctl\n");
|
||||
}
|
||||
if (errors) {
|
||||
printf("FAIL: there were %d errors\n", errors);
|
||||
} else {
|
||||
printf("PASS: error count is 0\n");
|
||||
}
|
||||
exit(errors);
|
||||
} else {
|
||||
/* child */
|
||||
mainloop(semid);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
@@ -1,157 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Copyright (c) International Business Machines Corp., 2002
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
|
||||
* the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* FILE : sem02.c
|
||||
*
|
||||
* DESCRIPTION : The application creates several threads using pthread_create().
|
||||
* One thread performs a semop() with the SEM_UNDO flag set. The change in
|
||||
* sempaphore value performed by that semop should be "undone" only when the
|
||||
* last pthread exits.
|
||||
*
|
||||
* EXPECTED OUTPUT:
|
||||
* Waiter, pid = <pid#>
|
||||
* Poster, pid = <pid#>, posting
|
||||
* Poster posted
|
||||
* Poster exiting
|
||||
* Waiter waiting, pid = <pid#>
|
||||
* Waiter done waiting
|
||||
*
|
||||
* HISTORY:
|
||||
* written by Dave Olien (oliend@us.ibm.com)
|
||||
* 03/06/2002 Robbie Williamson (robbiew@us.ibm.com)
|
||||
* -ported
|
||||
* 07/04/2003 Paul Larson (plars@linuxtestproject.org)
|
||||
* -ported to LTP
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ipc.h>
|
||||
#include "lapi/sem.h"
|
||||
#include "test.h"
|
||||
|
||||
#define KEY IPC_PRIVATE
|
||||
|
||||
#define NUMTHREADS 2
|
||||
|
||||
void *retval[NUMTHREADS];
|
||||
void *waiter(void *);
|
||||
void *poster(void *);
|
||||
void cleanup(void);
|
||||
|
||||
char *TCID = "sem02";
|
||||
int TST_TOTAL = 1;
|
||||
|
||||
struct sembuf Psembuf = { 0, -1, SEM_UNDO };
|
||||
struct sembuf Vsembuf = { 0, 1, SEM_UNDO };
|
||||
|
||||
int sem_id;
|
||||
int err_ret; /* This is used to determine PASS/FAIL status */
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i, rc;
|
||||
union semun semunion;
|
||||
|
||||
pthread_t pt[NUMTHREADS];
|
||||
pthread_attr_t attr;
|
||||
|
||||
tst_parse_opts(argc, argv, NULL, NULL);
|
||||
/* Create the semaphore set */
|
||||
sem_id = semget(KEY, 1, 0666 | IPC_CREAT);
|
||||
if (sem_id < 0) {
|
||||
printf("semget failed, errno = %d\n", errno);
|
||||
exit(1);
|
||||
}
|
||||
/* initialize data structure associated to the semaphore */
|
||||
semunion.val = 1;
|
||||
semctl(sem_id, 0, SETVAL, semunion);
|
||||
|
||||
/* setup the attributes of the thread */
|
||||
/* set the scope to be system to make sure the threads compete on a */
|
||||
/* global scale for cpu */
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
|
||||
|
||||
err_ret = 1; /* Set initial error value to 1 */
|
||||
/* Create the threads */
|
||||
for (i = 0; i < NUMTHREADS; i++) {
|
||||
if (i == 0)
|
||||
rc = pthread_create(&pt[i], &attr, waiter, retval[i]);
|
||||
else
|
||||
rc = pthread_create(&pt[i], &attr, poster, retval[i]);
|
||||
}
|
||||
|
||||
/* Sleep long enough to see that the other threads do what they are supposed to do */
|
||||
sleep(20);
|
||||
semunion.val = 1;
|
||||
semctl(sem_id, 0, IPC_RMID, semunion);
|
||||
if (err_ret == 1)
|
||||
tst_resm(TFAIL, "failed");
|
||||
else
|
||||
tst_resm(TPASS, "passed");
|
||||
cleanup();
|
||||
|
||||
tst_exit();
|
||||
}
|
||||
|
||||
/* This thread sleeps 10 seconds then waits on the semaphore. As long
|
||||
as someone has posted on the semaphore, and no undo has taken
|
||||
place, the semop should complete and we'll print "Waiter done
|
||||
waiting." */
|
||||
void *waiter(void *foo)
|
||||
{
|
||||
int pid;
|
||||
pid = getpid();
|
||||
|
||||
tst_resm(TINFO, "Waiter, pid = %d", pid);
|
||||
sleep(10);
|
||||
|
||||
tst_resm(TINFO, "Waiter waiting, pid = %d", pid);
|
||||
semop(sem_id, &Psembuf, 1);
|
||||
tst_resm(TINFO, "Waiter done waiting");
|
||||
err_ret = 0; /* If the message above is displayed, the test is a PASS */
|
||||
pthread_exit(0);
|
||||
}
|
||||
|
||||
/* This thread immediately posts on the semaphore and then immediately
|
||||
exits. If the *thread* exits, the undo should not happen, and the
|
||||
waiter thread which will start waiting on it in 10 seconds, should
|
||||
still get it. */
|
||||
void *poster(void *foo)
|
||||
{
|
||||
int pid;
|
||||
|
||||
pid = getpid();
|
||||
tst_resm(TINFO, "Poster, pid = %d, posting", pid);
|
||||
semop(sem_id, &Vsembuf, 1);
|
||||
tst_resm(TINFO, "Poster posted");
|
||||
tst_resm(TINFO, "Poster exiting");
|
||||
|
||||
pthread_exit(0);
|
||||
}
|
||||
|
||||
void cleanup(void)
|
||||
{
|
||||
}
|
||||
@@ -1,340 +0,0 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 19yy <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) 19yy name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
||||
@@ -1,41 +0,0 @@
|
||||
.PHONY: test clean distclean reset test-simple test-kdump
|
||||
|
||||
all:
|
||||
$(MAKE) -C tools
|
||||
$(MAKE) -C tsrc
|
||||
$(MAKE) -C stress
|
||||
|
||||
clean:
|
||||
$(MAKE) -C tools clean
|
||||
$(MAKE) -C tsrc clean
|
||||
$(MAKE) -C stress clean
|
||||
$(MAKE) reset
|
||||
|
||||
distclean:
|
||||
$(MAKE) -C tools distclean
|
||||
$(MAKE) -C tsrc distclean
|
||||
$(MAKE) -C stress distclean
|
||||
$(MAKE) reset
|
||||
rm -rf bin/*
|
||||
|
||||
reset:
|
||||
rm -rf work/*
|
||||
rm -rf results/*
|
||||
|
||||
test: test-simple test-stress
|
||||
|
||||
test-simple:
|
||||
$(MAKE) reset
|
||||
./drivers/simple/driver.sh simple.conf
|
||||
$(MAKE) -C tsrc test
|
||||
|
||||
# requires LTP & page-types to be installed
|
||||
test-stress:
|
||||
$(MAKE) -C stress test
|
||||
|
||||
# requires special packages to be installed
|
||||
test-kdump:
|
||||
$(MAKE) reset
|
||||
./drivers/simple/driver.sh simple.conf
|
||||
./drivers/kdump/driver.sh kdump.conf
|
||||
$(MAKE) -C tsrc test
|
||||
@@ -1,115 +0,0 @@
|
||||
MCE test suite
|
||||
---------------
|
||||
|
||||
The MCE test suite is a collection of tools and test scripts for
|
||||
testing the Linux kernel machine check error recovery
|
||||
features. This is the code that deals with recovery from memory
|
||||
bit errors and other hardware problems.
|
||||
|
||||
For some more details on machine checks see http://www.mcelog.org
|
||||
|
||||
The goal is to cover most Linux kernel MCE processing code paths
|
||||
and features with automation tests.
|
||||
|
||||
In the Package
|
||||
--------------
|
||||
|
||||
Here is a short description of what is included in the package
|
||||
|
||||
README
|
||||
This document
|
||||
|
||||
COPYING
|
||||
GNU General Public License
|
||||
|
||||
Makefile
|
||||
Top level make file for MCE test suite
|
||||
|
||||
drivers/*
|
||||
Contains test drivers, which drive test procedure and do some
|
||||
common works for test drivers. There is one directory for each
|
||||
test driver, the user interface of a driver is the driver.sh
|
||||
in corresponding directory, such as:
|
||||
drivers/kdump/driver.sh
|
||||
is user interface of kdump test driver.
|
||||
|
||||
cases/*
|
||||
Contains all test cases, which may be organized in
|
||||
sub-directories, the interface of a class of test cases is a
|
||||
shell script under cases/, such as:
|
||||
-- cases/soft-inj/panic/cases.sh
|
||||
is for test cases triggered by soft-inject and may cause system
|
||||
panic during testing.
|
||||
-- cases/apei-inj/ucr/cases.sh
|
||||
is for test cases triggered by apei-inject.
|
||||
|
||||
config/*
|
||||
Contains test configuration files, which specifies the
|
||||
parameters for test driver, which test cases are used in test,
|
||||
the parameters for test cases, etc.
|
||||
|
||||
tsrc/*
|
||||
Some standalone test programs for various parts of the machine
|
||||
check code.
|
||||
|
||||
lib/*
|
||||
Contains some shell scripts, in which some common shell
|
||||
functions and variable definitions are defined to be used by
|
||||
multiple test drivers or test cases.
|
||||
|
||||
tools/*
|
||||
Some tools used by MCE test suites.
|
||||
|
||||
doc/*
|
||||
Documentation for MCE test suites include howto and
|
||||
descriptions of every test case.
|
||||
|
||||
results/
|
||||
When test is done, the test result will be placed in this
|
||||
directory, test results for a specific test driver will be
|
||||
placed in corresponding directory, such as test results of
|
||||
kdump test driver will be placed in "results/kdump". General
|
||||
test result is in results/$driver/result; additional results
|
||||
of various cases may be in corresponding directory, for
|
||||
example, files in
|
||||
results/kdump/soft-inj/panic/fatal/
|
||||
is for additional result for test case soft-inj/panic/fatal.
|
||||
|
||||
work/
|
||||
During test, some temporary file will be put in work
|
||||
directory, temporary files for a specific test driver will be
|
||||
placed in corresponding directory, such as temporary files of
|
||||
kdump test driver will be placed in "work/kdump". Test log is
|
||||
in work/$driver/log.
|
||||
|
||||
bin/
|
||||
Some tools used by test drivers or test cases will be
|
||||
installed into this directory.
|
||||
|
||||
stress/
|
||||
Linux MCE stress test suite.
|
||||
|
||||
Test Instruction
|
||||
----------------
|
||||
|
||||
Please refer to corresponding section in doc/howto.txt.
|
||||
|
||||
Very quick way to test this:
|
||||
be root
|
||||
make sure you have a kernel with CONFIG_X86_MCE_INJECT
|
||||
and CONFIG_HWPOISON_INJECT and soft-offlining support
|
||||
run "make test"
|
||||
|
||||
Futher Information
|
||||
------------------
|
||||
|
||||
For futher information about MCE test suite, please refer to documents
|
||||
in doc sub-directory.
|
||||
|
||||
doc/howto.txt: a more detailed HOWTO document
|
||||
|
||||
doc/stress-howto.txt: Detailed HOWTO document for MCE stress test suite
|
||||
|
||||
doc/cases/*.txt: Description of every test case, including test
|
||||
objective, code patch tested, reference and
|
||||
expected results
|
||||
@@ -1,33 +0,0 @@
|
||||
MCE APEI INJ testing cases
|
||||
=========================
|
||||
|
||||
Nov 6th, 2009
|
||||
|
||||
Jiajia Zheng
|
||||
|
||||
Start
|
||||
------------
|
||||
This test suite is based on apei-inj APEI haredware injection tool.
|
||||
It's structure and usage are the same with soft-inj test suite.
|
||||
To be root and invoke simple test driver on test configuration file as follow
|
||||
drivers/simple/driver.sh config/simple_apei_ucr.conf
|
||||
|
||||
Test Dependencies
|
||||
-----------------
|
||||
MCE APEI INJ test suite has following dependencies on kernel and other tools:
|
||||
|
||||
* Make sure following configuration options are enabled in linux kernel:
|
||||
CONFIG_FTRACE=y
|
||||
CONFIG_FUNCTION_TRACER=y
|
||||
|
||||
* page-types:
|
||||
A tool to query page types, which is accompanied with Linux kernel
|
||||
source (2.6.32 or newer, $KERNEL_SRC/Documentation/vm/page-types.c).
|
||||
For detail, please see 3.4 in doc/howto.txt.
|
||||
|
||||
* simple-process:
|
||||
APEI hardware injection will inject an error to a page used by this simple-process. Intall simple-process.
|
||||
cd mce-test/tools/simple_process
|
||||
make
|
||||
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# APEI injection based test cases : memory patrol scrub cases: test cases
|
||||
# are triggered via the apei-inject, and they will not trigger kernel panic.
|
||||
#
|
||||
# Copyright (C) 2008, Intel Corp.
|
||||
# Author: Huang Ying <ying.huang@intel.com>
|
||||
# Zheng Jiajia <jiajia.zheng@intel.com>
|
||||
#
|
||||
# This file is released under the GPLv2.
|
||||
#
|
||||
|
||||
. $ROOT/lib/functions.sh
|
||||
. $ROOT/lib/dirs.sh
|
||||
. $ROOT/lib/mce.sh
|
||||
. $ROOT/lib/apei-inject.sh
|
||||
|
||||
enumerate()
|
||||
{
|
||||
apei_inject_enumerate
|
||||
}
|
||||
|
||||
trigger()
|
||||
{
|
||||
case "$bcase" in
|
||||
mem_uncorrected)
|
||||
start_tracing "do_machine_check"
|
||||
;;
|
||||
*)
|
||||
echo '!!! Unknown case: $this_case !!!'
|
||||
esac
|
||||
apei_inject_trigger
|
||||
stop_tracing
|
||||
}
|
||||
|
||||
get_result()
|
||||
{
|
||||
apei_inject_get_klog
|
||||
get_gcov drivers/acpi/apei/einj.c
|
||||
|
||||
case "$bcase" in
|
||||
mem_uncorrected)
|
||||
get_mcelog_from_dev $mcelog_result
|
||||
;;
|
||||
*)
|
||||
echo '!!! Unknown case: $this_case !!!'
|
||||
esac
|
||||
}
|
||||
|
||||
verify()
|
||||
{
|
||||
case "$bcase" in
|
||||
mem_uncorrected)
|
||||
apei_inject_verify_mcelog
|
||||
verify_klog $klog
|
||||
apei_inject_verify_trace "do_machine_check"
|
||||
;;
|
||||
*)
|
||||
echo "!!! Unknown case: $this_case !!!"
|
||||
esac
|
||||
}
|
||||
|
||||
apei_inject_main "$@"
|
||||
@@ -1 +0,0 @@
|
||||
TYPE 0x10
|
||||
@@ -1,10 +0,0 @@
|
||||
CPU 0 BANK 2
|
||||
STATUS UNCORRECTED SRAO 0xcf
|
||||
MCGSTATUS RIPV MCIP
|
||||
MISC 0x8c
|
||||
ADDR 0x1234
|
||||
RIP 0x73:0x2eadbabe
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Software injection based test cases - non-panic cases: test cases
|
||||
# are triggered via the mce-inject tool, and they will not trigger kernel
|
||||
# panic.
|
||||
#
|
||||
# Copyright (C) 2008, Intel Corp.
|
||||
# Author: Huang Ying <ying.huang@intel.com>
|
||||
#
|
||||
# This file is released under the GPLv2.
|
||||
#
|
||||
|
||||
. $ROOT/lib/functions.sh
|
||||
. $ROOT/lib/dirs.sh
|
||||
. $ROOT/lib/mce.sh
|
||||
. $ROOT/lib/soft-inject.sh
|
||||
|
||||
enumerate()
|
||||
{
|
||||
soft_inject_enumerate
|
||||
}
|
||||
|
||||
trigger()
|
||||
{
|
||||
soft_inject_trigger
|
||||
}
|
||||
|
||||
get_result()
|
||||
{
|
||||
soft_inject_get_klog
|
||||
get_gcov arch/x86/kernel/cpu/mcheck/mce.c
|
||||
|
||||
case "$bcase" in
|
||||
corrected|corrected_hold|corrected_over|corrected_no_en)
|
||||
get_mcelog_from_dev $mcelog_result
|
||||
;;
|
||||
*)
|
||||
echo '!!! Unknown case: $this_case !!!'
|
||||
esac
|
||||
}
|
||||
|
||||
verify()
|
||||
{
|
||||
local removes="TSC TIME PROCESSOR"
|
||||
case "$bcase" in
|
||||
corrected|corrected_hold|corrected_over|corrected_no_en)
|
||||
soft_inject_verify_mcelog
|
||||
verify_klog $klog
|
||||
;;
|
||||
*)
|
||||
echo "!!! Unknown case: $this_case !!!"
|
||||
esac
|
||||
}
|
||||
|
||||
soft_inject_main "$@"
|
||||
@@ -1,14 +0,0 @@
|
||||
#
|
||||
# log corrected machine checks
|
||||
CPU 0 BANK 1
|
||||
STATUS CORRECTED
|
||||
ADDR 0xabcd
|
||||
HOLD
|
||||
CPU 1 BANK 0
|
||||
#
|
||||
CPU 1 BANK 2
|
||||
STATUS CORRECTED
|
||||
MISC 0xabcd
|
||||
ADDR 0x1234
|
||||
HOLD
|
||||
CPU 0 BANK 0
|
||||
@@ -1,10 +0,0 @@
|
||||
#
|
||||
# log two corrected machine checks
|
||||
CPU 0 BANK 1
|
||||
STATUS CORRECTED
|
||||
ADDR 0xabcd
|
||||
HOLD
|
||||
#
|
||||
CPU 1 BANK 2
|
||||
STATUS CORRECTED
|
||||
ADDR 0x1234
|
||||
@@ -1,5 +0,0 @@
|
||||
#
|
||||
CPU 0 BANK 3
|
||||
STATUS VAL
|
||||
HOLD
|
||||
CPU 1 BANK 0
|
||||
@@ -1,4 +0,0 @@
|
||||
CPU 0 BANK 2
|
||||
STATUS VAL OVER EN
|
||||
HOLD
|
||||
CPU 1 BANK 0
|
||||
@@ -1,89 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Software injection based test cases - panic cases: test cases are
|
||||
# triggered via the mce-inject tool, and they will trigger kernel panic.
|
||||
#
|
||||
# Copyright (C) 2008, Intel Corp.
|
||||
# Author: Huang Ying <ying.huang@intel.com>
|
||||
#
|
||||
# This file is released under the GPLv2.
|
||||
#
|
||||
|
||||
. $ROOT/lib/functions.sh
|
||||
. $ROOT/lib/dirs.sh
|
||||
. $ROOT/lib/mce.sh
|
||||
. $ROOT/lib/soft-inject.sh
|
||||
|
||||
enumerate()
|
||||
{
|
||||
soft_inject_enumerate
|
||||
}
|
||||
|
||||
trigger()
|
||||
{
|
||||
reset_severity_cov
|
||||
soft_inject_trigger
|
||||
}
|
||||
|
||||
get_result()
|
||||
{
|
||||
soft_inject_get_klog
|
||||
get_gcov arch/x86/kernel/cpu/mcheck/mce.c
|
||||
get_severity_cov
|
||||
|
||||
case "$bcase" in
|
||||
fatal*)
|
||||
soft_inject_get_mcelog
|
||||
;;
|
||||
*)
|
||||
echo '!!! Unknown case: $this_case !!!'
|
||||
esac
|
||||
}
|
||||
|
||||
verify()
|
||||
{
|
||||
local removes="TSC TIME PROCESSOR"
|
||||
local curr_cpu_panic=": Fatal machine check on current CPU"
|
||||
local fatal_panic="Fatal Machine check"
|
||||
local pcc_exp="Processor context corrupt"
|
||||
case "$bcase" in
|
||||
fatal|fatal_irq|fatal_over)
|
||||
removes="$removes RIP"
|
||||
soft_inject_verify_mcelog
|
||||
verify_klog $klog
|
||||
soft_inject_verify_panic "$fatal_panic"
|
||||
soft_inject_verify_exp "$pcc_exp"
|
||||
;;
|
||||
fatal_ripv|fatal_eipv|fatal_userspace)
|
||||
soft_inject_verify_mcelog
|
||||
verify_klog $klog
|
||||
soft_inject_verify_panic "$fatal_panic"
|
||||
soft_inject_verify_exp "$pcc_exp"
|
||||
;;
|
||||
fatal_no_en)
|
||||
removes="$removes RIP"
|
||||
soft_inject_verify_mcelog
|
||||
verify_klog $klog
|
||||
soft_inject_verify_panic "Machine check from unknown source"
|
||||
;;
|
||||
fatal_timeout)
|
||||
removes="$removes RIP"
|
||||
soft_inject_verify_mcelog
|
||||
verify_klog $klog
|
||||
soft_inject_verify_panic "$curr_cpu_panic"
|
||||
soft_inject_verify_timeout
|
||||
soft_inject_verify_exp "$pcc_exp"
|
||||
;;
|
||||
fatal_timeout_ripv)
|
||||
soft_inject_verify_mcelog
|
||||
verify_klog $klog
|
||||
soft_inject_verify_panic "$curr_cpu_panic"
|
||||
soft_inject_verify_timeout
|
||||
soft_inject_verify_exp "$pcc_exp"
|
||||
;;
|
||||
*)
|
||||
echo "!!! Unknown case: $this_case !!!"
|
||||
esac
|
||||
}
|
||||
|
||||
soft_inject_main "$@"
|
||||
@@ -1,8 +0,0 @@
|
||||
# WARNING
|
||||
# this will panic your machine!
|
||||
# don't try casually
|
||||
CPU 0 BANK 4
|
||||
MCGSTATUS MCIP
|
||||
STATUS FATAL S
|
||||
RIP 12343434
|
||||
MISC 11
|
||||
@@ -1,7 +0,0 @@
|
||||
# WARNING
|
||||
# this will panic your machine!
|
||||
# don't try casually
|
||||
CPU 1 BANK 4
|
||||
MCGSTATUS MCIP EIPV
|
||||
STATUS FATAL S
|
||||
RIP 0x10:0x12343434
|
||||
@@ -1,9 +0,0 @@
|
||||
# WARNING
|
||||
# this will panic your machine!
|
||||
# don't try casually
|
||||
CPU 0 BANK 4
|
||||
MCGSTATUS MCIP
|
||||
STATUS FATAL S
|
||||
RIP 12343434
|
||||
MISC 11
|
||||
IN_IRQ
|
||||
@@ -1,8 +0,0 @@
|
||||
# WARNING
|
||||
# this will panic your machine!
|
||||
# don't try casually
|
||||
CPU 0 BANK 4
|
||||
MCGSTATUS MCIP
|
||||
STATUS UC VAL PCC S
|
||||
RIP 0x10:12343434
|
||||
MISC 11
|
||||
@@ -1,9 +0,0 @@
|
||||
# WARNING
|
||||
# this will panic your machine!
|
||||
# don't try casually
|
||||
CPU 0 BANK 4
|
||||
MCGSTATUS MCIP
|
||||
STATUS FATAL OVER S
|
||||
RIP 12343434
|
||||
MISC 11
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
# WARNING
|
||||
# this will panic your machine!
|
||||
# don't try casually
|
||||
CPU 1 BANK 4
|
||||
MCGSTATUS MCIP RIPV
|
||||
STATUS FATAL S
|
||||
RIP 0x10:0x12343434
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user