删除老版本ltp代码

Signed-off-by: rocket-turtle <qigongming@huawei.com>
This commit is contained in:
rocket-turtle
2024-11-05 19:29:50 +08:00
parent f4a08e68e2
commit 3e8caed096
1378 changed files with 7 additions and 110243 deletions
-46
View File
@@ -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) .
-213
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-59
View File
@@ -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).
-59
View File
@@ -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].
-62
View File
@@ -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
-476
View 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");
}
}
-------------------------------------------------------------------------------
-763
View File
@@ -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
-------------------------------------------------------------------------------
-66
View File
@@ -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].
-336
View File
@@ -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.
-41
View File
@@ -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
View File
@@ -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()
-54
View File
@@ -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 */
-56
View File
@@ -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__ */
-31
View File
@@ -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__ */
-24
View File
@@ -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__ */
-27
View File
@@ -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__ */
-22
View File
@@ -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,
};
-21
View File
@@ -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,
};
-22
View File
@@ -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
};
-17
View File
@@ -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))
])
-12
View File
@@ -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))
])
-16
View File
@@ -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
View File
@@ -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
View File
@@ -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
-175
View File
@@ -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
View File
@@ -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;
}
-80
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
-478
View File
@@ -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);
}
-79
View File
@@ -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
-38
View File
@@ -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
-8
View File
@@ -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
-4
View File
@@ -1,4 +0,0 @@
#! /bin/csh
echo "this is a shell script"
echo "used to test file command"
-4
View File
@@ -1,4 +0,0 @@
#! /bin/ksh
echo "this is a shell script"
echo "used to test file command"
-14
View File
@@ -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
-45
View File
@@ -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
-50
View File
@@ -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.
-27
View File
@@ -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);
}
-11
View File
@@ -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;
}
-158
View File
@@ -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
-3
View File
@@ -1,3 +0,0 @@
/create-files
/random-access
/random-access-del-create
-41
View File
@@ -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
-45
View File
@@ -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 $
-28
View File
@@ -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);
}
-119
View File
@@ -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
-124
View File
@@ -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
-30
View File
@@ -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
-164
View File
@@ -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);
}
-157
View File
@@ -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)
{
}
-340
View File
@@ -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.
-41
View File
@@ -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
-115
View File
@@ -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