[med-svn] [Git][med-team/sambamba][upstream] New upstream version 0.6.8
Andreas Tille
gitlab at salsa.debian.org
Thu Oct 4 09:23:15 BST 2018
Andreas Tille pushed to branch upstream at Debian Med / sambamba
Commits:
22dc4a79 by Andreas Tille at 2018-10-04T08:06:06Z
New upstream version 0.6.8
- - - - -
21 changed files:
- .gitmodules
- .travis.yml
- INSTALL.md
- Makefile
- Makefile.guix
- README.md
- RELEASE-NOTES.md
- + contrib/shunit2-2.0.3/CHANGES-2.0.txt
- + contrib/shunit2-2.0.3/LGPL-2.1
- + contrib/shunit2-2.0.3/README.txt
- + contrib/shunit2-2.0.3/contributors.txt
- + contrib/shunit2-2.0.3/shunit2
- cram/htslib.d
- gen_ldc_version_info.py
- run_tests.sh
- sambamba/main.d
- sambamba/markdup.d
- test/benchmark/stats.org
- + test/issue_356.sam
- test/test_suite.sh
- utils/version_.d
Changes:
=====================================
.gitmodules
=====================================
@@ -1,12 +1,12 @@
[submodule "htslib"]
path = htslib
url = https://github.com/lomereiter/htslib.git
-[submodule "undeaD"]
- path = undeaD
- url = https://github.com/dlang/undeaD
-[submodule "BioD"]
- path = BioD
- url = https://github.com/biod/BioD.git
[submodule "lz4"]
path = lz4
url = https://github.com/lz4/lz4.git
+[submodule "BioD"]
+ path = BioD
+ url = https://github.com/biod/BioD.git
+[submodule "undeaD"]
+ path = undeaD
+ url = https://github.com/biod/undeaD.git
=====================================
.travis.yml
=====================================
@@ -8,15 +8,8 @@ matrix:
include:
- os: linux
compiler: gcc
- addons:
- apt:
- packages:
- # Our dev environment is a more recent GNU C++
- # note that Debian liblz4-dev no longer supports LZ4 frames
- # - liblz4-dev
- - shunit2
- os: osx
compiler: clang
script:
- make
- # - make test - disable tests because shunit2 we use is older
\ No newline at end of file
+ - make check
=====================================
INSTALL.md
=====================================
@@ -2,10 +2,27 @@
## Sambamba dependencies
-* D compiler
-* gcc tool chain
-* BioD
-* htslib
-* undeaD
+* D compiler (ldc)
+* BioD (git submodule)
+* gcc tool chain (for htslib and lz4)
+* htslib (git submodule)
+* undeaD (git submodule)
* libz
* liblz4
+
+## Install Sambamba from source
+
+After checking out the source from github with git submodules is is
+possibleto install the build tools with GNU Guix
+
+ guix package -i gcc gdb bash ld-wrapper ldc which python2 git
+
+Even better, with Guix, you can create a light-weight container in the source tree
+and run our development setup
+
+ guix environment -C guix --ad-hoc gcc gdb bash ld-wrapper ldc which python git
+ make clean
+ make -j 4
+ make check
+
+this way all dependencies are isolated.
=====================================
Makefile
=====================================
@@ -1,24 +1,39 @@
# This is a minimalistic make file to build sambamba with ldc2 as per instructions on
# https://github.com/biod/sambamba#compiling-sambamba
#
+# Targets (64-bit):
+#
+# Linux
+# OSX
+#
# Typical usage:
#
-# make LIBRARY_PATH=~/opt/ldc2-1.7.0-linux-x86_64/lib debug|profile|release|static
+# make LIBRARY_PATH=~/opt/ldc2-$ver-linux-x86_64/lib debug|profile|release|static
#
# Static release with optimization (for releases):
#
-# make LIBRARY_PATH=~/opt/ldc2-1.7.0-linux-x86_64/lib pgo-static
+# make LIBRARY_PATH=~/opt/ldc2-$ver-linux-x86_64/lib pgo-static
#
# Debug version
#
-# make LIBRARY_PATH=~/opt/ldc2-1.7.0-linux-x86_64/lib debug
+# make LIBRARY_PATH=~/opt/ldc2-$ver-linux-x86_64/lib debug
+#
D_COMPILER=ldc2
+
+UNAME_S := $(shell uname -s)
+ifeq ($(UNAME_S),Darwin)
+ SYS = OSX
+else
+ SYS = LINUX
+ LINK_OBJ = utils/ldc_version_info_.o
+endif
+
DFLAGS = -wi -I. -IBioD -IundeaD/src -g
DLIBS = $(LIBRARY_PATH)/libphobos2-ldc.a $(LIBRARY_PATH)/libdruntime-ldc.a
DLIBS_DEBUG = $(LIBRARY_PATH)/libphobos2-ldc-debug.a $(LIBRARY_PATH)/libdruntime-ldc-debug.a
-LIBS = htslib/libhts.a lz4/lib/liblz4.a -L-L$(LIBRARY_PATH) -L-lrt -L-lpthread -L-lm
+LIBS = htslib/libhts.a lz4/lib/liblz4.a -L-L$(LIBRARY_PATH) -L-lpthread -L-lm
LIBS_STATIC = $(LIBRARY_PATH)/libc.a $(DLIBS) htslib/libhts.a $(LIBRARY_PATH)/liblz4.a
SRC = $(wildcard main.d utils/*.d thirdparty/*.d cram/*.d) $(wildcard undeaD/src/undead/*.d) $(wildcard BioD/bio/*/*.d BioD/bio/*/*/*.d BioD/bio2/*.d BioD/bio2/*/*.d) $(wildcard sambamba/*.d sambamba/*/*.d sambamba/*/*/*.d)
OBJ = $(SRC:.d=.o) utils/ldc_version_info_.o
@@ -49,7 +64,7 @@ htslib-static:
cd htslib && $(MAKE)
ldc-version-info:
- ./gen_ldc_version_info.py $(shell which ldmd2) > utils/ldc_version_info_.d
+ python3 ./gen_ldc_version_info.py $(shell which ldmd2) > utils/ldc_version_info_.d
cat utils/ldc_version_info_.d
utils/ldc_version_info_.o: ldc-version-info
@@ -78,7 +93,7 @@ singleobj:
# ---- Link step
$(OUT): build-setup singleobj utils/ldc_version_info_.o
$(info linking...)
- $(D_COMPILER) $(DFLAGS) -of=bin/sambamba bin/sambamba.o utils/ldc_version_info_.o $(LIBS)
+ $(D_COMPILER) $(DFLAGS) -of=bin/sambamba bin/sambamba.o $(LINK_OBJ) $(LIBS)
test:
./run_tests.sh
@@ -97,7 +112,7 @@ install:
install -m 0755 bin/sambamba $(prefix)/bin
clean: clean-d
- cd htslib ; make clean
+ cd htslib ; $(MAKE) clean
rm -f profile.data
rm -f profile.raw
=====================================
Makefile.guix
=====================================
@@ -1,10 +1,10 @@
-# GNU Guix makefile. GNU Guix is the package manager for GNU and we use it for
-# sambamba development and deployment. Normally use the standard Makefile
-# instead.
+# GNU Guix makefile. GNU Guix is the package manager for GNU and we
+# use it for sambamba development and deployment. Normally use the
+# standard Makefile instead because it compiles into a singleobj.
#
# To build sambamba on GNU Guix:
#
-# make -f Makefile.guix
+# make -f Makefile.guix GUIX=~/opt/sambamba-dev-env
#
# run with
#
@@ -18,7 +18,10 @@
#
# The following two are modified by the Guix package:
D_COMPILER=ldc2
-LDC_LIB_PATH=$(HOME)/.guix-profile/lib
+ifndef GUIX
+ GUIX=$(HOME)/.guix-profile
+endif
+LDC_LIB_PATH=$(GUIX)/lib
UNDEAD_PATH=../undeaD/src
BIOD_PATH=../BioD
@@ -31,7 +34,7 @@ RPATH = -L--rpath=$(dir $(realpath $(LDC_LIB_PATH)/libz.so)):$(dir $(realpath $
LIBS = htslib/libhts.a -L-L$(LDC_LIB_PATH) -L-lrt -L-lpthread -L-lm -L-lz -L-llz4
# LIBS = htslib/libhts.a -L-lrt -L-lpthread -L-lm -L-lz -L-llz4
LIBS_STATIC = $(DLIBS) htslib/libhts.a $(LDC_LIB_PATH)/liblz4.a
-SRC = $(wildcard utils/*.d thirdparty/*.d cram/*.d) $(wildcard $(UNDEAD_PATH)/undead/**/*.d) $(wildcard $(UNDEAD_PATH)/undead/*.d) $(wildcard $(BIOD_PATH)/bio/*/*.d $(BIOD_PATH)/bio/*/*/*.d) $(wildcard sambamba/*.d sambamba/*/*.d sambamba/*/*/*.d) utils/ldc_version_info_.d
+SRC = $(wildcard main.d utils/*.d thirdparty/*.d cram/*.d) $(wildcard undeaD/src/undead/*.d undeaD/src/undead/*/*.d) $(wildcard BioD/bio/*/*.d BioD/bio/*/*/*.d BioD/bio2/*.d BioD/bio2/*/*.d) $(wildcard sambamba/*.d sambamba/*/*.d sambamba/*/*/*.d)
OBJ = $(SRC:.d=.o)
OUT = bin/sambamba
=====================================
README.md
=====================================
@@ -2,15 +2,36 @@
# sambamba
-## Table of Contents
+Table of Contents
+=================
+
+ * [sambamba](#sambamba)
+ * [Table of Contents](#table-of-contents)
+ * [Introduction](#introduction)
+ * [Binary installation](#binary-installation)
+ * [Install stable release](#install-stable-release)
+ * [Bioconda install](#bioconda-install)
+ * [GNU Guix install](#gnu-guix-install)
+ * [Debian GNU/Linux install](#debian-gnulinux-install)
+ * [Homebrew install](#homebrew-install)
+ * [Getting help](#getting-help)
+ * [Reporting a sambamba bug or issue](#reporting-a-sambamba-bug-or-issue)
+ * [Check list:](#check-list)
+ * [Code of conduct](#code-of-conduct)
+ * [Compiling Sambamba](#compiling-sambamba)
+ * [Compilation dependencies](#compilation-dependencies)
+ * [Compiling for Linux](#compiling-for-linux)
+ * [GNU Guix](#gnu-guix)
+ * [Compiling for Mac OS X](#compiling-for-mac-os-x)
+ * [Development](#development)
+ * [Debugging and troubleshooting](#debugging-and-troubleshooting)
+ * [Segfaults on certain Intel Xeons](#segfaults-on-certain-intel-xeons)
+ * [Dump core](#dump-core)
+ * [Use catchsegv](#use-catchsegv)
+ * [Using gdb](#using-gdb)
+ * [License](#license)
+ * [Credit](#credit)
-- [Introduction](#intro)
-- [Binary installation](#install)
-- [Getting help](#help)
-- [Compiling](#compile)
-- [Debugging and troubleshooting](#debug)
-- [License](#license)
-- [Credits](#credits)
<a name="intro"></a>
# Introduction
@@ -33,8 +54,8 @@ configurations. Here are some comparison
[metrics](https://public-docs.crg.es/rguigo/Data/epalumbo/sambamba_ws_report.html). For
example for flagstat sambamba is 1.4x faster than samtools. For index
they are similar. For Markdup almost 6x faster and for view 4x
-faster. For sort sambamba has been beaten generally, though sambamba
-is up to 2x faster on large RAM machines.
+faster. For sort sambamba has been beaten, though sambamba is up to 2x
+faster than samtools on large RAM machines (120GB+).
In addition sambamba has a few interesting features to offer, in particular
@@ -58,7 +79,7 @@ Sambamba is free and open source software, licensed under GPLv2+.
See manual pages [online](https://lomereiter.github.io/sambamba/docs/sambamba-view.html)
to know more about what is available and how to use it.
-For more information on Sambamba contact the mailing list (see below).
+For more information on Sambamba contact the mailing list (see [Getting help](#getting-help)).
<a name="install"></a>
# Binary installation
@@ -69,7 +90,7 @@ are Github source and binary
[releases](https://github.com/biod/sambamba/releases). Simply download
the tarball, unpack it and run it. For example
-```sh
+```bash
wget https://github.com/biod/sambamba/releases/download/v0.6.8/sambamba_v0.6.8_linux.tar.bz2
tar xvjf sambamba_v0.6.8_linux.tar.bz2
./sambamba_v0.6.8
@@ -95,13 +116,12 @@ A [GNU Guix package](https://www.gnu.org/software/guix/packages/s.html) for samb
## Debian GNU/Linux install
-Debian: see Debian packages.
+Debian: see [Debian packages](https://tracker.debian.org/pkg/sambamba).
## Homebrew install
Users of Homebrew can also use the formula from `homebrew-science`.
-
<a name="help"></a>
# Getting help
@@ -155,20 +175,11 @@ Note: in general there is no need to compile sambamba. You can use a
recent binary install as listed above.
The preferred method for compiling Sambamba is with the LDC compiler
-which targets LLVM.
+which targets LLVM. LLVM versions 6 is faster than earlier editions.
## Compilation dependencies
-- git (to check out the repo)
-- gcc compiler 4.9 or later (for htslib)
-- D compiler 1.7.0 or later (ldc2, see below)
-- python2 (parses D-compiler header for version info)
-- zlib (library)
-- lz4 (library)
-- htslib (submodule)
-- BioD (source)
-- undeaD (source)
-- python2
+See [INSTALL.md](./INSTALL.md).
## Compiling for Linux
@@ -190,7 +201,7 @@ cd sambamba
make
```
-To build a debug release run
+To build a development/debug version run
```sh
make clean && make debug
@@ -203,6 +214,8 @@ you can run
make check
```
+See also [INSTALL.md](./INSTALL.md).
+
### GNU Guix
To build sambamba the LDC compiler is also available in GNU Guix:
@@ -213,15 +226,14 @@ guix package -i ldc
## Compiling for Mac OS X
-Note: the Makefile does not work. Someone want to fix that using the
-Makefile.old version? See also https://github.com/biod/sambamba/issues/338.
+Sambamba builds on MacOS. We have a Travis [integration test](https://travis-ci.org/pjotrp/sambamba) as
+an example. It can be something like
```sh
brew install ldc
git clone --recursive https://github.com/biod/sambamba.git
cd sambamba
- git clone https://github.com/dlang/undeaD
- make sambamba-ldmd2-64
+ make
```
## Development
@@ -232,6 +244,7 @@ documentation can be found in the source code and the [development
documentation](https://github.com/biod/sambamba-dev-docs).
<a name="debug"></a>
+
# Debugging and troubleshooting
## Segfaults on certain Intel Xeons
@@ -305,6 +318,8 @@ work on Sambamba, please cite the following publication:
A. Tarasov, A. J. Vilella, E. Cuppen, I. J. Nijman, and P. Prins. [Sambamba: fast processing of NGS alignment formats](https://doi.org/10.1093/bioinformatics/btv098). Bioinformatics, 2015.
+## Bibtex reference
+
```bibtex
@article{doi:10.1093/bioinformatics/btv098,
=====================================
RELEASE-NOTES.md
=====================================
@@ -1,15 +1,79 @@
-## ChangeLog v0.6.8-pre1 (20180207)
+## ChangeLog v0.6.8 (20181004)
-Minor release with a much faster binary. 10-20% faster than v0.6.6,
-due to ldc and LLVM improvements. Fixes speed regression of v0.6.7 for
-large files. See also [performance](https://github.com/biod/sambamba/blob/master/test/benchmark/stats.org)
+Pre-release with a much faster statically compiled binary. 10-20%
+faster than v0.6.6, due to ldc and LLVM improvements. Fixes speed
+regression of v0.6.7 for large files due to singleobj compilation. See
+also #345 and
+[performance](https://github.com/biod/sambamba/blob/master/test/benchmark/stats.org)
+64-bit compilation should be fine on ldc 1.10+. i386 target is still a problem.
+
++ Fix mark duplicates in files with many contigs, see #361 (thanks Devon Ryan @dpryan79)
++ Fix missing PM tag in #356 (thanks Kurt Hetrick @Kurt-Hetrick)
++ Fix Bcftools version checking #352 (thanks Nathan S. Watson-Haigh @nathanhaigh)
++ Fixate version info in BAM output headers for reproducibility. See #357
+ Fixed Makefile for general use, see #332
+ Started benchmarking, see #283 and https://github.com/biod/sambamba/blob/master/test/benchmark/stats.org
+ Readded [Travis-ci support](https://travis-ci.org/biod/sambamba) for Linux (MacOS is disabled #338)
++ Fixed MacOS build in Travis with ae269cfbdf2e78750ce7f8dc70ad32f80a6682df
+ Updated BioD to latest https://github.com/biod/BioD/commit/5e56b2bb45324af2194b3339d298fd827c8003ae
+ Bug fixes:
* #328 Debug version: SAM output of CRAM file is populated with debug on pipe
* #331 Segmentation fault attempting to view header in json format
* #335 Intel Xeon bug may segfault Sambamba - this was tracked down to an Intel Xeon bug
+ * #345 sambamba index 0.6.7 takes 4x longer than 0.6.6 on the same files
+ Documentation updates
++ Updated lz4 to latest (still source in tree because Debian dropped frame support in liblz4-dev)
++ Added support for GNU Guix and build containers
++ Added shunit2 to the source tree for testing
++ Update python build dependencies to use python3.x
++ Fixed a number of D compiler messages on deprecated features (ldc 1.11)
+
+To install the image, download and
+
+```sh
+md5sum sambamba-0.6.8.gz
+25efb5604ae5fe7c750e8020326787c5 sambamba-0.8.6.gz
+gzip -d sambamba-0.6.8.gz
+chmod a+x sambamba-0.6.8
+
+./sambamba-0.8.6
+
+sambamba 0.6.8 by Artem Tarasov and Pjotr Prins (C) 2012-2018
+ LDC 1.10.0 / DMD v2.080.1 / LLVM6.0.1 / bootstrap LDC - the LLVM D compiler (0.17.4)
+```
+
+The binary images were reproducibly built on x86_64 with
+
+```sh
+~/.config/guix/current/bin/guix pull -l
+Generation 3 Sep 25 2018 09:39:08
+ guix 932839f
+ repository URL: https://git.savannah.gnu.org/git/guix.git
+ branch: origin/master
+ commit: 932839ff124ff3b0dd3070914fb1c5beec69bf32
+
+
+guix environment -C guix --ad-hoc gcc gdb bash ld-wrapper ldc which python git
+make clean && make -j 16 && make check
+
+for x in `ldd bin/sambamba|cut -d ' ' -f 3` ; do realpath $x ; done
+/gnu/store/l4lr0f5cjd0nbsaaf8b5dmcw1a1yypr3-glibc-2.27/lib/libpthread-2.27.so
+/gnu/store/l4lr0f5cjd0nbsaaf8b5dmcw1a1yypr3-glibc-2.27/lib/libm-2.27.so
+/gnu/store/l4lr0f5cjd0nbsaaf8b5dmcw1a1yypr3-glibc-2.27/lib/librt-2.27.so
+/gnu/store/l4lr0f5cjd0nbsaaf8b5dmcw1a1yypr3-glibc-2.27/lib/libdl-2.27.so
+/gnu/store/bmaxmigwnlbdpls20px2ipq1fll36ncd-gcc-8.2.0-lib/lib/libgcc_s.so.1
+/gnu/store/l4lr0f5cjd0nbsaaf8b5dmcw1a1yypr3-glibc-2.27/lib/libc-2.27.so
+# build static image
+make clean && make release -j 16 && make check
+```
+
+Git submodule versions were
+
+```
+ git submodule status
+ 2f0634b187e0f454809432093238cf31e9fbfee6 BioD (v0.2.0-5-g2f0634b)
+ 2f3c3ea7b301f9b45737a793c0b2dcf0240e5ee5 htslib (0.2.0-rc10-271-g2f3c3ea)
+ b3692db46d2b23a7c0af2d5e69988c94f126e10a lz4 (v1.8.2)
+ 9be93876982b5f14fcca60832563b3cd767dd84d undeaD (v1.0.1-49-g9be9387)
+ ```
=====================================
contrib/shunit2-2.0.3/CHANGES-2.0.txt
=====================================
@@ -0,0 +1,68 @@
+CHANGES WITH 2.0.4
+
+Unset additional variables that were missed.
+
+Fixed off-by-one in exit value for scripts caught by the trap handler.
+
+The library did not fail gracefully when the 'od' command was not installed.
+
+
+CHANGES WITH 2.0.3
+
+Back ported the Makefile from 2.1.1pre that included changes to the
+docs-docbook-prep target.
+
+Changed the test in assertFalse() so that any non-zero value registers as
+false. (Credits to Bryan Larsen)
+
+Updated the testPartyLikeItIs1999() function in the Quick Start documentation.
+The 'expected' and 'actual' values were swapped. (Credits to Richard Jensen)
+
+It was pointed out that the simple 'failed' message for a failed assert was not
+only insufficient, it was nonstandard (when compared to JUnit) and didn't
+provide the user with an expected vs actual result. The code was revised
+somewhat to bring closer into alignment with JUnit (v4.3.1 specifically) so
+that it feels more "normal". (Credits to Richard Jensen)
+
+As part of the JUnit realignment, it was noticed that fail*() functions in
+JUnit don't actually do any comparisons themselves. They only generate a
+failure message. Updated the code to match.
+
+Added self-testing unit tests. Kinda horkey, but they did find bugs during the
+JUnit realignment.
+
+Fixed the code for returning from asserts as the return was being called before
+the unsetting of variables occurred. (Credits to Mathias Goldau)
+
+The assert(True|False)() functions now accept an integer value for a
+conditional test. A value of '0' is considered 'true', while any non-zero value
+is considered 'false'.
+
+All public functions now fill use default values to work properly with the '-x'
+shell debugging flag.
+
+Fixed the method of percent calculation for the report to get achieve better
+accuracy.
+
+
+CHANGES WITH 2.0.2
+
+Fixed problem with fail(). The failure message was not properly printed.
+
+Reworked the Makefile so that the DocBook XML and XSLT files are properly
+downloaded before parsing can continue.
+
+
+CHANGES WITH 2.0.1
+
+Fixed some really stupid mistakes with the fail* functions. They were doing the
+exact opposite of what they were supposed to be doing.
+
+
+CHANGES WITH 2.0.0
+
+Made the first stand-alone release!
+
+
+$Revision$
+vim:spell
=====================================
contrib/shunit2-2.0.3/LGPL-2.1
=====================================
@@ -0,0 +1,504 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 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.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+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 and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, 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 library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete 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 distribute a copy of this License along with the
+Library.
+
+ 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 Library or any portion
+of it, thus forming a work based on the Library, 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) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+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 Library, 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 Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you 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.
+
+ If distribution of 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 satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be 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.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library 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.
+
+ 9. 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 Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+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 with
+this License.
+
+ 11. 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 Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library 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 Library.
+
+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.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library 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.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser 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 Library
+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 Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+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
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "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
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. 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 LIBRARY 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
+LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), 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 Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. 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 library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; 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.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
=====================================
contrib/shunit2-2.0.3/README.txt
=====================================
@@ -0,0 +1,153 @@
+#------------------------------------------------------------------------------
+# SourceForge
+#
+
+This project is stored on SourceForge as http://sf.net/projects/shunit2. The
+source code can be accessed using the following information.
+
+* Subversion
+$ svn co https://shunit2.svn.sourceforge.net/svnroot/shunit2/trunk/source shunit2
+
+Subversion may also be browsed via a web browser at
+http://svn.sourceforge.net/shunit2
+
+#------------------------------------------------------------------------------
+# Making a release
+#
+
+For these steps, it is assumed we are working with release 2.0.0.
+
+Steps:
+* write release notes
+* update version
+* finish changelog
+* check all the code in
+* tag the release
+* export the release
+* create tarball
+* md5sum the tarball and sign with gpg
+* update website
+* post to SourceForge and Freshmeat
+
+WRITE RELEASE NOTES
+
+This should be pretty self explainatory. Use one of the release notes from a
+previous release as an example.
+
+To get the versions of the various shells, do the following:
+Cygwin
+ bash: $ bash --version
+ ksh: actually pdksh
+ pdksh: look in the downloaded Cygwin directory
+Linux
+ bash: $ bash --version
+ dash: look at installed version
+ ksh: $ ksh --version
+ pdksh: $ strings /bin/pdksh |grep 'PD KSH'
+ zsh: $ zsh --version
+Solaris 10
+ sh: not possible
+ bash: $ bash --version
+ ksh: $ strings /usr/bin/ksh |grep 'Version'
+
+UPDATE VERSION
+
+Edit the shunit2 source code, and change the version number in the comment, as
+well as in the __SHUNIT_VERSION variable. Next, edit the
+src/docbook/shunit2.xml file, edit the version in the <title> element, and make
+sure there is a revision section for this release.
+
+FINISH DOCUMENTATION
+
+Make sure that any remaning changes get put into the CHANGES-X.X.txt file.
+
+Finish writing the RELEASE_NOTES-X.X.X.txt. Once it is finished, run it through
+the 'fmt' command to make it pretty.
+
+$ fmt -w 80 RELEASE_NOTES-2.0.0.txt >RELEASE_NOTES-2.0.0.txt.new
+$ mv RELEASE_NOTES-2.0.0.txt.new RELEASE_NOTES-2.0.0.txt
+
+We want to have an up-to-date version of the documentation in the release, so
+we'd better build it.
+
+$ pwd
+.../shunit2/source/2.0
+$ make docs
+...
+$ cp -p build/shunit2.html doc
+$ svn ci -m "" doc/shunit2.html
+
+CHECK IN ALL THE CODE
+
+This step is pretty self-explainatory
+
+TAG THE RELEASE
+
+$ pwd
+.../shunit2/source
+$ ls
+2.0 2.1
+$ svn cp -m "Release 2.0.0" \
+2.0 https://shunit2.svn.sourceforge.net/svnroot/shunit2/tags/source/2.0.0
+
+EXPORT THE RELEASE
+
+$ pwd
+.../shunit2/builds
+$ svn export \
+https://shunit2.svn.sourceforge.net/svnroot/shunit2/tags/source/2.0.0 \
+shunit2-2.0.0
+
+CREATE TARBALL
+
+$ tar cfz ../releases/shunit2-2.0.0.tgz shunit2-2.0.0
+
+MD5SUM THE TARBALL AND SIGN WITH GPG
+
+$ cd ../releases
+$ md5sum shunit2-2.0.0.tgz >shunit2-2.0.0.tgz.md5
+$ gpg --default-key kate.ward at forestent.com --detach-sign shunit2-2.0.0.tgz
+
+UPDATE WEBSITE
+
+Again, pretty self-explainatory. Make sure to copy the MD5 and GPG signature
+files. Once that is done, make sure to tag the website so we can go back in
+time if needed.
+
+$ pwd
+.../shunit2
+$ ls
+source website
+$ svn cp -m "Release 2.0.0" \
+website https://shunit2.svn.sourceforge.net/svnroot/shunit2/tags/website/20060916
+
+Now, update the website. It too is held in Subversion, so ssh into SourceForge
+and use 'svn up' to grab the latest version.
+
+POST TO SOURCEFORGE AND FRESHMEAT
+
+http://sourceforge.net/projects/shunit2/
+http://freshmeat.net/
+
+#------------------------------------------------------------------------------
+# Related documentation
+#
+
+Docbook XML
+ docbook-xml-4.4.zip
+ http://www.docbook.org/xml/4.4/docbook-xml-4.4.zip
+ http://www.oasis-open.org/docbook/xml/4.4/docbook-xml-4.4.zip
+ docbook-xml-4.5.zip
+ http://www.docbook.org/xml/4.5/docbook-xml-4.5.zip
+
+Docbook XSL
+ docbook-xsl-1.71.0.tar.bz2
+ http://prdownloads.sourceforge.net/docbook/docbook-xsl-1.71.0.tar.bz2?download
+ docbook-xsl-1.71.1.tar.bz2
+ http://downloads.sourceforge.net/docbook/docbook-xsl-1.71.1.tar.bz2?use_mirror=puzzle
+
+JUnit
+ http://www.junit.org
+
+
+$Revision$
=====================================
contrib/shunit2-2.0.3/contributors.txt
=====================================
@@ -0,0 +1,10 @@
+The original author of shunit2 is Kate Ward. The following people have
+contributed in some way or another to shunit2.
+
+Bryan Larsen
+Kevin Van Horn
+Mathias Goldau
+Richard Jensen
+Rob Holland
+
+$Revision$
=====================================
contrib/shunit2-2.0.3/shunit2
=====================================
@@ -0,0 +1,799 @@
+# $Id$
+# vim:syntax=sh:sts=2
+# vim:foldmethod=marker:foldmarker=/**,*/
+#
+#/**
+# <?xml version="1.0" encoding="UTF-8"?>
+# <s:shelldoc xmlns:s="http://www.forestent.com/projects/shelldoc/xsl/2005.0">
+# <s:header>
+# shUnit 2.0.4
+# Shell Unit Test Framework
+#
+# http://code.google.com/p/shunit2/
+#
+# written by Kate Ward <kate.ward at forestent.com>
+# released under the LGPL
+#
+# this module implements a xUnit based unit test framework similar to JUnit
+# </s:header>
+#*/
+
+# shell flags for shunit:
+# u - treat unset variables as an error when performing parameter expansion
+__SHUNIT_SHELL_FLAGS='u'
+
+# save the current set of shell flags, and then set some for ourselves
+__shunit_oldShellFlags="$-"
+for _shunit_shellFlag in `echo "${__SHUNIT_SHELL_FLAGS}" |sed 's/\(.\)/\1 /g'`
+do
+ set -${_shunit_shellFlag}
+done
+unset _shunit_shellFlag
+
+# constants
+
+__SHUNIT_VERSION='2.0.4pre'
+
+__SHUNIT_TRUE=0
+__SHUNIT_FALSE=1
+__SHUNIT_ERROR=2
+
+__SHUNIT_ASSERT_MSG_PREFIX='ASSERT:'
+
+for _su_const in `set |grep "^__SHUNIT_" |cut -d= -f1`; do
+ readonly ${_su_const}
+done
+unset _su_const
+
+# variables
+__shunit_suite=''
+
+__shunit_testsPassed=0
+__shunit_testsFailed=0
+__shunit_testsTotal=0
+
+#-----------------------------------------------------------------------------
+# assert functions
+#
+
+#/**
+# <s:function group="asserts">
+# <entry align="right">
+# <emphasis>void</emphasis>
+# </entry>
+# <entry>
+# <funcsynopsis>
+# <funcprototype>
+# <funcdef><function>assertEquals</function></funcdef>
+# <paramdef>string <parameter>[message]</parameter></paramdef>
+# <paramdef>string <parameter>expected</parameter></paramdef>
+# <paramdef>string <parameter>actual</parameter></paramdef>
+# </funcprototype>
+# </funcsynopsis>
+# <para>Asserts that <emphasis>expected</emphasis> and
+# <emphasis>actual</emphasis> are equal to one another. The message is
+# optional.</para>
+# </entry>
+# </s:function>
+#*/
+assertEquals()
+{
+ _su_message=''
+ if [ $# -eq 3 ]; then
+ _su_message=$1
+ shift
+ fi
+ _su_expected=${1:-}
+ _su_actual=${2:-}
+
+ shunit_return=${__SHUNIT_TRUE}
+ if [ "${_su_expected}" = "${_su_actual}" ]; then
+ _shunit_testPassed
+ else
+ failNotEquals "${_su_message}" "${_su_expected}" "${_su_actual}"
+ shunit_return=${__SHUNIT_FALSE}
+ fi
+
+ unset _su_message _su_expected _su_actual
+ return ${shunit_return}
+}
+
+#/**
+# <s:function group="asserts">
+# <entry align="right">
+# <emphasis>void</emphasis>
+# </entry>
+# <entry>
+# <funcsynopsis>
+# <funcprototype>
+# <funcdef><function>assertNull</function></funcdef>
+# <paramdef>string <parameter>[message]</parameter></paramdef>
+# <paramdef>string <parameter>value</parameter></paramdef>
+# </funcprototype>
+# </funcsynopsis>
+# <para>Asserts that <emphasis>value</emphasis> is <literal>null</literal>,
+# or in shell terms a zero-length string. The message is optional.</para>
+# </entry>
+# </s:function>
+#*/
+assertNull()
+{
+ if [ $# -eq 2 ]; then
+ assertTrue "$1" "[ -z '$2' ]"
+ else
+ assertTrue "[ -z '${1:-}' ]"
+ fi
+}
+
+#/**
+# <s:function group="asserts">
+# <entry align="right">
+# <emphasis>void</emphasis>
+# </entry>
+# <entry>
+# <funcsynopsis>
+# <funcprototype>
+# <funcdef><function>assertNotNull</function></funcdef>
+# <paramdef>string <parameter>[message]</parameter></paramdef>
+# <paramdef>string <parameter>value</parameter></paramdef>
+# </funcprototype>
+# </funcsynopsis>
+# <para>Asserts that <emphasis>value</emphasis> is <emphasis
+# role="strong">not</emphasis> <literal>null</literal>, or in shell terms not
+# a zero-length string. The message is optional.</para>
+# </entry>
+# </s:function>
+#*/
+assertNotNull()
+{
+ if [ $# -eq 2 ]; then
+ assertTrue "$1" "[ -n '$2' ]"
+ else
+ assertTrue "[ -n '${1:-}' ]"
+ fi
+}
+
+#/**
+# <s:function group="asserts">
+# <entry align="right">
+# <emphasis>void</emphasis>
+# </entry>
+# <entry>
+# <funcsynopsis>
+# <funcprototype>
+# <funcdef><function>assertSame</function></funcdef>
+# <paramdef>string <parameter>[message]</parameter></paramdef>
+# <paramdef>string <parameter>expected</parameter></paramdef>
+# <paramdef>string <parameter>actual</parameter></paramdef>
+# </funcprototype>
+# </funcsynopsis>
+# <para>This function is functionally equivalent to
+# <function>assertEquals</function>.</para>
+# </entry>
+# </s:function>
+#*/
+assertSame()
+{
+ assertEquals "${@:-}"
+}
+
+#/**
+# <s:function group="asserts">
+# <entry align="right">
+# <emphasis>void</emphasis>
+# </entry>
+# <entry>
+# <funcsynopsis>
+# <funcprototype>
+# <funcdef><function>assertNotSame</function></funcdef>
+# <paramdef>string <parameter>[message]</parameter></paramdef>
+# <paramdef>string <parameter>unexpected</parameter></paramdef>
+# <paramdef>string <parameter>actual</parameter></paramdef>
+# </funcprototype>
+# </funcsynopsis>
+# <para>Asserts that <emphasis>unexpected</emphasis> and
+# <emphasis>actual</emphasis> are <emphasis role="strong">not</emphasis>
+# equal to one another. The message is optional.</para>
+# </entry>
+# </s:function>
+#*/
+assertNotSame()
+{
+ _su_message=''
+ if [ $# -eq 3 ]; then
+ _su_message=$1
+ shift
+ fi
+ _su_unexpected=${1:-}
+ _su_actual=${2:-}
+
+ shunit_return=${__SHUNIT_TRUE}
+ if [ "${_su_unexpected}" != "${_su_actual}" ]; then
+ _shunit_testPassed
+ else
+ failSame "${_su_message}"
+ shunit_return=${__SHUNIT_FALSE}
+ fi
+
+ unset _su_message _su_unexpected _su_actual
+ return ${shunit_return}
+}
+
+#/**
+# <s:function group="asserts">
+# <entry align="right">
+# <emphasis>void</emphasis>
+# </entry>
+# <entry>
+# <funcsynopsis>
+# <funcprototype>
+# <funcdef><function>assertTrue</function></funcdef>
+# <paramdef>string <parameter>[message]</parameter></paramdef>
+# <paramdef>string <parameter>condition</parameter></paramdef>
+# </funcprototype>
+# </funcsynopsis>
+# <para>Asserts that a given shell test condition is true. The message is
+# optional.</para>
+# <para>Testing whether something is true or false is easy enough by using
+# the assertEquals/assertNotSame functions. Shell supports much more
+# complicated tests though, and a means to support them was needed. As such,
+# this function tests that conditions are true or false through evaluation
+# rather than just looking for a true or false.</para>
+# <funcsynopsis>
+# The following test will succeed: <funcsynopsisinfo>assertTrue "[ 34 -gt 23 ]"</funcsynopsisinfo>
+# The following test will fail with a message: <funcsynopsisinfo>assertTrue "test failed" "[ -r '/non/existent/file' ]"</funcsynopsisinfo>
+# </funcsynopsis>
+# </entry>
+# </s:function>
+#*/
+assertTrue()
+{
+ _su_message=''
+ if [ $# -eq 2 ]; then
+ _su_message=$1
+ shift
+ fi
+ _su_condition=${1:-}
+
+ shunit_return=${__SHUNIT_TRUE}
+
+ # see if condition is an integer, i.e. a return value
+ _su_match=`expr "${_su_condition}" : '\([0-9]*\)'`
+ if [ -z "${_su_condition}" ]; then
+ # null condition
+ shunit_return=${__SHUNIT_FALSE}
+ elif [ "${_su_condition}" = "${_su_match}" ]; then
+ # possible return value. treating 0 as true, and non-zero as false.
+ [ ${_su_condition} -ne 0 ] && shunit_return=${__SHUNIT_FALSE}
+ else
+ # (hopefully) a condition
+ ( eval ${_su_condition} ) >/dev/null 2>&1
+ [ $? -ne 0 ] && shunit_return=${__SHUNIT_FALSE}
+ fi
+
+ # record the test
+ if [ ${shunit_return} -eq ${__SHUNIT_TRUE} ]; then
+ _shunit_testPassed
+ else
+ _shunit_testFailed "${_su_message}"
+ fi
+
+ unset _su_message _su_condition _su_match
+ return ${shunit_return}
+}
+
+#/**
+# <s:function group="asserts">
+# <entry align="right">
+# <emphasis>void</emphasis>
+# </entry>
+# <entry>
+# <funcsynopsis>
+# <funcprototype>
+# <funcdef><function>assertFalse</function></funcdef>
+# <paramdef>string <parameter>[message]</parameter></paramdef>
+# <paramdef>string <parameter>condition</parameter></paramdef>
+# </funcprototype>
+# </funcsynopsis>
+# <para>Asserts that a given shell test condition is false. The message is
+# optional.</para>
+# <para>Testing whether something is true or false is easy enough by using
+# the assertEquals/assertNotSame functions. Shell supports much more
+# complicated tests though, and a means to support them was needed. As such,
+# this function tests that conditions are true or false through evaluation
+# rather than just looking for a true or false.</para>
+# <funcsynopsis>
+# The following test will succeed: <funcsynopsisinfo>assertFalse "[ 'apples' = 'oranges' ]"</funcsynopsisinfo>
+# The following test will fail with a message: <funcsynopsisinfo>assertFalse "test failed" "[ 1 -eq 1 -a 2 -eq 2 ]"</funcsynopsisinfo>
+# </funcsynopsis>
+# </entry>
+# </s:function>
+#*/
+assertFalse()
+{
+ _su_message=''
+ if [ $# -eq 2 ]; then
+ _su_message=$1
+ shift
+ fi
+ _su_condition=${1:-}
+
+ shunit_return=${__SHUNIT_TRUE}
+
+ # see if condition is an integer, i.e. a return value
+ _su_match=`expr "${_su_condition}" : '\([0-9]*\)'`
+ if [ -z "${_su_condition}" ]; then
+ # null condition
+ shunit_return=${__SHUNIT_FALSE}
+ elif [ "${_su_condition}" = "${_su_match}" ]; then
+ # possible return value. treating 0 as true, and non-zero as false.
+ [ ${_su_condition} -eq 0 ] && shunit_return=${__SHUNIT_FALSE}
+ else
+ # (hopefully) a condition
+ ( eval ${_su_condition} ) >/dev/null 2>&1
+ [ $? -eq 0 ] && shunit_return=${__SHUNIT_FALSE}
+ fi
+
+ # record the test
+ if [ ${shunit_return} -eq ${__SHUNIT_TRUE} ]; then
+ _shunit_testPassed
+ else
+ _shunit_testFailed "${_su_message}"
+ fi
+
+ unset _su_message _su_condition _su_match
+ return ${shunit_return}
+}
+
+#-----------------------------------------------------------------------------
+# failure functions
+#
+
+#/**
+# <s:function group="failures">
+# <entry align="right">
+# <emphasis>void</emphasis>
+# </entry>
+# <entry>
+# <funcsynopsis>
+# <funcprototype>
+# <funcdef><function>fail</function></funcdef>
+# <paramdef>string <parameter>[message]</parameter></paramdef>
+# </funcprototype>
+# </funcsynopsis>
+# <para>Fails the test immediately, with the optional message.</para>
+# </entry>
+# </s:function>
+#*/
+fail()
+{
+ _su_message=${1:-}
+
+ _shunit_testFailed "${_su_message}"
+
+ unset _su_message
+}
+
+#/**
+# <s:function group="failures">
+# <entry align="right">
+# <emphasis>void</emphasis>
+# </entry>
+# <entry>
+# <funcsynopsis>
+# <funcprototype>
+# <funcdef><function>failNotEquals</function></funcdef>
+# <paramdef>string <parameter>[message]</parameter></paramdef>
+# <paramdef>string <parameter>unexpected</parameter></paramdef>
+# <paramdef>string <parameter>actual</parameter></paramdef>
+# </funcprototype>
+# </funcsynopsis>
+# <para>Fails the test if <emphasis>unexpected</emphasis> and
+# <emphasis>actual</emphasis> are <emphasis role="strong">not</emphasis>
+# equal to one another. The message is optional.</para>
+# </entry>
+# </s:function>
+#*/
+failNotEquals()
+{
+ _su_message=''
+ if [ $# -eq 3 ]; then
+ _su_message=$1
+ shift
+ fi
+ _su_unexpected=${1:-}
+ _su_actual=${2:-}
+
+ _shunit_testFailed "${_su_message:+${_su_message} }expected:<${_su_unexpected}> but was:<${_su_actual}>"
+
+ unset _su_message _su_unexpected _su_actual
+}
+
+#/**
+# <s:function group="failures">
+# <entry align="right">
+# <emphasis>void</emphasis>
+# </entry>
+# <entry>
+# <funcsynopsis>
+# <funcprototype>
+# <funcdef><function>failSame</function></funcdef>
+# <paramdef>string <parameter>[message]</parameter></paramdef>
+# </funcprototype>
+# </funcsynopsis>
+# <para>Indicate test failure because arguments were not the same. The
+# message is optional.</para>
+# </entry>
+# </s:function>
+#*/
+failSame()
+{
+ _su_message=${1:-}
+
+ _shunit_testFailed "${_su_message:+${_su_message} }expected not same"
+
+ unset _su_message
+}
+
+#/**
+# <s:function group="failures">
+# <entry align="right">
+# <emphasis>void</emphasis>
+# </entry>
+# <entry>
+# <funcsynopsis>
+# <funcprototype>
+# <funcdef><function>failNotSame</function></funcdef>
+# <paramdef>string <parameter>[message]</parameter></paramdef>
+# <paramdef>string <parameter>expected</parameter></paramdef>
+# <paramdef>string <parameter>actual</parameter></paramdef>
+# </funcprototype>
+# </funcsynopsis>
+# <para>Fails the test if <emphasis>expected</emphasis> and
+# <emphasis>actual</emphasis> are equal to one another. The message is
+# optional.</para>
+# </entry>
+# </s:function>
+#*/
+failNotSame()
+{
+ failNotEquals "${@:-}"
+}
+
+#-----------------------------------------------------------------------------
+# suite functions
+#
+
+#/**
+# <s:function group="suites">
+# <entry align="right">
+# <emphasis>void</emphasis>
+# </entry>
+# <entry>
+# <funcsynopsis>
+# <funcprototype>
+# <funcdef><function>suite</function></funcdef>
+# <paramdef />
+# </funcprototype>
+# </funcsynopsis>
+# <para>This function can be optionally overridden by the user in their test
+# suite.</para>
+# <para>If this function exists, it will be called when
+# <command>shunit2</command> is sourced. If it does not exist, shUnit2 will
+# search the parent script for all functions beginning with the word
+# <literal>test</literal>, and they will be added dynamically to the test
+# suite.</para>
+# </entry>
+# </s:function>
+#*/
+# Note: see _shunit_mktempFunc() for actual implementation
+# suite() { :; }
+
+#/**
+# <s:function group="suites">
+# <entry align="right">
+# <emphasis>void</emphasis>
+# </entry>
+# <entry>
+# <funcsynopsis>
+# <funcprototype>
+# <funcdef><function>suite_addTest</function></funcdef>
+# <paramdef>string <parameter>function</parameter></paramdef>
+# </funcprototype>
+# </funcsynopsis>
+# <para>This function adds a function name to the list of tests scheduled for
+# execution as part of this test suite. This function should only be called
+# from within the <function>suite()</function> function.</para>
+# </entry>
+# </s:function>
+#*/
+suite_addTest()
+{
+ _su_func=${1:-}
+
+ __shunit_suite="${__shunit_suite:+${__shunit_suite} }${_su_func}"
+
+ unset _su_func
+}
+
+#/**
+# <s:function group="suites">
+# <entry align="right">
+# <emphasis>void</emphasis>
+# </entry>
+# <entry>
+# <funcsynopsis>
+# <funcprototype>
+# <funcdef><function>oneTimeSetUp</function></funcdef>
+# <paramdef />
+# </funcprototype>
+# </funcsynopsis>
+# <para>This function can be be optionally overridden by the user in their
+# test suite.</para>
+# <para>If this function exists, it will be called once before any tests are
+# run. It is useful to prepare a common environment for all tests.</para>
+# </entry>
+# </s:function>
+#*/
+# Note: see _shunit_mktempFunc() for actual implementation
+# oneTimeSetUp() { :; }
+
+#/**
+# <s:function group="suites">
+# <entry align="right">
+# <emphasis>void</emphasis>
+# </entry>
+# <entry>
+# <funcsynopsis>
+# <funcprototype>
+# <funcdef><function>oneTimeTearDown</function></funcdef>
+# <paramdef />
+# </funcprototype>
+# </funcsynopsis>
+# <para>This function can be be optionally overridden by the user in their
+# test suite.</para>
+# <para>If this function exists, it will be called once after all tests are
+# completed. It is useful to clean up the environment after all tests.</para>
+# </entry>
+# </s:function>
+#*/
+# Note: see _shunit_mktempFunc() for actual implementation
+# oneTimeTearDown() { :; }
+
+#/**
+# <s:function group="suites">
+# <entry align="right">
+# <emphasis>void</emphasis>
+# </entry>
+# <entry>
+# <funcsynopsis>
+# <funcprototype>
+# <funcdef><function>setUp</function></funcdef>
+# <paramdef />
+# </funcprototype>
+# </funcsynopsis>
+# <para>This function can be be optionally overridden by the user in their
+# test suite.</para>
+# <para>If this function exists, it will be called before each test is run.
+# It is useful to reset the environment before each test.</para>
+# </entry>
+# </s:function>
+#*/
+# Note: see _shunit_mktempFunc() for actual implementation
+# setUp() { :; }
+
+#/**
+# <s:function group="suites">
+# <entry align="right">
+# <emphasis>void</emphasis>
+# </entry>
+# <entry>
+# <funcsynopsis>
+# <funcprototype>
+# <funcdef><function>tearDown</function></funcdef>
+# <paramdef />
+# </funcprototype>
+# </funcsynopsis>
+# <para>This function can be be optionally overridden by the user in their
+# test suite.</para>
+# <para>If this function exists, it will be called after each test completes.
+# It is useful to clean up the environment after each test.</para>
+# </entry>
+# </s:function>
+#*/
+# Note: see _shunit_mktempFunc() for actual implementation
+# tearDown() { :; }
+
+#------------------------------------------------------------------------------
+# internal shUnit2 functions
+#
+
+_shunit_cleanup()
+{
+ name=$1
+
+ case ${name} in
+ EXIT) signal=0 ;;
+ INT) signal=2 ;;
+ TERM) signal=15 ;;
+ esac
+
+ # do our work
+ rm -fr "${__shunit_tmpDir}"
+
+ # exit for all non-EXIT signals
+ if [ ${name} != 'EXIT' ]; then
+ echo "trapped and now handling the ${name} signal" >&2
+ _shunit_generateReport
+ # disable EXIT trap
+ trap 0
+ # add 128 to signal and exit
+ exit `expr ${signal} + 128`
+ fi
+}
+
+_shunit_execSuite()
+{
+ echo '#'
+ echo '# Performing tests'
+ echo '#'
+ for _su_func in ${__shunit_suite}; do
+ # execute the per-test setup function
+ setUp
+
+ # execute the test
+ echo "${_su_func}"
+ eval ${_su_func}
+
+ # execute the per-test tear-down function
+ tearDown
+ done
+
+ unset _su_func
+}
+
+_shunit_functionExists()
+{
+ _su__func=$1
+ type ${_su__func} 2>/dev/null |grep "is a function$" >/dev/null
+ _su__return=$?
+ unset _su__func
+ return ${_su__return}
+}
+
+_shunit_generateReport()
+{
+ _su__awkPercent='{printf("%0.0f%%", $1*100/$2)}'
+ if [ ${__shunit_testsTotal} -gt 0 ]; then
+ _su__success=`echo ${__shunit_testsPassed} ${__shunit_testsTotal} |\
+ awk "${_su__awkPercent}"`
+ else
+ _su__success=0
+ fi
+
+ cat <<EOF
+
+#
+# Test report
+#
+tests passed: ${__shunit_testsPassed}
+tests failed: ${__shunit_testsFailed}
+tests total: ${__shunit_testsTotal}
+success rate: ${_su__success}
+EOF
+
+ unset _su__success
+}
+
+# this function is a cross-platform temporary directory creation tool. not all
+# OSes have the mktemp function, so one is included here.
+_shunit_mktempDir()
+{
+ # try the standard mktemp function
+ ( exec mktemp -dqt shunit.XXXXXX 2>/dev/null ) && return
+
+ # the standard mktemp didn't work. doing our own.
+ if [ -r '/dev/urandom' -a -x '/usr/bin/od' ]; then
+ _su__random=`/usr/bin/od -vAn -N4 -tx4 </dev/urandom \
+ |sed 's/^[^0-9a-f]*//'`
+ elif [ -n "${RANDOM:-}" ]; then
+ # $RANDOM works
+ _su__random=${RANDOM}${RANDOM}${RANDOM}$$
+ else
+ # $RANDOM doesn't work
+ _su__date=`date '+%Y%m%d%H%M%S'`
+ _su__random=`expr ${_su__date} / $$`
+ fi
+
+ _su__tmpDir="${TMPDIR-/tmp}/shunit.${_su__random}"
+ ( umask 077 && mkdir "${_su__tmpDir}" ) || {
+ echo 'shUnit:FATAL could not create temporary directory! exiting' >&2
+ return ${__SHUNIT_ERROR}
+ }
+
+ echo ${_su__tmpDir}
+ unset _su__date _su__random _su__tmpDir
+}
+
+# this function is here to work around issues in Cygwin
+_shunit_mktempFunc()
+{
+ for _su__func in oneTimeSetUp oneTimeTearDown setUp tearDown suite; do
+ _su__file="${__shunit_tmpDir}/${_su__func}"
+ cat <<EOF >"${_su__file}"
+#! /bin/sh
+exit 0
+EOF
+ chmod +x "${_su__file}"
+ done
+
+ unset _su__file
+}
+
+_shunit_testPassed()
+{
+ __shunit_testsPassed=`expr ${__shunit_testsPassed} + 1`
+ __shunit_testsTotal=`expr ${__shunit_testsTotal} + 1`
+}
+
+_shunit_testFailed()
+{
+ _su__msg=$1
+
+ __shunit_testsFailed=`expr ${__shunit_testsFailed} + 1`
+ __shunit_testsTotal=`expr ${__shunit_testsTotal} + 1`
+ echo "${__SHUNIT_ASSERT_MSG_PREFIX}${_su__msg}" >&2
+
+ unset _su__msg
+}
+
+#------------------------------------------------------------------------------
+# main
+#
+
+# create a temporary storage location
+__shunit_tmpDir=`_shunit_mktempDir` || exit ${__SHUNIT_ERROR}
+
+# setup traps to clean up after ourselves
+trap '_shunit_cleanup EXIT' 0
+trap '_shunit_cleanup INT' 2
+trap '_shunit_cleanup TERM' 15
+
+# create phantom functions to work around issues with Cygwin
+_shunit_mktempFunc
+PATH="${__shunit_tmpDir}:${PATH}"
+
+# execute the oneTimeSetUp function (if it exists)
+#_shunit_functionExists oneTimeSetUp && oneTimeSetUp
+oneTimeSetUp
+
+# deprecated: execute the suite function defined in the parent test script
+suite
+
+# if no suite function was defined, dynamically build a list of functions
+if [ -z "${__shunit_suite}" ]; then
+ funcs=`grep "^[ \t]*test[A-Za-z0-9_]* *()" $0 |sed 's/[^A-Za-z0-9_]//g'`
+ for func in ${funcs}; do
+ suite_addTest ${func}
+ done
+fi
+
+# execute the tests
+_shunit_execSuite
+
+# execute the oneTimeTearDown function (if it exists)
+oneTimeTearDown
+
+# generate report
+_shunit_generateReport
+
+# restore the previous set of shell flags
+for _shunit_shellFlag in ${__SHUNIT_SHELL_FLAGS}; do
+ echo ${__shunit_oldShellFlags} |grep ${_shunit_shellFlag} >/dev/null \
+ || set +${_shunit_shellFlag}
+done
+unset _shunit_shellFlag
+
+#/**
+# </s:shelldoc>
+#*/
=====================================
cram/htslib.d
=====================================
@@ -756,6 +756,7 @@ struct _Anonymous_22
}
cram_block_method method;
cram_block_method orig_method;
+ /*
enum cram_content_type
{
CT_ERROR = -1,
@@ -766,6 +767,7 @@ struct _Anonymous_22
EXTERNAL = 4,
CORE = 5
}
+ */
cram_content_type content_type;
int content_id;
int comp_size;
@@ -833,6 +835,7 @@ struct cram_map
struct _Anonymous_24
{
+ /*
enum cram_content_type
{
CT_ERROR = -1,
@@ -843,6 +846,7 @@ struct _Anonymous_24
EXTERNAL = 4,
CORE = 5
}
+ */
cram_content_type content_type;
int ref_seq_id;
int ref_seq_start;
=====================================
gen_ldc_version_info.py
=====================================
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python
from __future__ import print_function
import re, sys, subprocess
@@ -10,7 +10,7 @@ if len(sys.argv) < 2:
ldc = sys.argv[1].replace("ldmd2", "ldc2")
ldc_output = subprocess.Popen([ldc, '-version'], stdout=subprocess.PIPE).communicate()[0]
version_re = r"""^.+\((?P<LDC>[^\)]+)\):\n\s*based on DMD (?P<DMD>\S+) and LLVM (?P<LLVM>\S+)\n(?:\s*built with (?P<BOOTSTRAP>.*)\n)?"""
-match = re.match(version_re, ldc_output, re.MULTILINE)
+match = re.match(version_re, ldc_output.decode("utf-8") , re.MULTILINE)
if not match:
sys.exit("ERROR: failed to generated LDC version information")
=====================================
run_tests.sh
=====================================
@@ -1,6 +1,9 @@
-#!/usr/bin/env bash
+#!/bin/sh
# download shunit2 in order to run tests:
# curl -L "https://dl.dropboxusercontent.com/u/7916095/shunit2-2.0.3.tgz" | tar zx --overwrite
-./test/test_suite.sh | tee /dev/stderr | grep -q 'success rate: 100%'
+echo "Running tests..."
+./test/test_suite.sh 2>&1 | tr '\r' '\n' > test.log
+cat test.log
+cat test.log | grep -q 'success rate: 100%'
=====================================
sambamba/main.d
=====================================
@@ -19,7 +19,9 @@
*/
+import std.algorithm;
import std.experimental.logger;
+import std.range.primitives;
import sambamba.depth;
import sambamba.index;
@@ -73,6 +75,10 @@ Usage: sambamba [command] [args...]
To get help on a particular command, call it without args.
+Global options
+
+ -q quiet mode (do not show banner)
+
For bug reports and feature requests see
https://github.com/biod/
@@ -81,7 +87,7 @@ For bug reports and feature requests see
void printVersion() {
stderr.writeln();
- stderr.writeln("sambamba " ~ VERSION ~ " by Artem Tarasov and Pjotr Prins (C) 2012-2017");
+ stderr.writeln("sambamba " ~ VERSION ~ " by Artem Tarasov and Pjotr Prins (C) 2012-2018");
stderr.writeln(" LDC " ~ LDC_VERSION_STRING ~ " / DMD " ~ DMD_VERSION_STRING ~
" / LLVM" ~ LLVM_VERSION_STRING ~ " / bootstrap " ~ BOOTSTRAP_VERSION_STRING);
stderr.writeln();
@@ -89,14 +95,16 @@ void printVersion() {
int main(string[] args) {
globalLogLevel(LogLevel.info);
- printVersion();
+ if (args.find("-q").empty)
+ printVersion();
- if (args.length == 1) {
+ auto args2 = args.remove!(a => a == "-q");
+ if (args2.length == 1) {
printUsage();
return 1;
}
- auto _args = args[0] ~ args[2 .. $];
+ auto _args = args2[0] ~ args2[2 .. $];
switch (args[1]) {
case "view": return view_main(_args);
=====================================
sambamba/markdup.d
=====================================
@@ -37,6 +37,9 @@ import std.traits, std.typecons, std.range, std.algorithm, std.parallelism,
std.exception, std.file, std.typetuple, std.conv, std.array, std.bitmanip,
core.stdc.stdlib, std.datetime, undead.stream : BufferedFile, FileMode;
+import std.datetime;
+import std.datetime.stopwatch : benchmark, StopWatch;
+
/// Read + its index (0-based)
struct IndexedBamRead {
ulong index;
@@ -270,7 +273,7 @@ struct CollateReadPairRange(R, bool keepFragments, alias charsHashFunc)
version(profile) {
~this() {
stderr.writeln("duped during compaction: ", _duped_during_compaction);
- stderr.writeln("time spent on compaction: ", _compact_sw.peek().msecs, " ms");
+ stderr.writeln("time spent on compaction: ", _compact_sw.peek().total!"msecs", " ms");
}
}
@@ -715,12 +718,12 @@ auto collectSingleEndInfo(IndexedBamRead read, ReadGroupIndex read_group_index)
result.coord = computeFivePrimeCoord(read);
result.idx = read.index;
result.score = computeScore(read);
- result.ref_id = cast(ushort)read.ref_id;
+ result.ref_id = read.ref_id;
result.reversed = read.is_reverse_strand ? 1 : 0;
result.paired = (read.is_paired && !read.mate_is_unmapped) ? 1 : 0;
auto rg = read_group_index.getId(getRG(read));
- result.library_id = cast(short)read_group_index.getLibraryId(rg);
+ result.library_id = read_group_index.getLibraryId(rg);
return result;
}
@@ -1071,7 +1074,9 @@ auto getDuplicateOffsets(R)(R reads, ReadGroupIndex rg_index,
stderr.write(" collecting indices of duplicate reads... ");
sw.start();
auto duplicates = collectDuplicates(paired_ends, single_ends, second_ends, cfg, pool);
- sw.stop(); stderr.writeln(" done in ", sw.peek().msecs, " ms"); sw.reset();
+ sw.stop();
+ immutable t = sw.peek();
+ stderr.writeln(" done in ", t.total!"msecs", " ms"); sw.reset();
stderr.writeln(" found ", duplicates.length, " duplicates");
paired_ends.removeTemporaryFiles();
@@ -1256,9 +1261,7 @@ int markdup_main(string[] args) {
auto dup_idx_storage = getDuplicateOffsets(reads, rg_index, taskPool, cfg);
auto elapsed = sw.peek();
- stderr.writeln("collected list of positions in ",
- elapsed.seconds / 60, " min ",
- elapsed.seconds % 60, " sec");
+ stderr.writeln("collected list of positions in ",elapsed.total!"minutes"," min ",elapsed.total!"seconds" % 60," sec");
// marking or removing duplicates
bam = new MultiBamReader(args[1 .. $-1]); // FIXME: initialized twice
@@ -1298,9 +1301,8 @@ int markdup_main(string[] args) {
}
sw.stop();
- stderr.writeln("total time elapsed: ",
- sw.peek().seconds / 60, " min ",
- sw.peek().seconds % 60, " sec");
+ auto elapsed2 = sw.peek();
+ stderr.writeln("collected list of positions in ",elapsed2.total!"minutes"," min ",elapsed2.total!"seconds" % 60," sec");
} catch (Throwable e) {
stderr.writeln("sambamba-markdup: ", e.msg);
=====================================
test/benchmark/stats.org
=====================================
@@ -1,15 +1,56 @@
* Performance metrics
** View
+*** 4x Intel(R) Core(TM) i5-2520M CPU @ 2.50GHz (hyperthreaded)
+**** sambamba 0.6.8-pre3
-*** 8x Intel(R) Core(TM) i7-6770HQ CPU @ 2.60GHz, 16Gb, SSD
+#+BEGIN_SRC
+monza:~/tmp$ time ./sambamba view /gnu/data/HG00100.chrom20.ILLUMINA.bwa.GBR.low_coverage.20130415.bam.orig > /dev/null
+
+sambamba 0.6.8-pre3 by Artem Tarasov and Pjotr Prins (C) 2012-2018
+ LDC 1.11.0 / DMD v2.081.2 / LLVM6.0.1 / bootstrap LDC - the LLVM D compiler (0.17.6)
+
+real 0m6.930s
+user 0m26.940s
+sys 0m0.516s
+
+sambamba 0.6.8-pre2 by Artem Tarasov and Pjotr Prins (C) 2012-2018
+ LDC 1.10.0 / DMD v2.080.1 / LLVM6.0.1 / bootstrap LDC - the LLVM D compiler (0.17.4)
+
+real 0m6.854s
+user 0m26.456s
+sys 0m0.584s
+
+ linux-vdso.so.1 (0x00007ffd227fc000)
+ librt.so.1 => /gnu/store/n6nvxlk2j8ysffjh3jphn1k5silnakh6-glibc-2.25/lib/librt.so.1 (0x00007f5d31082000)
+ libpthread.so.0 => /gnu/store/n6nvxlk2j8ysffjh3jphn1k5silnakh6-glibc-2.25/lib/libpthread.so.0 (0x00007f5d30e64000)
+ libm.so.6 => /gnu/store/n6nvxlk2j8ysffjh3jphn1k5silnakh6-glibc-2.25/lib/libm.so.6 (0x00007f5d30b52000)
+ libdl.so.2 => /gnu/store/n6nvxlk2j8ysffjh3jphn1k5silnakh6-glibc-2.25/lib/libdl.so.2 (0x00007f5d3094e000)
+ libgcc_s.so.1 => /gnu/store/h3z6nshhdlc8zgh4mi13x1br03xipi9r-gcc-7.2.0-lib/lib/libgcc_s.so.1 (0x00007f5d30737000)
+ libc.so.6 => /gnu/store/n6nvxlk2j8ysffjh3jphn1k5silnakh6-glibc-2.25/lib/libc.so.6 (0x00007f5d30398000)
+ /gnu/store/n6nvxlk2j8ysffjh3jphn1k5silnakh6-glibc-2.25/lib/ld-linux-x86-64.so.2 (0x00007f5d3128a000)
+#+END_SRC
-**** sambamba 0.6.7
+*** 8x Intel(R) Core(TM) i7-6770HQ CPU @ 2.60GHz, 16Gb, SSD (hyperthreaded)
#+BEGIN_SRC sh
time ./build/sambamba view /gnu/data/HG00100.chrom20.ILLUMINA.bwa.GBR.low_coverage.20130415.bam.orig > /dev/null
#+END_SRC
+**** sambamba 0.6.8
+
+#+BEGIN_SRC
+sambamba 0.6.8 by Artem Tarasov and Pjotr Prins (C) 2012-2018
+ LDC 1.10.0 / DMD v2.080.1 / LLVM6.0.1 / bootstrap LDC - the LLVM D compiler (0.17.4)
+
+real 0m2.869s
+user 0m21.972s
+sys 0m0.356s
+
+#+END_SRC
+
+**** sambamba 0.6.7
+
#+BEGIN_SRC
This version was built with:
LDC 1.1.1
@@ -33,38 +74,80 @@ sys 0m0.344s
#+END_SRC
** Sort
-
*** 56x Intel(R) Xeon(R) CPU E5-2683 v3 @ 2.00GHz, 256Gb
-**** sambamba 0.6.6
-
#+BEGIN_SRC sh
time ./sambamba_v0.6.6 sort -m 20615843020 -N -o /dev/null ENCFF696RLQ.bam -p
#+END_SRC
+**** sambamba 0.6.8
+
#+BEGIN_SRC
-This version was built with:
- LDC 0.17.1
- using DMD v2.068.2
- using LLVM 3.8.0
- bootstrapped with version not available
+sambamba 0.6.8 by Artem Tarasov and Pjotr Prins (C) 2012-2018
+ LDC 1.10.0 / DMD v2.080.1 / LLVM6.0.1 / bootstrap LDC - the LLVM D compiler (0.17.4)
-real 10m0.932s
-user 151m39.172s
-sys 3m7.596s
+real 7m50.558s
+user 89m10.808s
+sys 2m57.188s
+#+END_SRC
+
+and with 120GB RAM
+
+#+BEGIN_SRC
+sambamba 0.6.8 by Artem Tarasov and Pjotr Prins (C) 2012-2018
+ LDC 1.10.0 / DMD v2.080.1 / LLVM6.0.1 / bootstrap LDC - the LLVM D compiler (0.17.4)
+
+real 3m49.953s
+user 81m16.956s
+sys 1m58.332s
+#+END_SRC
+
+**** sambamba 0.6.8-pre1
+
+#+BEGIN_SRC
+Wed Feb 7 03:43:14 CST 2018
+sambamba 0.6.8-pre1
This version was built with:
- LDC 1.1.1
- using DMD v2.071.2
- using LLVM 3.9.1
- bootstrapped with LDC - the LLVM D compiler (1.1.1)
+ LDC 1.7.0
+ using DMD v2.077.1
+ using LLVM 5.0.1
+ bootstrapped with LDC - the LLVM D compiler (1.7.0)
+
+real 8m0.528s
+user 88m44.084s
+sys 2m45.888s
-real 9m22.501s
-user 98m24.748s
-sys 2m51.996s
#+END_SRC
-Note, updating compiler shows a speed gain for 0.6.6.
+When sambamba is given enough RAM to hold everything in memory sambamba is twice
+as fast (apparently half the time goes to intermediate IO)
+
+#+BEGIN_SRC sh
+time ./sambamba sort -N -o /dev/null ENCFF696RLQ.bam -p -m 120G
+#+END_SRC
+
+#+BEGIN_SRC
+real 3m46.856s
+user 81m44.524s
+sys 1m56.388s
+#+END_SRC
+
+with 64GB it is
+
+#+BEGIN_SRC
+real 5m36.062s
+user 88m43.176s
+sys 3m0.536s
+#+END_SRC
+
+and with 32GB it is
+
+#+BEGIN_SRC
+real 7m22.125s
+user 89m6.188s
+sys 2m51.228s
+#+END_SRC
**** sambamba 0.6.7
@@ -143,48 +226,109 @@ sys 2m56.244s
So, the release is reverted an after a version bump:
-**** sambamba 0.6.8
+**** sambamba 0.6.6
#+BEGIN_SRC
-Wed Feb 7 03:43:14 CST 2018
-sambamba 0.6.8-pre1
-
This version was built with:
- LDC 1.7.0
- using DMD v2.077.1
- using LLVM 5.0.1
- bootstrapped with LDC - the LLVM D compiler (1.7.0)
+ LDC 0.17.1
+ using DMD v2.068.2
+ using LLVM 3.8.0
+ bootstrapped with version not available
-real 8m0.528s
-user 88m44.084s
-sys 2m45.888s
-#+END_SRC
+real 10m0.932s
+user 151m39.172s
+sys 3m7.596s
-When sambamba is given enough RAM to hold everything in memory sambamba is twice
-as fast (apparently half the time goes to intermediate IO)
+This version was built with:
+ LDC 1.1.1
+ using DMD v2.071.2
+ using LLVM 3.9.1
+ bootstrapped with LDC - the LLVM D compiler (1.1.1)
-#+BEGIN_SRC sh
-time ./sambamba sort -N -o /dev/null ENCFF696RLQ.bam -p -m 120G
+real 9m22.501s
+user 98m24.748s
+sys 2m51.996s
#+END_SRC
-#+BEGIN_SRC
-real 3m46.856s
-user 81m44.524s
-sys 1m56.388s
-#+END_SRC
+Note, updating compiler shows a speed gain for 0.6.6.
-with 64GB it is
+** Markdup
+*** 8x Intel(R) Core(TM) i7-6770HQ CPU @ 2.60GHz, 16Gb, SSD (hyperthreaded)
+
+**** sambamba 0.6.8
#+BEGIN_SRC
-real 5m36.062s
-user 88m43.176s
-sys 3m0.536s
+sambamba 0.6.8 by Artem Tarasov and Pjotr Prins (C) 2012-2018
+ LDC 1.10.0 / DMD v2.080.1 / LLVM6.0.1 / bootstrap LDC - the LLVM D compiler (0.17.4)
+
+finding positions of the duplicate reads in the file...
+ sorted 11286293 end pairs
+ and 156042 single ends (among them 0 unmatched pairs)
+ collecting indices of duplicate reads... done in 1325 ms
+ found 6603388 duplicates
+collected list of positions in 0 min 16 sec
+marking duplicates...
+collected list of positions in 1 min 2 sec
+ Command being timed: "./bin/sambamba markdup /gnu/data/in_raw.sorted.bam /gnu/data/in_raw.sorted.bam t2.bam"
+ User time (seconds): 406.49
+ System time (seconds): 3.86
+ Percent of CPU this job got: 649%
+ Elapsed (wall clock) time (h:mm:ss or m:ss): 1:03.13
+ Average shared text size (kbytes): 0
+ Average unshared data size (kbytes): 0
+ Average stack size (kbytes): 0
+ Average total size (kbytes): 0
+ Maximum resident set size (kbytes): 1709720
+ Average resident set size (kbytes): 0
+ Major (requiring I/O) page faults: 0
+ Minor (reclaiming a frame) page faults: 1140382
+ Voluntary context switches: 393213
+ Involuntary context switches: 8993
+ Swaps: 0
+ File system inputs: 0
+ File system outputs: 2663824
+ Socket messages sent: 0
+ Socket messages received: 0
+ Signals delivered: 0
+ Page size (bytes): 4096
+ Exit status: 0
#+END_SRC
-and with 32GB it is
+Uses slightly more memory but is faster than
+
+**** sambamba 0.6.7-pre1
#+BEGIN_SRC
-real 7m22.125s
-user 89m6.188s
-sys 2m51.228s
+/usr/bin/time --verbose sambamba markdup /gnu/data/in_raw.sorted.bam /gnu/data/in_raw.sorted.bam t2.bam
+finding positions of the duplicate reads in the file...
+ sorted 11286293 end pairs
+ and 156042 single ends (among them 0 unmatched pairs)
+ collecting indices of duplicate reads... done in 1521 ms
+ found 6603388 duplicates
+collected list of positions in 0 min 16 sec
+marking duplicates...
+total time elapsed: 1 min 4 sec
+ Command being timed: "sambamba markdup /gnu/data/in_raw.sorted.bam /gnu/data/in_raw.sorted.bam t2.bam"
+ User time (seconds): 423.78
+ System time (seconds): 4.47
+ Percent of CPU this job got: 666%
+ Elapsed (wall clock) time (h:mm:ss or m:ss): 1:04.24
+ Average shared text size (kbytes): 0
+ Average unshared data size (kbytes): 0
+ Average stack size (kbytes): 0
+ Average total size (kbytes): 0
+ Maximum resident set size (kbytes): 1542764
+ Average resident set size (kbytes): 0
+ Major (requiring I/O) page faults: 0
+ Minor (reclaiming a frame) page faults: 1839470
+ Voluntary context switches: 368082
+ Involuntary context switches: 8537
+ Swaps: 0
+ File system inputs: 0
+ File system outputs: 2643840
+ Socket messages sent: 0
+ Socket messages received: 0
+ Signals delivered: 0
+ Page size (bytes): 4096
+ Exit status: 0
#+END_SRC
=====================================
test/issue_356.sam
=====================================
@@ -0,0 +1,23 @@
+ at HD VN:1.3 SO:coordinate
+ at SQ SN:chr1 LN:1575
+ at SQ SN:chr2 LN:1584
+ at RG ID:foo LB:foo PL:ILLUMINA SM:foo PU:foo CN:foo DT:2017-12-10T00:00:00-0500 PG:foo PM:HiSeq2500_HighOutput
+EAS56_57:6:190:289:82 69 chr1 100 0 * = 100 0 CTCAAGGTTGTTGCAAGGGGGTCTATGTGAACAAA <<<7<<<;<<<<<<<<8;;<7;4<;<;;;;;94<; MF:i:192
+EAS56_57:6:190:289:82 137 chr1 100 73 35M = 100 0 AGGGGTGCAGAGCCGAGTCACGGGGTTGCCAGCAC <<<<<<;<<<<<<<<<<;<<;<<<<;8<6;9;;2; MF:i:64 Aq:i:0 NM:i:0 UQ:i:0 H0:i:1 H1:i:0
+EAS51_64:3:190:727:308 99 chr1 103 99 35M = 263 195 GGTGCAGAGCCGAGTCACGGGGTTGCCAGCACAGG <<<<<<<<<<<<<<<<<<<<<<<<<<<::<<<844 MF:i:18 Aq:i:73 NM:i:0 UQ:i:0 H0:i:1 H1:i:0
+EAS112_34:7:141:80:875 99 chr1 110 99 35M = 265 190 AGCCGAGTCACGGGGTTGCCAGCACAGGGGCTTAA <<<<<<<<<<<<<<<<<<<<<<:<<8;<<8+7;-7 MF:i:18 Aq:i:69 NM:i:0 UQ:i:0 H0:i:1 H1:i:0
+EAS219_FC30151:3:40:1128:1940 163 chr1 112 99 35M = 291 214 CCGAGTCACGGGGTTGCCAGCACAGGGGCTTAACC <<<<<<<<<<<<<<<<<<<;<<5;;<<<9;;;;7: MF:i:18 Aq:i:70 NM:i:0 UQ:i:0 H0:i:1 H1:i:0
+EAS51_62:5:290:319:736 69 chr1 113 0 * = 113 0 GTTCTCAAGGTTGTTGCAAGGGGGTCTATGTGAAC <<<<<<:7:<.<<<<7<<.<.<<.9*<4<:<4%74 MF:i:192
+EAS51_62:5:290:319:736 137 chr1 113 73 35M = 113 0 CGAGTCACGGGGTTGCCAGCACAGGGGCTTAACCT ==;=======7====6=;==:;;====66=::27: MF:i:64 Aq:i:0 NM:i:0 UQ:i:0 H0:i:1 H1:i:0
+B7_597:2:132:493:921 69 chr1 119 0 * = 119 0 GTTCTCAAGGTTGTTGCAAGGGGGTCTATGTGAAC <<<<<<<<<<<<<<<<<<<;<<<<77;0<;;6777 MF:i:192
+B7_597:2:132:493:921 137 chr1 119 75 35M = 119 0 ACGGGGTTGCCAGCACAGGGGCTTAACCTCTGGTG <<<<<<<<<<<<<<<<;<<<<<<<<;<<<<;;88: MF:i:64 Aq:i:0 NM:i:0 UQ:i:0 H0:i:1 H1:i:0
+EAS114_30:7:283:799:560 163 chr1 121 66 35M = 283 197 GGGGTTGCCAGCACAGGGGCTTAACCTCTGGTGAC <<<<+<<<<8<<<+<<<<<;<<:07;8;7402447 MF:i:18 Aq:i:66 NM:i:0 UQ:i:0 H0:i:1 H1:i:0
+EAS192_3:1:225:195:543 99 chr1 123 99 35M = 299 211 GGTTGCCAGCACAGGGGCTTAACCTCTGGTGACTG <<<<<<<<<<<<<<<<<<<<<<<9<<;::388998 MF:i:18 Aq:i:72 NM:i:0 UQ:i:0 H0:i:1 H1:i:0
+B7_589:6:114:714:317 99 chr1 126 99 35M = 311 220 TGCCAGCACAGGGGCTTAACCTCTGGTGACTGCCA <<<<<<<<<<<<<<<<<<<<<<<<<<<;<<<5;<; MF:i:18 Aq:i:75 NM:i:0 UQ:i:0 H0:i:1 H1:i:0
+EAS114_39:1:70:147:84 163 chr1 128 73 35M = 285 192 CCAGCACAGGGGCTTAACCTCTGGTGACTGCCAGA <<<<<<<<<<<<<<<<<<<<;<<<<<<<<<;(5<< MF:i:18 Aq:i:73 NM:i:0 UQ:i:0 H0:i:1 H1:i:0
+EAS188_7:2:187:227:818 163 chr1 129 99 35M = 290 196 CAGCACAGGGGCTTAACCTCTGGTGACTGCCAGAG <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<3<;<< MF:i:18 Aq:i:76 NM:i:0 UQ:i:0 H0:i:1 H1:i:0
+EAS1_97:4:77:29:126 99 chr1 131 99 35M = 315 219 GCACAGGGGCTTAACCTCTGGTGACTGCCAGAGCT <<<<<<<<<<3<<<<<<<;;;7<;<<449<-:977 MF:i:18 Aq:i:69 NM:i:0 UQ:i:0 H0:i:1 H1:i:0
+EAS114_30:4:327:795:103 99 chr1 133 99 35M = 302 204 ACAGGGGCTTAACCTCTGGTGACTGCCAGAGCTGC <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<;<<; MF:i:18 Aq:i:75 NM:i:0 UQ:i:0 H0:i:1 H1:i:0
+EAS114_30:3:139:117:262 69 chr1 135 0 * = 135 0 GTTCTCAAGGTTGTTGCAAGGGGGTCTATGTGAAC <<<7<<<<<<<<<<<<<<<<<<<;<;<<<<<37;3 MF:i:192
+EAS114_30:3:139:117:262 137 chr1 135 76 35M = 135 0 AGGGGCTTAACCTCTGGTGACTGCCAGAGCTGCTG <<<<;<<<<<<<<<<<<<:<<<<<:<<8<<<<:<: MF:i:64 Aq:i:0 NM:i:0 UQ:i:0 H0:i:1 H1:i:0
+EAS219_FC30151:5:29:817:854 73 chr1 135 77 35M = 135 0 AGGGGCTTAACCTCTGGTGACTGCCAGAGCTGCTG <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< MF:i:64 Aq:i:0 NM:i:0 UQ:i:0 H0:i:1 H1:i:0
=====================================
test/test_suite.sh
=====================================
@@ -1,9 +1,13 @@
-#!/usr/bin/env bash
+#!/bin/sh
sambamba=./bin/sambamba
+opts="-q"
outdir=output
mkdir -p $outdir
+md5sum=`which md5sum`
+[ -z $md5sum ] && md5sum="md5 -r " # for OSX
+
# Name sorted and pos sorted
nsortedbam=$outdir/ex1_header.nsorted.bam
sortedbam=$outdir/ex1_header.sorted.bam
@@ -11,43 +15,43 @@ sortedbam=$outdir/ex1_header.sorted.bam
testSamtoBam() {
outfn=$nsortedbam
# first identity SAM but without header
- $sambamba view -S test/ex1_header.sam -f sam > $nsortedbam.sam.1
- assertEquals "ff5d66e6cd1cab4e8e6330f2829b7c41" $(md5sum $nsortedbam.sam.1 |cut -c 1-32)
+ $sambamba $opts view -S test/ex1_header.sam -f sam > $nsortedbam.sam.1
+ assertEquals "ff5d66e6cd1cab4e8e6330f2829b7c41" $($md5sum $nsortedbam.sam.1 |cut -c 1-32)
# now convert to BAM
- $sambamba view -S test/ex1_header.sam -f bam > $nsortedbam
+ $sambamba $opts view -S test/ex1_header.sam -f bam > $nsortedbam
# BAM back to identity
- $sambamba view $nsortedbam -f sam > $nsortedbam.sam.2
- assertEquals "ff5d66e6cd1cab4e8e6330f2829b7c41" $(md5sum $nsortedbam.sam.2 |cut -c 1-32)
+ $sambamba $opts view $nsortedbam -f sam > $nsortedbam.sam.2
+ assertEquals "ff5d66e6cd1cab4e8e6330f2829b7c41" $($md5sum $nsortedbam.sam.2 |cut -c 1-32)
# Test BAM
- assertEquals "b5d64266e9544a656f0efbd0f8030b20" $(md5sum $nsortedbam |cut -c 1-32)
+ assertEquals "b5d64266e9544a656f0efbd0f8030b20" $($md5sum $nsortedbam |cut -c 1-32)
# ex1_header.sorted.bam with index
- $sambamba sort $outfn -o $sortedbam
- assertEquals "b5d64266e9544a656f0efbd0f8030b20" $(md5sum $outfn |cut -c 1-32)
- $sambamba index $nsortedbam
- assertEquals "aabb4fb319497dec1069028dd354eeda" `./bin/sambamba view -f unpack $nsortedbam |md5sum|cut -c 1-32`
- assertEquals "68e19d0f1092e1f0429ba07b418d1d9f" `./bin/sambamba view -f unpack $sortedbam |md5sum|cut -c 1-32`
+ $sambamba $opts sort $outfn -o $sortedbam
+ assertEquals "b5d64266e9544a656f0efbd0f8030b20" $($md5sum $outfn |cut -c 1-32)
+ $sambamba $opts index $nsortedbam
+ assertEquals "aabb4fb319497dec1069028dd354eeda" `$sambamba $opts view -f unpack $nsortedbam |$md5sum|cut -c 1-32`
+ assertEquals "68e19d0f1092e1f0429ba07b418d1d9f" `$sambamba $opts view -f unpack $sortedbam |$md5sum|cut -c 1-32`
}
testSubSample() {
return # not testing subsampling yet
# bam file is part of BioD
outfn=$outdir/subsample.bam
- $sambamba subsample --type fasthash $outdir/ex1_header.sorted.bam --max-cov 1000 -o$outfn > $outdir/subsample.out
+ $sambamba $opts subsample --type fasthash $outdir/ex1_header.sorted.bam --max-cov 1000 -o$outfn > $outdir/subsample.out
assertEquals 0 $?
- assertEquals "ab4a69f0093674e9feec54afc2411059" $(md5sum $outfn |cut -c 1-32)
+ assertEquals "ab4a69f0093674e9feec54afc2411059" $($md5sum $outfn |cut -c 1-32)
# should be same as sorted bam
- assertEquals "6e226f6acc8466115600d4de52ca8944" `./bin/sambamba view -f unpack $outfn |md5sum|cut -c 1-32`
+ assertEquals "6e226f6acc8466115600d4de52ca8944" `$sambamba $opts view -f unpack $outfn |$md5sum|cut -c 1-32`
outfn=$outdir/subsample2.bam
- $sambamba subsample -r --type fasthash $outdir/ex1_header.sorted.bam --max-cov 10 -o$outfn > $outdir/subsample2.out
+ $sambamba $opts subsample -r --type fasthash $outdir/ex1_header.sorted.bam --max-cov 10 -o$outfn > $outdir/subsample2.out
assertEquals 0 $?
- assertEquals "4092fb75c87cde6efc47ff0a4dc443fb" `./bin/sambamba view -f unpack $outfn |md5sum|cut -c 1-32`
+ assertEquals "4092fb75c87cde6efc47ff0a4dc443fb" `$sambamba $opts view -f unpack $outfn |$md5sum|cut -c 1-32`
}
testSortByName() {
outfn=$outdir/ex1_header.nsorted.sam
# use very tiny buffer of 200K so that multithreading is used
- $sambamba sort -t2 -n $sortedbam -o $nsortedbam -m 200K
- $sambamba view -t2 $nsortedbam > $outfn
+ $sambamba $opts sort -t2 -n $sortedbam -o $nsortedbam -m 200K
+ $sambamba $opts view -t2 $nsortedbam > $outfn
assertEquals "3270" `wc -l < $outfn`
cat $outfn | cut -f1 | LC_ALL=C sort -c
assertEquals 0 $?
@@ -55,137 +59,144 @@ testSortByName() {
testSortByCoordinate() {
outfn=$outdir/ex1_header.sorted2.bam
- $sambamba sort -t2 -m 300K $nsortedbam -o $outfn
- $sambamba index -t2
+ $sambamba $opts sort -t2 -m 300K $nsortedbam -o $outfn
+ # $sambamba $opts index -t2
assertEquals 0 $?
- $sambamba view -t2 $outfn > $outfn.sam
+ $sambamba $opts view -t2 $outfn > $outfn.sam
# check sorted with cat output/ex1_header.sorted2.bam.sam |awk '{print $3 " " $4}'|less
- assertEquals "d92c51b9e067590d7d5a18a0bdbbe0cc" `./bin/sambamba view -f unpack $outfn |md5sum|cut -c 1-32`
+ assertEquals "d92c51b9e067590d7d5a18a0bdbbe0cc" `$sambamba $opts view -f unpack $outfn |$md5sum|cut -c 1-32`
}
testSlice() {
- $sambamba slice $sortedbam chr1 -o /dev/null
+ $sambamba $opts slice $sortedbam chr1 -o /dev/null
assertEquals 0 $?
}
testSliceMultipleRegions() {
- $sambamba slice test/issue_204.bam 2:166860000-166870000 2:166860000-166870000 |\
- $sambamba view -c /dev/stdin > /dev/null
+ $sambamba $opts slice test/issue_204.bam 2:166860000-166870000 2:166860000-166870000 |\
+ $sambamba $opts view -c /dev/stdin > /dev/null
assertEquals 0 $?
}
testSliceMultipleRegionsBed() {
- assertEquals "156" `$sambamba slice -L test/chr2_chr3_test_region.bed test/issue_204.bam |\
- $sambamba view -c /dev/stdin`
+ assertEquals "156" `$sambamba $opts slice -L test/chr2_chr3_test_region.bed test/issue_204.bam |\
+ $sambamba $opts view -c /dev/stdin`
}
testView() {
- assertEquals "1806" `$sambamba view -c $sortedbam chr2`
- assertEquals "1464" `$sambamba view -c $sortedbam chr1`
- assertEquals "0" `$sambamba view -c $sortedbam '*'`
+ assertEquals "1806" `$sambamba $opts view -c $sortedbam chr2`
+ assertEquals "1464" `$sambamba $opts view -c $sortedbam chr1`
+ assertEquals "0" `$sambamba $opts view -c $sortedbam '*'`
}
testOverwriteProtection() {
- $sambamba view $nsortedbam -f bam -o ./$nsortedbam 2>/dev/null
+ $sambamba $opts view $nsortedbam -f bam -o ./$nsortedbam 2>/dev/null
assertNotSame 0 $?
- $sambamba merge $sortedbam $sortedbam $sortedbam 2>/dev/null
+ $sambamba $opts merge $sortedbam $sortedbam $sortedbam 2>/dev/null
assertNotSame 0 $?
- $sambamba sort -m 50M $nsortedbam -o ./bin/../$nsortedbam 2>/dev/null
+ $sambamba $opts sort -m 50M $nsortedbam -o ./bin/../$nsortedbam 2>/dev/null
assertNotSame 0 $?
- $sambamba markdup $nsortedbam ./bin/../$nsortedbam 2>/dev/null
+ $sambamba $opts markdup $nsortedbam ./bin/../$nsortedbam 2>/dev/null
assertNotSame 0 $?
- $sambamba slice $nsortedbam chr1 -o ./bin/../$nsortedbam 2>/dev/null
+ $sambamba $opts slice $nsortedbam chr1 -o ./bin/../$nsortedbam 2>/dev/null
assertNotSame 0 $?
}
testSortingEmptyFile() {
- $sambamba view $sortedbam -f bam -F "ref_id > 3" -o $outdir/empty.bam 2>/dev/null
- $sambamba sort -m 50M $outdir/empty.bam -o $outdir/empty2.bam 2>/dev/null
- assertEquals "0" `$sambamba view -c $outdir/empty2.bam`
+ $sambamba $opts view $sortedbam -f bam -F "ref_id > 3" -o $outdir/empty.bam 2>/dev/null
+ $sambamba $opts sort -m 50M $outdir/empty.bam -o $outdir/empty2.bam 2>/dev/null
+ assertEquals "0" `$sambamba $opts view -c $outdir/empty2.bam`
}
testMarkdupEmptyFile() {
- $sambamba view $sortedbam -f bam -F "ref_id > 3" -o $outdir/empty.bam 2>/dev/null
- $sambamba markdup $outdir/empty.bam $outdir/empty.dedup.bam 2>/dev/null
- assertEquals "0" `$sambamba view -c $outdir/empty.dedup.bam`
+ $sambamba $opts view $sortedbam -f bam -F "ref_id > 3" -o $outdir/empty.bam 2>/dev/null
+ $sambamba $opts markdup $outdir/empty.bam $outdir/empty.dedup.bam 2>/dev/null
+ assertEquals "0" `$sambamba $opts view -c $outdir/empty.dedup.bam`
}
testCramWriting() {
- $sambamba view -S htslib/test/c1\#pad2.sam -T htslib/test/c1.fa -f cram -o $outdir/c1_pad2.cram
+ $sambamba $opts view -S htslib/test/c1\#pad2.sam -T htslib/test/c1.fa -f cram -o $outdir/c1_pad2.cram
assertEquals 0 $?
}
testCramReading() {
- $sambamba view -C $outdir/c1_pad2.cram >/dev/null
+ $sambamba $opts view -C $outdir/c1_pad2.cram >/dev/null
assertEquals 0 $?
}
testIndexUsage() {
- rm *.bai && rm c1_*
- $sambamba view -S htslib/test/c1\#pad2.sam -T htslib/test/c1.fa -f cram -o $outdir/c1_pad2.cram &&
- $sambamba index -C $outdir/c1_pad2.cram && test -e $outdir/c1_pad2.cram.crai; assertEquals 0 $?
- $sambamba index -C $outdir/c1_pad2.cram $outdir/c1_cram_index && test -e $outdir/c1_cram_index.crai; assertEquals 0 $?
- $sambamba index $sortedbam && test -e $sortedbam.bai; assertEquals 0 $?
- $sambamba index $sortedbam $outdir/ex1_header.sorted.bai && test -e $outdir/ex1_header.sorted.bai; assertEquals 0 $?
+ rm -f $outdir/*.bai && rm -f $outdir/c1_*
+ $sambamba $opts view -S htslib/test/c1\#pad2.sam -T htslib/test/c1.fa -f cram -o $outdir/c1_pad2.cram &&
+ $sambamba $opts index -C $outdir/c1_pad2.cram && test -e $outdir/c1_pad2.cram.crai; assertEquals 0 $?
+ $sambamba $opts index -C $outdir/c1_pad2.cram $outdir/c1_cram_index && test -e $outdir/c1_cram_index.crai; assertEquals 0 $?
+ $sambamba $opts index $sortedbam && test -e $sortedbam.bai; assertEquals 0 $?
+ $sambamba $opts index $sortedbam $outdir/ex1_header.sorted.bai && test -e $outdir/ex1_header.sorted.bai; assertEquals 0 $?
}
testIssue193() {
rm -f $outdir/output_193.txt
- $sambamba depth base test/issue_193.bam > $outdir/output_193.txt 2>/dev/null
+ $sambamba $opts depth base test/issue_193.bam > $outdir/output_193.txt 2>/dev/null
diff -q $outdir/output_193.txt test/issue_193_expected_output.txt
assertEquals 0 $?
}
testIssue204() {
rm -f $outdir/output_204.txt
- $sambamba index test/issue_204.bam
- $sambamba depth region test/issue_204.bam -L 2:166868600-166868813 -T 15 -T 20 -T 25 -m > $outdir/output_204.txt 2>/dev/null
+ $sambamba $opts index test/issue_204.bam
+ $sambamba $opts depth region test/issue_204.bam -L 2:166868600-166868813 -T 15 -T 20 -T 25 -m > $outdir/output_204.txt 2>/dev/null
diff -q $outdir/output_204.txt test/issue_204_expected_output.txt
assertEquals 0 $?
}
testIssue206() {
- $sambamba markdup $sortedbam $outdir/ex1_header.dedup.bam 2>/dev/null
- $sambamba view -H $outdir/ex1_header.dedup.bam | grep '@PG' | grep -q 'sambamba'
+ $sambamba $opts markdup $sortedbam $outdir/ex1_header.dedup.bam 2>/dev/null
+ $sambamba $opts view -H $outdir/ex1_header.dedup.bam | grep '@PG' | grep -q 'sambamba'
assertEquals 0 $?
- $sambamba view $sortedbam -f bam -o $outdir/ex1_header.filtered.bam \
+ $sambamba $opts view $sortedbam -f bam -o $outdir/ex1_header.filtered.bam \
-F "supplementary or secondary_alignment"
# skip failing test - filtered bam is not complete
- # $sambamba view -H $outdir/ex1_header.filtered.bam | grep '@PG' | grep -q 'secondary'
+ # $sambamba $opts view -H $outdir/ex1_header.filtered.bam | grep '@PG' | grep -q 'secondary'
assertEquals 0 $?
}
testIssue225() {
- $sambamba index test/issue225.bam
- $sambamba depth base -c 1 test/issue225.bam > $outdir/depth_base_225_1.txt 2>/dev/null
+ $sambamba $opts index test/issue225.bam
+ $sambamba $opts depth base -c 1 test/issue225.bam > $outdir/depth_base_225_1.txt 2>/dev/null
diff -q $outdir/depth_base_225_1.txt test/issue225.out
assertEquals 0 $?
- $sambamba depth base -c 0 test/issue225.bam > $outdir/depth_base_225_0.txt 2>/dev/null
+ $sambamba $opts depth base -c 0 test/issue225.bam > $outdir/depth_base_225_0.txt 2>/dev/null
diff -q $outdir/depth_base_225_0.txt test/issue225.z.out
assertEquals 0 $?
# exercise BED codepath as well
- $sambamba depth base -c 1 -L chrM test/issue225.bam > $outdir/depth_base_225_1.txt 2>/dev/null
+ $sambamba $opts depth base -c 1 -L chrM test/issue225.bam > $outdir/depth_base_225_1.txt 2>/dev/null
diff -q $outdir/depth_base_225_1.txt test/issue225.out
assertEquals 0 $?
- $sambamba depth base -c 0 -L chrM test/issue225.bam > $outdir/depth_base_225_0.txt 2>/dev/null
+ $sambamba $opts depth base -c 0 -L chrM test/issue225.bam > $outdir/depth_base_225_0.txt 2>/dev/null
diff -q $outdir/depth_base_225_0.txt test/issue225.z.out
assertEquals 0 $?
}
testIssue331() {
- $sambamba view -H -f json test/issue_204.bam > $outdir/issue_331_header.json
+ $sambamba $opts view -H -f json test/issue_204.bam > $outdir/issue_331_header.json
assertEquals 0 $?
diff -q $outdir/issue_331_header.json test/regression/issue_331_header.json
assertEquals 0 $?
}
+testIssue356(){
+ # check for missing PM tag in @RG
+ $sambamba $opts view -S test/issue_356.sam -f bam -o $outdir/issue_356.bam
+ $sambamba $opts view $outdir/issue_356.bam -H|grep -q "PM:HiSeq2500_HighOutput"
+ assertEquals 0 $?
+}
+
shunit2=`which shunit2`
if [ -x "$shunit2" ]; then
. $shunit2
else
- . shunit2-2.0.3/src/shell/shunit2
+ . contrib/shunit2-2.0.3/shunit2
fi
=====================================
utils/version_.d
=====================================
@@ -1,6 +1,6 @@
module utils.version_;
-immutable string VERSION = "0.6.8-pre2";
+immutable string VERSION = "0.6.8";
immutable string HEADER_VERSION = "1.0"; // goes in header for reproducibility between sambamba versions
import bio.sam.header;
View it on GitLab: https://salsa.debian.org/med-team/sambamba/commit/22dc4a7940dc5de9eada1184d972cdcab89ba973
--
View it on GitLab: https://salsa.debian.org/med-team/sambamba/commit/22dc4a7940dc5de9eada1184d972cdcab89ba973
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20181004/07bb0e96/attachment-0001.html>
More information about the debian-med-commit
mailing list