Compare commits
No commits in common. "master" and "mark_fallbacks_published" have entirely different histories.
master
...
mark_fallb
377 changed files with 960 additions and 42108 deletions
9
.gitignore
vendored
9
.gitignore
vendored
|
@ -9,13 +9,9 @@
|
||||||
/python/dist
|
/python/dist
|
||||||
/javascript/checksums.txt
|
/javascript/checksums.txt
|
||||||
/javascript/checksums.txt.asc
|
/javascript/checksums.txt.asc
|
||||||
/javascript/olm_prefix.js
|
|
||||||
/compile_commands.json
|
/compile_commands.json
|
||||||
/.clang-format
|
/.clang-format
|
||||||
.ccls-cache/
|
.ccls-cache/
|
||||||
/python/.eggs
|
|
||||||
/python/install-temp
|
|
||||||
/result
|
|
||||||
|
|
||||||
# Xcode
|
# Xcode
|
||||||
build/
|
build/
|
||||||
|
@ -37,7 +33,4 @@ xcuserdata/
|
||||||
*.dSYM.zip
|
*.dSYM.zip
|
||||||
*.dSYM
|
*.dSYM
|
||||||
Pods/
|
Pods/
|
||||||
*.xcworkspace
|
*.xcworkspace
|
||||||
|
|
||||||
# JetBrains tools
|
|
||||||
.idea/
|
|
|
@ -1,100 +1,3 @@
|
||||||
Changes in `3.2.16 <https://gitlab.matrix.org/matrix-org/olm/tags/3.2.16>`_
|
|
||||||
===========================================================================
|
|
||||||
|
|
||||||
This release includes the following changes since 3.2.15:
|
|
||||||
|
|
||||||
* Fix and modernize the Python packaging (thanks to Alfred Wingate)
|
|
||||||
|
|
||||||
Changes in `3.2.15 <https://gitlab.matrix.org/matrix-org/olm/tags/3.2.15>`_
|
|
||||||
===========================================================================
|
|
||||||
|
|
||||||
This release includes the following changes since 3.2.14:
|
|
||||||
|
|
||||||
* Improvements to Python packaging
|
|
||||||
* No longer depend on ``future`` since Python 2 is no longer supported.
|
|
||||||
* Improve compatibility with tox 4.
|
|
||||||
* Add support for making standalone sdist.
|
|
||||||
* Improvements to Nix flake (Thanks to Jon Ringer)
|
|
||||||
* Improve structure.
|
|
||||||
* Enable Darwin builds.
|
|
||||||
* Typescript type fix.
|
|
||||||
|
|
||||||
Changes in `3.2.14 <https://gitlab.matrix.org/matrix-org/olm/tags/3.2.14>`_
|
|
||||||
===========================================================================
|
|
||||||
|
|
||||||
This release includes the following changes since 3.2.13:
|
|
||||||
|
|
||||||
* TypeScript type improvements.
|
|
||||||
* Improvements to Python packaging
|
|
||||||
* Documentation improvements.
|
|
||||||
|
|
||||||
Changes in `3.2.13 <https://gitlab.matrix.org/matrix-org/olm/tags/3.2.13>`_
|
|
||||||
===========================================================================
|
|
||||||
|
|
||||||
This release includes the following changes since 3.2.12:
|
|
||||||
|
|
||||||
* Fix compilation with newer versions of emscripten.
|
|
||||||
* The npm package is compiled with emscripten 3.1.17 to fix compatibility with
|
|
||||||
node 18.
|
|
||||||
* Add py.typed to Python wheels.
|
|
||||||
* Some documentation fixes and updates.
|
|
||||||
* Improve the pkgconfig file.
|
|
||||||
|
|
||||||
Changes in `3.2.12 <https://gitlab.matrix.org/matrix-org/olm/tags/3.2.12>`_
|
|
||||||
===========================================================================
|
|
||||||
|
|
||||||
This release includes the following changes since 3.2.11:
|
|
||||||
|
|
||||||
* Expose olm_sas_calculate_mac_fixed_base64 in the bindings.
|
|
||||||
* Allow memory to grow in wasm. Thanks to benkuly for the suggestion.
|
|
||||||
* Fix Python type hints.
|
|
||||||
* Some Python build fixes.
|
|
||||||
* Initial work on a Nix flake for building and testing.
|
|
||||||
|
|
||||||
Changes in `3.2.11 <https://gitlab.matrix.org/matrix-org/olm/tags/3.2.11>`_
|
|
||||||
===========================================================================
|
|
||||||
|
|
||||||
This release includes the following changes since 3.2.10:
|
|
||||||
|
|
||||||
* Fix building documentation. Thanks to Jonas Smedegaard. The documents
|
|
||||||
written in Markdown are now converted to HTML using Pandoc.
|
|
||||||
* Add methods for getting unpublished fallback key in Objective-C binding.
|
|
||||||
* Add public pickle/unpickle methods to Java binding.
|
|
||||||
* Add wrapper for olm_session_describe to Java binding. Thanks to Alex Baker.
|
|
||||||
|
|
||||||
Changes in `3.2.10 <https://gitlab.matrix.org/matrix-org/olm/tags/3.2.10>`_
|
|
||||||
===========================================================================
|
|
||||||
|
|
||||||
This release includes no change since 3.2.9, but is created to be able to
|
|
||||||
publish again the Android library on MavenCentral.
|
|
||||||
|
|
||||||
Changes in `3.2.9 <https://gitlab.matrix.org/matrix-org/olm/tags/3.2.9>`_
|
|
||||||
=========================================================================
|
|
||||||
|
|
||||||
This release includes the following changes since 3.2.8:
|
|
||||||
|
|
||||||
* Switch C++ tests to use doctest. Thanks to Nicolas Werner.
|
|
||||||
* Switch JavaScript tests to use jasmine instead of deprecated jasmine-node.
|
|
||||||
* Add session describe function to Python binding. Thanks to Tulir Asokan.
|
|
||||||
|
|
||||||
Changes in `3.2.8 <https://gitlab.matrix.org/matrix-org/olm/tags/3.2.8>`_
|
|
||||||
=========================================================================
|
|
||||||
|
|
||||||
This release includes the following changes since 3.2.7:
|
|
||||||
|
|
||||||
* Improve handling of olm_session_describe when the buffer is too small.
|
|
||||||
* Ensure random arrays are blanked in JavaScript bindings.
|
|
||||||
|
|
||||||
Changes in `3.2.7 <https://gitlab.matrix.org/matrix-org/olm/tags/3.2.7>`_
|
|
||||||
=========================================================================
|
|
||||||
|
|
||||||
This release includes the following changes since 3.2.6:
|
|
||||||
|
|
||||||
* Fix installation with the Makefile.
|
|
||||||
* Fix exporting again, so we only export olm symbols.
|
|
||||||
* Fix WASM build. Thanks to Benjamin Kampmann.
|
|
||||||
* Add more functions for fallback keys.
|
|
||||||
|
|
||||||
Changes in `3.2.6 <https://gitlab.matrix.org/matrix-org/olm/tags/3.2.6>`_
|
Changes in `3.2.6 <https://gitlab.matrix.org/matrix-org/olm/tags/3.2.6>`_
|
||||||
=========================================================================
|
=========================================================================
|
||||||
|
|
||||||
|
@ -177,13 +80,11 @@ Changes in `3.1.5 <https://gitlab.matrix.org/matrix-org/olm/tags/3.1.5>`_
|
||||||
This release includes the following changes since 3.1.4:
|
This release includes the following changes since 3.1.4:
|
||||||
|
|
||||||
* Build improvements:
|
* Build improvements:
|
||||||
|
|
||||||
* Fix CMake handling when installing in a non-standard location. Thanks to
|
* Fix CMake handling when installing in a non-standard location. Thanks to
|
||||||
Alexey Rusakov.
|
Alexey Rusakov.
|
||||||
* Add support in the Makefile for creating a WASM-ready archive. Thanks to
|
* Add support in the Makefile for creating a WASM-ready archive. Thanks to
|
||||||
stoically.
|
stoically.
|
||||||
* Improve support for LLVM is Makefile. Thanks to caywin25 for reporting.
|
* Improve support for LLVM is Makefile. Thanks to caywin25 for reporting.
|
||||||
|
|
||||||
* Add a TypeScript definition file.
|
* Add a TypeScript definition file.
|
||||||
* Some documentation and example fixes.
|
* Some documentation and example fixes.
|
||||||
* Add list of bindings to the README.
|
* Add list of bindings to the README.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
cmake_minimum_required(VERSION 3.4)
|
cmake_minimum_required(VERSION 3.4)
|
||||||
|
|
||||||
project(olm VERSION 3.2.16 LANGUAGES CXX C)
|
project(olm VERSION 3.2.6 LANGUAGES CXX C)
|
||||||
|
|
||||||
option(OLM_TESTS "Build tests" ON)
|
option(OLM_TESTS "Build tests" ON)
|
||||||
option(BUILD_SHARED_LIBS "Build as a shared library" ON)
|
option(BUILD_SHARED_LIBS "Build as a shared library" ON)
|
||||||
|
|
16
Makefile
16
Makefile
|
@ -5,9 +5,10 @@ VERSION := $(MAJOR).$(MINOR).$(PATCH)
|
||||||
PREFIX ?= /usr/local
|
PREFIX ?= /usr/local
|
||||||
BUILD_DIR := build
|
BUILD_DIR := build
|
||||||
RELEASE_OPTIMIZE_FLAGS ?= -O3
|
RELEASE_OPTIMIZE_FLAGS ?= -O3
|
||||||
DEBUG_OPTIMIZE_FLAGS ?= -g -O0 -U_FORTIFY_SOURCE
|
DEBUG_OPTIMIZE_FLAGS ?= -g -O0
|
||||||
JS_OPTIMIZE_FLAGS ?= -O3
|
JS_OPTIMIZE_FLAGS ?= -O3
|
||||||
FUZZER_OPTIMIZE_FLAGS ?= -O3
|
FUZZER_OPTIMIZE_FLAGS ?= -O3
|
||||||
|
CC = gcc
|
||||||
EMCC = emcc
|
EMCC = emcc
|
||||||
EMAR = emar
|
EMAR = emar
|
||||||
AR = ar
|
AR = ar
|
||||||
|
@ -30,7 +31,7 @@ JS_ASMJS_TARGET := javascript/olm_legacy.js
|
||||||
WASM_TARGET := $(BUILD_DIR)/wasm/libolm.a
|
WASM_TARGET := $(BUILD_DIR)/wasm/libolm.a
|
||||||
|
|
||||||
JS_EXPORTED_FUNCTIONS := javascript/exported_functions.json
|
JS_EXPORTED_FUNCTIONS := javascript/exported_functions.json
|
||||||
JS_EXPORTED_RUNTIME_METHODS := [ALLOC_STACK,writeAsciiToMemory,intArrayFromString,UTF8ToString,stringToUTF8]
|
JS_EXPORTED_RUNTIME_METHODS := [ALLOC_STACK]
|
||||||
JS_EXTERNS := javascript/externs.js
|
JS_EXTERNS := javascript/externs.js
|
||||||
|
|
||||||
PUBLIC_HEADERS := include/olm/olm.h include/olm/outbound_group_session.h include/olm/inbound_group_session.h include/olm/pk.h include/olm/sas.h include/olm/error.h include/olm/olm_export.h
|
PUBLIC_HEADERS := include/olm/olm.h include/olm/outbound_group_session.h include/olm/inbound_group_session.h include/olm/pk.h include/olm/sas.h include/olm/error.h include/olm/olm_export.h
|
||||||
|
@ -93,7 +94,7 @@ LDFLAGS += -Wall -Werror
|
||||||
CFLAGS_NATIVE = -fPIC
|
CFLAGS_NATIVE = -fPIC
|
||||||
CXXFLAGS_NATIVE = -fPIC
|
CXXFLAGS_NATIVE = -fPIC
|
||||||
|
|
||||||
EMCCFLAGS = --closure 1 --memory-init-file 0 -s NO_FILESYSTEM=1 -s INVOKE_RUN=0 -s MODULARIZE=1 -Wno-error=closure
|
EMCCFLAGS = --closure 1 --memory-init-file 0 -s NO_FILESYSTEM=1 -s INVOKE_RUN=0 -s MODULARIZE=1
|
||||||
|
|
||||||
# Olm generally doesn't need a lot of memory to encrypt / decrypt its usual
|
# Olm generally doesn't need a lot of memory to encrypt / decrypt its usual
|
||||||
# payloads (ie. Matrix messages), but we do need about 128K of heap to encrypt
|
# payloads (ie. Matrix messages), but we do need about 128K of heap to encrypt
|
||||||
|
@ -103,12 +104,12 @@ EMCCFLAGS = --closure 1 --memory-init-file 0 -s NO_FILESYSTEM=1 -s INVOKE_RUN=0
|
||||||
# (This can't be changed by the app with wasm since it's baked into the wasm).
|
# (This can't be changed by the app with wasm since it's baked into the wasm).
|
||||||
# (emscripten also mandates at least 16MB of memory for asm.js now, so
|
# (emscripten also mandates at least 16MB of memory for asm.js now, so
|
||||||
# we don't use this for the legacy build.)
|
# we don't use this for the legacy build.)
|
||||||
EMCCFLAGS_WASM += -s TOTAL_STACK=65536 -s TOTAL_MEMORY=262144 -s ALLOW_MEMORY_GROWTH
|
EMCCFLAGS_WASM += -s TOTAL_STACK=65536 -s TOTAL_MEMORY=262144
|
||||||
|
|
||||||
EMCCFLAGS_ASMJS += -s WASM=0
|
EMCCFLAGS_ASMJS += -s WASM=0
|
||||||
|
|
||||||
EMCC.c = $(EMCC) $(CFLAGS) $(CPPFLAGS) -c -DNDEBUG -DOLM_STATIC_DEFINE=1
|
EMCC.c = $(EMCC) $(CFLAGS) $(CPPFLAGS) -c
|
||||||
EMCC.cc = $(EMCC) $(CXXFLAGS) $(CPPFLAGS) -c -DNDEBUG -DOLM_STATIC_DEFINE=1
|
EMCC.cc = $(EMCC) $(CXXFLAGS) $(CPPFLAGS) -c
|
||||||
EMCC_LINK = $(EMCC) $(LDFLAGS) $(EMCCFLAGS)
|
EMCC_LINK = $(EMCC) $(LDFLAGS) $(EMCCFLAGS)
|
||||||
|
|
||||||
AFL_CC = afl-clang-fast
|
AFL_CC = afl-clang-fast
|
||||||
|
@ -400,9 +401,6 @@ $(BUILD_DIR)/fuzzers/fuzz_%_msan: fuzzing/fuzzers/fuzz_%.cpp $(FUZZER_MSAN_OBJEC
|
||||||
%.html: %.rst
|
%.html: %.rst
|
||||||
rst2html $< $@
|
rst2html $< $@
|
||||||
|
|
||||||
%.html: %.md
|
|
||||||
pandoc --from markdown --to html5 --standalone --lua-filter gitlab-math.lua --katex -o $@ $<
|
|
||||||
|
|
||||||
### dependencies
|
### dependencies
|
||||||
|
|
||||||
-include $(RELEASE_OBJECTS:.o=.d)
|
-include $(RELEASE_OBJECTS:.o=.d)
|
||||||
|
|
|
@ -3,7 +3,7 @@ Pod::Spec.new do |s|
|
||||||
# The libolm version
|
# The libolm version
|
||||||
MAJOR = 3
|
MAJOR = 3
|
||||||
MINOR = 2
|
MINOR = 2
|
||||||
PATCH = 16
|
PATCH = 6
|
||||||
|
|
||||||
s.name = "OLMKit"
|
s.name = "OLMKit"
|
||||||
s.version = "#{MAJOR}.#{MINOR}.#{PATCH}"
|
s.version = "#{MAJOR}.#{MINOR}.#{PATCH}"
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
import PackageDescription
|
import PackageDescription
|
||||||
|
|
||||||
let major = 3, minor = 2, patch = 16
|
let major = 3, minor = 2, patch = 6
|
||||||
|
|
||||||
let package = Package(
|
let package = Package(
|
||||||
name: "Olm",
|
name: "Olm",
|
||||||
|
|
108
README.md
108
README.md
|
@ -9,69 +9,6 @@ The specification of the Olm ratchet can be found in [docs/olm.md](docs/olm.md).
|
||||||
This library also includes an implementation of the Megolm cryptographic
|
This library also includes an implementation of the Megolm cryptographic
|
||||||
ratchet, as specified in [docs/megolm.md](docs/megolm.md).
|
ratchet, as specified in [docs/megolm.md](docs/megolm.md).
|
||||||
|
|
||||||
## Installing
|
|
||||||
|
|
||||||
### Linux and other Unix-like systems
|
|
||||||
|
|
||||||
Your distribution may have pre-compiled packages available. If not, or if you
|
|
||||||
need a newer version, you will need to compile from source. See the "Building"
|
|
||||||
section below for more details.
|
|
||||||
|
|
||||||
### macOS
|
|
||||||
|
|
||||||
The easiest way to install on macOS is via Homebrew. If you do not have
|
|
||||||
Homebrew installed, follow the instructions at https://brew.sh/ to install it.
|
|
||||||
|
|
||||||
You can then install libolm by running
|
|
||||||
|
|
||||||
```bash
|
|
||||||
brew install libolm
|
|
||||||
```
|
|
||||||
|
|
||||||
If you also need the Python packages, you can run
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pip3 install python-olm --global-option="build_ext" --global-option="--include-dirs="`brew --prefix libolm`"/include" --global-option="--library-dirs="`brew --prefix libolm`"/lib"
|
|
||||||
```
|
|
||||||
|
|
||||||
Note that this will install an older version of the Python bindings, which may
|
|
||||||
be missing some functions. If you need the latest version, you will need to
|
|
||||||
build from source.
|
|
||||||
|
|
||||||
### Windows
|
|
||||||
|
|
||||||
You will need to build from source. See the "Building" section below for more
|
|
||||||
details.
|
|
||||||
|
|
||||||
### Bindings
|
|
||||||
|
|
||||||
#### JavaScript
|
|
||||||
|
|
||||||
You can use pre-built npm packages, available at
|
|
||||||
<https://gitlab.matrix.org/matrix-org/olm/-/packages?type=npm>.
|
|
||||||
|
|
||||||
#### Python
|
|
||||||
|
|
||||||
A Python source package and pre-built packages for certain architectures from
|
|
||||||
<https://pypi.org/project/python-olm/>. If a pre-built package is not
|
|
||||||
available for your architecture, you will need:
|
|
||||||
|
|
||||||
- cmake (recommended) or GNU make
|
|
||||||
- a C/C++ compiler
|
|
||||||
|
|
||||||
to build the source package.
|
|
||||||
|
|
||||||
You can then run `pip install python-olm`.
|
|
||||||
|
|
||||||
Currently, we try to provide packages for all supported versions of Python on
|
|
||||||
x86-64, i686, and aarch64, but we cannot guarantee that packages for all
|
|
||||||
versions will be available on all architectures.
|
|
||||||
|
|
||||||
#### Android
|
|
||||||
|
|
||||||
Pre-built Android bindings are available at
|
|
||||||
<https://gitlab.matrix.org/matrix-org/olm/-/packages?type=Maven>.
|
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
To build olm as a shared library run:
|
To build olm as a shared library run:
|
||||||
|
@ -104,38 +41,22 @@ target_link_libraries(my_exe Olm::Olm)
|
||||||
|
|
||||||
### Bindings
|
### Bindings
|
||||||
|
|
||||||
#### JavaScript
|
To build the JavaScript bindings, install emscripten from https://emscripten.org/ and then run:
|
||||||
|
|
||||||
The recommended way to build the JavaScript bindings is using
|
|
||||||
[Nix](https://nixos.org/). With Nix, you can run
|
|
||||||
|
|
||||||
```bash
|
|
||||||
nix build .\#javascript
|
|
||||||
```
|
|
||||||
|
|
||||||
to build the bindings.
|
|
||||||
|
|
||||||
If you do not have Nix you can, install emscripten from https://emscripten.org/
|
|
||||||
and then run:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
make js
|
make js
|
||||||
```
|
```
|
||||||
|
|
||||||
Emscripten can also be run via Docker, in which case, you need to pass through
|
Note that if you run emscripten in a docker container, you need to pass through
|
||||||
the EMCC_CLOSURE_ARGS environment variable.
|
the EMCC_CLOSURE_ARGS environment variable.
|
||||||
|
|
||||||
#### Android
|
|
||||||
|
|
||||||
To build the android project for Android bindings, run:
|
To build the android project for Android bindings, run:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd android
|
cd android
|
||||||
./gradlew clean build
|
./gradlew clean assembleRelease
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Objective-C
|
|
||||||
|
|
||||||
To build the Xcode workspace for Objective-C bindings, run:
|
To build the Xcode workspace for Objective-C bindings, run:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
@ -144,9 +65,7 @@ pod install
|
||||||
open OLMKit.xcworkspace
|
open OLMKit.xcworkspace
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Python
|
To build the Python bindings, first build olm as a shared library as above, and
|
||||||
|
|
||||||
To build the Python 3 bindings, first build olm as a library as above, and
|
|
||||||
then run:
|
then run:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
@ -154,6 +73,9 @@ cd python
|
||||||
make
|
make
|
||||||
```
|
```
|
||||||
|
|
||||||
|
to make both the Python 2 and Python 3 bindings. To make only one version, use
|
||||||
|
``make olm-python2`` or ``make olm-python3`` instead of just ``make``.
|
||||||
|
|
||||||
### Using make instead of cmake
|
### Using make instead of cmake
|
||||||
|
|
||||||
**WARNING:** Using cmake is the preferred method for building the olm library;
|
**WARNING:** Using cmake is the preferred method for building the olm library;
|
||||||
|
@ -194,11 +116,9 @@ repository, some bindings are (in alphabetical order):
|
||||||
library for Matrix, including Olm methods
|
library for Matrix, including Olm methods
|
||||||
- [maunium.net/go/mautrix/crypto/olm](https://github.com/tulir/mautrix-go/tree/master/crypto/olm)
|
- [maunium.net/go/mautrix/crypto/olm](https://github.com/tulir/mautrix-go/tree/master/crypto/olm)
|
||||||
(Apache-2.0) fork of Dhole/go-olm
|
(Apache-2.0) fork of Dhole/go-olm
|
||||||
- [nim-olm](https://codeberg.org/BarrOff/nim-olm) (MIT) Nim bindings
|
- [nim-olm](https://gitea.com/BarrOff/nim-olm) (MIT) Nim bindings
|
||||||
- [olm-sys](https://gitlab.gnome.org/BrainBlasted/olm-sys) (Apache-2.0) Rust
|
- [olm-sys](https://gitlab.gnome.org/BrainBlasted/olm-sys) (Apache-2.0) Rust
|
||||||
bindings
|
bindings
|
||||||
- [Trixnity](https://gitlab.com/trixnity/trixnity) (Apache-2.0) Kotlin SDK for
|
|
||||||
Matrix, including Olm bindings
|
|
||||||
|
|
||||||
Note that bindings may have a different license from libolm, and are *not*
|
Note that bindings may have a different license from libolm, and are *not*
|
||||||
endorsed by the Matrix.org Foundation C.I.C.
|
endorsed by the Matrix.org Foundation C.I.C.
|
||||||
|
@ -206,8 +126,8 @@ endorsed by the Matrix.org Foundation C.I.C.
|
||||||
## Release process
|
## Release process
|
||||||
|
|
||||||
First: bump version numbers in ``common.mk``, ``CMakeLists.txt``,
|
First: bump version numbers in ``common.mk``, ``CMakeLists.txt``,
|
||||||
``javascript/package.json``, ``python/pyproject.toml``, ``OLMKit.podspec``,
|
``javascript/package.json``, ``python/olm/__version__.py``, ``OLMKit.podspec``, ``Package.swift``,
|
||||||
``Package.swift``, and ``android/gradle.properties``.
|
and ``android/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java`` in function ``getVersion()```.
|
||||||
|
|
||||||
Also, ensure the changelog is up to date, and that everything is committed to
|
Also, ensure the changelog is up to date, and that everything is committed to
|
||||||
git.
|
git.
|
||||||
|
@ -247,14 +167,6 @@ Python and JavaScript packages are published to the registry at
|
||||||
documentation contains instructions on how to set up twine (Python) and npm
|
documentation contains instructions on how to set up twine (Python) and npm
|
||||||
(JavaScript) to upload to the registry.
|
(JavaScript) to upload to the registry.
|
||||||
|
|
||||||
To publish the Android library to MavenCentral (you will need some secrets), in the /android folder:
|
|
||||||
- Run the command `./gradlew clean build publish --no-daemon --no-parallel --stacktrace`. The generated AAR must be approx 500 kb.
|
|
||||||
- Connect to https://s01.oss.sonatype.org
|
|
||||||
- Click on Staging Repositories and check the the files have been uploaded
|
|
||||||
- Click on close
|
|
||||||
- Wait (check Activity tab until step "Repository closed" is displayed)
|
|
||||||
- Click on release. The staging repository will disappear
|
|
||||||
- Check that the release is available in https://repo1.maven.org/maven2/org/matrix/android/olm-sdk/ (it can take a few minutes)
|
|
||||||
|
|
||||||
## Design
|
## Design
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,8 @@
|
||||||
SET(CMAKE_SYSTEM_NAME Windows)
|
SET(CMAKE_SYSTEM_NAME Windows)
|
||||||
|
|
||||||
# which compilers to use for C and C++
|
# which compilers to use for C and C++
|
||||||
SET(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc-posix)
|
SET(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc)
|
||||||
SET(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++-posix)
|
SET(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++)
|
||||||
SET(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres)
|
SET(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres)
|
||||||
|
|
||||||
# here is the target environment located
|
# here is the target environment located
|
||||||
|
|
BIN
android/.DS_Store
vendored
Normal file
BIN
android/.DS_Store
vendored
Normal file
Binary file not shown.
|
@ -5,16 +5,20 @@ OlmLibSdk exposes an android wrapper to libolm.
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
------------
|
------------
|
||||||
|
Create a libs directory in your project directory
|
||||||
|
Copy the olm-sdk.aar into it.
|
||||||
|
|
||||||
Android Olm library is released on MavenCentral.
|
In your build.gradle file, add in the android section::
|
||||||
|
|
||||||
Add this dependency to your project:
|
repositories {
|
||||||
|
flatDir {
|
||||||
|
dir 'libs'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
```groovy
|
Add in the dependencies category::
|
||||||
implementation "org.matrix.android:olm:3.2.8"
|
|
||||||
```
|
|
||||||
|
|
||||||
Latest version: ![Latest version](https://img.shields.io/maven-central/v/org.matrix.android/olm)
|
compile(name: 'olm-sdk', ext: 'aar')
|
||||||
|
|
||||||
Development
|
Development
|
||||||
-----------
|
-----------
|
||||||
|
|
|
@ -6,10 +6,8 @@ buildscript {
|
||||||
google()
|
google()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
// Release notes of Android Gradle Plugin (AGP):
|
classpath 'com.android.tools.build:gradle:4.1.3'
|
||||||
// https://developer.android.com/studio/releases/gradle-plugin
|
|
||||||
classpath 'com.android.tools.build:gradle:7.0.4'
|
|
||||||
classpath 'com.vanniktech:gradle-maven-publish-plugin:0.18.0'
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
// in the individual module build.gradle files
|
// in the individual module build.gradle files
|
||||||
}
|
}
|
||||||
|
@ -20,17 +18,6 @@ allprojects {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
google()
|
google()
|
||||||
}
|
}
|
||||||
|
|
||||||
plugins.withId("com.vanniktech.maven.publish.base") {
|
|
||||||
group = project.getProperties().getOrDefault("GROUP", "0.0.0")
|
|
||||||
version = project.getProperties().getOrDefault("VERSION_NAME", "name")
|
|
||||||
|
|
||||||
mavenPublishing {
|
|
||||||
publishToMavenCentral("S01")
|
|
||||||
pomFromGradleProperties()
|
|
||||||
signAllPublications()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
task clean(type: Delete) {
|
task clean(type: Delete) {
|
||||||
|
|
|
@ -21,29 +21,3 @@
|
||||||
|
|
||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
org.gradle.configureondemand=false
|
org.gradle.configureondemand=false
|
||||||
|
|
||||||
# Maven publication
|
|
||||||
# Ref: https://github.com/vanniktech/gradle-maven-publish-plugin
|
|
||||||
GROUP=org.matrix.android
|
|
||||||
POM_ARTIFACT_ID=olm
|
|
||||||
VERSION_NAME=3.2.16
|
|
||||||
|
|
||||||
POM_PACKAGING=aar
|
|
||||||
|
|
||||||
POM_NAME=Olm Android wrapper
|
|
||||||
POM_DESCRIPTION=An Android wrapper to libolm.
|
|
||||||
POM_INCEPTION_YEAR=2021
|
|
||||||
POM_URL=https://gitlab.matrix.org/matrix-org/olm
|
|
||||||
|
|
||||||
POM_LICENSE_NAME=The Apache Software License, Version 2.0
|
|
||||||
POM_LICENCE_URL=https://www.apache.org/licenses/LICENSE-2.0.txt
|
|
||||||
POM_LICENCE_DIST=repo
|
|
||||||
|
|
||||||
POM_SCM_URL=https://gitlab.matrix.org/matrix-org/olm
|
|
||||||
POM_SCM_CONNECTION=scm:git:https://gitlab.matrix.org/matrix-org/olm.git
|
|
||||||
POM_SCM_DEV_CONNECTION=scm:git:ssh://git@gitlab.int.matrix.org:matrix-org/olm.git
|
|
||||||
|
|
||||||
POM_DEVELOPER_ID=matrixdev
|
|
||||||
POM_DEVELOPER_NAME=matrixdev
|
|
||||||
POM_DEVELOPER_URL=https://gitlab.matrix.org/matrix-org
|
|
||||||
POM_DEVELOPER_EMAIL=android@element.io
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
#Thu Oct 13 09:38:01 CEST 2016
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionSha256Sum=c9490e938b221daf0094982288e4038deed954a3f12fb54cbf270ddf4e37d879
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-all.zip
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip
|
distributionSha256Sum=81003f83b0056d20eedf48cddd4f52a9813163d4ba185bcf8abd34b8eeea4cbd
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|
3
android/jitpack.yml
Normal file
3
android/jitpack.yml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
install:
|
||||||
|
- ./gradlew :olm-sdk:build :olm-sdk:publishToMavenLocal -x :olm-sdk:test
|
||||||
|
- find . -name "*.aar"
|
|
@ -1,26 +1,20 @@
|
||||||
import org.apache.tools.ant.taskdefs.condition.Os
|
import org.apache.tools.ant.taskdefs.condition.Os
|
||||||
import com.vanniktech.maven.publish.AndroidLibrary
|
|
||||||
import com.vanniktech.maven.publish.JavadocJar
|
|
||||||
|
|
||||||
apply plugin: 'com.android.library'
|
apply plugin: 'com.android.library'
|
||||||
apply plugin: "com.vanniktech.maven.publish.base"
|
apply plugin: 'maven-publish'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdk 31
|
compileSdkVersion 30
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdk 14
|
minSdkVersion 14
|
||||||
targetSdk 31
|
targetSdkVersion 30
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
|
||||||
buildConfigField "String", "OLM_VERSION", "\"${project.getProperties().getOrDefault("VERSION_NAME", "0.0.0")}\""
|
|
||||||
|
|
||||||
// The following argument makes the Android Test Orchestrator run its
|
// The following argument makes the Android Test Orchestrator run its
|
||||||
// "pm clear" command after each test invocation. This command ensures
|
// "pm clear" command after each test invocation. This command ensures
|
||||||
// that the app's state is completely cleared between tests.
|
// that the app's state is completely cleared between tests.
|
||||||
testInstrumentationRunnerArguments clearPackageData: 'true'
|
testInstrumentationRunnerArguments clearPackageData: 'true'
|
||||||
|
|
||||||
buildConfigField "String", "OLM_VERSION", "\"${project.getProperties().getOrDefault("VERSION_NAME", "0.0.0")}\""
|
|
||||||
}
|
}
|
||||||
buildTypes {
|
buildTypes {
|
||||||
debug {
|
debug {
|
||||||
|
@ -80,27 +74,6 @@ android {
|
||||||
compileTask.dependsOn buildJavaDoc
|
compileTask.dependsOn buildJavaDoc
|
||||||
}
|
}
|
||||||
|
|
||||||
task androidJavadocs(type: Javadoc) {
|
|
||||||
source = android.sourceSets.main.java.srcDirs
|
|
||||||
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
|
|
||||||
android.libraryVariants.all { variant ->
|
|
||||||
if (variant.name == 'release') {
|
|
||||||
owner.classpath += variant.javaCompileProvider.get().classpath
|
|
||||||
}
|
|
||||||
}
|
|
||||||
exclude '**/R.html', '**/R.*.html', '**/index.html'
|
|
||||||
}
|
|
||||||
|
|
||||||
task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {
|
|
||||||
archiveClassifier.set('javadoc')
|
|
||||||
from androidJavadocs.destinationDir
|
|
||||||
}
|
|
||||||
|
|
||||||
task androidSourcesJar(type: Jar) {
|
|
||||||
archiveClassifier.set('sources')
|
|
||||||
from android.sourceSets.main.java.srcDirs
|
|
||||||
}
|
|
||||||
|
|
||||||
clean.dependsOn cleanNative
|
clean.dependsOn cleanNative
|
||||||
|
|
||||||
|
|
||||||
|
@ -112,11 +85,6 @@ android {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
compileOptions {
|
|
||||||
sourceCompatibility JavaVersion.VERSION_11
|
|
||||||
targetCompatibility JavaVersion.VERSION_11
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def getNdkFolder() {
|
def getNdkFolder() {
|
||||||
|
@ -156,12 +124,18 @@ dependencies {
|
||||||
testImplementation 'junit:junit:4.13.2'
|
testImplementation 'junit:junit:4.13.2'
|
||||||
androidTestImplementation 'junit:junit:4.13.2'
|
androidTestImplementation 'junit:junit:4.13.2'
|
||||||
|
|
||||||
androidTestImplementation 'androidx.test:core:1.4.0'
|
androidTestImplementation 'androidx.test:core:1.3.0'
|
||||||
androidTestImplementation 'androidx.test:runner:1.4.0'
|
androidTestImplementation 'androidx.test:runner:1.3.0'
|
||||||
androidTestImplementation 'androidx.test:rules:1.4.0'
|
androidTestImplementation 'androidx.test:rules:1.3.0'
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
||||||
}
|
}
|
||||||
|
|
||||||
mavenPublishing {
|
project.afterEvaluate {
|
||||||
configure(new AndroidLibrary(new JavadocJar.Empty(), false))
|
publishing {
|
||||||
|
publications {
|
||||||
|
release(MavenPublication) {
|
||||||
|
from components.release
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1011,75 +1011,4 @@ public class OlmSessionTest {
|
||||||
assertTrue(bobSession.isReleased());
|
assertTrue(bobSession.isReleased());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void test07AliceBobSessionDescribe() {
|
|
||||||
// creates alice & bob accounts
|
|
||||||
OlmAccount aliceAccount = null;
|
|
||||||
OlmAccount bobAccount = null;
|
|
||||||
try {
|
|
||||||
aliceAccount = new OlmAccount();
|
|
||||||
bobAccount = new OlmAccount();
|
|
||||||
} catch (OlmException e) {
|
|
||||||
fail(e.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
// test accounts creation
|
|
||||||
assertTrue(0 != bobAccount.getOlmAccountId());
|
|
||||||
assertTrue(0 != aliceAccount.getOlmAccountId());
|
|
||||||
|
|
||||||
// CREATE ALICE SESSION
|
|
||||||
|
|
||||||
OlmSession aliceSession = null;
|
|
||||||
try {
|
|
||||||
aliceSession = new OlmSession();
|
|
||||||
} catch (OlmException e) {
|
|
||||||
fail("Exception Msg=" + e.getMessage());
|
|
||||||
}
|
|
||||||
assertTrue(0 != aliceSession.getOlmSessionId());
|
|
||||||
|
|
||||||
// CREATE ALICE SESSION
|
|
||||||
OlmSession bobSession = null;
|
|
||||||
try {
|
|
||||||
bobSession = new OlmSession();
|
|
||||||
} catch (OlmException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
fail(e.getMessage());
|
|
||||||
}
|
|
||||||
assertTrue(0 != bobSession.getOlmSessionId());
|
|
||||||
|
|
||||||
String aliceSessionDescribe = null;
|
|
||||||
try {
|
|
||||||
aliceSessionDescribe = aliceSession.sessionDescribe();
|
|
||||||
} catch (Exception e) {
|
|
||||||
fail(e.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
assertNotNull(aliceSessionDescribe);
|
|
||||||
|
|
||||||
String bobSessionDescribe = null;
|
|
||||||
try {
|
|
||||||
bobSessionDescribe = bobSession.sessionDescribe();
|
|
||||||
} catch (Exception e) {
|
|
||||||
fail(e.getMessage());
|
|
||||||
}
|
|
||||||
assertNotNull(bobSessionDescribe);
|
|
||||||
|
|
||||||
// must be the same for both ends of the conversation
|
|
||||||
assertEquals(aliceSessionDescribe, bobSessionDescribe);
|
|
||||||
|
|
||||||
assertEquals(
|
|
||||||
"sender chain index: 0 receiver chain indices: skipped message keys:",
|
|
||||||
aliceSessionDescribe
|
|
||||||
);
|
|
||||||
|
|
||||||
aliceAccount.releaseAccount();
|
|
||||||
bobAccount.releaseAccount();
|
|
||||||
assertTrue(aliceAccount.isReleased());
|
|
||||||
assertTrue(bobAccount.isReleased());
|
|
||||||
|
|
||||||
bobSession.releaseSession();
|
|
||||||
aliceSession.releaseSession();
|
|
||||||
assertTrue(bobSession.isReleased());
|
|
||||||
assertTrue(aliceSession.isReleased());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -493,23 +493,4 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private native byte[] fallbackKeyJni();
|
private native byte[] fallbackKeyJni();
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Forget about the old fallback key.
|
|
||||||
*
|
|
||||||
* This should be called once you are reasonably certain that you will not
|
|
||||||
* receive any more messages that use the old fallback key (e.g. 5 minutes
|
|
||||||
* after the new fallback key has been published).
|
|
||||||
* @throws OlmException the failure reason
|
|
||||||
**/
|
|
||||||
public void forgetFallbackKey() throws OlmException {
|
|
||||||
try {
|
|
||||||
forgetFallbackKeyJni();
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_FORGET_FALLBACK_KEY, e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private native void forgetFallbackKeyJni();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,6 @@ public class OlmException extends IOException {
|
||||||
public static final int EXCEPTION_CODE_ACCOUNT_SIGN_MESSAGE = 107;
|
public static final int EXCEPTION_CODE_ACCOUNT_SIGN_MESSAGE = 107;
|
||||||
public static final int EXCEPTION_CODE_ACCOUNT_GENERATE_FALLBACK_KEY = 108;
|
public static final int EXCEPTION_CODE_ACCOUNT_GENERATE_FALLBACK_KEY = 108;
|
||||||
public static final int EXCEPTION_CODE_ACCOUNT_FALLBACK_KEY = 109;
|
public static final int EXCEPTION_CODE_ACCOUNT_FALLBACK_KEY = 109;
|
||||||
public static final int EXCEPTION_CODE_ACCOUNT_FORGET_FALLBACK_KEY = 110;
|
|
||||||
|
|
||||||
public static final int EXCEPTION_CODE_CREATE_INBOUND_GROUP_SESSION = 200;
|
public static final int EXCEPTION_CODE_CREATE_INBOUND_GROUP_SESSION = 200;
|
||||||
public static final int EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION = 201;
|
public static final int EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION = 201;
|
||||||
|
@ -60,7 +59,6 @@ public class OlmException extends IOException {
|
||||||
public static final int EXCEPTION_CODE_SESSION_ENCRYPT_MESSAGE = 404;
|
public static final int EXCEPTION_CODE_SESSION_ENCRYPT_MESSAGE = 404;
|
||||||
public static final int EXCEPTION_CODE_SESSION_DECRYPT_MESSAGE = 405;
|
public static final int EXCEPTION_CODE_SESSION_DECRYPT_MESSAGE = 405;
|
||||||
public static final int EXCEPTION_CODE_SESSION_SESSION_IDENTIFIER = 406;
|
public static final int EXCEPTION_CODE_SESSION_SESSION_IDENTIFIER = 406;
|
||||||
public static final int EXCEPTION_CODE_SESSION_SESSION_DESCRIBE = 407;
|
|
||||||
|
|
||||||
public static final int EXCEPTION_CODE_UTILITY_CREATION = 500;
|
public static final int EXCEPTION_CODE_UTILITY_CREATION = 500;
|
||||||
public static final int EXCEPTION_CODE_UTILITY_VERIFY_SIGNATURE = 501;
|
public static final int EXCEPTION_CODE_UTILITY_VERIFY_SIGNATURE = 501;
|
||||||
|
|
|
@ -369,29 +369,4 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri
|
||||||
* @return the deserialized session
|
* @return the deserialized session
|
||||||
**/
|
**/
|
||||||
private native long deserializeJni(byte[] aSerializedData, byte[] aKey);
|
private native long deserializeJni(byte[] aSerializedData, byte[] aKey);
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a pickled inbound group session as a bytes buffer.<br>
|
|
||||||
* The session is serialized and encrypted with aKey.
|
|
||||||
* In case of failure, an error human readable
|
|
||||||
* description is provide in aErrorMsg.
|
|
||||||
* @param aKey encryption key
|
|
||||||
* @param aErrorMsg error message description
|
|
||||||
* @return the pickled inbound group session as bytes buffer
|
|
||||||
*/
|
|
||||||
public byte[] pickle(byte[] aKey, StringBuffer aErrorMsg) {
|
|
||||||
return serialize(aKey, aErrorMsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads an inbound group session from a pickled bytes buffer.<br>
|
|
||||||
* See {@link #serialize(byte[], StringBuffer)}
|
|
||||||
* @param aSerializedData bytes buffer
|
|
||||||
* @param aKey key used to encrypted
|
|
||||||
* @exception Exception the exception
|
|
||||||
*/
|
|
||||||
public void unpickle(byte[] aSerializedData, byte[] aKey) throws Exception {
|
|
||||||
deserialize(aSerializedData, aKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ public class OlmManager {
|
||||||
* @return the library version
|
* @return the library version
|
||||||
*/
|
*/
|
||||||
public String getVersion() {
|
public String getVersion() {
|
||||||
return BuildConfig.OLM_VERSION;
|
return "3.2.6";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -293,28 +293,4 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser
|
||||||
**/
|
**/
|
||||||
private native long deserializeJni(byte[] aSerializedData, byte[] aKey);
|
private native long deserializeJni(byte[] aSerializedData, byte[] aKey);
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a pickled outbound group session as a bytes buffer.<br>
|
|
||||||
* The session is serialized and encrypted with aKey.
|
|
||||||
* In case of failure, an error human readable
|
|
||||||
* description is provide in aErrorMsg.
|
|
||||||
* @param aKey encryption key
|
|
||||||
* @param aErrorMsg error message description
|
|
||||||
* @return the pickled outbound group session as bytes buffer
|
|
||||||
*/
|
|
||||||
public byte[] pickle(byte[] aKey, StringBuffer aErrorMsg) {
|
|
||||||
return serialize(aKey, aErrorMsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads an outbound group session from a pickled bytes buffer.<br>
|
|
||||||
* See {@link #serialize(byte[], StringBuffer)}
|
|
||||||
* @param aSerializedData bytes buffer
|
|
||||||
* @param aKey key used to encrypted
|
|
||||||
* @exception Exception the exception
|
|
||||||
*/
|
|
||||||
public void unpickle(byte[] aSerializedData, byte[] aKey) throws Exception {
|
|
||||||
deserialize(aSerializedData, aKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,16 +106,6 @@ public class OlmSAS {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String calculateMacFixedBase64(String message, String info) throws OlmException {
|
|
||||||
try {
|
|
||||||
byte[] bytes = calculateMacFixedBase64Jni(message.getBytes("UTF-8"), info.getBytes("UTF-8"));
|
|
||||||
if (bytes != null) return new String(bytes, "UTF-8");
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
throw new OlmException(OlmException.EXCEPTION_CODE_SAS_ERROR, e.getMessage());
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String calculateMacLongKdf(String message, String info) throws OlmException {
|
public String calculateMacLongKdf(String message, String info) throws OlmException {
|
||||||
try {
|
try {
|
||||||
byte[] bytes = calculateMacLongKdfJni(message.getBytes("UTF-8"), info.getBytes("UTF-8"));
|
byte[] bytes = calculateMacLongKdfJni(message.getBytes("UTF-8"), info.getBytes("UTF-8"));
|
||||||
|
@ -150,8 +140,6 @@ public class OlmSAS {
|
||||||
|
|
||||||
private native byte[] calculateMacJni(byte[] message, byte[] info);
|
private native byte[] calculateMacJni(byte[] message, byte[] info);
|
||||||
|
|
||||||
private native byte[] calculateMacFixedBase64Jni(byte[] message, byte[] info);
|
|
||||||
|
|
||||||
private native byte[] calculateMacLongKdfJni(byte[] message, byte[] info);
|
private native byte[] calculateMacLongKdfJni(byte[] message, byte[] info);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -223,23 +223,6 @@ public class OlmSession extends CommonSerializeUtils implements Serializable {
|
||||||
*/
|
*/
|
||||||
private native byte[] getSessionIdentifierJni();
|
private native byte[] getSessionIdentifierJni();
|
||||||
|
|
||||||
public String sessionDescribe() throws OlmException {
|
|
||||||
try {
|
|
||||||
byte[] buffer = olmSessionDescribeJni();
|
|
||||||
|
|
||||||
if (null != buffer) {
|
|
||||||
return new String(buffer, "UTF-8");
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(LOG_TAG, "## sessionDescribe(): " + e.getMessage());
|
|
||||||
throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_SESSION_DESCRIBE, e.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private native byte[] olmSessionDescribeJni();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the PRE_KEY({@link OlmMessage#MESSAGE_TYPE_PRE_KEY}) message is for this in-bound session.<br>
|
* Checks if the PRE_KEY({@link OlmMessage#MESSAGE_TYPE_PRE_KEY}) message is for this in-bound session.<br>
|
||||||
* This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY).
|
* This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY).
|
||||||
|
@ -465,30 +448,5 @@ public class OlmSession extends CommonSerializeUtils implements Serializable {
|
||||||
* @return the deserialized session
|
* @return the deserialized session
|
||||||
**/
|
**/
|
||||||
private native long deserializeJni(byte[] aSerializedData, byte[] aKey);
|
private native long deserializeJni(byte[] aSerializedData, byte[] aKey);
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a pickled session as a bytes buffer.<br>
|
|
||||||
* The session is serialized and encrypted with aKey.
|
|
||||||
* In case of failure, an error human readable
|
|
||||||
* description is provide in aErrorMsg.
|
|
||||||
* @param aKey encryption key
|
|
||||||
* @param aErrorMsg error message description
|
|
||||||
* @return the pickled session as bytes buffer
|
|
||||||
*/
|
|
||||||
public byte[] pickle(byte[] aKey, StringBuffer aErrorMsg) {
|
|
||||||
return serialize(aKey, aErrorMsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads a session from a pickled bytes buffer.<br>
|
|
||||||
* See {@link #serialize(byte[], StringBuffer)}
|
|
||||||
* @param aSerializedData bytes buffer
|
|
||||||
* @param aKey key used to encrypted
|
|
||||||
* @exception Exception the exception
|
|
||||||
*/
|
|
||||||
public void unpickle(byte[] aSerializedData, byte[] aKey) throws Exception {
|
|
||||||
deserialize(aSerializedData, aKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -521,7 +521,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(fallbackKeyJni)(JNIEnv *env, jobject t
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// keys memory allocation
|
// keys memory allocation
|
||||||
size_t keysLength = olm_account_unpublished_fallback_key_length(accountPtr);
|
size_t keysLength = olm_account_fallback_key_length(accountPtr);
|
||||||
uint8_t *keysBytesPtr = (uint8_t *)malloc(keysLength*sizeof(uint8_t));
|
uint8_t *keysBytesPtr = (uint8_t *)malloc(keysLength*sizeof(uint8_t));
|
||||||
|
|
||||||
if (!keysBytesPtr)
|
if (!keysBytesPtr)
|
||||||
|
@ -532,7 +532,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(fallbackKeyJni)(JNIEnv *env, jobject t
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// retrieve key pairs in keysBytesPtr
|
// retrieve key pairs in keysBytesPtr
|
||||||
size_t keysResult = olm_account_unpublished_fallback_key(accountPtr, keysBytesPtr, keysLength);
|
size_t keysResult = olm_account_fallback_key(accountPtr, keysBytesPtr, keysLength);
|
||||||
|
|
||||||
if (keysResult == olm_error()) {
|
if (keysResult == olm_error()) {
|
||||||
LOGE("## fallbackKeyJni(): failure - error getting fallback key Msg=%s",(const char *)olm_account_last_error(accountPtr));
|
LOGE("## fallbackKeyJni(): failure - error getting fallback key Msg=%s",(const char *)olm_account_last_error(accountPtr));
|
||||||
|
@ -567,36 +567,6 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(fallbackKeyJni)(JNIEnv *env, jobject t
|
||||||
return byteArrayRetValue;
|
return byteArrayRetValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Forget about the old fallback key.
|
|
||||||
*
|
|
||||||
* This should be called once you are reasonably certain that you will not
|
|
||||||
* receive any more messages that use the old fallback key (e.g. 5 minutes
|
|
||||||
* after the new fallback key has been published).
|
|
||||||
**/
|
|
||||||
JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(forgetFallbackKeyJni)(JNIEnv *env, jobject thiz)
|
|
||||||
{
|
|
||||||
const char* errorMessage = NULL;
|
|
||||||
OlmAccount *accountPtr = getAccountInstanceId(env, thiz);
|
|
||||||
|
|
||||||
if (!accountPtr)
|
|
||||||
{
|
|
||||||
LOGE("## forgetFallbackKeyJni(): failure - invalid Account ptr");
|
|
||||||
errorMessage = "invalid Account ptr";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
olm_account_forget_old_fallback_key(accountPtr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (errorMessage)
|
|
||||||
{
|
|
||||||
env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sign a message with the ed25519 key (fingerprint) for this account.<br>
|
* Sign a message with the ed25519 key (fingerprint) for this account.<br>
|
||||||
* The signed message is returned by the function.
|
* The signed message is returned by the function.
|
||||||
|
@ -650,7 +620,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject t
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOGD("## signMessageJni(): success - retCode=%lu signatureLength=%lu", static_cast<long unsigned int>(resultSign), static_cast<long unsigned int>(signatureLength));
|
LOGD("## signMessageJni(): success - retCode=%lu signatureLength=%lu", static_cast<long unsigned int>(resultSign), static_cast<long unsigned int>(signatureLength));
|
||||||
|
|
||||||
signedMsgRetValueBuffer = env->NewByteArray(signatureLength);
|
signedMsgRetValueBuffer = env->NewByteArray(signatureLength);
|
||||||
env->SetByteArrayRegion(signedMsgRetValueBuffer, 0 , signatureLength, (jbyte*)signedMsgPtr);
|
env->SetByteArrayRegion(signedMsgRetValueBuffer, 0 , signatureLength, (jbyte*)signedMsgPtr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,6 @@ JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env,
|
||||||
// fallback keys
|
// fallback keys
|
||||||
JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(generateFallbackKeyJni)(JNIEnv *env, jobject thiz);
|
JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(generateFallbackKeyJni)(JNIEnv *env, jobject thiz);
|
||||||
JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(fallbackKeyJni)(JNIEnv *env, jobject thiz);
|
JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(fallbackKeyJni)(JNIEnv *env, jobject thiz);
|
||||||
JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(forgetFallbackKeyJni)(JNIEnv *env, jobject thiz);
|
|
||||||
|
|
||||||
// signing
|
// signing
|
||||||
JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aMessage);
|
JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aMessage);
|
||||||
|
|
|
@ -309,86 +309,6 @@ JNIEXPORT jbyteArray OLM_SAS_FUNC_DEF(calculateMacJni)(JNIEnv *env, jobject thiz
|
||||||
return returnValue;
|
return returnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jbyteArray OLM_SAS_FUNC_DEF(calculateMacFixedBase64Jni)(JNIEnv *env, jobject thiz,jbyteArray messageBuffer,jbyteArray infoBuffer) {
|
|
||||||
LOGD("## calculateMacFixedBase64Jni(): IN");
|
|
||||||
const char* errorMessage = NULL;
|
|
||||||
jbyteArray returnValue = 0;
|
|
||||||
OlmSAS* sasPtr = getOlmSasInstanceId(env, thiz);
|
|
||||||
|
|
||||||
jbyte *messagePtr = NULL;
|
|
||||||
jboolean messageWasCopied = JNI_FALSE;
|
|
||||||
|
|
||||||
jbyte *infoPtr = NULL;
|
|
||||||
jboolean infoWasCopied = JNI_FALSE;
|
|
||||||
|
|
||||||
if (!sasPtr)
|
|
||||||
{
|
|
||||||
LOGE("## calculateMacFixedBase64Jni(): failure - invalid SAS ptr=NULL");
|
|
||||||
errorMessage = "invalid SAS ptr=NULL";
|
|
||||||
} else if(!messageBuffer) {
|
|
||||||
LOGE("## calculateMacFixedBase64Jni(): failure - invalid message");
|
|
||||||
errorMessage = "invalid info";
|
|
||||||
}
|
|
||||||
else if (!(messagePtr = env->GetByteArrayElements(messageBuffer, &messageWasCopied)))
|
|
||||||
{
|
|
||||||
LOGE(" ## calculateMacFixedBase64Jni(): failure - message JNI allocation OOM");
|
|
||||||
errorMessage = "message JNI allocation OOM";
|
|
||||||
}
|
|
||||||
else if (!(infoPtr = env->GetByteArrayElements(infoBuffer, &infoWasCopied)))
|
|
||||||
{
|
|
||||||
LOGE(" ## calculateMacFixedBase64Jni(): failure - info JNI allocation OOM");
|
|
||||||
errorMessage = "info JNI allocation OOM";
|
|
||||||
} else {
|
|
||||||
|
|
||||||
size_t infoLength = (size_t)env->GetArrayLength(infoBuffer);
|
|
||||||
size_t messageLength = (size_t)env->GetArrayLength(messageBuffer);
|
|
||||||
size_t macLength = olm_sas_mac_length(sasPtr);
|
|
||||||
|
|
||||||
void *macPtr = malloc(macLength*sizeof(uint8_t));
|
|
||||||
|
|
||||||
size_t result = olm_sas_calculate_mac_fixed_base64(sasPtr,messagePtr,messageLength,infoPtr,infoLength,macPtr,macLength);
|
|
||||||
if (result == olm_error())
|
|
||||||
{
|
|
||||||
errorMessage = (const char *)olm_sas_last_error(sasPtr);
|
|
||||||
LOGE("## calculateMacFixedBase64Jni(): failure - error calculating SAS mac Msg=%s", errorMessage);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
returnValue = env->NewByteArray(macLength);
|
|
||||||
env->SetByteArrayRegion(returnValue, 0 , macLength, (jbyte*)macPtr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (macPtr) {
|
|
||||||
free(macPtr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// free alloc
|
|
||||||
if (infoPtr)
|
|
||||||
{
|
|
||||||
if (infoWasCopied)
|
|
||||||
{
|
|
||||||
memset(infoPtr, 0, (size_t)env->GetArrayLength(infoBuffer));
|
|
||||||
}
|
|
||||||
env->ReleaseByteArrayElements(infoBuffer, infoPtr, JNI_ABORT);
|
|
||||||
}
|
|
||||||
if (messagePtr)
|
|
||||||
{
|
|
||||||
if (messageWasCopied)
|
|
||||||
{
|
|
||||||
memset(messagePtr, 0, (size_t)env->GetArrayLength(messageBuffer));
|
|
||||||
}
|
|
||||||
env->ReleaseByteArrayElements(messageBuffer, messagePtr, JNI_ABORT);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (errorMessage)
|
|
||||||
{
|
|
||||||
env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
return returnValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
JNIEXPORT jbyteArray OLM_SAS_FUNC_DEF(calculateMacLongKdfJni)(JNIEnv *env, jobject thiz,jbyteArray messageBuffer,jbyteArray infoBuffer) {
|
JNIEXPORT jbyteArray OLM_SAS_FUNC_DEF(calculateMacLongKdfJni)(JNIEnv *env, jobject thiz,jbyteArray messageBuffer,jbyteArray infoBuffer) {
|
||||||
LOGD("## calculateMacLongKdfJni(): IN");
|
LOGD("## calculateMacLongKdfJni(): IN");
|
||||||
const char* errorMessage = NULL;
|
const char* errorMessage = NULL;
|
||||||
|
@ -467,4 +387,4 @@ JNIEXPORT jbyteArray OLM_SAS_FUNC_DEF(calculateMacLongKdfJni)(JNIEnv *env, jobje
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnValue;
|
return returnValue;
|
||||||
}
|
}
|
|
@ -32,7 +32,6 @@ JNIEXPORT jbyteArray OLM_SAS_FUNC_DEF(getPubKeyJni)(JNIEnv *env, jobject thiz);
|
||||||
JNIEXPORT void OLM_SAS_FUNC_DEF(setTheirPubKey)(JNIEnv *env, jobject thiz,jbyteArray pubKey);
|
JNIEXPORT void OLM_SAS_FUNC_DEF(setTheirPubKey)(JNIEnv *env, jobject thiz,jbyteArray pubKey);
|
||||||
JNIEXPORT jbyteArray OLM_SAS_FUNC_DEF(generateShortCodeJni)(JNIEnv *env, jobject thiz, jbyteArray infoStringBytes, jint byteNb);
|
JNIEXPORT jbyteArray OLM_SAS_FUNC_DEF(generateShortCodeJni)(JNIEnv *env, jobject thiz, jbyteArray infoStringBytes, jint byteNb);
|
||||||
JNIEXPORT jbyteArray OLM_SAS_FUNC_DEF(calculateMacJni)(JNIEnv *env, jobject thiz, jbyteArray messageBuffer, jbyteArray infoBuffer);
|
JNIEXPORT jbyteArray OLM_SAS_FUNC_DEF(calculateMacJni)(JNIEnv *env, jobject thiz, jbyteArray messageBuffer, jbyteArray infoBuffer);
|
||||||
JNIEXPORT jbyteArray OLM_SAS_FUNC_DEF(calculateMacFixedBase64Jni)(JNIEnv *env, jobject thiz, jbyteArray messageBuffer, jbyteArray infoBuffer);
|
|
||||||
JNIEXPORT jbyteArray OLM_SAS_FUNC_DEF(calculateMacLongKdfJni)(JNIEnv *env, jobject thiz, jbyteArray messageBuffer, jbyteArray infoBuffer);
|
JNIEXPORT jbyteArray OLM_SAS_FUNC_DEF(calculateMacLongKdfJni)(JNIEnv *env, jobject thiz, jbyteArray messageBuffer, jbyteArray infoBuffer);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -798,58 +798,6 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env,
|
||||||
return returnValue;
|
return returnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(olmSessionDescribeJni(JNIEnv *env, jobject thiz))
|
|
||||||
{
|
|
||||||
const char* errorMessage = NULL;
|
|
||||||
jbyteArray returnValue = 0;
|
|
||||||
|
|
||||||
LOGD("## olmSessionDescribeJni(): IN ");
|
|
||||||
|
|
||||||
OlmSession *sessionPtr = getSessionInstanceId(env, thiz);
|
|
||||||
|
|
||||||
if (!sessionPtr)
|
|
||||||
{
|
|
||||||
LOGE("## olmSessionDescribeJni(): failure - invalid Session ptr=NULL");
|
|
||||||
errorMessage = "invalid Session ptr=NULL";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int maxLength = 600;
|
|
||||||
char* describePtr = NULL;
|
|
||||||
describePtr = (char*) malloc(maxLength * sizeof *describePtr);
|
|
||||||
if (!describePtr)
|
|
||||||
{
|
|
||||||
LOGE("## olmSessionDescribeJni(): failure - describe allocation OOM");
|
|
||||||
errorMessage = "describe allocation OOM";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
olm_session_describe(sessionPtr, describePtr, maxLength);
|
|
||||||
int length = strlen(describePtr);
|
|
||||||
if (length == 0)
|
|
||||||
{
|
|
||||||
LOGE("## olmSessionDescribeJni(): failure - get session describe");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOGD("## olmSessionDescribeJni(): success - describe=%.*s", (char*)describePtr);
|
|
||||||
|
|
||||||
returnValue = env->NewByteArray(length);
|
|
||||||
env->SetByteArrayRegion(returnValue, 0, length, (jbyte*)describePtr);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(describePtr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (errorMessage)
|
|
||||||
{
|
|
||||||
env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
return returnValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize and encrypt session instance.<br>
|
* Serialize and encrypt session instance.<br>
|
||||||
* An exception is thrown if the operation fails.
|
* An exception is thrown if the operation fails.
|
||||||
|
|
|
@ -47,7 +47,6 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobjec
|
||||||
JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg);
|
JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg);
|
||||||
|
|
||||||
JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, jobject thiz);
|
JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, jobject thiz);
|
||||||
JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(olmSessionDescribeJni)(JNIEnv *env, jobject thiz);
|
|
||||||
|
|
||||||
// serialization
|
// serialization
|
||||||
JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKey);
|
JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKey);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
|
|
||||||
MAJOR := 3
|
MAJOR := 3
|
||||||
MINOR := 2
|
MINOR := 2
|
||||||
PATCH := 16
|
PATCH := 6
|
||||||
|
|
|
@ -109,7 +109,7 @@ discriminate between sessions.
|
||||||
### Sharing session data
|
### Sharing session data
|
||||||
|
|
||||||
To allow other participants in the conversation to decrypt messages, the
|
To allow other participants in the conversation to decrypt messages, the
|
||||||
session data is formatted as described in [Session-sharing format](#session-sharing-format). It is then
|
session data is formatted as described in [Session-sharing format](#Session-sharing-format). It is then
|
||||||
shared with other participants in the conversation via a secure peer-to-peer
|
shared with other participants in the conversation via a secure peer-to-peer
|
||||||
channel (such as that provided by [Olm][]).
|
channel (such as that provided by [Olm][]).
|
||||||
|
|
||||||
|
@ -182,13 +182,9 @@ but the decision of which ratchet states to cache is left to the application.
|
||||||
|
|
||||||
## Data exchange formats
|
## Data exchange formats
|
||||||
|
|
||||||
### Session sharing format
|
### Session-sharing format
|
||||||
|
|
||||||
This format is used for the initial sharing of a Megolm session with other
|
The Megolm key-sharing format is as follows:
|
||||||
group participants who need to be able to read messages encrypted by this
|
|
||||||
session.
|
|
||||||
|
|
||||||
The session sharing format is as follows:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
+---+----+--------+--------+--------+--------+------+-----------+
|
+---+----+--------+--------+--------+--------+------+-----------+
|
||||||
|
@ -206,33 +202,6 @@ part of the Ed25519 keypair $`K`$.
|
||||||
The data is then signed using the Ed25519 keypair, and the 64-byte signature is
|
The data is then signed using the Ed25519 keypair, and the 64-byte signature is
|
||||||
appended.
|
appended.
|
||||||
|
|
||||||
### Session export format
|
|
||||||
|
|
||||||
Once the session is initially shared with the group participants, each
|
|
||||||
participant needs to retain a copy of the session if they want to maintain
|
|
||||||
their ability to decrypt messages encrypted with that session.
|
|
||||||
|
|
||||||
For forward-secrecy purposes, a participant may choose to store a ratcheted
|
|
||||||
version of the session. But since the ratchet index is covered by the
|
|
||||||
signature, this would invalidate the signature. So we define a similar format,
|
|
||||||
called the *session export format*, which is identical to the [session sharing
|
|
||||||
format](#session-sharing-format) except for dropping the signature.
|
|
||||||
|
|
||||||
The Megolm session export format is thus as follows:
|
|
||||||
|
|
||||||
```
|
|
||||||
+---+----+--------+--------+--------+--------+------+
|
|
||||||
| V | i | R(i,0) | R(i,1) | R(i,2) | R(i,3) | Kpub |
|
|
||||||
+---+----+--------+--------+--------+--------+------+
|
|
||||||
0 1 5 37 69 101 133 165 bytes
|
|
||||||
```
|
|
||||||
|
|
||||||
The version byte, ``V``, is ``"\x01"``.
|
|
||||||
|
|
||||||
This is followed by the ratchet index, $`i`$, which is encoded as a
|
|
||||||
big-endian 32-bit integer; the ratchet values $`R_{i,j}`$; and the public
|
|
||||||
part of the Ed25519 keypair $`K`$.
|
|
||||||
|
|
||||||
### Message format
|
### Message format
|
||||||
|
|
||||||
Megolm messages consist of a one byte version, followed by a variable length
|
Megolm messages consist of a one byte version, followed by a variable length
|
||||||
|
|
60
flake.lock
60
flake.lock
|
@ -1,60 +0,0 @@
|
||||||
{
|
|
||||||
"nodes": {
|
|
||||||
"flake-utils": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1659877975,
|
|
||||||
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1664871473,
|
|
||||||
"narHash": "sha256-1LzbW6G6Uz8akWiOdlIi435GAm1ct5jF5tovw/9to0o=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "b7a6fde153d9470afdb6aa1da51c4117f03b84ed",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"ref": "nixos-unstable",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"npmlock2nix": {
|
|
||||||
"flake": false,
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1654775747,
|
|
||||||
"narHash": "sha256-9pXHDpIjmsK5390wmpGHu9aA4QOPpegPBvThHeBlef4=",
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "npmlock2nix",
|
|
||||||
"rev": "5c4f247688fc91d665df65f71c81e0726621aaa8",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "npmlock2nix",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-utils": "flake-utils",
|
|
||||||
"nixpkgs": "nixpkgs",
|
|
||||||
"npmlock2nix": "npmlock2nix"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": "root",
|
|
||||||
"version": 7
|
|
||||||
}
|
|
40
flake.nix
40
flake.nix
|
@ -1,40 +0,0 @@
|
||||||
{
|
|
||||||
description = "An implementation of the Double Ratchet cryptographic ratchet";
|
|
||||||
|
|
||||||
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
|
||||||
# We can't use the current stable release because of
|
|
||||||
# https://github.com/emscripten-core/emscripten/issues/16913
|
|
||||||
inputs.flake-utils.url = "github:numtide/flake-utils";
|
|
||||||
inputs.npmlock2nix = {
|
|
||||||
url = "github:nix-community/npmlock2nix";
|
|
||||||
flake = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
outputs = { self, nixpkgs, flake-utils, npmlock2nix }:
|
|
||||||
let
|
|
||||||
localOverlay = import ./nix/overlay.nix;
|
|
||||||
pkgsForSystem = system: import nixpkgs {
|
|
||||||
inherit system;
|
|
||||||
overlays = [
|
|
||||||
(final: prev: {
|
|
||||||
npmlock2nix = final.callPackage npmlock2nix {};
|
|
||||||
node_modules = final.npmlock2nix.node_modules { src = ./javascript; };
|
|
||||||
})
|
|
||||||
localOverlay
|
|
||||||
];
|
|
||||||
};
|
|
||||||
in (
|
|
||||||
# some systems cause issues, e.g. i686-linux is unsupported by gradle,
|
|
||||||
# which causes "nix flake check" to fail. Investigate more later, but for
|
|
||||||
# now, we will just allow x86_64-linux
|
|
||||||
flake-utils.lib.eachSystem [ "x86_64-linux" "x86_64-darwin" "aarch64-darwin" ] (system: rec {
|
|
||||||
legacyPackages = pkgsForSystem system;
|
|
||||||
checks = {
|
|
||||||
inherit (legacyPackages) olm-gcc-cmake olm-clang-cmake olm-gcc-make;
|
|
||||||
};
|
|
||||||
packages = {
|
|
||||||
javascript = legacyPackages.olm-javascript;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
));
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
function Math(el)
|
|
||||||
if el.mathtype == "InlineMath" then
|
|
||||||
if el.text:sub(1,1) == '`' and el.text:sub(#el.text) == '`' then
|
|
||||||
local text = el.text:sub(2,#el.text-1)
|
|
||||||
return pandoc.Math(el.mathtype, text)
|
|
||||||
else
|
|
||||||
local cont = pandoc.read(el.text)
|
|
||||||
return { pandoc.Str("$") } .. cont.blocks[1].content .. { pandoc.Str("$") }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function CodeBlock(el)
|
|
||||||
if el.classes[1] == "math" then
|
|
||||||
return pandoc.Para({ pandoc.Math("DisplayMath", el.text) })
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -99,9 +99,9 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
T * this_pos = _data;
|
T * this_pos = _data;
|
||||||
const T * other_pos = other._data;
|
T * const other_pos = other._data;
|
||||||
while (other_pos != other._end) {
|
while (other_pos != other._end) {
|
||||||
*this_pos = *other_pos;
|
*this_pos = *other;
|
||||||
++this_pos;
|
++this_pos;
|
||||||
++other_pos;
|
++other_pos;
|
||||||
}
|
}
|
||||||
|
|
|
@ -387,10 +387,7 @@ OLM_EXPORT int olm_session_has_received_message(
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write a null-terminated string describing the internal state of an olm
|
* Write a null-terminated string describing the internal state of an olm
|
||||||
* session to the buffer provided for debugging and logging purposes. If the
|
* session to the buffer provided for debugging and logging purposes.
|
||||||
* buffer is not large enough to hold the entire string, it will be truncated
|
|
||||||
* and will end with "...". A buffer length of 600 will be enough to hold any
|
|
||||||
* output.
|
|
||||||
*/
|
*/
|
||||||
OLM_EXPORT void olm_session_describe(OlmSession * session, char *buf, size_t buflen);
|
OLM_EXPORT void olm_session_describe(OlmSession * session, char *buf, size_t buflen);
|
||||||
|
|
||||||
|
|
|
@ -9,15 +9,15 @@
|
||||||
# ifndef OLM_EXPORT
|
# ifndef OLM_EXPORT
|
||||||
# ifdef olm_EXPORTS
|
# ifdef olm_EXPORTS
|
||||||
/* We are building this library */
|
/* We are building this library */
|
||||||
# define OLM_EXPORT
|
# define OLM_EXPORT __attribute__((visibility("default")))
|
||||||
# else
|
# else
|
||||||
/* We are using this library */
|
/* We are using this library */
|
||||||
# define OLM_EXPORT
|
# define OLM_EXPORT __attribute__((visibility("default")))
|
||||||
# endif
|
# endif
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
# ifndef OLM_NO_EXPORT
|
# ifndef OLM_NO_EXPORT
|
||||||
# define OLM_NO_EXPORT
|
# define OLM_NO_EXPORT __attribute__((visibility("hidden")))
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
38
javascript/index.d.ts
vendored
38
javascript/index.d.ts
vendored
|
@ -18,28 +18,27 @@ export as namespace Olm;
|
||||||
|
|
||||||
declare class Account {
|
declare class Account {
|
||||||
constructor();
|
constructor();
|
||||||
free(): void;
|
free();
|
||||||
create(): void;
|
create();
|
||||||
identity_keys(): string;
|
identity_keys(): string;
|
||||||
sign(message: string | Uint8Array): string;
|
sign(message: string | Uint8Array): string;
|
||||||
one_time_keys(): string;
|
one_time_keys(): string;
|
||||||
mark_keys_as_published(): void;
|
mark_keys_as_published();
|
||||||
max_number_of_one_time_keys(): number;
|
max_number_of_one_time_keys(): number;
|
||||||
generate_one_time_keys(number_of_keys: number): void;
|
generate_one_time_keys(number_of_keys: number);
|
||||||
remove_one_time_keys(session: Session): void;
|
remove_one_time_keys(session: Session);
|
||||||
generate_fallback_key(): void;
|
generate_fallback_key();
|
||||||
fallback_key(): string;
|
fallback_key(): string;
|
||||||
unpublished_fallback_key(): string;
|
unpublished_fallback_key(): string;
|
||||||
forget_old_fallback_key(): void;
|
|
||||||
pickle(key: string | Uint8Array): string;
|
pickle(key: string | Uint8Array): string;
|
||||||
unpickle(key: string | Uint8Array, pickle: string): void;
|
unpickle(key: string | Uint8Array, pickle: string);
|
||||||
}
|
}
|
||||||
|
|
||||||
declare class Session {
|
declare class Session {
|
||||||
constructor();
|
constructor();
|
||||||
free(): void;
|
free(): void;
|
||||||
pickle(key: string | Uint8Array): string;
|
pickle(key: string | Uint8Array): string;
|
||||||
unpickle(key: string | Uint8Array, pickle: string): void;
|
unpickle(key: string | Uint8Array, pickle: string);
|
||||||
create_outbound(
|
create_outbound(
|
||||||
account: Account, their_identity_key: string, their_one_time_key: string,
|
account: Account, their_identity_key: string, their_one_time_key: string,
|
||||||
): void;
|
): void;
|
||||||
|
@ -51,10 +50,7 @@ declare class Session {
|
||||||
has_received_message(): boolean;
|
has_received_message(): boolean;
|
||||||
matches_inbound(one_time_key_message: string): boolean;
|
matches_inbound(one_time_key_message: string): boolean;
|
||||||
matches_inbound_from(identity_key: string, one_time_key_message: string): boolean;
|
matches_inbound_from(identity_key: string, one_time_key_message: string): boolean;
|
||||||
encrypt(plaintext: string): {
|
encrypt(plaintext: string): object;
|
||||||
type: 0 | 1; // 0: PreKey, 1: Message
|
|
||||||
body: string;
|
|
||||||
};
|
|
||||||
decrypt(message_type: number, message: string): string;
|
decrypt(message_type: number, message: string): string;
|
||||||
describe(): string;
|
describe(): string;
|
||||||
}
|
}
|
||||||
|
@ -70,13 +66,10 @@ declare class InboundGroupSession {
|
||||||
constructor();
|
constructor();
|
||||||
free(): void;
|
free(): void;
|
||||||
pickle(key: string | Uint8Array): string;
|
pickle(key: string | Uint8Array): string;
|
||||||
unpickle(key: string | Uint8Array, pickle: string): void;
|
unpickle(key: string | Uint8Array, pickle: string);
|
||||||
create(session_key: string): string;
|
create(session_key: string): string;
|
||||||
import_session(session_key: string): string;
|
import_session(session_key: string): string;
|
||||||
decrypt(message: string): {
|
decrypt(message: string): object;
|
||||||
message_index: number;
|
|
||||||
plaintext: string;
|
|
||||||
};
|
|
||||||
session_id(): string;
|
session_id(): string;
|
||||||
first_known_index(): number;
|
first_known_index(): number;
|
||||||
export_session(message_index: number): string;
|
export_session(message_index: number): string;
|
||||||
|
@ -86,7 +79,7 @@ declare class OutboundGroupSession {
|
||||||
constructor();
|
constructor();
|
||||||
free(): void;
|
free(): void;
|
||||||
pickle(key: string | Uint8Array): string;
|
pickle(key: string | Uint8Array): string;
|
||||||
unpickle(key: string | Uint8Array, pickle: string): void;
|
unpickle(key: string | Uint8Array, pickle: string);
|
||||||
create(): void;
|
create(): void;
|
||||||
encrypt(plaintext: string): string;
|
encrypt(plaintext: string): string;
|
||||||
session_id(): string;
|
session_id(): string;
|
||||||
|
@ -98,11 +91,7 @@ declare class PkEncryption {
|
||||||
constructor();
|
constructor();
|
||||||
free(): void;
|
free(): void;
|
||||||
set_recipient_key(key: string): void;
|
set_recipient_key(key: string): void;
|
||||||
encrypt(plaintext: string): {
|
encrypt(plaintext: string): object;
|
||||||
ciphertext: string;
|
|
||||||
mac: string;
|
|
||||||
ephemeral: string;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
declare class PkDecryption {
|
declare class PkDecryption {
|
||||||
|
@ -131,7 +120,6 @@ declare class SAS {
|
||||||
set_their_key(their_key: string): void;
|
set_their_key(their_key: string): void;
|
||||||
generate_bytes(info: string, length: number): Uint8Array;
|
generate_bytes(info: string, length: number): Uint8Array;
|
||||||
calculate_mac(input: string, info: string): string;
|
calculate_mac(input: string, info: string): string;
|
||||||
calculate_mac_fixed_base64(input: string, info: string): string;
|
|
||||||
calculate_mac_long_kdf(input: string, info: string): string;
|
calculate_mac_long_kdf(input: string, info: string): string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
/** @constructor */
|
|
||||||
function InboundGroupSession() {
|
function InboundGroupSession() {
|
||||||
var size = Module['_olm_inbound_group_session_size']();
|
var size = Module['_olm_inbound_group_session_size']();
|
||||||
this.buf = malloc(size);
|
this.buf = malloc(size);
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
/** @constructor */
|
|
||||||
function OutboundGroupSession() {
|
function OutboundGroupSession() {
|
||||||
var size = Module['_olm_outbound_group_session_size']();
|
var size = Module['_olm_outbound_group_session_size']();
|
||||||
this.buf = malloc(size);
|
this.buf = malloc(size);
|
||||||
|
@ -68,14 +67,9 @@ OutboundGroupSession.prototype['create'] = restore_stack(function() {
|
||||||
Module['_olm_init_outbound_group_session_random_length']
|
Module['_olm_init_outbound_group_session_random_length']
|
||||||
)(this.ptr);
|
)(this.ptr);
|
||||||
var random = random_stack(random_length);
|
var random = random_stack(random_length);
|
||||||
try {
|
outbound_group_session_method(Module['_olm_init_outbound_group_session'])(
|
||||||
outbound_group_session_method(Module['_olm_init_outbound_group_session'])(
|
this.ptr, random, random_length
|
||||||
this.ptr, random, random_length
|
);
|
||||||
);
|
|
||||||
} finally {
|
|
||||||
// clear the random buffer
|
|
||||||
bzero(random, random_length);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
OutboundGroupSession.prototype['encrypt'] = function(plaintext) {
|
OutboundGroupSession.prototype['encrypt'] = function(plaintext) {
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
/** @constructor */
|
|
||||||
function PkEncryption() {
|
function PkEncryption() {
|
||||||
var size = Module['_olm_pk_encryption_size']();
|
var size = Module['_olm_pk_encryption_size']();
|
||||||
this.buf = malloc(size);
|
this.buf = malloc(size);
|
||||||
|
@ -99,7 +98,6 @@ PkEncryption.prototype['encrypt'] = restore_stack(function(
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
/** @constructor */
|
|
||||||
function PkDecryption() {
|
function PkDecryption() {
|
||||||
var size = Module['_olm_pk_decryption_size']();
|
var size = Module['_olm_pk_decryption_size']();
|
||||||
this.buf = malloc(size);
|
this.buf = malloc(size);
|
||||||
|
@ -275,7 +273,6 @@ PkDecryption.prototype['decrypt'] = restore_stack(function (
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
/** @constructor */
|
|
||||||
function PkSigning() {
|
function PkSigning() {
|
||||||
var size = Module['_olm_pk_signing_size']();
|
var size = Module['_olm_pk_signing_size']();
|
||||||
this.buf = malloc(size);
|
this.buf = malloc(size);
|
||||||
|
|
|
@ -44,7 +44,6 @@ function bzero(ptr, n) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @constructor */
|
|
||||||
function Account() {
|
function Account() {
|
||||||
var size = Module['_olm_account_size']();
|
var size = Module['_olm_account_size']();
|
||||||
this.buf = malloc(size);
|
this.buf = malloc(size);
|
||||||
|
@ -74,14 +73,9 @@ Account.prototype['create'] = restore_stack(function() {
|
||||||
Module['_olm_create_account_random_length']
|
Module['_olm_create_account_random_length']
|
||||||
)(this.ptr);
|
)(this.ptr);
|
||||||
var random = random_stack(random_length);
|
var random = random_stack(random_length);
|
||||||
try {
|
account_method(Module['_olm_create_account'])(
|
||||||
account_method(Module['_olm_create_account'])(
|
this.ptr, random, random_length
|
||||||
this.ptr, random, random_length
|
);
|
||||||
);
|
|
||||||
} finally {
|
|
||||||
// clear the random buffer
|
|
||||||
bzero(random, random_length);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Account.prototype['identity_keys'] = restore_stack(function() {
|
Account.prototype['identity_keys'] = restore_stack(function() {
|
||||||
|
@ -146,14 +140,9 @@ Account.prototype['generate_one_time_keys'] = restore_stack(function(
|
||||||
Module['_olm_account_generate_one_time_keys_random_length']
|
Module['_olm_account_generate_one_time_keys_random_length']
|
||||||
)(this.ptr, number_of_keys);
|
)(this.ptr, number_of_keys);
|
||||||
var random = random_stack(random_length);
|
var random = random_stack(random_length);
|
||||||
try {
|
account_method(Module['_olm_account_generate_one_time_keys'])(
|
||||||
account_method(Module['_olm_account_generate_one_time_keys'])(
|
this.ptr, number_of_keys, random, random_length
|
||||||
this.ptr, number_of_keys, random, random_length
|
);
|
||||||
);
|
|
||||||
} finally {
|
|
||||||
// clear the random buffer
|
|
||||||
bzero(random, random_length);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Account.prototype['remove_one_time_keys'] = restore_stack(function(session) {
|
Account.prototype['remove_one_time_keys'] = restore_stack(function(session) {
|
||||||
|
@ -167,14 +156,20 @@ Account.prototype['generate_fallback_key'] = restore_stack(function() {
|
||||||
Module['_olm_account_generate_fallback_key_random_length']
|
Module['_olm_account_generate_fallback_key_random_length']
|
||||||
)(this.ptr);
|
)(this.ptr);
|
||||||
var random = random_stack(random_length);
|
var random = random_stack(random_length);
|
||||||
try {
|
account_method(Module['_olm_account_generate_fallback_key'])(
|
||||||
account_method(Module['_olm_account_generate_fallback_key'])(
|
this.ptr, random, random_length
|
||||||
this.ptr, random, random_length
|
);
|
||||||
);
|
});
|
||||||
} finally {
|
|
||||||
// clear the random buffer
|
Account.prototype['fallback_key'] = restore_stack(function() {
|
||||||
bzero(random, random_length);
|
var keys_length = account_method(
|
||||||
}
|
Module['_olm_account_fallback_key_length']
|
||||||
|
)(this.ptr);
|
||||||
|
var keys = stack(keys_length + NULL_BYTE_PADDING_LENGTH);
|
||||||
|
account_method(Module['_olm_account_fallback_key'])(
|
||||||
|
this.ptr, keys, keys_length
|
||||||
|
);
|
||||||
|
return UTF8ToString(keys, keys_length);
|
||||||
});
|
});
|
||||||
|
|
||||||
Account.prototype['fallback_key'] = restore_stack(function() {
|
Account.prototype['fallback_key'] = restore_stack(function() {
|
||||||
|
@ -199,7 +194,7 @@ Account.prototype['unpublished_fallback_key'] = restore_stack(function() {
|
||||||
return UTF8ToString(keys, keys_length);
|
return UTF8ToString(keys, keys_length);
|
||||||
});
|
});
|
||||||
|
|
||||||
Account.prototype['forget_old_fallback_key'] = restore_stack(function() {
|
Account.prototype['forget_old_fallback'] = restore_stack(function() {
|
||||||
account_method(Module['_olm_account_forget_old_fallback_key'])(
|
account_method(Module['_olm_account_forget_old_fallback_key'])(
|
||||||
this.ptr
|
this.ptr
|
||||||
);
|
);
|
||||||
|
@ -245,7 +240,6 @@ Account.prototype['unpickle'] = restore_stack(function(key, pickle) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/** @constructor */
|
|
||||||
function Session() {
|
function Session() {
|
||||||
var size = Module['_olm_session_size']();
|
var size = Module['_olm_session_size']();
|
||||||
this.buf = malloc(size);
|
this.buf = malloc(size);
|
||||||
|
@ -532,7 +526,6 @@ Session.prototype['describe'] = restore_stack(function() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/** @constructor */
|
|
||||||
function Utility() {
|
function Utility() {
|
||||||
var size = Module['_olm_utility_size']();
|
var size = Module['_olm_utility_size']();
|
||||||
this.buf = malloc(size);
|
this.buf = malloc(size);
|
||||||
|
|
|
@ -14,6 +14,7 @@ if (typeof(window) !== 'undefined') {
|
||||||
var bytes = nodeCrypto['randomBytes'](buf.length);
|
var bytes = nodeCrypto['randomBytes'](buf.length);
|
||||||
buf.set(bytes);
|
buf.set(bytes);
|
||||||
};
|
};
|
||||||
|
process = global["process"];
|
||||||
} else {
|
} else {
|
||||||
throw new Error("Cannot find global to attach library to");
|
throw new Error("Cannot find global to attach library to");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
/** @constructor */
|
|
||||||
function SAS() {
|
function SAS() {
|
||||||
var size = Module['_olm_sas_size']();
|
var size = Module['_olm_sas_size']();
|
||||||
var random_length = Module['_olm_create_sas_random_length']();
|
var random_length = Module['_olm_create_sas_random_length']();
|
||||||
|
@ -83,22 +82,6 @@ SAS.prototype['calculate_mac'] = restore_stack(function(input, info) {
|
||||||
return UTF8ToString(mac_buffer, mac_length);
|
return UTF8ToString(mac_buffer, mac_length);
|
||||||
});
|
});
|
||||||
|
|
||||||
SAS.prototype['calculate_mac_fixed_base64'] = restore_stack(function(input, info) {
|
|
||||||
var input_array = array_from_string(input);
|
|
||||||
var input_buffer = stack(input_array);
|
|
||||||
var info_array = array_from_string(info);
|
|
||||||
var info_buffer = stack(info_array);
|
|
||||||
var mac_length = sas_method(Module['_olm_sas_mac_length'])(this.ptr);
|
|
||||||
var mac_buffer = stack(mac_length + NULL_BYTE_PADDING_LENGTH);
|
|
||||||
sas_method(Module['_olm_sas_calculate_mac_fixed_base64'])(
|
|
||||||
this.ptr,
|
|
||||||
input_buffer, input_array.length,
|
|
||||||
info_buffer, info_array.length,
|
|
||||||
mac_buffer, mac_length
|
|
||||||
);
|
|
||||||
return UTF8ToString(mac_buffer, mac_length);
|
|
||||||
});
|
|
||||||
|
|
||||||
SAS.prototype['calculate_mac_long_kdf'] = restore_stack(function(input, info) {
|
SAS.prototype['calculate_mac_long_kdf'] = restore_stack(function(input, info) {
|
||||||
var input_array = array_from_string(input);
|
var input_array = array_from_string(input);
|
||||||
var input_buffer = stack(input_array);
|
var input_buffer = stack(input_array);
|
||||||
|
|
241
javascript/package-lock.json
generated
241
javascript/package-lock.json
generated
|
@ -1,241 +0,0 @@
|
||||||
{
|
|
||||||
"name": "@matrix-org/olm",
|
|
||||||
"version": "3.2.11",
|
|
||||||
"lockfileVersion": 2,
|
|
||||||
"requires": true,
|
|
||||||
"packages": {
|
|
||||||
"": {
|
|
||||||
"name": "@matrix-org/olm",
|
|
||||||
"version": "3.2.11",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"devDependencies": {
|
|
||||||
"jasmine": "^3.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/balanced-match": {
|
|
||||||
"version": "1.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
|
||||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/brace-expansion": {
|
|
||||||
"version": "1.1.11",
|
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
|
||||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"balanced-match": "^1.0.0",
|
|
||||||
"concat-map": "0.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/concat-map": {
|
|
||||||
"version": "0.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
|
||||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/fs.realpath": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
|
||||||
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/glob": {
|
|
||||||
"version": "7.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
|
|
||||||
"integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"fs.realpath": "^1.0.0",
|
|
||||||
"inflight": "^1.0.4",
|
|
||||||
"inherits": "2",
|
|
||||||
"minimatch": "^3.0.4",
|
|
||||||
"once": "^1.3.0",
|
|
||||||
"path-is-absolute": "^1.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "*"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/isaacs"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/inflight": {
|
|
||||||
"version": "1.0.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
|
||||||
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"once": "^1.3.0",
|
|
||||||
"wrappy": "1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/inherits": {
|
|
||||||
"version": "2.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
|
||||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/jasmine": {
|
|
||||||
"version": "3.99.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/jasmine/-/jasmine-3.99.0.tgz",
|
|
||||||
"integrity": "sha512-YIThBuHzaIIcjxeuLmPD40SjxkEcc8i//sGMDKCgkRMVgIwRJf5qyExtlJpQeh7pkeoBSOe6lQEdg+/9uKg9mw==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"glob": "^7.1.6",
|
|
||||||
"jasmine-core": "~3.99.0"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"jasmine": "bin/jasmine.js"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/jasmine-core": {
|
|
||||||
"version": "3.99.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.99.1.tgz",
|
|
||||||
"integrity": "sha512-Hu1dmuoGcZ7AfyynN3LsfruwMbxMALMka+YtZeGoLuDEySVmVAPaonkNoBRIw/ectu8b9tVQCJNgp4a4knp+tg==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"node_modules/minimatch": {
|
|
||||||
"version": "3.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
|
||||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"brace-expansion": "^1.1.7"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "*"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/once": {
|
|
||||||
"version": "1.4.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
|
||||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
|
||||||
"wrappy": "1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/path-is-absolute": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
|
||||||
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
|
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.10.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/wrappy": {
|
|
||||||
"version": "1.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
|
||||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
|
|
||||||
"dev": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"balanced-match": {
|
|
||||||
"version": "1.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
|
||||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"brace-expansion": {
|
|
||||||
"version": "1.1.11",
|
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
|
||||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"balanced-match": "^1.0.0",
|
|
||||||
"concat-map": "0.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"concat-map": {
|
|
||||||
"version": "0.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
|
||||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"fs.realpath": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
|
||||||
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"glob": {
|
|
||||||
"version": "7.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
|
|
||||||
"integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"fs.realpath": "^1.0.0",
|
|
||||||
"inflight": "^1.0.4",
|
|
||||||
"inherits": "2",
|
|
||||||
"minimatch": "^3.0.4",
|
|
||||||
"once": "^1.3.0",
|
|
||||||
"path-is-absolute": "^1.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"inflight": {
|
|
||||||
"version": "1.0.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
|
||||||
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"once": "^1.3.0",
|
|
||||||
"wrappy": "1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"inherits": {
|
|
||||||
"version": "2.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
|
||||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"jasmine": {
|
|
||||||
"version": "3.99.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/jasmine/-/jasmine-3.99.0.tgz",
|
|
||||||
"integrity": "sha512-YIThBuHzaIIcjxeuLmPD40SjxkEcc8i//sGMDKCgkRMVgIwRJf5qyExtlJpQeh7pkeoBSOe6lQEdg+/9uKg9mw==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"glob": "^7.1.6",
|
|
||||||
"jasmine-core": "~3.99.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"jasmine-core": {
|
|
||||||
"version": "3.99.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.99.1.tgz",
|
|
||||||
"integrity": "sha512-Hu1dmuoGcZ7AfyynN3LsfruwMbxMALMka+YtZeGoLuDEySVmVAPaonkNoBRIw/ectu8b9tVQCJNgp4a4knp+tg==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"minimatch": {
|
|
||||||
"version": "3.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
|
||||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"brace-expansion": "^1.1.7"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"once": {
|
|
||||||
"version": "1.4.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
|
||||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"wrappy": "1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"path-is-absolute": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
|
||||||
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"wrappy": {
|
|
||||||
"version": "1.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
|
||||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
|
|
||||||
"dev": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@matrix-org/olm",
|
"name": "@matrix-org/olm",
|
||||||
"version": "3.2.16",
|
"version": "3.2.6",
|
||||||
"description": "An implementation of the Double Ratchet cryptographic ratchet",
|
"description": "An implementation of the Double Ratchet cryptographic ratchet",
|
||||||
"main": "olm.js",
|
"main": "olm.js",
|
||||||
"files": [
|
"files": [
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "make -C .. js",
|
"build": "make -C .. js",
|
||||||
"test": "jasmine --config=test/jasmine.json"
|
"test": "jasmine-node test --verbose --junitreport --captureExceptions"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
@ -30,6 +30,9 @@
|
||||||
},
|
},
|
||||||
"homepage": "https://gitlab.matrix.org/matrix-org/olm",
|
"homepage": "https://gitlab.matrix.org/matrix-org/olm",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"jasmine": "^3.0.0"
|
"jasmine-node": "^1.14.5"
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"@matrix-org:registry":"https://gitlab.matrix.org/api/v4/projects/27/packages/npm/"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
{
|
|
||||||
"spec_dir": "test",
|
|
||||||
"spec_files": [
|
|
||||||
"**/*.spec.js"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -19,7 +19,7 @@ var Olm = require('../olm');
|
||||||
describe("sas", function() {
|
describe("sas", function() {
|
||||||
var alice, bob;
|
var alice, bob;
|
||||||
|
|
||||||
beforeEach(function(done) {
|
beforeEach(async function(done) {
|
||||||
Olm.init().then(function() {
|
Olm.init().then(function() {
|
||||||
alice = new Olm.SAS();
|
alice = new Olm.SAS();
|
||||||
bob = new Olm.SAS();
|
bob = new Olm.SAS();
|
||||||
|
|
|
@ -1,123 +1,123 @@
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
* Filename: aes.h
|
* Filename: aes.h
|
||||||
* Author: Brad Conte (brad AT bradconte.com)
|
* Author: Brad Conte (brad AT bradconte.com)
|
||||||
* Copyright:
|
* Copyright:
|
||||||
* Disclaimer: This code is presented "as is" without any guarantees.
|
* Disclaimer: This code is presented "as is" without any guarantees.
|
||||||
* Details: Defines the API for the corresponding AES implementation.
|
* Details: Defines the API for the corresponding AES implementation.
|
||||||
*********************************************************************/
|
*********************************************************************/
|
||||||
|
|
||||||
#ifndef AES_H
|
#ifndef AES_H
|
||||||
#define AES_H
|
#define AES_H
|
||||||
|
|
||||||
/*************************** HEADER FILES ***************************/
|
/*************************** HEADER FILES ***************************/
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
|
||||||
/****************************** MACROS ******************************/
|
/****************************** MACROS ******************************/
|
||||||
#define AES_BLOCK_SIZE 16 // AES operates on 16 bytes at a time
|
#define AES_BLOCK_SIZE 16 // AES operates on 16 bytes at a time
|
||||||
|
|
||||||
/**************************** DATA TYPES ****************************/
|
/**************************** DATA TYPES ****************************/
|
||||||
typedef uint8_t BYTE; // 8-bit byte
|
typedef unsigned char BYTE; // 8-bit byte
|
||||||
typedef uint32_t WORD; // 32-bit word, change to "long" for 16-bit machines
|
typedef unsigned int WORD; // 32-bit word, change to "long" for 16-bit machines
|
||||||
|
|
||||||
/*********************** FUNCTION DECLARATIONS **********************/
|
/*********************** FUNCTION DECLARATIONS **********************/
|
||||||
///////////////////
|
///////////////////
|
||||||
// AES
|
// AES
|
||||||
///////////////////
|
///////////////////
|
||||||
// Key setup must be done before any AES en/de-cryption functions can be used.
|
// Key setup must be done before any AES en/de-cryption functions can be used.
|
||||||
void aes_key_setup(const BYTE key[], // The key, must be 128, 192, or 256 bits
|
void aes_key_setup(const BYTE key[], // The key, must be 128, 192, or 256 bits
|
||||||
WORD w[], // Output key schedule to be used later
|
WORD w[], // Output key schedule to be used later
|
||||||
int keysize); // Bit length of the key, 128, 192, or 256
|
int keysize); // Bit length of the key, 128, 192, or 256
|
||||||
|
|
||||||
void aes_encrypt(const BYTE in[], // 16 bytes of plaintext
|
void aes_encrypt(const BYTE in[], // 16 bytes of plaintext
|
||||||
BYTE out[], // 16 bytes of ciphertext
|
BYTE out[], // 16 bytes of ciphertext
|
||||||
const WORD key[], // From the key setup
|
const WORD key[], // From the key setup
|
||||||
int keysize); // Bit length of the key, 128, 192, or 256
|
int keysize); // Bit length of the key, 128, 192, or 256
|
||||||
|
|
||||||
void aes_decrypt(const BYTE in[], // 16 bytes of ciphertext
|
void aes_decrypt(const BYTE in[], // 16 bytes of ciphertext
|
||||||
BYTE out[], // 16 bytes of plaintext
|
BYTE out[], // 16 bytes of plaintext
|
||||||
const WORD key[], // From the key setup
|
const WORD key[], // From the key setup
|
||||||
int keysize); // Bit length of the key, 128, 192, or 256
|
int keysize); // Bit length of the key, 128, 192, or 256
|
||||||
|
|
||||||
///////////////////
|
///////////////////
|
||||||
// AES - CBC
|
// AES - CBC
|
||||||
///////////////////
|
///////////////////
|
||||||
int aes_encrypt_cbc(const BYTE in[], // Plaintext
|
int aes_encrypt_cbc(const BYTE in[], // Plaintext
|
||||||
size_t in_len, // Must be a multiple of AES_BLOCK_SIZE
|
size_t in_len, // Must be a multiple of AES_BLOCK_SIZE
|
||||||
BYTE out[], // Ciphertext, same length as plaintext
|
BYTE out[], // Ciphertext, same length as plaintext
|
||||||
const WORD key[], // From the key setup
|
const WORD key[], // From the key setup
|
||||||
int keysize, // Bit length of the key, 128, 192, or 256
|
int keysize, // Bit length of the key, 128, 192, or 256
|
||||||
const BYTE iv[]); // IV, must be AES_BLOCK_SIZE bytes long
|
const BYTE iv[]); // IV, must be AES_BLOCK_SIZE bytes long
|
||||||
|
|
||||||
// Only output the CBC-MAC of the input.
|
// Only output the CBC-MAC of the input.
|
||||||
int aes_encrypt_cbc_mac(const BYTE in[], // plaintext
|
int aes_encrypt_cbc_mac(const BYTE in[], // plaintext
|
||||||
size_t in_len, // Must be a multiple of AES_BLOCK_SIZE
|
size_t in_len, // Must be a multiple of AES_BLOCK_SIZE
|
||||||
BYTE out[], // Output MAC
|
BYTE out[], // Output MAC
|
||||||
const WORD key[], // From the key setup
|
const WORD key[], // From the key setup
|
||||||
int keysize, // Bit length of the key, 128, 192, or 256
|
int keysize, // Bit length of the key, 128, 192, or 256
|
||||||
const BYTE iv[]); // IV, must be AES_BLOCK_SIZE bytes long
|
const BYTE iv[]); // IV, must be AES_BLOCK_SIZE bytes long
|
||||||
|
|
||||||
///////////////////
|
///////////////////
|
||||||
// AES - CTR
|
// AES - CTR
|
||||||
///////////////////
|
///////////////////
|
||||||
void increment_iv(BYTE iv[], // Must be a multiple of AES_BLOCK_SIZE
|
void increment_iv(BYTE iv[], // Must be a multiple of AES_BLOCK_SIZE
|
||||||
int counter_size); // Bytes of the IV used for counting (low end)
|
int counter_size); // Bytes of the IV used for counting (low end)
|
||||||
|
|
||||||
void aes_encrypt_ctr(const BYTE in[], // Plaintext
|
void aes_encrypt_ctr(const BYTE in[], // Plaintext
|
||||||
size_t in_len, // Any byte length
|
size_t in_len, // Any byte length
|
||||||
BYTE out[], // Ciphertext, same length as plaintext
|
BYTE out[], // Ciphertext, same length as plaintext
|
||||||
const WORD key[], // From the key setup
|
const WORD key[], // From the key setup
|
||||||
int keysize, // Bit length of the key, 128, 192, or 256
|
int keysize, // Bit length of the key, 128, 192, or 256
|
||||||
const BYTE iv[]); // IV, must be AES_BLOCK_SIZE bytes long
|
const BYTE iv[]); // IV, must be AES_BLOCK_SIZE bytes long
|
||||||
|
|
||||||
void aes_decrypt_ctr(const BYTE in[], // Ciphertext
|
void aes_decrypt_ctr(const BYTE in[], // Ciphertext
|
||||||
size_t in_len, // Any byte length
|
size_t in_len, // Any byte length
|
||||||
BYTE out[], // Plaintext, same length as ciphertext
|
BYTE out[], // Plaintext, same length as ciphertext
|
||||||
const WORD key[], // From the key setup
|
const WORD key[], // From the key setup
|
||||||
int keysize, // Bit length of the key, 128, 192, or 256
|
int keysize, // Bit length of the key, 128, 192, or 256
|
||||||
const BYTE iv[]); // IV, must be AES_BLOCK_SIZE bytes long
|
const BYTE iv[]); // IV, must be AES_BLOCK_SIZE bytes long
|
||||||
|
|
||||||
///////////////////
|
///////////////////
|
||||||
// AES - CCM
|
// AES - CCM
|
||||||
///////////////////
|
///////////////////
|
||||||
// Returns True if the input parameters do not violate any constraint.
|
// Returns True if the input parameters do not violate any constraint.
|
||||||
int aes_encrypt_ccm(const BYTE plaintext[], // IN - Plaintext.
|
int aes_encrypt_ccm(const BYTE plaintext[], // IN - Plaintext.
|
||||||
WORD plaintext_len, // IN - Plaintext length.
|
WORD plaintext_len, // IN - Plaintext length.
|
||||||
const BYTE associated_data[], // IN - Associated Data included in authentication, but not encryption.
|
const BYTE associated_data[], // IN - Associated Data included in authentication, but not encryption.
|
||||||
unsigned short associated_data_len, // IN - Associated Data length in bytes.
|
unsigned short associated_data_len, // IN - Associated Data length in bytes.
|
||||||
const BYTE nonce[], // IN - The Nonce to be used for encryption.
|
const BYTE nonce[], // IN - The Nonce to be used for encryption.
|
||||||
unsigned short nonce_len, // IN - Nonce length in bytes.
|
unsigned short nonce_len, // IN - Nonce length in bytes.
|
||||||
BYTE ciphertext[], // OUT - Ciphertext, a concatination of the plaintext and the MAC.
|
BYTE ciphertext[], // OUT - Ciphertext, a concatination of the plaintext and the MAC.
|
||||||
WORD *ciphertext_len, // OUT - The length of the ciphertext, always plaintext_len + mac_len.
|
WORD *ciphertext_len, // OUT - The length of the ciphertext, always plaintext_len + mac_len.
|
||||||
WORD mac_len, // IN - The desired length of the MAC, must be 4, 6, 8, 10, 12, 14, or 16.
|
WORD mac_len, // IN - The desired length of the MAC, must be 4, 6, 8, 10, 12, 14, or 16.
|
||||||
const BYTE key[], // IN - The AES key for encryption.
|
const BYTE key[], // IN - The AES key for encryption.
|
||||||
int keysize); // IN - The length of the key in bits. Valid values are 128, 192, 256.
|
int keysize); // IN - The length of the key in bits. Valid values are 128, 192, 256.
|
||||||
|
|
||||||
// Returns True if the input parameters do not violate any constraint.
|
// Returns True if the input parameters do not violate any constraint.
|
||||||
// Use mac_auth to ensure decryption/validation was preformed correctly.
|
// Use mac_auth to ensure decryption/validation was preformed correctly.
|
||||||
// If authentication does not succeed, the plaintext is zeroed out. To overwride
|
// If authentication does not succeed, the plaintext is zeroed out. To overwride
|
||||||
// this, call with mac_auth = NULL. The proper proceedure is to decrypt with
|
// this, call with mac_auth = NULL. The proper proceedure is to decrypt with
|
||||||
// authentication enabled (mac_auth != NULL) and make a second call to that
|
// authentication enabled (mac_auth != NULL) and make a second call to that
|
||||||
// ignores authentication explicitly if the first call failes.
|
// ignores authentication explicitly if the first call failes.
|
||||||
int aes_decrypt_ccm(const BYTE ciphertext[], // IN - Ciphertext, the concatination of encrypted plaintext and MAC.
|
int aes_decrypt_ccm(const BYTE ciphertext[], // IN - Ciphertext, the concatination of encrypted plaintext and MAC.
|
||||||
WORD ciphertext_len, // IN - Ciphertext length in bytes.
|
WORD ciphertext_len, // IN - Ciphertext length in bytes.
|
||||||
const BYTE assoc[], // IN - The Associated Data, required for authentication.
|
const BYTE assoc[], // IN - The Associated Data, required for authentication.
|
||||||
unsigned short assoc_len, // IN - Associated Data length in bytes.
|
unsigned short assoc_len, // IN - Associated Data length in bytes.
|
||||||
const BYTE nonce[], // IN - The Nonce to use for decryption, same one as for encryption.
|
const BYTE nonce[], // IN - The Nonce to use for decryption, same one as for encryption.
|
||||||
unsigned short nonce_len, // IN - Nonce length in bytes.
|
unsigned short nonce_len, // IN - Nonce length in bytes.
|
||||||
BYTE plaintext[], // OUT - The plaintext that was decrypted. Will need to be large enough to hold ciphertext_len - mac_len.
|
BYTE plaintext[], // OUT - The plaintext that was decrypted. Will need to be large enough to hold ciphertext_len - mac_len.
|
||||||
WORD *plaintext_len, // OUT - Length in bytes of the output plaintext, always ciphertext_len - mac_len .
|
WORD *plaintext_len, // OUT - Length in bytes of the output plaintext, always ciphertext_len - mac_len .
|
||||||
WORD mac_len, // IN - The length of the MAC that was calculated.
|
WORD mac_len, // IN - The length of the MAC that was calculated.
|
||||||
int *mac_auth, // OUT - TRUE if authentication succeeded, FALSE if it did not. NULL pointer will ignore the authentication.
|
int *mac_auth, // OUT - TRUE if authentication succeeded, FALSE if it did not. NULL pointer will ignore the authentication.
|
||||||
const BYTE key[], // IN - The AES key for decryption.
|
const BYTE key[], // IN - The AES key for decryption.
|
||||||
int keysize); // IN - The length of the key in BITS. Valid values are 128, 192, 256.
|
int keysize); // IN - The length of the key in BITS. Valid values are 128, 192, 256.
|
||||||
|
|
||||||
///////////////////
|
///////////////////
|
||||||
// Test functions
|
// Test functions
|
||||||
///////////////////
|
///////////////////
|
||||||
int aes_test();
|
int aes_test();
|
||||||
int aes_ecb_test();
|
int aes_ecb_test();
|
||||||
int aes_cbc_test();
|
int aes_cbc_test();
|
||||||
int aes_ctr_test();
|
int aes_ctr_test();
|
||||||
int aes_ccm_test();
|
int aes_ccm_test();
|
||||||
|
|
||||||
#endif // AES_H
|
#endif // AES_H
|
||||||
|
|
|
@ -11,14 +11,13 @@
|
||||||
|
|
||||||
/*************************** HEADER FILES ***************************/
|
/*************************** HEADER FILES ***************************/
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
/****************************** MACROS ******************************/
|
/****************************** MACROS ******************************/
|
||||||
#define SHA256_BLOCK_SIZE 32 // SHA256 outputs a 32 byte digest
|
#define SHA256_BLOCK_SIZE 32 // SHA256 outputs a 32 byte digest
|
||||||
|
|
||||||
/**************************** DATA TYPES ****************************/
|
/**************************** DATA TYPES ****************************/
|
||||||
typedef uint8_t BYTE; // 8-bit byte
|
typedef unsigned char BYTE; // 8-bit byte
|
||||||
typedef uint32_t WORD; // 32-bit word, change to "long" for 16-bit machines
|
typedef unsigned int WORD; // 32-bit word, change to "long" for 16-bit machines
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
BYTE data[64];
|
BYTE data[64];
|
||||||
|
|
|
@ -1,82 +0,0 @@
|
||||||
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
|
|
||||||
|
|
||||||
DisableFormat: false
|
|
||||||
Language: Cpp
|
|
||||||
Standard: Cpp11
|
|
||||||
IndentWidth: 4
|
|
||||||
TabWidth: 4
|
|
||||||
UseTab: Never
|
|
||||||
ColumnLimit: 100
|
|
||||||
ReflowComments: false
|
|
||||||
SortIncludes: false
|
|
||||||
|
|
||||||
AlignConsecutiveAssignments: true
|
|
||||||
AlignConsecutiveDeclarations: true
|
|
||||||
AlignEscapedNewlinesLeft: false
|
|
||||||
AlignOperands: true
|
|
||||||
AlignTrailingComments: true
|
|
||||||
AlignAfterOpenBracket: true
|
|
||||||
DerivePointerAlignment: false
|
|
||||||
PointerAlignment: Left
|
|
||||||
IndentCaseLabels: true
|
|
||||||
ContinuationIndentWidth: 8
|
|
||||||
NamespaceIndentation: Inner
|
|
||||||
CompactNamespaces: true
|
|
||||||
FixNamespaceComments: true
|
|
||||||
AccessModifierOffset: -4
|
|
||||||
|
|
||||||
SpaceAfterControlStatementKeyword: false
|
|
||||||
SpaceAfterCStyleCast: false
|
|
||||||
SpaceBeforeAssignmentOperators: true
|
|
||||||
SpaceBeforeParens: Never
|
|
||||||
SpaceInEmptyParentheses: false
|
|
||||||
SpacesBeforeTrailingComments: 1
|
|
||||||
SpacesInAngles: false
|
|
||||||
SpacesInCStyleCastParentheses: false
|
|
||||||
SpacesInContainerLiterals: false
|
|
||||||
SpacesInParentheses: false
|
|
||||||
SpacesInSquareBrackets: false
|
|
||||||
Cpp11BracedListStyle: true
|
|
||||||
|
|
||||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
|
||||||
MaxEmptyLinesToKeep: 1
|
|
||||||
BinPackArguments: true
|
|
||||||
BinPackParameters: true
|
|
||||||
AlwaysBreakAfterReturnType: None
|
|
||||||
AlwaysBreakAfterDefinitionReturnType: None
|
|
||||||
AlwaysBreakTemplateDeclarations: true
|
|
||||||
BreakConstructorInitializersBeforeComma: true
|
|
||||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
|
||||||
ConstructorInitializerIndentWidth: 8
|
|
||||||
|
|
||||||
AllowShortIfStatementsOnASingleLine: false
|
|
||||||
AllowShortLoopsOnASingleLine: false
|
|
||||||
AllowShortBlocksOnASingleLine: true
|
|
||||||
AllowShortCaseLabelsOnASingleLine: true
|
|
||||||
AllowAllParametersOfDeclarationOnNextLine: true
|
|
||||||
AllowShortFunctionsOnASingleLine: All
|
|
||||||
|
|
||||||
BreakBeforeBinaryOperators: false
|
|
||||||
BreakBeforeTernaryOperators: false
|
|
||||||
BreakStringLiterals: true
|
|
||||||
BreakBeforeBraces: Custom
|
|
||||||
BraceWrapping:
|
|
||||||
AfterClass: true
|
|
||||||
AfterEnum: true
|
|
||||||
AfterNamespace: false
|
|
||||||
AfterStruct: true
|
|
||||||
AfterUnion: true
|
|
||||||
|
|
||||||
BeforeCatch: false
|
|
||||||
BeforeElse: false
|
|
||||||
IndentBraces: false
|
|
||||||
AfterFunction: false
|
|
||||||
AfterControlStatement: false
|
|
||||||
|
|
||||||
# penalties not thought of yet
|
|
||||||
PenaltyBreakBeforeFirstCallParameter: 19
|
|
||||||
PenaltyBreakComment: 60
|
|
||||||
PenaltyBreakString: 1000
|
|
||||||
PenaltyBreakFirstLessLess: 120
|
|
||||||
PenaltyExcessCharacter: 1000000
|
|
||||||
PenaltyReturnTypeOnItsOwnLine: 1000
|
|
|
@ -1,12 +0,0 @@
|
||||||
root = true
|
|
||||||
|
|
||||||
[*]
|
|
||||||
charset = utf-8
|
|
||||||
trim_trailing_whitespace = true
|
|
||||||
end_of_line = lf
|
|
||||||
indent_style = space
|
|
||||||
indent_size = 4
|
|
||||||
insert_final_newline = true
|
|
||||||
|
|
||||||
[*.yml]
|
|
||||||
indent_size = 2
|
|
1
lib/doctest/.gitattributes
vendored
1
lib/doctest/.gitattributes
vendored
|
@ -1 +0,0 @@
|
||||||
* text=auto
|
|
4
lib/doctest/.github/FUNDING.yml
vendored
4
lib/doctest/.github/FUNDING.yml
vendored
|
@ -1,4 +0,0 @@
|
||||||
github: onqtam
|
|
||||||
patreon: onqtam
|
|
||||||
custom: https://www.paypal.me/onqtam/10
|
|
||||||
|
|
29
lib/doctest/.github/issue_template.md
vendored
29
lib/doctest/.github/issue_template.md
vendored
|
@ -1,29 +0,0 @@
|
||||||
## Description
|
|
||||||
<!--
|
|
||||||
If your issue is a bugreport, this means describing what you did,
|
|
||||||
what did you want to happen and what actually did happen.
|
|
||||||
|
|
||||||
If your issue is a feature request, describe the feature and why do you
|
|
||||||
want it.
|
|
||||||
-->
|
|
||||||
|
|
||||||
|
|
||||||
### Steps to reproduce
|
|
||||||
<!--
|
|
||||||
This is only relevant for bug reports, but if you do have one,
|
|
||||||
please provide a minimal set of steps to reproduce the problem.
|
|
||||||
|
|
||||||
Usually this means providing a small and self-contained code using doctest
|
|
||||||
and specifying compiler flags/tools used if relevant.
|
|
||||||
-->
|
|
||||||
|
|
||||||
|
|
||||||
### Extra information
|
|
||||||
<!--
|
|
||||||
Fill in any extra information that might be important for your issue.
|
|
||||||
|
|
||||||
If your issue is a bugreport, definitely fill out at least the following.
|
|
||||||
-->
|
|
||||||
* doctest version: **v42.42.42**
|
|
||||||
* Operating System: **Joe's discount operating system**
|
|
||||||
* Compiler+version: **Hidden Dragon v1.2.3**
|
|
26
lib/doctest/.github/pull_request_template.md
vendored
26
lib/doctest/.github/pull_request_template.md
vendored
|
@ -1,26 +0,0 @@
|
||||||
<!--
|
|
||||||
Make sure the PR is against the dev branch and not master which contains
|
|
||||||
the latest stable release. Also make sure to have read CONTRIBUTING.md.
|
|
||||||
Please do not submit pull requests changing the single-include `doctest.h`
|
|
||||||
file, it is generated from the 2 files in the doctest/parts/ folder.
|
|
||||||
-->
|
|
||||||
|
|
||||||
|
|
||||||
## Description
|
|
||||||
<!--
|
|
||||||
Describe the what and the why of your pull request. Remember that these two
|
|
||||||
are usually a bit different. As an example, if you have made various changes
|
|
||||||
to decrease the number of new strings allocated, that's what. The why probably
|
|
||||||
was that you have a large set of tests and found that this speeds them up.
|
|
||||||
-->
|
|
||||||
|
|
||||||
## GitHub Issues
|
|
||||||
<!--
|
|
||||||
If this PR was motivated by some existing issues, reference them here.
|
|
||||||
|
|
||||||
If it is a simple bug-fix, please also add a line like 'Closes #123'
|
|
||||||
to your commit message, so that it is automatically closed.
|
|
||||||
If it is not, don't, as it might take several iterations for a feature
|
|
||||||
to be done properly. If in doubt, leave it open and reference it in the
|
|
||||||
PR itself, so that maintainers can decide.
|
|
||||||
-->
|
|
|
@ -1,67 +0,0 @@
|
||||||
# For most projects, this workflow file will not need changing; you simply need
|
|
||||||
# to commit it to your repository.
|
|
||||||
#
|
|
||||||
# You may wish to alter this file to override the set of languages analyzed,
|
|
||||||
# or to provide custom queries or build logic.
|
|
||||||
#
|
|
||||||
# ******** NOTE ********
|
|
||||||
# We have attempted to detect the languages in your repository. Please check
|
|
||||||
# the `language` matrix defined below to confirm you have the correct set of
|
|
||||||
# supported CodeQL languages.
|
|
||||||
#
|
|
||||||
name: "CodeQL"
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ master ]
|
|
||||||
pull_request:
|
|
||||||
# The branches below must be a subset of the branches above
|
|
||||||
branches: [ master ]
|
|
||||||
schedule:
|
|
||||||
- cron: '38 1 * * *'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
analyze:
|
|
||||||
name: Analyze
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
language: [ 'cpp' ]
|
|
||||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
|
|
||||||
# Learn more:
|
|
||||||
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
|
||||||
- name: Initialize CodeQL
|
|
||||||
uses: github/codeql-action/init@v1
|
|
||||||
with:
|
|
||||||
languages: ${{ matrix.language }}
|
|
||||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
|
||||||
# By default, queries listed here will override any specified in a config file.
|
|
||||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
|
||||||
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
|
||||||
|
|
||||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
|
||||||
# If this step fails, then you should remove it and run the build manually (see below)
|
|
||||||
- name: Autobuild
|
|
||||||
uses: github/codeql-action/autobuild@v1
|
|
||||||
|
|
||||||
# ℹ️ Command-line programs to run using the OS shell.
|
|
||||||
# 📚 https://git.io/JvXDl
|
|
||||||
|
|
||||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
|
||||||
# and modify them (or add more) to build your code if your project
|
|
||||||
# uses a compiled language
|
|
||||||
|
|
||||||
#- run: |
|
|
||||||
# make bootstrap
|
|
||||||
# make release
|
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
|
||||||
uses: github/codeql-action/analyze@v1
|
|
490
lib/doctest/.github/workflows/main.yml
vendored
490
lib/doctest/.github/workflows/main.yml
vendored
|
@ -1,490 +0,0 @@
|
||||||
name: CI
|
|
||||||
|
|
||||||
on: [push, pull_request]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
ci:
|
|
||||||
name: ${{ matrix.name }}
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
|
|
||||||
env:
|
|
||||||
CMAKE_GENERATOR: Ninja
|
|
||||||
ASAN_OPTIONS: strict_string_checks=true:detect_odr_violation=2:detect_stack_use_after_return=true:check_initialization_order=true:strict_init_order=true
|
|
||||||
TSAN_OPTIONS: force_seq_cst_atomics=1
|
|
||||||
CTEST_OUTPUT_ON_FAILURE: ON
|
|
||||||
CTEST_PARALLEL_LEVEL: 2
|
|
||||||
ACTIONS_ALLOW_UNSECURE_COMMANDS: true # because of the set-env calls
|
|
||||||
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
# Github Actions requires a single row to be added to the build matrix.
|
|
||||||
# See https://help.github.com/en/articles/workflow-syntax-for-github-actions.
|
|
||||||
name: [
|
|
||||||
ubuntu-18.04-gcc-4.8,
|
|
||||||
ubuntu-18.04-gcc-4.9,
|
|
||||||
ubuntu-18.04-gcc-5,
|
|
||||||
ubuntu-18.04-gcc-6,
|
|
||||||
ubuntu-18.04-gcc-7,
|
|
||||||
ubuntu-18.04-gcc-8,
|
|
||||||
ubuntu-18.04-gcc-9,
|
|
||||||
ubuntu-latest-gcc-10,
|
|
||||||
ubuntu-18.04-clang-3.5,
|
|
||||||
ubuntu-18.04-clang-3.6,
|
|
||||||
ubuntu-18.04-clang-3.7,
|
|
||||||
ubuntu-18.04-clang-3.8,
|
|
||||||
ubuntu-18.04-clang-3.9,
|
|
||||||
ubuntu-18.04-clang-4.0,
|
|
||||||
ubuntu-18.04-clang-5.0,
|
|
||||||
ubuntu-18.04-clang-6.0,
|
|
||||||
ubuntu-18.04-clang-7,
|
|
||||||
ubuntu-18.04-clang-8,
|
|
||||||
# ubuntu-latest-clang-9,
|
|
||||||
ubuntu-latest-clang-10,
|
|
||||||
# ubuntu-latest-clang-11,
|
|
||||||
windows-2016-cl,
|
|
||||||
windows-2016-clang-cl,
|
|
||||||
windows-2016-clang,
|
|
||||||
# windows-2016-gcc,
|
|
||||||
windows-2019-cl,
|
|
||||||
windows-2019-clang-cl,
|
|
||||||
windows-2019-clang,
|
|
||||||
# windows-2019-gcc,
|
|
||||||
macOS-latest-xcode-11.3,
|
|
||||||
]
|
|
||||||
|
|
||||||
include:
|
|
||||||
- name: ubuntu-18.04-gcc-4.8
|
|
||||||
os: ubuntu-18.04
|
|
||||||
compiler: gcc
|
|
||||||
version: "4.8"
|
|
||||||
|
|
||||||
- name: ubuntu-18.04-gcc-4.9
|
|
||||||
os: ubuntu-18.04
|
|
||||||
compiler: gcc
|
|
||||||
version: "4.9"
|
|
||||||
|
|
||||||
- name: ubuntu-18.04-gcc-5
|
|
||||||
os: ubuntu-18.04
|
|
||||||
compiler: gcc
|
|
||||||
version: "5"
|
|
||||||
|
|
||||||
- name: ubuntu-18.04-gcc-6
|
|
||||||
os: ubuntu-18.04
|
|
||||||
compiler: gcc
|
|
||||||
version: "6"
|
|
||||||
|
|
||||||
- name: ubuntu-18.04-gcc-7
|
|
||||||
os: ubuntu-18.04
|
|
||||||
compiler: gcc
|
|
||||||
version: "7"
|
|
||||||
|
|
||||||
- name: ubuntu-18.04-gcc-8
|
|
||||||
os: ubuntu-18.04
|
|
||||||
compiler: gcc
|
|
||||||
version: "8"
|
|
||||||
|
|
||||||
- name: ubuntu-18.04-gcc-9
|
|
||||||
os: ubuntu-18.04
|
|
||||||
compiler: gcc
|
|
||||||
version: "9"
|
|
||||||
|
|
||||||
- name: ubuntu-latest-gcc-10
|
|
||||||
os: ubuntu-latest
|
|
||||||
compiler: gcc
|
|
||||||
version: "10"
|
|
||||||
|
|
||||||
- name: ubuntu-18.04-clang-3.5
|
|
||||||
os: ubuntu-18.04
|
|
||||||
compiler: clang
|
|
||||||
version: "3.5"
|
|
||||||
|
|
||||||
- name: ubuntu-18.04-clang-3.6
|
|
||||||
os: ubuntu-18.04
|
|
||||||
compiler: clang
|
|
||||||
version: "3.6"
|
|
||||||
|
|
||||||
- name: ubuntu-18.04-clang-3.7
|
|
||||||
os: ubuntu-18.04
|
|
||||||
compiler: clang
|
|
||||||
version: "3.7"
|
|
||||||
|
|
||||||
- name: ubuntu-18.04-clang-3.8
|
|
||||||
os: ubuntu-18.04
|
|
||||||
compiler: clang
|
|
||||||
version: "3.8"
|
|
||||||
|
|
||||||
- name: ubuntu-18.04-clang-3.9
|
|
||||||
os: ubuntu-18.04
|
|
||||||
compiler: clang
|
|
||||||
version: "3.9"
|
|
||||||
|
|
||||||
- name: ubuntu-18.04-clang-4.0
|
|
||||||
os: ubuntu-18.04
|
|
||||||
compiler: clang
|
|
||||||
version: "4.0"
|
|
||||||
|
|
||||||
- name: ubuntu-18.04-clang-5.0
|
|
||||||
os: ubuntu-18.04
|
|
||||||
compiler: clang
|
|
||||||
version: "5.0"
|
|
||||||
|
|
||||||
- name: ubuntu-18.04-clang-6.0
|
|
||||||
os: ubuntu-18.04
|
|
||||||
compiler: clang
|
|
||||||
version: "6.0"
|
|
||||||
|
|
||||||
- name: ubuntu-18.04-clang-7
|
|
||||||
os: ubuntu-18.04
|
|
||||||
compiler: clang
|
|
||||||
version: "7"
|
|
||||||
|
|
||||||
- name: ubuntu-18.04-clang-8
|
|
||||||
os: ubuntu-18.04
|
|
||||||
compiler: clang
|
|
||||||
version: "8"
|
|
||||||
|
|
||||||
# fails like this: https://github.com/onqtam/doctest/runs/1562896476?check_suite_focus=true
|
|
||||||
# - name: ubuntu-latest-clang-9
|
|
||||||
# os: ubuntu-latest
|
|
||||||
# compiler: clang
|
|
||||||
# version: "9"
|
|
||||||
|
|
||||||
- name: ubuntu-latest-clang-10
|
|
||||||
os: ubuntu-latest
|
|
||||||
compiler: clang
|
|
||||||
version: "10"
|
|
||||||
|
|
||||||
# fails like this: https://github.com/onqtam/doctest/runs/1562896512?check_suite_focus=true
|
|
||||||
# - name: ubuntu-latest-clang-11
|
|
||||||
# os: ubuntu-latest
|
|
||||||
# compiler: clang
|
|
||||||
# version: "11"
|
|
||||||
|
|
||||||
- name: windows-2016-cl
|
|
||||||
os: windows-2016
|
|
||||||
compiler: cl
|
|
||||||
|
|
||||||
- name: windows-2016-clang-cl
|
|
||||||
os: windows-2016
|
|
||||||
compiler: clang-cl
|
|
||||||
|
|
||||||
- name: windows-2016-clang
|
|
||||||
os: windows-2016
|
|
||||||
compiler: clang
|
|
||||||
|
|
||||||
- name: windows-2019-cl
|
|
||||||
os: windows-2019
|
|
||||||
compiler: cl
|
|
||||||
|
|
||||||
# fails to install it...
|
|
||||||
# - name: windows-2016-gcc
|
|
||||||
# os: windows-2016
|
|
||||||
# compiler: gcc
|
|
||||||
|
|
||||||
- name: windows-2019-clang-cl
|
|
||||||
os: windows-2019
|
|
||||||
compiler: clang-cl
|
|
||||||
|
|
||||||
- name: windows-2019-clang
|
|
||||||
os: windows-2019
|
|
||||||
compiler: clang
|
|
||||||
|
|
||||||
# fails to install it...
|
|
||||||
# - name: windows-2019-gcc
|
|
||||||
# os: windows-2019
|
|
||||||
# compiler: gcc
|
|
||||||
|
|
||||||
- name: macOS-latest-xcode-11.3
|
|
||||||
os: macOS-10.15
|
|
||||||
compiler: xcode
|
|
||||||
version: "11.3"
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v1
|
|
||||||
|
|
||||||
- name: Install (Linux)
|
|
||||||
if: runner.os == 'Linux'
|
|
||||||
run: |
|
|
||||||
# CMake 3.15 allows specifying the generator using the CMAKE_GENERATOR
|
|
||||||
# environment variable.
|
|
||||||
curl -sSL https://github.com/Kitware/CMake/releases/download/v3.15.4/cmake-3.15.4-Linux-x86_64.tar.gz -o cmake.tar.gz
|
|
||||||
sudo tar xf cmake.tar.gz --strip 1 -C /usr/local
|
|
||||||
|
|
||||||
# Required for libc6-dbg:i386 and g++-multilib packages which are
|
|
||||||
# needed for x86 builds.
|
|
||||||
sudo dpkg --add-architecture i386
|
|
||||||
|
|
||||||
# clang-3.7 and earlier are not available in Bionic anymore so we get
|
|
||||||
# them from the Xenial repositories instead.
|
|
||||||
sudo add-apt-repository "deb http://dk.archive.ubuntu.com/ubuntu/ xenial main"
|
|
||||||
sudo add-apt-repository "deb http://dk.archive.ubuntu.com/ubuntu/ xenial universe"
|
|
||||||
|
|
||||||
# LLVM 9 is not in Bionic's repositories so we add the official LLVM repository.
|
|
||||||
if [ "${{ matrix.compiler }}" = "clang" ] && [ "${{ matrix.version }}" = "9" ]; then
|
|
||||||
sudo add-apt-repository "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main"
|
|
||||||
fi
|
|
||||||
|
|
||||||
sudo apt-get update
|
|
||||||
# sudo apt-get install libopenmpi-dev
|
|
||||||
# sudo apt-get install openmpi-bin
|
|
||||||
|
|
||||||
# libc6-dbg:i386 is required for running valgrind on x86.
|
|
||||||
sudo apt-get install -y ninja-build valgrind libc6-dbg:i386
|
|
||||||
|
|
||||||
if [ "${{ matrix.compiler }}" = "gcc" ]; then
|
|
||||||
sudo apt-get install -y g++-${{ matrix.version }} g++-${{ matrix.version }}-multilib
|
|
||||||
echo "::set-env name=CC::gcc-${{ matrix.version }}"
|
|
||||||
echo "::set-env name=CXX::g++-${{ matrix.version }}"
|
|
||||||
else
|
|
||||||
sudo apt-get install -y clang-${{ matrix.version }} g++-multilib
|
|
||||||
echo "::set-env name=CC::clang-${{ matrix.version }}"
|
|
||||||
echo "::set-env name=CXX::clang++-${{ matrix.version }}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Install (macOS)
|
|
||||||
if: runner.os == 'macOS'
|
|
||||||
run: |
|
|
||||||
brew install cmake ninja
|
|
||||||
|
|
||||||
if [ "${{ matrix.compiler }}" = "gcc" ]; then
|
|
||||||
brew install gcc@${{ matrix.version }}
|
|
||||||
echo "::set-env name=CC::gcc-${{ matrix.version }}"
|
|
||||||
echo "::set-env name=CXX::g++-${{ matrix.version }}"
|
|
||||||
else
|
|
||||||
ls -ls /Applications/
|
|
||||||
sudo xcode-select -switch /Applications/Xcode_${{ matrix.version }}.app
|
|
||||||
echo "::set-env name=CC::clang"
|
|
||||||
echo "::set-env name=CXX::clang++"
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Install (Windows)
|
|
||||||
if: runner.os == 'Windows'
|
|
||||||
shell: powershell
|
|
||||||
run: |
|
|
||||||
Invoke-Expression (New-Object System.Net.WebClient).DownloadString('https://get.scoop.sh')
|
|
||||||
scoop install ninja --global
|
|
||||||
|
|
||||||
if ("${{ matrix.compiler }}".StartsWith("clang")) {
|
|
||||||
scoop install llvm --global
|
|
||||||
}
|
|
||||||
|
|
||||||
if ("${{ matrix.compiler }}" -eq "gcc") {
|
|
||||||
# Chocolatey GCC is broken on the windows-2019 image.
|
|
||||||
# See: https://github.com/DaanDeMeyer/doctest/runs/231595515
|
|
||||||
# See: https://github.community/t5/GitHub-Actions/Something-is-wrong-with-the-chocolatey-installed-version-of-gcc/td-p/32413
|
|
||||||
scoop install gcc --global
|
|
||||||
echo "::set-env name=CC::gcc"
|
|
||||||
echo "::set-env name=CXX::g++"
|
|
||||||
} elseif ("${{ matrix.compiler }}" -eq "clang") {
|
|
||||||
echo "::set-env name=CC::clang"
|
|
||||||
echo "::set-env name=CXX::clang++"
|
|
||||||
} else {
|
|
||||||
echo "::set-env name=CC::${{ matrix.compiler }}"
|
|
||||||
echo "::set-env name=CXX::${{ matrix.compiler }}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Scoop modifies the PATH so we make the modified PATH global.
|
|
||||||
echo "::set-env name=PATH::$env:PATH"
|
|
||||||
|
|
||||||
- name: Configure ASAN/UBSAN
|
|
||||||
if: runner.os == 'Linux' || runner.os == 'macOS'
|
|
||||||
run: |
|
|
||||||
# https://stackoverflow.com/a/37939589/11900641
|
|
||||||
function version { echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }'; }
|
|
||||||
|
|
||||||
# Disable sanitizers in configurations where we know they are buggy.
|
|
||||||
|
|
||||||
# TODO: Move these conditions to the if clause if Github Actions ever
|
|
||||||
# adds support for comparing versions.
|
|
||||||
# See: https://github.community/t5/GitHub-Actions/Allow-comparing-versions-in-if-conditions/m-p/33912#M1710
|
|
||||||
|
|
||||||
if [ "${{ runner.os }}" = "Linux" ] && \
|
|
||||||
[ "${{ matrix.compiler }}" = "gcc" ] && \
|
|
||||||
[ $(version ${{ matrix.version }}) -le $(version "5.0") ]; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "${{ runner.os }}" = "Linux" ] && \
|
|
||||||
[ "${{ matrix.compiler }}" = "clang" ] && \
|
|
||||||
[ $(version ${{ matrix.version }}) -le $(version "6.0") ]; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "${{ runner.os }}" = "macOS" ] && \
|
|
||||||
[ "${{ matrix.compiler }}" = "xcode" ] && \
|
|
||||||
[ $(version ${{ matrix.version }}) -le $(version "9.4.1") ]; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "${{ runner.os }}" = "macOS" ] && \
|
|
||||||
[ "${{ matrix.compiler }}" = "gcc" ]; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
ASAN_UBSAN_FLAGS="-fsanitize=address,undefined -fno-omit-frame-pointer"
|
|
||||||
|
|
||||||
# Link statically against ASAN libraries because dynamically linking
|
|
||||||
# against ASAN libraries causes problems when using dlopen on Ubuntu.
|
|
||||||
# See: https://github.com/DaanDeMeyer/doctest/runs/249002713
|
|
||||||
if [ "${{ runner.os }}" = "Linux" ] && [ "${{ matrix.compiler }}" = "gcc" ]; then
|
|
||||||
ASAN_UBSAN_FLAGS="$ASAN_UBSAN_FLAGS -static-libasan"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Compiling in bash on Windows doesn't work and powershell doesn't
|
|
||||||
# exit on non-zero exit codes so we're forced to use cmd which means
|
|
||||||
# we don't have a cross platform way to access environment variables.
|
|
||||||
# To circumvent this, we put the sanitizer flags in an environment
|
|
||||||
# variable that is automatically picked up by CMake.
|
|
||||||
echo "::set-env name=CXXFLAGS::$ASAN_UBSAN_FLAGS"
|
|
||||||
|
|
||||||
- name: Configure TSAN
|
|
||||||
if: runner.os == 'Linux' || runner.os == 'macOS'
|
|
||||||
run: |
|
|
||||||
# https://stackoverflow.com/a/37939589/11900641
|
|
||||||
function version { echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }'; }
|
|
||||||
|
|
||||||
if [ "${{ runner.os }}" = "Linux" ] && \
|
|
||||||
[ "${{ matrix.compiler }}" = "gcc" ] && \
|
|
||||||
[ $(version ${{ matrix.version }}) -le $(version "6.0") ]; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "${{ runner.os }}" = "Linux" ] && \
|
|
||||||
[ "${{ matrix.compiler }}" = "clang" ] && \
|
|
||||||
[ $(version ${{ matrix.version }}) -le $(version "3.9") ]; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "${{ runner.os }}" = "macOS" ] && \
|
|
||||||
[ "${{ matrix.compiler }}" = "gcc" ]; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
TSAN_FLAGS="-fsanitize=thread -pie -fPIE"
|
|
||||||
|
|
||||||
if [ "${{ runner.os }}" = "Linux" ] && [ "${{ matrix.compiler }}" = "gcc" ]; then
|
|
||||||
TSAN_FLAGS="$TSAN_FLAGS -static-libtsan"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# The thread sanitizers build does not run on Windows so we can just
|
|
||||||
# use bash syntax to access the TSAN flags in the thread sanitizers
|
|
||||||
# build step.
|
|
||||||
echo "::set-env name=TSAN_FLAGS::$TSAN_FLAGS"
|
|
||||||
|
|
||||||
- name: Configure x64
|
|
||||||
if: runner.os == 'Windows'
|
|
||||||
run: .github\workflows\vsenv.bat -arch=x64 -host_arch=x64
|
|
||||||
|
|
||||||
- name: Build & Test Debug x64
|
|
||||||
run: |
|
|
||||||
cmake -E remove_directory build
|
|
||||||
cmake -B build -S . -DCMAKE_BUILD_TYPE=Debug -DDOCTEST_TEST_MODE=COMPARE
|
|
||||||
cmake --build build
|
|
||||||
cd build
|
|
||||||
ctest
|
|
||||||
|
|
||||||
- name: Build & Test Release x64
|
|
||||||
run: |
|
|
||||||
cmake -E remove_directory build
|
|
||||||
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release -DDOCTEST_TEST_MODE=COMPARE
|
|
||||||
cmake --build build
|
|
||||||
cd build
|
|
||||||
ctest
|
|
||||||
|
|
||||||
# Valgrind doesn't support the latest macOS versions.
|
|
||||||
# `-DCMAKE_CXX_FLAGS=""` overrides CXXFLAGS (disables sanitizers).
|
|
||||||
|
|
||||||
- name: Build & Test Debug x64 Valgrind
|
|
||||||
if: runner.os == 'Linux'
|
|
||||||
run: |
|
|
||||||
cmake -E remove_directory build
|
|
||||||
cmake -B build -S . -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="" -DDOCTEST_TEST_MODE=VALGRIND
|
|
||||||
cmake --build build
|
|
||||||
cd build
|
|
||||||
ctest
|
|
||||||
|
|
||||||
- name: Build & Test Release x64 Valgrind
|
|
||||||
if: runner.os == 'Linux'
|
|
||||||
run: |
|
|
||||||
cmake -E remove_directory build
|
|
||||||
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="" -DDOCTEST_TEST_MODE=VALGRIND
|
|
||||||
cmake --build build
|
|
||||||
cd build
|
|
||||||
ctest
|
|
||||||
|
|
||||||
- name: Build & Test Debug x64 Thread Sanitizers
|
|
||||||
if: runner.os == 'Linux' || runner.os == 'macOS'
|
|
||||||
run: |
|
|
||||||
cmake -E remove_directory build
|
|
||||||
cmake -B build -S . -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="$TSAN_FLAGS" -DDOCTEST_TEST_MODE=COMPARE
|
|
||||||
cmake --build build
|
|
||||||
cd build
|
|
||||||
ctest
|
|
||||||
|
|
||||||
- name: Build & Test Debug x64 without RTTI
|
|
||||||
if: runner.os == 'Linux' || runner.os == 'macOS'
|
|
||||||
run: |
|
|
||||||
cmake -E remove_directory build
|
|
||||||
cmake -B build -S . -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-fno-rtti" -DDOCTEST_TEST_MODE=COMPARE
|
|
||||||
cmake --build build
|
|
||||||
cd build
|
|
||||||
ctest
|
|
||||||
|
|
||||||
- name: Build x64 Debug without exceptions
|
|
||||||
if: runner.os == 'Linux' || runner.os == 'macOS'
|
|
||||||
run: |
|
|
||||||
cmake -E remove_directory build
|
|
||||||
cmake -B build -S . -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-fno-exceptions -DDOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS"
|
|
||||||
cmake --build build
|
|
||||||
|
|
||||||
# MinGW x86 tests fail on Windows: https://github.com/DaanDeMeyer/doctest/runs/240600881.
|
|
||||||
# MacOS doesn't support x86 from Xcode 10 onwards.
|
|
||||||
|
|
||||||
- name: Configure x86
|
|
||||||
shell: pwsh
|
|
||||||
if: (runner.os == 'Windows' && matrix.compiler != 'gcc') || runner.os == 'Linux'
|
|
||||||
run: |
|
|
||||||
if ("${{ runner.os }}" -eq "Windows") {
|
|
||||||
& .github\workflows\vsenv.bat -arch=x86 -host_arch=x64
|
|
||||||
}
|
|
||||||
|
|
||||||
if ("${{ matrix.compiler }}" -notcontains "cl") {
|
|
||||||
echo "::set-env name=CXXFLAGS::$env:CXXFLAGS -m32"
|
|
||||||
}
|
|
||||||
|
|
||||||
- name: Build & Test Debug x86
|
|
||||||
if: (runner.os == 'Windows' && matrix.compiler != 'gcc') || runner.os == 'Linux'
|
|
||||||
run: |
|
|
||||||
cmake -E remove_directory build
|
|
||||||
cmake -B build -S . -DCMAKE_BUILD_TYPE=Debug -DDOCTEST_TEST_MODE=COMPARE
|
|
||||||
cmake --build build
|
|
||||||
cd build
|
|
||||||
ctest
|
|
||||||
|
|
||||||
- name: Build & Test Release x86
|
|
||||||
if: (runner.os == 'Windows' && matrix.compiler != 'gcc') || runner.os == 'Linux'
|
|
||||||
run: |
|
|
||||||
cmake -E remove_directory build
|
|
||||||
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release -DDOCTEST_TEST_MODE=COMPARE
|
|
||||||
cmake --build build
|
|
||||||
cd build
|
|
||||||
ctest
|
|
||||||
|
|
||||||
- name: Build & Test Debug x86 Valgrind
|
|
||||||
if: runner.os == 'Linux'
|
|
||||||
run: |
|
|
||||||
cmake -E remove_directory build
|
|
||||||
cmake -B build -S . -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-m32" -DDOCTEST_TEST_MODE=VALGRIND
|
|
||||||
cmake --build build
|
|
||||||
cd build
|
|
||||||
ctest
|
|
||||||
|
|
||||||
- name: Build & Test Release x86 Valgrind
|
|
||||||
if: runner.os == 'Linux'
|
|
||||||
run: |
|
|
||||||
cmake -E remove_directory build
|
|
||||||
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-m32" -DDOCTEST_TEST_MODE=VALGRIND
|
|
||||||
cmake --build build
|
|
||||||
cd build
|
|
||||||
ctest
|
|
17
lib/doctest/.github/workflows/vsenv.bat
vendored
17
lib/doctest/.github/workflows/vsenv.bat
vendored
|
@ -1,17 +0,0 @@
|
||||||
@echo off
|
|
||||||
|
|
||||||
SET VSWHERE="C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere"
|
|
||||||
|
|
||||||
:: See https://github.com/microsoft/vswhere/wiki/Find-VC
|
|
||||||
for /f "usebackq delims=*" %%i in (`%VSWHERE% -latest -property installationPath`) do (
|
|
||||||
call "%%i"\Common7\Tools\vsdevcmd.bat %*
|
|
||||||
)
|
|
||||||
|
|
||||||
:: Loop over all environment variables and make them global using set-env.
|
|
||||||
:: See: https://help.github.com/en/articles/development-tools-for-github-actions#set-an-environment-variable-set-env
|
|
||||||
:: See: https://stackoverflow.com/questions/39183272/loop-through-all-environmental-variables-and-take-actions-depending-on-prefix
|
|
||||||
setlocal
|
|
||||||
for /f "delims== tokens=1,2" %%a in ('set') do (
|
|
||||||
echo ::set-env name=%%a::%%b
|
|
||||||
)
|
|
||||||
endlocal
|
|
40
lib/doctest/.gitignore
vendored
40
lib/doctest/.gitignore
vendored
|
@ -1,40 +0,0 @@
|
||||||
# Compiled Object files
|
|
||||||
*.slo
|
|
||||||
*.lo
|
|
||||||
*.o
|
|
||||||
*.obj
|
|
||||||
|
|
||||||
# Compiled Dynamic libraries
|
|
||||||
*.so
|
|
||||||
*.dylib
|
|
||||||
*.dll
|
|
||||||
|
|
||||||
# Compiled Static libraries
|
|
||||||
*.lai
|
|
||||||
*.la
|
|
||||||
*.a
|
|
||||||
*.lib
|
|
||||||
|
|
||||||
# Executables
|
|
||||||
*.exe
|
|
||||||
*.out
|
|
||||||
*.app
|
|
||||||
|
|
||||||
# Text garbage
|
|
||||||
*.ii
|
|
||||||
*.s
|
|
||||||
|
|
||||||
# My garbage :)
|
|
||||||
Win32/
|
|
||||||
x64/
|
|
||||||
doctest_with_main.dir/
|
|
||||||
scripts/bench/project/*
|
|
||||||
scripts/bench/catch*.hpp
|
|
||||||
scripts/bench/results.txt
|
|
||||||
build/
|
|
||||||
build-mingw/
|
|
||||||
*.pyc
|
|
||||||
*vscode*
|
|
||||||
.idea/
|
|
||||||
cmake-build-*/
|
|
||||||
bazel-*
|
|
|
@ -1,413 +0,0 @@
|
||||||
# # this file is HEAVILY influenced by https://github.com/boostorg/hana/blob/master/.travis.yml
|
|
||||||
|
|
||||||
# dist: trusty
|
|
||||||
# language: c++
|
|
||||||
|
|
||||||
# notifications:
|
|
||||||
# email: false
|
|
||||||
# # gitter
|
|
||||||
# webhooks:
|
|
||||||
# urls: https://webhooks.gitter.im/e/10941dd1c67e5e967706
|
|
||||||
# on_success: change
|
|
||||||
# on_failure: always
|
|
||||||
# git:
|
|
||||||
# depth: 500
|
|
||||||
|
|
||||||
# # both apt and ccache make the builds slower...
|
|
||||||
# #cache:
|
|
||||||
# # - apt
|
|
||||||
# # - ccache
|
|
||||||
|
|
||||||
# env:
|
|
||||||
# global:
|
|
||||||
# # - USE_CCACHE=1
|
|
||||||
# # - CCACHE_SLOPPINESS=pch_defines,time_macros
|
|
||||||
# # - CCACHE_COMPRESS=1
|
|
||||||
# # - CCACHE_MAXSIZE=200M
|
|
||||||
# # - CCACHE_CPP2=1
|
|
||||||
# - CMAKE_OPTIONS_GLOBAL="-DCMAKE_EXPORT_COMPILE_COMMANDS=ON"
|
|
||||||
|
|
||||||
# addons:
|
|
||||||
# coverity_scan:
|
|
||||||
# # COVERITY_SCAN_TOKEN added as env var in travis project
|
|
||||||
# project:
|
|
||||||
# name: onqtam/doctest
|
|
||||||
# notification_email: vik.kirilov@gmail.com
|
|
||||||
# build_command: clang++ scripts/hello_world.cpp -I doctest
|
|
||||||
# branch_pattern: coverity_scan
|
|
||||||
# # these apt sources will be referenced later (by using *name)
|
|
||||||
# apt:
|
|
||||||
# sources: &apt_sources
|
|
||||||
# - ubuntu-toolchain-r-test
|
|
||||||
# - llvm-toolchain-trusty
|
|
||||||
# - llvm-toolchain-precise-3.7
|
|
||||||
# - llvm-toolchain-trusty-3.9
|
|
||||||
# - llvm-toolchain-trusty-4.0
|
|
||||||
# - llvm-toolchain-trusty-5.0
|
|
||||||
# - llvm-toolchain-trusty-6.0
|
|
||||||
# - llvm-toolchain-trusty-7
|
|
||||||
# - llvm-toolchain-trusty-8
|
|
||||||
# - llvm-toolchain-trusty-9
|
|
||||||
# - llvm-toolchain-trusty-10
|
|
||||||
|
|
||||||
# compiler: clang
|
|
||||||
# os: linux
|
|
||||||
|
|
||||||
# matrix:
|
|
||||||
# include:
|
|
||||||
# # coverage
|
|
||||||
# - env: COMPILER=g++ CODE_COVERAGE=true
|
|
||||||
# compiler: gcc
|
|
||||||
# addons:
|
|
||||||
# apt:
|
|
||||||
# packages: ["lcov"]
|
|
||||||
|
|
||||||
# # static code analysis
|
|
||||||
# - env: COMPILER=clang++-4.0 STATIC_CODE_ANALYSIS=true
|
|
||||||
# addons: &static_analysis
|
|
||||||
# apt:
|
|
||||||
# packages: ["clang-4.0", "clang-tidy-4.0", "cppcheck"]
|
|
||||||
# sources: *apt_sources
|
|
||||||
|
|
||||||
# # GCC 4.8
|
|
||||||
# - env: COMPILER=g++-4.8 HAS_ASAN=true SANITIZER_CXX_FLAGS="-fuse-ld=gold -static-libasan" TSAN_CXX_FLAGS="-ltsan" # TSAN broken for some time - seg faults
|
|
||||||
# compiler: gcc
|
|
||||||
# addons: &gcc48
|
|
||||||
# apt:
|
|
||||||
# packages: ["g++-4.8", "valgrind", "libc6-dbg", "linux-libc-dev"]
|
|
||||||
# sources: *apt_sources
|
|
||||||
|
|
||||||
# # GCC 4.9
|
|
||||||
# - env: COMPILER=g++-4.9 HAS_ASAN=true HAS_UBSAN=true SANITIZER_CXX_FLAGS="-fuse-ld=gold -static-libasan" TSAN_CXX_FLAGS="-ltsan" # TSAN broken for some time - seg faults
|
|
||||||
# compiler: gcc
|
|
||||||
# addons: &gcc49
|
|
||||||
# apt:
|
|
||||||
# packages: ["g++-4.9", "valgrind", "libc6-dbg", "linux-libc-dev"]
|
|
||||||
# sources: *apt_sources
|
|
||||||
|
|
||||||
# # GCC 5
|
|
||||||
# - env: COMPILER=g++-5 HAS_ASAN=true HAS_UBSAN=true SANITIZER_CXX_FLAGS="-fuse-ld=gold -static-libasan" TSAN_CXX_FLAGS="-ltsan" # TSAN broken for some time - seg faults
|
|
||||||
# compiler: gcc
|
|
||||||
# addons: &gcc5
|
|
||||||
# apt:
|
|
||||||
# packages: ["g++-5", "valgrind", "libc6-dbg", "linux-libc-dev"]
|
|
||||||
# sources: *apt_sources
|
|
||||||
|
|
||||||
# # GCC 6
|
|
||||||
# - env: COMPILER=g++-6 HAS_ASAN=true HAS_UBSAN=true SANITIZER_CXX_FLAGS="-fuse-ld=gold -static-libasan" TSAN_CXX_FLAGS="-ltsan" # TSAN broken for some time - seg faults
|
|
||||||
# compiler: gcc
|
|
||||||
# addons: &gcc6
|
|
||||||
# apt:
|
|
||||||
# packages: ["g++-6", "valgrind", "libc6-dbg", "linux-libc-dev"]
|
|
||||||
# sources: *apt_sources
|
|
||||||
|
|
||||||
# # GCC 7
|
|
||||||
# - env: COMPILER=g++-7 HAS_ASAN=true HAS_UBSAN=true SANITIZER_CXX_FLAGS="-fuse-ld=gold -static-libasan" TSAN_CXX_FLAGS="-ltsan" # TSAN broken for some time - seg faults
|
|
||||||
# compiler: gcc
|
|
||||||
# sudo: required # see this issue for more details: https://github.com/travis-ci/travis-ci/issues/9033
|
|
||||||
# addons: &gcc7
|
|
||||||
# apt:
|
|
||||||
# packages: ["g++-7", "valgrind", "libc6-dbg", "linux-libc-dev"]
|
|
||||||
# sources: *apt_sources
|
|
||||||
|
|
||||||
# # GCC 8
|
|
||||||
# - env: COMPILER=g++-8 HAS_ASAN=true HAS_UBSAN=true HAS_TSAN=true SANITIZER_CXX_FLAGS="-fuse-ld=gold -static-libasan" TSAN_CXX_FLAGS="-ltsan"
|
|
||||||
# compiler: gcc
|
|
||||||
# sudo: required # see this issue for more details: https://github.com/travis-ci/travis-ci/issues/9033
|
|
||||||
# addons: &gcc8
|
|
||||||
# apt:
|
|
||||||
# packages: ["g++-8", "valgrind", "libc6-dbg", "linux-libc-dev"]
|
|
||||||
# sources: *apt_sources
|
|
||||||
|
|
||||||
# # GCC 9
|
|
||||||
# - env: COMPILER=g++-9 HAS_ASAN=true HAS_UBSAN=true HAS_TSAN=true SANITIZER_CXX_FLAGS="-fuse-ld=gold -static-libasan" TSAN_CXX_FLAGS="-ltsan"
|
|
||||||
# compiler: gcc
|
|
||||||
# sudo: required # see this issue for more details: https://github.com/travis-ci/travis-ci/issues/9033
|
|
||||||
# addons: &gcc9
|
|
||||||
# apt:
|
|
||||||
# packages: ["g++-9", "valgrind", "libc6-dbg", "linux-libc-dev"]
|
|
||||||
# sources: *apt_sources
|
|
||||||
|
|
||||||
# # GCC 10
|
|
||||||
# - env: COMPILER=g++-10 HAS_ASAN=true HAS_UBSAN=true HAS_TSAN=true SANITIZER_CXX_FLAGS="-fuse-ld=gold -static-libasan" TSAN_CXX_FLAGS="-ltsan"
|
|
||||||
# compiler: gcc
|
|
||||||
# sudo: required # see this issue for more details: https://github.com/travis-ci/travis-ci/issues/9033
|
|
||||||
# addons: &gcc10
|
|
||||||
# apt:
|
|
||||||
# packages: ["g++-10", "valgrind", "libc6-dbg", "linux-libc-dev"]
|
|
||||||
# sources: *apt_sources
|
|
||||||
|
|
||||||
# # Clang 3.5
|
|
||||||
# - env: COMPILER=clang++-3.5 HAS_ASAN=true HAS_UBSAN=true # no HAS_TSAN - see errors: https://travis-ci.org/onqtam/doctest/builds/417926743
|
|
||||||
# addons: &clang35
|
|
||||||
# apt:
|
|
||||||
# packages: ["clang-3.5", "valgrind", "libc6-dbg", "g++-6"]
|
|
||||||
# sources: *apt_sources
|
|
||||||
|
|
||||||
# # Clang 3.6
|
|
||||||
# - env: COMPILER=clang++-3.6 HAS_ASAN=true HAS_UBSAN=true # no HAS_TSAN - see errors: https://travis-ci.org/onqtam/doctest/builds/417926743
|
|
||||||
# addons: &clang36
|
|
||||||
# apt:
|
|
||||||
# packages: ["clang-3.6", "valgrind", "libc6-dbg", "g++-6"]
|
|
||||||
# sources: *apt_sources
|
|
||||||
|
|
||||||
# # Clang 3.7
|
|
||||||
# - env: COMPILER=clang++-3.7
|
|
||||||
# addons: &clang37
|
|
||||||
# apt:
|
|
||||||
# packages: ["clang-3.7", "valgrind", "libc6-dbg", "g++-6"]
|
|
||||||
# sources: *apt_sources
|
|
||||||
|
|
||||||
# # Clang 3.8
|
|
||||||
# - env: COMPILER=clang++-3.8 HAS_ASAN=true HAS_UBSAN=true # no HAS_TSAN - see errors: https://travis-ci.org/onqtam/doctest/builds/417926743
|
|
||||||
# addons: &clang38
|
|
||||||
# apt:
|
|
||||||
# packages: ["clang-3.8", "valgrind", "libc6-dbg", "g++-6"]
|
|
||||||
# sources: *apt_sources
|
|
||||||
|
|
||||||
# # Clang 3.9
|
|
||||||
# - env: COMPILER=clang++-3.9 # no HAS_ASAN/HAS_UBSAN - see errors: https://travis-ci.org/onqtam/doctest/jobs/386263910
|
|
||||||
# addons: &clang39
|
|
||||||
# apt:
|
|
||||||
# packages: ["clang-3.9", "valgrind", "libc6-dbg", "g++-6"]
|
|
||||||
# sources: *apt_sources
|
|
||||||
|
|
||||||
# # Clang 4.0
|
|
||||||
# - env: COMPILER=clang++-4.0 HAS_ASAN=true HAS_UBSAN=true HAS_TSAN=true
|
|
||||||
# sudo: required # see this issue for more details: https://github.com/travis-ci/travis-ci/issues/9033
|
|
||||||
# addons: &clang40
|
|
||||||
# apt:
|
|
||||||
# packages: ["clang-4.0", "valgrind", "libc6-dbg", "g++-6"]
|
|
||||||
# sources: *apt_sources
|
|
||||||
|
|
||||||
# # Clang 5.0
|
|
||||||
# - env: COMPILER=clang++-5.0 HAS_ASAN=true HAS_UBSAN=true HAS_TSAN=true
|
|
||||||
# sudo: required # see this issue for more details: https://github.com/travis-ci/travis-ci/issues/9033
|
|
||||||
# addons: &clang50
|
|
||||||
# apt:
|
|
||||||
# packages: ["clang-5.0", "valgrind", "libc6-dbg", "g++-6"]
|
|
||||||
# sources: *apt_sources
|
|
||||||
|
|
||||||
# # Clang 6.0
|
|
||||||
# - env: COMPILER=clang++-6.0 HAS_ASAN=true HAS_UBSAN=true HAS_TSAN=true
|
|
||||||
# sudo: required # see this issue for more details: https://github.com/travis-ci/travis-ci/issues/9033
|
|
||||||
# addons: &clang60
|
|
||||||
# apt:
|
|
||||||
# packages: ["clang-6.0", "valgrind", "libc6-dbg", "g++-6"]
|
|
||||||
# sources: *apt_sources
|
|
||||||
|
|
||||||
# # Clang 7
|
|
||||||
# - env: COMPILER=clang++-7 HAS_ASAN=true HAS_UBSAN=true HAS_TSAN=true
|
|
||||||
# sudo: required # see this issue for more details: https://github.com/travis-ci/travis-ci/issues/9033
|
|
||||||
# addons: &clang7
|
|
||||||
# apt:
|
|
||||||
# packages: ["clang-7", "valgrind", "libc6-dbg", "g++-6"]
|
|
||||||
# sources: *apt_sources
|
|
||||||
|
|
||||||
# # Clang 8
|
|
||||||
# - env: COMPILER=clang++-8 HAS_ASAN=true HAS_UBSAN=true HAS_TSAN=true
|
|
||||||
# sudo: required # see this issue for more details: https://github.com/travis-ci/travis-ci/issues/9033
|
|
||||||
# addons: &clang8
|
|
||||||
# apt:
|
|
||||||
# packages: ["clang-8", "valgrind", "libc6-dbg", "g++-6"]
|
|
||||||
# sources: *apt_sources
|
|
||||||
|
|
||||||
# # Clang 9
|
|
||||||
# - env: COMPILER=clang++-9 HAS_ASAN=true HAS_UBSAN=true HAS_TSAN=true
|
|
||||||
# sudo: required # see this issue for more details: https://github.com/travis-ci/travis-ci/issues/9033
|
|
||||||
# addons: &clang9
|
|
||||||
# apt:
|
|
||||||
# packages: ["clang-9", "valgrind", "libc6-dbg", "g++-6"]
|
|
||||||
# sources: *apt_sources
|
|
||||||
|
|
||||||
# # Clang 10
|
|
||||||
# - env: COMPILER=clang++-10 HAS_ASAN=true HAS_UBSAN=true HAS_TSAN=true
|
|
||||||
# sudo: required # see this issue for more details: https://github.com/travis-ci/travis-ci/issues/9033
|
|
||||||
# addons: &clang9
|
|
||||||
# apt:
|
|
||||||
# packages: ["clang-10", "valgrind", "libc6-dbg", "g++-6"]
|
|
||||||
# sources: *apt_sources
|
|
||||||
|
|
||||||
# # Xcode 9.4 Clang
|
|
||||||
# - env: COMPILER=clang++ HAS_UBSAN=true HAS_TSAN=true # no HAS_ASAN - errors since using thread_local even in single-threaded cases - see errors: https://travis-ci.org/onqtam/doctest/builds/417181981
|
|
||||||
# osx_image: xcode9.4
|
|
||||||
# os: osx
|
|
||||||
|
|
||||||
# # Xcode 10.0 Clang
|
|
||||||
# - env: COMPILER=clang++ HAS_ASAN=true HAS_UBSAN=true HAS_TSAN=true
|
|
||||||
# osx_image: xcode10
|
|
||||||
# os: osx
|
|
||||||
|
|
||||||
# # Xcode 10.2 Clang
|
|
||||||
# - env: COMPILER=clang++ HAS_ASAN=true HAS_UBSAN=true HAS_TSAN=true
|
|
||||||
# osx_image: xcode10.2
|
|
||||||
# os: osx
|
|
||||||
|
|
||||||
# # Xcode 11.2 Clang
|
|
||||||
# - env: COMPILER=clang++ HAS_ASAN=true HAS_UBSAN=true HAS_TSAN=true
|
|
||||||
# osx_image: xcode11.2
|
|
||||||
# os: osx
|
|
||||||
|
|
||||||
# # OSX LLVM-GCC
|
|
||||||
# - env: COMPILER=g++ HAS_ASAN=true HAS_TSAN=true
|
|
||||||
# compiler: gcc
|
|
||||||
# osx_image: xcode10
|
|
||||||
# os: osx
|
|
||||||
|
|
||||||
# allow_failures:
|
|
||||||
|
|
||||||
# # static code analysis
|
|
||||||
# - env: COMPILER=clang++-4.0 STATIC_CODE_ANALYSIS=true
|
|
||||||
|
|
||||||
# # seems to not be present yet: https://travis-ci.org/github/onqtam/doctest/jobs/688097537
|
|
||||||
# # GCC 10
|
|
||||||
# - env: COMPILER=g++-10 HAS_ASAN=true HAS_UBSAN=true HAS_TSAN=true SANITIZER_CXX_FLAGS="-fuse-ld=gold -static-libasan" TSAN_CXX_FLAGS="-ltsan"
|
|
||||||
# compiler: gcc
|
|
||||||
# sudo: required
|
|
||||||
|
|
||||||
# # Clang 10
|
|
||||||
# - env: COMPILER=clang++-10 HAS_ASAN=true HAS_UBSAN=true HAS_TSAN=true
|
|
||||||
# sudo: required
|
|
||||||
|
|
||||||
# install:
|
|
||||||
# - if [[ "${CODE_COVERAGE}" == "true" ]]; then gem install coveralls-lcov ; fi
|
|
||||||
|
|
||||||
# ############################################################################
|
|
||||||
# # All the dependencies are installed in ${TRAVIS_BUILD_DIR}/deps/
|
|
||||||
# ############################################################################
|
|
||||||
|
|
||||||
# # Make a dir for all
|
|
||||||
# - DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"
|
|
||||||
# - mkdir -p ${DEPS_DIR} && cd ${DEPS_DIR}
|
|
||||||
|
|
||||||
# # Install a recent CMake
|
|
||||||
# - |
|
|
||||||
# if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
|
|
||||||
# CMAKE_URL="http://www.cmake.org/files/v3.7/cmake-3.7.2-Linux-x86_64.tar.gz"
|
|
||||||
# mkdir cmake && travis_retry wget --no-check-certificate --quiet -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C cmake
|
|
||||||
# export PATH=${DEPS_DIR}/cmake/bin:${PATH}
|
|
||||||
# fi
|
|
||||||
|
|
||||||
# # Install OCLint
|
|
||||||
# - |
|
|
||||||
# if [[ "${STATIC_CODE_ANALYSIS}" = "true" ]]; then
|
|
||||||
# OCLINT_URL="https://github.com/oclint/oclint/releases/download/v0.12/oclint-0.12-x86_64-linux-3.13.0-112-generic.tar.gz"
|
|
||||||
# mkdir oclint && travis_retry wget --no-check-certificate --quiet -O - ${OCLINT_URL} | tar --strip-components=1 -xz -C oclint
|
|
||||||
# export PATH=${DEPS_DIR}/oclint/bin:${PATH}
|
|
||||||
# fi
|
|
||||||
|
|
||||||
# # Go back to ${TRAVIS_BUILD_DIR}
|
|
||||||
# - cd ${TRAVIS_BUILD_DIR}
|
|
||||||
|
|
||||||
# ############################################################################
|
|
||||||
# # Install stuff with homebrew under OSX
|
|
||||||
# ############################################################################
|
|
||||||
|
|
||||||
# - |
|
|
||||||
# if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
|
|
||||||
# brew update
|
|
||||||
# # brew install ccache
|
|
||||||
# # brew install valgrind
|
|
||||||
# # cmake
|
|
||||||
# if brew list -1 | grep -q "^cmake\$"; then
|
|
||||||
# brew outdated cmake || brew upgrade cmake
|
|
||||||
# else
|
|
||||||
# brew install cmake
|
|
||||||
# fi
|
|
||||||
# fi
|
|
||||||
|
|
||||||
# - export CXX="${COMPILER}"
|
|
||||||
# # - export CXX="ccache ${COMPILER}"
|
|
||||||
# # - ccache -s
|
|
||||||
|
|
||||||
# before_script:
|
|
||||||
# - ${CXX} --version
|
|
||||||
|
|
||||||
# script:
|
|
||||||
# # coverage
|
|
||||||
# - |
|
|
||||||
# if [[ "${CODE_COVERAGE}" = "true" ]]; then
|
|
||||||
# cmake ${CMAKE_OPTIONS_GLOBAL} ${CMAKE_OPTIONS} -DCMAKE_CXX_COMPILER=${CXX} -DCMAKE_CXX_FLAGS="-fprofile-arcs -ftest-coverage -std=c++0x" -DCMAKE_BUILD_TYPE=Debug . || exit 1
|
|
||||||
# make -k -j2 || exit 1
|
|
||||||
# ctest -j2 --output-on-failure || exit 1
|
|
||||||
|
|
||||||
# lcov -d . -c -o coverage.info # parse coverage data
|
|
||||||
# lcov -r coverage.info "/usr*" -o coverage.info # remove data for system headers
|
|
||||||
# lcov -r coverage.info "$(readlink -f examples)/*" -o coverage.info # remove data for .cpp files
|
|
||||||
# lcov -r coverage.info "$(readlink -f scripts)/*" -o coverage.info # remove data for .cpp files
|
|
||||||
# lcov -l coverage.info # just list a short summary of the results
|
|
||||||
# coveralls-lcov --repo-token=${COVERALLS_REPO_TOKEN} coverage.info # upload results
|
|
||||||
|
|
||||||
# # do not continue with other build configurations after that
|
|
||||||
# exit
|
|
||||||
# fi
|
|
||||||
|
|
||||||
# # static code analysis
|
|
||||||
# - |
|
|
||||||
# if [[ "${STATIC_CODE_ANALYSIS}" = "true" ]]; then
|
|
||||||
# # setup a test file "doctest.cpp" that is the header + a test case at the end
|
|
||||||
# echo "#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN\n" >> doctest.cpp
|
|
||||||
# cat doctest/doctest.h >> doctest.cpp
|
|
||||||
# echo -e "TEST_CASE(\"\") {\n\tint a = 6;\n\tSUBCASE(\"\") a = 5;\n\tCAPTURE(a);\n\tCHECK(a == 6);\n}\n" >> doctest.cpp
|
|
||||||
|
|
||||||
# # cppcheck
|
|
||||||
# cppcheck doctest.cpp --enable=all --suppress=unmatchedSuppression --suppress=missingIncludeSystem --suppress=unusedFunction --suppress=functionConst --inline-suppr --platform=unix64 --inconclusive --std=posix --inconclusive -v --error-exitcode=1 --template "{file}({line}): {severity} ({id}): {message}"
|
|
||||||
|
|
||||||
# # oclint
|
|
||||||
# oclint doctest.cpp -disable-rule=ShortVariableName -disable-rule=LongLine -disable-rule=LongMethod -disable-rule=HighNcssMethod -disable-rule=LongVariableName -disable-rule=HighCyclomaticComplexity -disable-rule=HighNPathComplexity -disable-rule=UnusedLocalVariable -disable-rule=DoubleNegative -disable-rule=MultipleUnaryOperator -disable-rule=DeepNestedBlock || exit 1
|
|
||||||
|
|
||||||
# # clang-tidy
|
|
||||||
# cd scripts/playground
|
|
||||||
# cmake ${CMAKE_OPTIONS_GLOBAL} ${CMAKE_OPTIONS} -DCMAKE_CXX_COMPILER=${CXX} . || exit 1
|
|
||||||
# clang-tidy-4.0 -std=c++11 -p=. *.cpp -header-filter=.* -warnings-as-errors=* -checks='*,-misc-misplaced-widening-cast,-misc-macro-parentheses,-misc-definitions-in-headers,-misc-unused-parameters,-llvm-header-guard,-llvm-include-order,-google-readability-braces-around-statements,-google-runtime-references,-google-readability-todo,-google-build-using-namespace,-google-explicit-constructor,-cert-err58-cpp,-cppcoreguidelines-pro-type-vararg,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-special-member-functions,-cppcoreguidelines-pro-type-reinterpret-cast,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-pro-type-member-init,-cppcoreguidelines-pro-type-union-access,-clang-analyzer-security.insecureAPI.strcpy,-modernize-loop-convert,-modernize-use-auto,-modernize-use-bool-literals,-readability-braces-around-statements,-readability-named-parameter,-readability-else-after-return,-readability-redundant-declaration,-readability-implicit-bool-cast,-clang-diagnostic-variadic-macros,-clang-diagnostic-c++11-compat' || exit 1
|
|
||||||
|
|
||||||
# # do not continue with other build configurations after that
|
|
||||||
# exit
|
|
||||||
# fi
|
|
||||||
|
|
||||||
# # initial run with options
|
|
||||||
# - cmake ${CMAKE_OPTIONS_GLOBAL} ${CMAKE_OPTIONS} -DCMAKE_CXX_COMPILER=${CXX} .
|
|
||||||
|
|
||||||
# # set the common CXX flags
|
|
||||||
# - export CXX_FLAGS="${CXX_FLAGS} -std=c++0x"
|
|
||||||
|
|
||||||
# # debug
|
|
||||||
# - cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="${CXX_FLAGS}" .
|
|
||||||
# - make clean && make -k -j2
|
|
||||||
# - if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then cmake -DDOCTEST_TEST_MODE=VALGRIND . && ctest -j2 --output-on-failure ; fi
|
|
||||||
# - cmake -DDOCTEST_TEST_MODE=COMPARE . && ctest -j2 --output-on-failure
|
|
||||||
# # release
|
|
||||||
# - cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="${CXX_FLAGS}" .
|
|
||||||
# - make clean && make -k -j2
|
|
||||||
# - if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then cmake -DDOCTEST_TEST_MODE=VALGRIND . && ctest -j2 --output-on-failure ; fi
|
|
||||||
# - cmake -DDOCTEST_TEST_MODE=COMPARE . && ctest -j2 --output-on-failure
|
|
||||||
|
|
||||||
# # sanitizers - again Debug/Release configs through address/undefined/thread sanitizers
|
|
||||||
# # on separate commands because when something fails I want to see which one exactly
|
|
||||||
# - cmake -DDOCTEST_TEST_MODE=NORMAL .
|
|
||||||
|
|
||||||
# - export ASAN_OPTIONS=verbosity=2:strict_string_checks=true:detect_odr_violation=2:detect_stack_use_after_return=true:check_initialization_order=true:strict_init_order=true
|
|
||||||
# - if [[ "${HAS_ASAN}" = "true" ]]; then cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="${CXX_FLAGS} ${SANITIZER_CXX_FLAGS} -g -fno-omit-frame-pointer -fsanitize=address" . && make clean && make -k -j2 && ctest -j2 --output-on-failure ; fi
|
|
||||||
# - if [[ "${HAS_ASAN}" = "true" ]]; then cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="${CXX_FLAGS} ${SANITIZER_CXX_FLAGS} -g -fno-omit-frame-pointer -fsanitize=address" . && make clean && make -k -j2 && ctest -j2 --output-on-failure ; fi
|
|
||||||
|
|
||||||
# - export UBSAN_OPTIONS=verbosity=2
|
|
||||||
# - if [[ "${HAS_UBSAN}" = "true" ]]; then cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="${CXX_FLAGS} ${SANITIZER_CXX_FLAGS} -g -fno-omit-frame-pointer -fsanitize=undefined" . && make clean && make -k -j2 && ctest -j2 --output-on-failure ; fi
|
|
||||||
# - if [[ "${HAS_UBSAN}" = "true" ]]; then cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="${CXX_FLAGS} ${SANITIZER_CXX_FLAGS} -g -fno-omit-frame-pointer -fsanitize=undefined" . && make clean && make -k -j2 && ctest -j2 --output-on-failure ; fi
|
|
||||||
|
|
||||||
# - export TSAN_OPTIONS=verbosity=2:force_seq_cst_atomics=1
|
|
||||||
# - if [[ "${HAS_TSAN}" = "true" ]]; then cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="${CXX_FLAGS} ${SANITIZER_CXX_FLAGS} -g -fno-omit-frame-pointer -fsanitize=thread -pie -fPIE ${TSAN_CXX_FLAGS}" . && make clean && make -k -j2 && ctest -j2 --output-on-failure ; fi
|
|
||||||
# - if [[ "${HAS_TSAN}" = "true" ]]; then cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="${CXX_FLAGS} ${SANITIZER_CXX_FLAGS} -g -fno-omit-frame-pointer -fsanitize=thread -pie -fPIE ${TSAN_CXX_FLAGS}" . && make clean && make -k -j2 && ctest -j2 --output-on-failure ; fi
|
|
||||||
|
|
||||||
# # test without rtti - just Debug
|
|
||||||
# - cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="${CXX_FLAGS} -fno-rtti" .
|
|
||||||
# - make clean && make -k -j2
|
|
||||||
# - cmake -DDOCTEST_TEST_MODE=COMPARE . && ctest -j2 --output-on-failure
|
|
||||||
|
|
||||||
# # test only compilation without exceptions - just Debug
|
|
||||||
# - cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="${CXX_FLAGS} -fno-exceptions -DDOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS" .
|
|
||||||
# - make clean && make -k -j2
|
|
||||||
|
|
||||||
# # - ccache -s
|
|
||||||
|
|
||||||
# #after_script:
|
|
||||||
# # - cat compile_commands.json
|
|
|
@ -1,743 +0,0 @@
|
||||||
# Change Log
|
|
||||||
|
|
||||||
## [2.4.7](https://github.com/doctest/doctest/tree/2.4.7) (2021-12-10)
|
|
||||||
[Full Changelog](https://github.com/doctest/doctest/compare/2.4.6...2.4.7)
|
|
||||||
|
|
||||||
**Implemented enhancements:**
|
|
||||||
|
|
||||||
- Add a default Bazel BUILD file [\#433](https://github.com/doctest/doctest/issues/433)
|
|
||||||
|
|
||||||
**Fixed bugs:**
|
|
||||||
|
|
||||||
- Stack-buffer-overflow probably because char array is viewed as NULL terminated string [\#476](https://github.com/doctest/doctest/issues/476)
|
|
||||||
|
|
||||||
**Closed issues:**
|
|
||||||
|
|
||||||
- "C4834: discarding return value" with REQUIRE\_THROWS [\#549](https://github.com/doctest/doctest/issues/549)
|
|
||||||
- Xcode 11.3 is gone from macOS-latest \(=macOS-11\) [\#547](https://github.com/doctest/doctest/issues/547)
|
|
||||||
- is it possible to define dependency for CHECKs [\#545](https://github.com/doctest/doctest/issues/545)
|
|
||||||
- Output summary explanation [\#541](https://github.com/doctest/doctest/issues/541)
|
|
||||||
- compiler errors in doctest.h using cmake in CLion [\#540](https://github.com/doctest/doctest/issues/540)
|
|
||||||
- Fails to build in VS2013 because of constexpr [\#539](https://github.com/doctest/doctest/issues/539)
|
|
||||||
- -Wreserved-identifier warnings with Clang 13.0.0 [\#536](https://github.com/doctest/doctest/issues/536)
|
|
||||||
- Build fails with latest MSVC 2019 \(v16.11\) due to /WX [\#535](https://github.com/doctest/doctest/issues/535)
|
|
||||||
- VS 16.11 warning about unreferenced function with internal linkage [\#533](https://github.com/doctest/doctest/issues/533)
|
|
||||||
- Faq googletest mocking dead link [\#532](https://github.com/doctest/doctest/issues/532)
|
|
||||||
- FR: Documentation: FAQ: Add sectoin 'multiple files' [\#526](https://github.com/doctest/doctest/issues/526)
|
|
||||||
- CMAKE: doctest\_discover\_tests\(\) error when ADD\_LABELS is not specified [\#524](https://github.com/doctest/doctest/issues/524)
|
|
||||||
- Register tests based on test data available [\#521](https://github.com/doctest/doctest/issues/521)
|
|
||||||
- naming override in different testcase files [\#517](https://github.com/doctest/doctest/issues/517)
|
|
||||||
- Segmentation fault during the compilation without the copy elision optimization [\#515](https://github.com/doctest/doctest/issues/515)
|
|
||||||
- Compiler warnings on Xcode 12.5 [\#514](https://github.com/doctest/doctest/issues/514)
|
|
||||||
- Using filter `-sc` does not work properly? [\#513](https://github.com/doctest/doctest/issues/513)
|
|
||||||
- \[question\] Example of tests in production code & DLLs & shared libraries? [\#511](https://github.com/doctest/doctest/issues/511)
|
|
||||||
- Dumping fixture state to disk on error [\#509](https://github.com/doctest/doctest/issues/509)
|
|
||||||
- Macros construct reserved identifiers [\#507](https://github.com/doctest/doctest/issues/507)
|
|
||||||
- Running doctest on embedded ARM Cortex µCs [\#506](https://github.com/doctest/doctest/issues/506)
|
|
||||||
- Asserts Outside of Tests Example Does Not Link [\#504](https://github.com/doctest/doctest/issues/504)
|
|
||||||
- \[FEATURE REQUEST\] Quiet flag [\#503](https://github.com/doctest/doctest/issues/503)
|
|
||||||
- Compile error on Intel C++ Classic Compilers [\#502](https://github.com/doctest/doctest/issues/502)
|
|
||||||
- compiling doctest in 32-bit with \_\_stdcall calling convention fails [\#500](https://github.com/doctest/doctest/issues/500)
|
|
||||||
- Duplicate 'const' compilation error from TEST\_CASE\_CLASS macro [\#498](https://github.com/doctest/doctest/issues/498)
|
|
||||||
- Packed fields can't be accessed in 2.4.6 [\#495](https://github.com/doctest/doctest/issues/495)
|
|
||||||
- Dangling pointers with .str\(\).c\_str\(\) [\#494](https://github.com/doctest/doctest/issues/494)
|
|
||||||
- Automatic adding of TEST\_SUITE labels to discovered tests fails if ADD\_LABELS not set [\#489](https://github.com/doctest/doctest/issues/489)
|
|
||||||
- Adding a bunch of REQUIRE/CHECK utilities [\#487](https://github.com/doctest/doctest/issues/487)
|
|
||||||
- Warning C4114 in MSVC [\#485](https://github.com/doctest/doctest/issues/485)
|
|
||||||
- Own repository [\#410](https://github.com/doctest/doctest/issues/410)
|
|
||||||
- Linking problem with Clang 10 on Windows [\#362](https://github.com/doctest/doctest/issues/362)
|
|
||||||
- Add option not to print the intro text [\#342](https://github.com/doctest/doctest/issues/342)
|
|
||||||
- \[Feature\] Better integration with tools \(VS Code Test Adapter Extension\) [\#320](https://github.com/doctest/doctest/issues/320)
|
|
||||||
- vscode test explorer [\#303](https://github.com/doctest/doctest/issues/303)
|
|
||||||
- Want an option not to print any intro [\#245](https://github.com/doctest/doctest/issues/245)
|
|
||||||
- Add way to disable printing of intro [\#181](https://github.com/doctest/doctest/issues/181)
|
|
||||||
|
|
||||||
**Merged pull requests:**
|
|
||||||
|
|
||||||
- Make String::operator+ non-member [\#564](https://github.com/doctest/doctest/pull/564) ([Saalvage](https://github.com/Saalvage))
|
|
||||||
- Add -minimal flag [\#562](https://github.com/doctest/doctest/pull/562) ([Saalvage](https://github.com/Saalvage))
|
|
||||||
- Quiet flag [\#561](https://github.com/doctest/doctest/pull/561) ([Saalvage](https://github.com/Saalvage))
|
|
||||||
- Fix redefinition error while using double time DOCTEST\_ANONYMOUS\(DOCTEST\_CAPTURE\_\) [\#557](https://github.com/doctest/doctest/pull/557) ([isaevil](https://github.com/isaevil))
|
|
||||||
- Fix error: missing initializer for member doctest::detail::TestSuite [\#556](https://github.com/doctest/doctest/pull/556) ([isaevil](https://github.com/isaevil))
|
|
||||||
- Xcode 11.3 with macos 10.15 [\#548](https://github.com/doctest/doctest/pull/548) ([jsoref](https://github.com/jsoref))
|
|
||||||
- Spelling [\#546](https://github.com/doctest/doctest/pull/546) ([jsoref](https://github.com/jsoref))
|
|
||||||
- Fix build with -Wunused-but-set-variable [\#543](https://github.com/doctest/doctest/pull/543) ([jktjkt](https://github.com/jktjkt))
|
|
||||||
- build\(meson\): use `override\_dependency` if supported [\#538](https://github.com/doctest/doctest/pull/538) ([Tachi107](https://github.com/Tachi107))
|
|
||||||
- Fix google death test URL [\#528](https://github.com/doctest/doctest/pull/528) ([emrecil](https://github.com/emrecil))
|
|
||||||
- Fixing issue with doctestAddTests.cmake [\#527](https://github.com/doctest/doctest/pull/527) ([jharmer95](https://github.com/jharmer95))
|
|
||||||
- Replace gendered pronouns [\#525](https://github.com/doctest/doctest/pull/525) ([mletterle](https://github.com/mletterle))
|
|
||||||
- Fixed intel compiler parser bug. Should fix \#502 [\#523](https://github.com/doctest/doctest/pull/523) ([BerengerBerthoul](https://github.com/BerengerBerthoul))
|
|
||||||
- specifying working directory for execute\_process in doctest\_discover\_tests [\#518](https://github.com/doctest/doctest/pull/518) ([philbucher](https://github.com/philbucher))
|
|
||||||
- Fix the logic that depends on optional copy elision optimization [\#516](https://github.com/doctest/doctest/pull/516) ([ivankochin](https://github.com/ivankochin))
|
|
||||||
- Fix reserved identifiers [\#510](https://github.com/doctest/doctest/pull/510) ([ts826848](https://github.com/ts826848))
|
|
||||||
- Fix build with GCC 11 [\#505](https://github.com/doctest/doctest/pull/505) ([jktjkt](https://github.com/jktjkt))
|
|
||||||
- minor fixes in MPI docs [\#499](https://github.com/doctest/doctest/pull/499) ([philbucher](https://github.com/philbucher))
|
|
||||||
- Add a minimal bazel config [\#497](https://github.com/doctest/doctest/pull/497) ([elliottt](https://github.com/elliottt))
|
|
||||||
- Handle escaped commas in parsed arguments [\#493](https://github.com/doctest/doctest/pull/493) ([friendlyanon](https://github.com/friendlyanon))
|
|
||||||
- Fixes Issue 476 . When running executables with "-s" stringifyBinaryE… [\#491](https://github.com/doctest/doctest/pull/491) ([navinp0304](https://github.com/navinp0304))
|
|
||||||
- Set variable to 0 if not set [\#490](https://github.com/doctest/doctest/pull/490) ([shivupa](https://github.com/shivupa))
|
|
||||||
|
|
||||||
## [2.4.6](https://github.com/doctest/doctest/tree/2.4.6) (2021-03-22)
|
|
||||||
[Full Changelog](https://github.com/doctest/doctest/compare/2.4.5...2.4.6)
|
|
||||||
|
|
||||||
**Fixed bugs:**
|
|
||||||
|
|
||||||
- REQUIRE does not compile when operator== in different namespace [\#443](https://github.com/doctest/doctest/issues/443)
|
|
||||||
- Using templated operator== inside TEST\_CASE changes deduced types of forwarding references [\#399](https://github.com/doctest/doctest/issues/399)
|
|
||||||
|
|
||||||
**Closed issues:**
|
|
||||||
|
|
||||||
- CMake doesn't link package [\#483](https://github.com/doctest/doctest/issues/483)
|
|
||||||
- Assertions are slow when running on Windows with a debugger attached [\#481](https://github.com/doctest/doctest/issues/481)
|
|
||||||
- Get list of registered test-case names [\#479](https://github.com/doctest/doctest/issues/479)
|
|
||||||
- Can't compile with glibc master \(future 2.34\): SIGSTKSZ is no longer a constant [\#473](https://github.com/doctest/doctest/issues/473)
|
|
||||||
- How to use Doctest with Github Actions [\#472](https://github.com/doctest/doctest/issues/472)
|
|
||||||
- Link error \(multiple definition...\) in simple project [\#470](https://github.com/doctest/doctest/issues/470)
|
|
||||||
- INFO does not compile when used like a function call [\#469](https://github.com/doctest/doctest/issues/469)
|
|
||||||
- std::uncaught\_exceptions is only available if compiling for macOS 10.12 or above [\#466](https://github.com/doctest/doctest/issues/466)
|
|
||||||
- Compile failure with WinRT on 2.4.5 [\#465](https://github.com/doctest/doctest/issues/465)
|
|
||||||
|
|
||||||
**Merged pull requests:**
|
|
||||||
|
|
||||||
- Improve speed with attached debugger \(Windows\) [\#482](https://github.com/doctest/doctest/pull/482) ([pgroke](https://github.com/pgroke))
|
|
||||||
- Convert to bool by casting, rather than double negation [\#480](https://github.com/doctest/doctest/pull/480) ([kitegi](https://github.com/kitegi))
|
|
||||||
- Fix compile error when targeting macOS version earlier and macOS 10.12 [\#478](https://github.com/doctest/doctest/pull/478) ([SamWindell](https://github.com/SamWindell))
|
|
||||||
- Fix MSVC linter warning about uninitialized TestSuite variables [\#471](https://github.com/doctest/doctest/pull/471) ([Reedbeta](https://github.com/Reedbeta))
|
|
||||||
- REQUIRE does not compile when operator== in different namespace \#443 . [\#468](https://github.com/doctest/doctest/pull/468) ([navinp0304](https://github.com/navinp0304))
|
|
||||||
- Automatically add TEST\_SUITE labels to discovered tests [\#464](https://github.com/doctest/doctest/pull/464) ([shivupa](https://github.com/shivupa))
|
|
||||||
|
|
||||||
## [2.4.5](https://github.com/doctest/doctest/tree/2.4.5) (2021-02-02)
|
|
||||||
[Full Changelog](https://github.com/doctest/doctest/compare/2.4.4...2.4.5)
|
|
||||||
|
|
||||||
**Closed issues:**
|
|
||||||
|
|
||||||
- Stack buffer overflow in `String` constructor [\#460](https://github.com/doctest/doctest/issues/460)
|
|
||||||
- Suppress warnings from clang-tidy [\#459](https://github.com/doctest/doctest/issues/459)
|
|
||||||
- compilation issue in MSVC when defining DOCTEST\_THREAD\_LOCAL to static [\#458](https://github.com/doctest/doctest/issues/458)
|
|
||||||
- nvcc compiler warning; doctest.h\(4138\): warning : expression has no effect [\#454](https://github.com/doctest/doctest/issues/454)
|
|
||||||
- Use of std::atomic can slow down multithreaded tests [\#452](https://github.com/doctest/doctest/issues/452)
|
|
||||||
|
|
||||||
**Merged pull requests:**
|
|
||||||
|
|
||||||
- Fix compilation on case-sensitive filesystems [\#463](https://github.com/doctest/doctest/pull/463) ([jhasse](https://github.com/jhasse))
|
|
||||||
- Use function-like macros for prefixless macro names [\#462](https://github.com/doctest/doctest/pull/462) ([tbleher](https://github.com/tbleher))
|
|
||||||
- Implement a multi lane atomic for assertion counts [\#453](https://github.com/doctest/doctest/pull/453) ([martinus](https://github.com/martinus))
|
|
||||||
|
|
||||||
## [2.4.4](https://github.com/doctest/doctest/tree/2.4.4) (2020-12-25)
|
|
||||||
[Full Changelog](https://github.com/doctest/doctest/compare/2.4.3...2.4.4)
|
|
||||||
|
|
||||||
**Closed issues:**
|
|
||||||
|
|
||||||
- 2.4.2: build fails [\#450](https://github.com/doctest/doctest/issues/450)
|
|
||||||
- combine the same tests for different build configurations from multiple shared objects without having symbol clashes [\#436](https://github.com/doctest/doctest/issues/436)
|
|
||||||
- Issue with GitHub Security Scanning: gmtime [\#423](https://github.com/doctest/doctest/issues/423)
|
|
||||||
|
|
||||||
## [2.4.3](https://github.com/doctest/doctest/tree/2.4.3) (2020-12-16)
|
|
||||||
[Full Changelog](https://github.com/doctest/doctest/compare/2.4.2...2.4.3)
|
|
||||||
|
|
||||||
## [2.4.2](https://github.com/doctest/doctest/tree/2.4.2) (2020-12-15)
|
|
||||||
[Full Changelog](https://github.com/doctest/doctest/compare/2.4.1...2.4.2)
|
|
||||||
|
|
||||||
**Closed issues:**
|
|
||||||
|
|
||||||
- DOCTEST\_CHECK\_THROWS\_WITH\_AS fails to work with dependant exception type [\#447](https://github.com/doctest/doctest/issues/447)
|
|
||||||
- MSVC warnings: narrowing conversion, signed/unsigned mismatch [\#446](https://github.com/doctest/doctest/issues/446)
|
|
||||||
- log contexts for failures in JUnit reporter [\#441](https://github.com/doctest/doctest/issues/441)
|
|
||||||
- MinGW "'mutex' in namespace 'std' does not name a type" error. [\#438](https://github.com/doctest/doctest/issues/438)
|
|
||||||
- Test runner thread initialization [\#435](https://github.com/doctest/doctest/issues/435)
|
|
||||||
- PLATFORM is misdetected on MacOSX Big Sur [\#415](https://github.com/doctest/doctest/issues/415)
|
|
||||||
- CHECK\_EQ with enum values [\#276](https://github.com/doctest/doctest/issues/276)
|
|
||||||
|
|
||||||
**Merged pull requests:**
|
|
||||||
|
|
||||||
- Squash MSVC warnings when including ntstatus.h [\#449](https://github.com/doctest/doctest/pull/449) ([nickhutchinson](https://github.com/nickhutchinson))
|
|
||||||
- Add MAIN\_PROJECT check for test option [\#445](https://github.com/doctest/doctest/pull/445) ([globberwops](https://github.com/globberwops))
|
|
||||||
- Suppress clang-analyzer-cplusplus.NewDeleteLeaks [\#444](https://github.com/doctest/doctest/pull/444) ([ncihnegn](https://github.com/ncihnegn))
|
|
||||||
- log contexts for failures in JUnit reporter [\#442](https://github.com/doctest/doctest/pull/442) ([runave](https://github.com/runave))
|
|
||||||
- Fix 32bit support on macOS [\#440](https://github.com/doctest/doctest/pull/440) ([AlexanderLanin](https://github.com/AlexanderLanin))
|
|
||||||
|
|
||||||
## [2.4.1](https://github.com/doctest/doctest/tree/2.4.1) (2020-11-04)
|
|
||||||
[Full Changelog](https://github.com/doctest/doctest/compare/2.4.0...2.4.1)
|
|
||||||
|
|
||||||
**Closed issues:**
|
|
||||||
|
|
||||||
- Avoid old C-style casts [\#424](https://github.com/doctest/doctest/issues/424)
|
|
||||||
- Segfault in unwind [\#422](https://github.com/doctest/doctest/issues/422)
|
|
||||||
- Inspect exception with gdb [\#421](https://github.com/doctest/doctest/issues/421)
|
|
||||||
- use-of-uninitialized-value [\#414](https://github.com/doctest/doctest/issues/414)
|
|
||||||
- Support unit tests with MPI [\#413](https://github.com/doctest/doctest/issues/413)
|
|
||||||
- Break into debugger support is missing for Linux [\#411](https://github.com/doctest/doctest/issues/411)
|
|
||||||
- What if built doctest as static library instead of header-only [\#408](https://github.com/doctest/doctest/issues/408)
|
|
||||||
- \[Question\] How to get test case name [\#407](https://github.com/doctest/doctest/issues/407)
|
|
||||||
- create extensions header for optional features requiring more std includes or newer C++ features [\#405](https://github.com/doctest/doctest/issues/405)
|
|
||||||
- tests/asserts summary lines are misaligned when counts exceed 999999 [\#402](https://github.com/doctest/doctest/issues/402)
|
|
||||||
- Call to 'ne' is ambiguous -- with solution [\#395](https://github.com/doctest/doctest/issues/395)
|
|
||||||
- Intermittent Segfaults [\#391](https://github.com/doctest/doctest/issues/391)
|
|
||||||
- Junit classname [\#390](https://github.com/doctest/doctest/issues/390)
|
|
||||||
- Add default printers for enums [\#121](https://github.com/doctest/doctest/issues/121)
|
|
||||||
|
|
||||||
**Merged pull requests:**
|
|
||||||
|
|
||||||
- Enum support \(fix for Issue \#121\) [\#429](https://github.com/doctest/doctest/pull/429) ([jkriegshauser](https://github.com/jkriegshauser))
|
|
||||||
- Support Clang 3.4 [\#428](https://github.com/doctest/doctest/pull/428) ([AlexanderLanin](https://github.com/AlexanderLanin))
|
|
||||||
- Silence remarks on old C-style casts [\#425](https://github.com/doctest/doctest/pull/425) ([UnePierre](https://github.com/UnePierre))
|
|
||||||
- Initial MPI unit tests implementation [\#418](https://github.com/doctest/doctest/pull/418) ([BerengerBerthoul](https://github.com/BerengerBerthoul))
|
|
||||||
- Add JUNIT\_OUTPUT\_DIR option to doctest\_discover\_tests [\#417](https://github.com/doctest/doctest/pull/417) ([Tradias](https://github.com/Tradias))
|
|
||||||
- Add option to build with std headers. [\#416](https://github.com/doctest/doctest/pull/416) ([avostrik](https://github.com/avostrik))
|
|
||||||
- Port Catch2 break into debugger for Linux. closes \#411 [\#412](https://github.com/doctest/doctest/pull/412) ([mikezackles](https://github.com/mikezackles))
|
|
||||||
- summary: align even large values \#402 [\#403](https://github.com/doctest/doctest/pull/403) ([dankamongmen](https://github.com/dankamongmen))
|
|
||||||
- Add breakpoint inline assembly for the Apple Silicon macOS. [\#400](https://github.com/doctest/doctest/pull/400) ([bruvzg](https://github.com/bruvzg))
|
|
||||||
- fix google's death test URI in roadmap [\#393](https://github.com/doctest/doctest/pull/393) ([ashutosh108](https://github.com/ashutosh108))
|
|
||||||
|
|
||||||
## [2.4.0](https://github.com/doctest/doctest/tree/2.4.0) (2020-06-27)
|
|
||||||
[Full Changelog](https://github.com/doctest/doctest/compare/2.3.8...2.4.0)
|
|
||||||
|
|
||||||
**Closed issues:**
|
|
||||||
|
|
||||||
- Count points based on the number of passed/failed cases? [\#386](https://github.com/doctest/doctest/issues/386)
|
|
||||||
- How to understand "\#data\_array" in std::string? [\#383](https://github.com/doctest/doctest/issues/383)
|
|
||||||
- crash: doctest with custom allocator [\#382](https://github.com/doctest/doctest/issues/382)
|
|
||||||
- Feature Request: format PRIVATE/PUBLIC/INTERFACE entries with constant indentation [\#378](https://github.com/doctest/doctest/issues/378)
|
|
||||||
- JUnit Reporter for Doctest [\#376](https://github.com/doctest/doctest/issues/376)
|
|
||||||
- Avoiding Feature Bloat [\#374](https://github.com/doctest/doctest/issues/374)
|
|
||||||
- StringMaker\<wchar\_t\> fail to compile with C++20 enabled \(GCC\) [\#357](https://github.com/doctest/doctest/issues/357)
|
|
||||||
- doctest\_discover\_tests and FetchContent\_Declare [\#351](https://github.com/doctest/doctest/issues/351)
|
|
||||||
- Junit reporter [\#318](https://github.com/doctest/doctest/issues/318)
|
|
||||||
|
|
||||||
**Merged pull requests:**
|
|
||||||
|
|
||||||
- Add a note that doctest can be installed through Homebrew [\#388](https://github.com/doctest/doctest/pull/388) ([cameronwhite](https://github.com/cameronwhite))
|
|
||||||
- provide alternative implementation of has\_insertion\_operator for C++20 [\#387](https://github.com/doctest/doctest/pull/387) ([lukaszgemborowski](https://github.com/lukaszgemborowski))
|
|
||||||
- Fix issue template to mention doctest [\#380](https://github.com/doctest/doctest/pull/380) ([nyanpasu64](https://github.com/nyanpasu64))
|
|
||||||
|
|
||||||
## [2.3.8](https://github.com/doctest/doctest/tree/2.3.8) (2020-05-17)
|
|
||||||
[Full Changelog](https://github.com/doctest/doctest/compare/2.3.7...2.3.8)
|
|
||||||
|
|
||||||
**Closed issues:**
|
|
||||||
|
|
||||||
- Scenario name can not be passed to -tc to execute single scenario [\#373](https://github.com/doctest/doctest/issues/373)
|
|
||||||
- Compile Error with CHECK\_NOTHROW when using 2 Template Arguments [\#372](https://github.com/doctest/doctest/issues/372)
|
|
||||||
- dll example won't compile [\#371](https://github.com/doctest/doctest/issues/371)
|
|
||||||
- Build error with MinGW \(Mingw-w64\) due to missing Windows.h \(with capital W\) [\#370](https://github.com/doctest/doctest/issues/370)
|
|
||||||
- How to override file\_line\_to\_stream? [\#369](https://github.com/doctest/doctest/issues/369)
|
|
||||||
- Memory sanitizer fails. [\#365](https://github.com/doctest/doctest/issues/365)
|
|
||||||
- Warning c6319 in Visual Studio [\#359](https://github.com/doctest/doctest/issues/359)
|
|
||||||
- Any option to show each test case's execute time? [\#358](https://github.com/doctest/doctest/issues/358)
|
|
||||||
- doctest in embedded [\#355](https://github.com/doctest/doctest/issues/355)
|
|
||||||
- Reloading a plugin with test cases leads to a segmentation fault [\#350](https://github.com/doctest/doctest/issues/350)
|
|
||||||
- Compiling with DOCTEST\_CONFIG\_COLORS\_ANSI fails on Windows [\#348](https://github.com/doctest/doctest/issues/348)
|
|
||||||
- Can I inherit ConsoleReporter? [\#344](https://github.com/doctest/doctest/issues/344)
|
|
||||||
- Noreturn and noexcept defines for Visual Studio 2013 support [\#327](https://github.com/doctest/doctest/issues/327)
|
|
||||||
- Data-driven testing -- print out the deepest DOCTEST\_SUBCASE [\#215](https://github.com/doctest/doctest/issues/215)
|
|
||||||
- Print the SUBCASE path when an assert fails in the TEST\_CASE body [\#125](https://github.com/doctest/doctest/issues/125)
|
|
||||||
|
|
||||||
**Merged pull requests:**
|
|
||||||
|
|
||||||
- fix: possible UB with nullptr increment [\#368](https://github.com/doctest/doctest/pull/368) ([oktonion](https://github.com/oktonion))
|
|
||||||
- Use CMake's CMP0077 policy if available [\#363](https://github.com/doctest/doctest/pull/363) ([thelink2012](https://github.com/thelink2012))
|
|
||||||
- Fix warning c6319 in Visual Studio 16.5 [\#361](https://github.com/doctest/doctest/pull/361) ([Cvelth](https://github.com/Cvelth))
|
|
||||||
|
|
||||||
## [2.3.7](https://github.com/doctest/doctest/tree/2.3.7) (2020-02-24)
|
|
||||||
[Full Changelog](https://github.com/doctest/doctest/compare/2.3.6...2.3.7)
|
|
||||||
|
|
||||||
**Closed issues:**
|
|
||||||
|
|
||||||
- Some of the GitHub CI builds are failing [\#334](https://github.com/doctest/doctest/issues/334)
|
|
||||||
- C++20 removed std::uncaught\_exception [\#333](https://github.com/doctest/doctest/issues/333)
|
|
||||||
- Doctest SEH handlers are called before \_\_except handlers [\#324](https://github.com/doctest/doctest/issues/324)
|
|
||||||
|
|
||||||
**Merged pull requests:**
|
|
||||||
|
|
||||||
- using std namespace where necessary and timer ticks fix [\#341](https://github.com/doctest/doctest/pull/341) ([oktonion](https://github.com/oktonion))
|
|
||||||
- fix std::uncaught\_exceptions [\#340](https://github.com/doctest/doctest/pull/340) ([cyyever](https://github.com/cyyever))
|
|
||||||
- Fix GitHub CI and add GitHub build badges [\#336](https://github.com/doctest/doctest/pull/336) ([claremacrae](https://github.com/claremacrae))
|
|
||||||
- http -\> https [\#331](https://github.com/doctest/doctest/pull/331) ([Coeur](https://github.com/Coeur))
|
|
||||||
- Switch to catching unhandled exceptions on Windows Closes \#324 [\#325](https://github.com/doctest/doctest/pull/325) ([jkriegshauser](https://github.com/jkriegshauser))
|
|
||||||
|
|
||||||
## [2.3.6](https://github.com/doctest/doctest/tree/2.3.6) (2019-12-16)
|
|
||||||
[Full Changelog](https://github.com/doctest/doctest/compare/2.3.5...2.3.6)
|
|
||||||
|
|
||||||
**Closed issues:**
|
|
||||||
|
|
||||||
- Link problem w/ BUILD=Release if MESSAGE\(\) with std::string/ostream-operator is used [\#316](https://github.com/doctest/doctest/issues/316)
|
|
||||||
- the FAQ about difference to Catch2 is missing tags [\#315](https://github.com/doctest/doctest/issues/315)
|
|
||||||
- include Windows.h in small caps to silence clang warnings [\#312](https://github.com/doctest/doctest/issues/312)
|
|
||||||
- Mistake in generator with lgtm error [\#311](https://github.com/doctest/doctest/issues/311)
|
|
||||||
- CMake: cannot install target doctest\_with\_main [\#310](https://github.com/doctest/doctest/issues/310)
|
|
||||||
- \[bug\] INFO\(\) and CAPTURE\(\) cannot compile using MSVC when used with DOCTEST\_CONFIG\_IMPLEMENTATION\_IN\_DLL [\#306](https://github.com/doctest/doctest/issues/306)
|
|
||||||
- Skip subcase [\#304](https://github.com/doctest/doctest/issues/304)
|
|
||||||
- Does some equivalent features from google test exist here? [\#300](https://github.com/doctest/doctest/issues/300)
|
|
||||||
- How to use doctest in dll only\(without main.cpp and .exe\) [\#299](https://github.com/doctest/doctest/issues/299)
|
|
||||||
- Warning: C26812: The enum type 'doctest::assertType::Enum' is unscoped. Prefer 'enum class' over 'enum' \(Enum.3\). [\#298](https://github.com/doctest/doctest/issues/298)
|
|
||||||
- test executable\_dll\_and\_plugin fails on Linux, GCC 8.1.0, -fsanitize=address [\#201](https://github.com/doctest/doctest/issues/201)
|
|
||||||
|
|
||||||
**Merged pull requests:**
|
|
||||||
|
|
||||||
- Fixed missing ostream include for MacOS when defining DOCTEST\_CONFIG\_… [\#314](https://github.com/doctest/doctest/pull/314) ([NKTomHaygarth](https://github.com/NKTomHaygarth))
|
|
||||||
- include windows.h in cmall caps to silence clang nonportable warnings [\#313](https://github.com/doctest/doctest/pull/313) ([suoniq](https://github.com/suoniq))
|
|
||||||
- Add .editorconfig file. [\#301](https://github.com/doctest/doctest/pull/301) ([DaanDeMeyer](https://github.com/DaanDeMeyer))
|
|
||||||
- Add Github Actions CI [\#285](https://github.com/doctest/doctest/pull/285) ([DaanDeMeyer](https://github.com/DaanDeMeyer))
|
|
||||||
|
|
||||||
## [2.3.5](https://github.com/doctest/doctest/tree/2.3.5) (2019-09-22)
|
|
||||||
[Full Changelog](https://github.com/doctest/doctest/compare/2.3.4...2.3.5)
|
|
||||||
|
|
||||||
**Closed issues:**
|
|
||||||
|
|
||||||
- \[feature request\] Assertion macros for throwing exception of a specific type with message - \<LEVEL\>\_THROWS\_WITH\_AS\(expr, string, ex\_type\) [\#295](https://github.com/doctest/doctest/issues/295)
|
|
||||||
- CHECK\_THROWS\_AS of non-default constructor wants to call default constructor [\#293](https://github.com/doctest/doctest/issues/293)
|
|
||||||
- Typos and spelling errors in source, documentation and scripts [\#291](https://github.com/doctest/doctest/issues/291)
|
|
||||||
- Customize test names / variable substitution [\#284](https://github.com/doctest/doctest/issues/284)
|
|
||||||
- SUBCASE in function not behaving as expected [\#282](https://github.com/doctest/doctest/issues/282)
|
|
||||||
- SUPER\_FAST\_ASSERTS fails to compile CHECK\_MESSAGE [\#281](https://github.com/doctest/doctest/issues/281)
|
|
||||||
- CHECK\_MESSAGE no longer works with DOCTEST\_CONFIG\_SUPER\_FAST\_ASSERTS [\#280](https://github.com/doctest/doctest/issues/280)
|
|
||||||
- CAPTURE of structured binding element no longer works [\#279](https://github.com/doctest/doctest/issues/279)
|
|
||||||
- Reporter: `test\_case\_end` no longer fired after test case restart [\#278](https://github.com/doctest/doctest/issues/278)
|
|
||||||
- Add debug break override support [\#277](https://github.com/doctest/doctest/issues/277)
|
|
||||||
- Running tests from within Visual Studio in a static lib project [\#275](https://github.com/doctest/doctest/issues/275)
|
|
||||||
- Compile-time error when using a raw string literal inside of REQUIRE \(MSVC 2017\) [\#274](https://github.com/doctest/doctest/issues/274)
|
|
||||||
- Give example for having tests in production code [\#252](https://github.com/doctest/doctest/issues/252)
|
|
||||||
- Memory leaks just by including doctest.h [\#205](https://github.com/doctest/doctest/issues/205)
|
|
||||||
- Feature request: print subcase when an exception is thrown inside one [\#136](https://github.com/doctest/doctest/issues/136)
|
|
||||||
|
|
||||||
**Merged pull requests:**
|
|
||||||
|
|
||||||
- Fix typos and misspellings found by codespell. [\#292](https://github.com/doctest/doctest/pull/292) ([warmsocks](https://github.com/warmsocks))
|
|
||||||
- Document order by issue correctly [\#290](https://github.com/doctest/doctest/pull/290) ([DaanDeMeyer](https://github.com/DaanDeMeyer))
|
|
||||||
- Document that -order-by=file is compiler-dependent [\#289](https://github.com/doctest/doctest/pull/289) ([DaanDeMeyer](https://github.com/DaanDeMeyer))
|
|
||||||
- Add -order-by=name to filter\_2 test [\#288](https://github.com/doctest/doctest/pull/288) ([DaanDeMeyer](https://github.com/DaanDeMeyer))
|
|
||||||
- Add support for compiling with clang-cl [\#286](https://github.com/doctest/doctest/pull/286) ([DaanDeMeyer](https://github.com/DaanDeMeyer))
|
|
||||||
- No minimum version limitation of Meson [\#283](https://github.com/doctest/doctest/pull/283) ([ydm](https://github.com/ydm))
|
|
||||||
|
|
||||||
## [2.3.4](https://github.com/doctest/doctest/tree/2.3.4) (2019-08-12)
|
|
||||||
[Full Changelog](https://github.com/doctest/doctest/compare/2.3.3...2.3.4)
|
|
||||||
|
|
||||||
**Closed issues:**
|
|
||||||
|
|
||||||
- Remove INFO\(\) limitation for using only lvalues and no rvalues [\#269](https://github.com/doctest/doctest/issues/269)
|
|
||||||
- Compile error on MAC OS with AppleClang 8.0.0.8000042 [\#266](https://github.com/doctest/doctest/issues/266)
|
|
||||||
- Throwing exception in a mocked method [\#265](https://github.com/doctest/doctest/issues/265)
|
|
||||||
- Illegal syntax for decorators compiles and runs without warning, but has no effect [\#264](https://github.com/doctest/doctest/issues/264)
|
|
||||||
- Support conditional expressions in REQUIRE [\#262](https://github.com/doctest/doctest/issues/262)
|
|
||||||
- Register a listener\(reporter\) that always listens [\#257](https://github.com/doctest/doctest/issues/257)
|
|
||||||
- Memory sanitizer complaint [\#255](https://github.com/doctest/doctest/issues/255)
|
|
||||||
- Windows Clang GNU command line warnings [\#253](https://github.com/doctest/doctest/issues/253)
|
|
||||||
- The build writes into the source directory [\#249](https://github.com/doctest/doctest/issues/249)
|
|
||||||
- How to enable tests inside another exe [\#246](https://github.com/doctest/doctest/issues/246)
|
|
||||||
- Testing multiple headers. [\#244](https://github.com/doctest/doctest/issues/244)
|
|
||||||
- CMakeLists.txt: Needs CMAKE\_CXX\_STANDARD=11 [\#243](https://github.com/doctest/doctest/issues/243)
|
|
||||||
- \[bug\] Can't compile the tests because of mutex, that is declared in the doctest [\#242](https://github.com/doctest/doctest/issues/242)
|
|
||||||
|
|
||||||
**Merged pull requests:**
|
|
||||||
|
|
||||||
- Improve Listener docs [\#273](https://github.com/doctest/doctest/pull/273) ([claremacrae](https://github.com/claremacrae))
|
|
||||||
- Rework `INFO` lazy evaluation to use lambdas. [\#270](https://github.com/doctest/doctest/pull/270) ([DaanDeMeyer](https://github.com/DaanDeMeyer))
|
|
||||||
- Prevent compile errors with AppleClang compiler [\#268](https://github.com/doctest/doctest/pull/268) ([ClausKlein](https://github.com/ClausKlein))
|
|
||||||
- Revert "fix : including windows.h header cause error" [\#263](https://github.com/doctest/doctest/pull/263) ([onqtam](https://github.com/onqtam))
|
|
||||||
- Fix static analyzer URLs [\#259](https://github.com/doctest/doctest/pull/259) ([godbyk](https://github.com/godbyk))
|
|
||||||
- fix : including windows.h header cause error [\#258](https://github.com/doctest/doctest/pull/258) ([rinechran](https://github.com/rinechran))
|
|
||||||
- only look for C++ compiler with CMake [\#256](https://github.com/doctest/doctest/pull/256) ([zhihaoy](https://github.com/zhihaoy))
|
|
||||||
- Fix \#253 [\#254](https://github.com/doctest/doctest/pull/254) ([DaanDeMeyer](https://github.com/DaanDeMeyer))
|
|
||||||
- add alias target for doctest for use in build tree [\#247](https://github.com/doctest/doctest/pull/247) ([trondhe](https://github.com/trondhe))
|
|
||||||
|
|
||||||
## [2.3.3](https://github.com/doctest/doctest/tree/2.3.3) (2019-06-02)
|
|
||||||
[Full Changelog](https://github.com/doctest/doctest/compare/2.3.2...2.3.3)
|
|
||||||
|
|
||||||
**Closed issues:**
|
|
||||||
|
|
||||||
- Build fails with gcc9 because of -Wstrict-overflow=5 which is too high [\#241](https://github.com/doctest/doctest/issues/241)
|
|
||||||
- doctest given defined with short macro name [\#239](https://github.com/doctest/doctest/issues/239)
|
|
||||||
- Splitting templated test across different translation units [\#238](https://github.com/doctest/doctest/issues/238)
|
|
||||||
- Compile errors with iosfwd.h and Visual Studio 2019 Preview [\#183](https://github.com/doctest/doctest/issues/183)
|
|
||||||
- Add CMake test support as catch\_discover\_tests\(\) in Catch2 [\#171](https://github.com/doctest/doctest/issues/171)
|
|
||||||
|
|
||||||
**Merged pull requests:**
|
|
||||||
|
|
||||||
- fix \#239 - use long macro name [\#240](https://github.com/doctest/doctest/pull/240) ([m-bd](https://github.com/m-bd))
|
|
||||||
- Add doctest\_discover\_tests\(\) [\#236](https://github.com/doctest/doctest/pull/236) ([reddwarf69](https://github.com/reddwarf69))
|
|
||||||
- Ignore redundant-decls warning on MinGW [\#235](https://github.com/doctest/doctest/pull/235) ([AMS21](https://github.com/AMS21))
|
|
||||||
- Fixed meson build file dependency declaration [\#233](https://github.com/doctest/doctest/pull/233) ([jormundgand](https://github.com/jormundgand))
|
|
||||||
|
|
||||||
## [2.3.2](https://github.com/doctest/doctest/tree/2.3.2) (2019-05-06)
|
|
||||||
[Full Changelog](https://github.com/doctest/doctest/compare/2.3.1...2.3.2)
|
|
||||||
|
|
||||||
**Closed issues:**
|
|
||||||
|
|
||||||
- scripts/bench/run\_all.py : module 'urllib' has no attribute 'urlretrieve' [\#230](https://github.com/doctest/doctest/issues/230)
|
|
||||||
- wrong set of tests registered with TEST\_CASE\_TEMPLATE get executed [\#228](https://github.com/doctest/doctest/issues/228)
|
|
||||||
- Logging not Working for me [\#227](https://github.com/doctest/doctest/issues/227)
|
|
||||||
- Link test runner executable into dll? [\#226](https://github.com/doctest/doctest/issues/226)
|
|
||||||
- Linking issue for executables after including doctest in library [\#224](https://github.com/doctest/doctest/issues/224)
|
|
||||||
- Strange REQUIRE\_THROWS behaviour [\#223](https://github.com/doctest/doctest/issues/223)
|
|
||||||
- Windows clang-cl -Wunused-variable warning [\#221](https://github.com/doctest/doctest/issues/221)
|
|
||||||
- Update doctest 2.3.1 in bincrafters [\#220](https://github.com/doctest/doctest/issues/220)
|
|
||||||
- make install, on 64 bit, installs cmake files into lib instead of lib64 folder [\#218](https://github.com/doctest/doctest/issues/218)
|
|
||||||
- TSAN: data race related to hasLoggedCurrentTestStart [\#217](https://github.com/doctest/doctest/issues/217)
|
|
||||||
- REQUIRE\_THROWS\_AS does not support class constructors [\#216](https://github.com/doctest/doctest/issues/216)
|
|
||||||
- Build failure on clang 7.0.1 on Fedora 29 [\#214](https://github.com/doctest/doctest/issues/214)
|
|
||||||
- add example compatible with -\> https://github.com/report-ci/ [\#212](https://github.com/doctest/doctest/issues/212)
|
|
||||||
- No DOCTEST\_WITH\_TESTS? [\#211](https://github.com/doctest/doctest/issues/211)
|
|
||||||
|
|
||||||
**Merged pull requests:**
|
|
||||||
|
|
||||||
- Added meson file, to declare a dependency. [\#232](https://github.com/doctest/doctest/pull/232) ([jormundgand](https://github.com/jormundgand))
|
|
||||||
- Explicitly specify the doctest\_with\_main C++ standard in CMake. [\#231](https://github.com/doctest/doctest/pull/231) ([DaanDeMeyer](https://github.com/DaanDeMeyer))
|
|
||||||
- Remove architecture check from CMake package [\#225](https://github.com/doctest/doctest/pull/225) ([mmha](https://github.com/mmha))
|
|
||||||
- add default install prefix [\#219](https://github.com/doctest/doctest/pull/219) ([a4z](https://github.com/a4z))
|
|
||||||
- \[regression\] Workaround MSVC preprocessor issue triggered by REQUIRE\_THROWS [\#213](https://github.com/doctest/doctest/pull/213) ([zhihaoy](https://github.com/zhihaoy))
|
|
||||||
|
|
||||||
## [2.3.1](https://github.com/doctest/doctest/tree/2.3.1) (2019-03-24)
|
|
||||||
[Full Changelog](https://github.com/doctest/doctest/compare/2.3.0...2.3.1)
|
|
||||||
|
|
||||||
**Merged pull requests:**
|
|
||||||
|
|
||||||
- Add two very simple examples of using doctest with CMake [\#209](https://github.com/doctest/doctest/pull/209) ([pr0g](https://github.com/pr0g))
|
|
||||||
|
|
||||||
## [2.3.0](https://github.com/doctest/doctest/tree/2.3.0) (2019-03-23)
|
|
||||||
[Full Changelog](https://github.com/doctest/doctest/compare/2.2.3...2.3.0)
|
|
||||||
|
|
||||||
**Closed issues:**
|
|
||||||
|
|
||||||
- Compilation with emscripten fails by default because of signal handling [\#207](https://github.com/doctest/doctest/issues/207)
|
|
||||||
- Compilation fails with cl.exe /Zc:wchar\_t- [\#206](https://github.com/doctest/doctest/issues/206)
|
|
||||||
- Parallel invocation of doctest's own testsuite via CTest fails [\#202](https://github.com/doctest/doctest/issues/202)
|
|
||||||
- Get the number of passed/failed tests in the code [\#200](https://github.com/doctest/doctest/issues/200)
|
|
||||||
- Tests alongside code with multiple executables [\#199](https://github.com/doctest/doctest/issues/199)
|
|
||||||
- Cppcheck 1.86 warnings [\#198](https://github.com/doctest/doctest/issues/198)
|
|
||||||
- Compiling as Dll maybe is wrong [\#196](https://github.com/doctest/doctest/issues/196)
|
|
||||||
- Forward-declaring identifiers in std:: is UB - consider including some of the cheaper C/C++ stdlib headers [\#194](https://github.com/doctest/doctest/issues/194)
|
|
||||||
- QtCreator + clang warning about operator \<\< precedence [\#191](https://github.com/doctest/doctest/issues/191)
|
|
||||||
- run test fixture from cli [\#190](https://github.com/doctest/doctest/issues/190)
|
|
||||||
- Installing doctest using cmake and make fails on Ubuntu 16.04 \(C++11 is not used\) [\#189](https://github.com/doctest/doctest/issues/189)
|
|
||||||
- c++17 requirement for testing private members [\#188](https://github.com/doctest/doctest/issues/188)
|
|
||||||
- \[feature request\] implement a user-extendable reporter system [\#138](https://github.com/doctest/doctest/issues/138)
|
|
||||||
- Same test runs multiple times when written in a header and included with different unnormalized paths [\#45](https://github.com/doctest/doctest/issues/45)
|
|
||||||
|
|
||||||
**Merged pull requests:**
|
|
||||||
|
|
||||||
- Fix unmatched bracket in DOCTEST\_TEST\_CASE\_CLASS [\#204](https://github.com/doctest/doctest/pull/204) ([patstew](https://github.com/patstew))
|
|
||||||
- Template apply [\#203](https://github.com/doctest/doctest/pull/203) ([zhihaoy](https://github.com/zhihaoy))
|
|
||||||
- No undefined behavior per C++ standard in detecting endianness. [\#195](https://github.com/doctest/doctest/pull/195) ([dimztimz](https://github.com/dimztimz))
|
|
||||||
- Fix propagating include directories of target doctest\_with\_main [\#193](https://github.com/doctest/doctest/pull/193) ([dimztimz](https://github.com/dimztimz))
|
|
||||||
- Move single header to a separate folder [\#187](https://github.com/doctest/doctest/pull/187) ([dimztimz](https://github.com/dimztimz))
|
|
||||||
- Fix Clang format to handle C++11 [\#186](https://github.com/doctest/doctest/pull/186) ([dimztimz](https://github.com/dimztimz))
|
|
||||||
- Rename doctest\_impl.h to doctest.cpp for less confusion. [\#185](https://github.com/doctest/doctest/pull/185) ([dimztimz](https://github.com/dimztimz))
|
|
||||||
|
|
||||||
## [2.2.3](https://github.com/doctest/doctest/tree/2.2.3) (2019-02-10)
|
|
||||||
[Full Changelog](https://github.com/doctest/doctest/compare/2.2.2...2.2.3)
|
|
||||||
|
|
||||||
**Closed issues:**
|
|
||||||
|
|
||||||
- Calling convention needed on a few functions [\#182](https://github.com/doctest/doctest/issues/182)
|
|
||||||
- Terminal color is not reset when a test fails with some signal [\#122](https://github.com/doctest/doctest/issues/122)
|
|
||||||
|
|
||||||
## [2.2.2](https://github.com/doctest/doctest/tree/2.2.2) (2019-01-28)
|
|
||||||
[Full Changelog](https://github.com/doctest/doctest/compare/2.2.1...2.2.2)
|
|
||||||
|
|
||||||
**Closed issues:**
|
|
||||||
|
|
||||||
- Add way to override getCurrentTicks\(\) implementation [\#178](https://github.com/doctest/doctest/issues/178)
|
|
||||||
- Wrap \<csignal\> include with ifdef [\#177](https://github.com/doctest/doctest/issues/177)
|
|
||||||
- How to stop doctest hijack unhandled exceptions? [\#176](https://github.com/doctest/doctest/issues/176)
|
|
||||||
- Change the include path of the `doctest` CMake interface target so users need to specify the folder as well [\#175](https://github.com/doctest/doctest/issues/175)
|
|
||||||
- Reduce scope of DebugOutputWindowReporter instance [\#174](https://github.com/doctest/doctest/issues/174)
|
|
||||||
- Can logging \(INFO\) be used in helper class outside of TEST\_CASE? [\#169](https://github.com/doctest/doctest/issues/169)
|
|
||||||
|
|
||||||
**Merged pull requests:**
|
|
||||||
|
|
||||||
- Change the include path in examples as \#175 [\#180](https://github.com/doctest/doctest/pull/180) ([ncihnegn](https://github.com/ncihnegn))
|
|
||||||
- Fix CMake include path \#175 [\#179](https://github.com/doctest/doctest/pull/179) ([ncihnegn](https://github.com/ncihnegn))
|
|
||||||
|
|
||||||
## [2.2.1](https://github.com/doctest/doctest/tree/2.2.1) (2019-01-15)
|
|
||||||
[Full Changelog](https://github.com/doctest/doctest/compare/2.2.0...2.2.1)
|
|
||||||
|
|
||||||
**Closed issues:**
|
|
||||||
|
|
||||||
- the `--no-throw` option shouldn't affect `\<LEVEL\>\_NOTHROW` asserts [\#173](https://github.com/doctest/doctest/issues/173)
|
|
||||||
- Make doctest work with XCode 6 and 7 \(no support for C++11 thread\_local\) [\#172](https://github.com/doctest/doctest/issues/172)
|
|
||||||
- Print vector content. [\#170](https://github.com/doctest/doctest/issues/170)
|
|
||||||
- Conan package [\#103](https://github.com/doctest/doctest/issues/103)
|
|
||||||
- \[feature request\] Thread-safety for asserts and logging facilities [\#4](https://github.com/doctest/doctest/issues/4)
|
|
||||||
|
|
||||||
## [2.2.0](https://github.com/doctest/doctest/tree/2.2.0) (2018-12-05)
|
|
||||||
[Full Changelog](https://github.com/doctest/doctest/compare/2.1.0...2.2.0)
|
|
||||||
|
|
||||||
**Closed issues:**
|
|
||||||
|
|
||||||
- remove the FAST\_ versions of the binary asserts \(not a breaking change!\) [\#167](https://github.com/doctest/doctest/issues/167)
|
|
||||||
- \[compile times\] make the DOCTEST\_CONFIG\_SUPER\_FAST\_ASSERTS identifier affect normal asserts too [\#166](https://github.com/doctest/doctest/issues/166)
|
|
||||||
|
|
||||||
## [2.1.0](https://github.com/doctest/doctest/tree/2.1.0) (2018-11-30)
|
|
||||||
[Full Changelog](https://github.com/doctest/doctest/compare/2.0.1...2.1.0)
|
|
||||||
|
|
||||||
**Closed issues:**
|
|
||||||
|
|
||||||
- doctest::String ctor with non-zero terminated string [\#165](https://github.com/doctest/doctest/issues/165)
|
|
||||||
- thread\_local is not supported on iOS 9.0 [\#164](https://github.com/doctest/doctest/issues/164)
|
|
||||||
- Compiler error on Android NDK r18 [\#163](https://github.com/doctest/doctest/issues/163)
|
|
||||||
- \[question\] One setup for multiple tests [\#160](https://github.com/doctest/doctest/issues/160)
|
|
||||||
- clang unwanted warning in user code [\#156](https://github.com/doctest/doctest/issues/156)
|
|
||||||
- Unsigned integer overflow in fileOrderComparator [\#151](https://github.com/doctest/doctest/issues/151)
|
|
||||||
- ThreadSanitizer: signal-unsafe call inside of a signal [\#147](https://github.com/doctest/doctest/issues/147)
|
|
||||||
- Feature request: check for exception string \(like Catch's CHECK\_THROWS\_WITH\) [\#97](https://github.com/doctest/doctest/issues/97)
|
|
||||||
|
|
||||||
**Merged pull requests:**
|
|
||||||
|
|
||||||
- Fixed build error under Android NDK [\#162](https://github.com/doctest/doctest/pull/162) ([tals](https://github.com/tals))
|
|
||||||
- Added clang-7 to travis build [\#161](https://github.com/doctest/doctest/pull/161) ([AMS21](https://github.com/AMS21))
|
|
||||||
- Remove clang-tidy warnings for static fields created by doctest [\#159](https://github.com/doctest/doctest/pull/159) ([rantasub](https://github.com/rantasub))
|
|
||||||
- Make it possible to change the command line options prefix [\#158](https://github.com/doctest/doctest/pull/158) ([tbleher](https://github.com/tbleher))
|
|
||||||
|
|
||||||
## [2.0.1](https://github.com/doctest/doctest/tree/2.0.1) (2018-10-24)
|
|
||||||
[Full Changelog](https://github.com/doctest/doctest/compare/2.0.0...2.0.1)
|
|
||||||
|
|
||||||
**Closed issues:**
|
|
||||||
|
|
||||||
- macro name collision with google log [\#157](https://github.com/doctest/doctest/issues/157)
|
|
||||||
- Add \#define to not run tests by default [\#152](https://github.com/doctest/doctest/issues/152)
|
|
||||||
- REQUIRE\_THROWS\_MESSAGE not checking message correctly [\#150](https://github.com/doctest/doctest/issues/150)
|
|
||||||
- Test case passes even though subcase failed [\#149](https://github.com/doctest/doctest/issues/149)
|
|
||||||
|
|
||||||
**Merged pull requests:**
|
|
||||||
|
|
||||||
- Correctly document when a main\(\) entry point will be created [\#155](https://github.com/doctest/doctest/pull/155) ([tbleher](https://github.com/tbleher))
|
|
||||||
- Correct format string for unsigned char [\#154](https://github.com/doctest/doctest/pull/154) ([tbleher](https://github.com/tbleher))
|
|
||||||
|
|
||||||
## [2.0.0](https://github.com/doctest/doctest/tree/2.0.0) (2018-08-23)
|
|
||||||
[Full Changelog](https://github.com/doctest/doctest/compare/1.2.9...2.0.0)
|
|
||||||
|
|
||||||
**Closed issues:**
|
|
||||||
|
|
||||||
- MSVC 2017 15.8.1, New Warnings as Errors [\#144](https://github.com/doctest/doctest/issues/144)
|
|
||||||
- Windows clang-cl -Wdeprecated-declarations warnings [\#143](https://github.com/doctest/doctest/issues/143)
|
|
||||||
- Logo Proposal for Doctest [\#141](https://github.com/doctest/doctest/issues/141)
|
|
||||||
- PCH Support [\#140](https://github.com/doctest/doctest/issues/140)
|
|
||||||
- improve compile times even further [\#139](https://github.com/doctest/doctest/issues/139)
|
|
||||||
- !!! BREAKING CHANGE !!! - Move to C++11 for next version of the library [\#137](https://github.com/doctest/doctest/issues/137)
|
|
||||||
- getCurrentTicks producing warning on MinGW [\#133](https://github.com/doctest/doctest/issues/133)
|
|
||||||
- \[enhancement\] Add support for "stand-alone assertions". [\#114](https://github.com/doctest/doctest/issues/114)
|
|
||||||
|
|
||||||
**Merged pull requests:**
|
|
||||||
|
|
||||||
- Suppress compiler warning on MinGW [\#134](https://github.com/doctest/doctest/pull/134) ([AMS21](https://github.com/AMS21))
|
|
||||||
|
|
||||||
## [1.2.9](https://github.com/doctest/doctest/tree/1.2.9) (2018-05-10)
|
|
||||||
[Full Changelog](https://github.com/doctest/doctest/compare/1.2.8...1.2.9)
|
|
||||||
|
|
||||||
**Closed issues:**
|
|
||||||
|
|
||||||
- GCC 8.0 std::uncaught\_exception\(\) is deprecated [\#130](https://github.com/doctest/doctest/issues/130)
|
|
||||||
- Signal stack size too small on Linux [\#129](https://github.com/doctest/doctest/issues/129)
|
|
||||||
- Support Intel Compiler [\#128](https://github.com/doctest/doctest/issues/128)
|
|
||||||
- Please add support for MSVC 2005 [\#127](https://github.com/doctest/doctest/issues/127)
|
|
||||||
- scan-build report "Dereference of null pointer" for function wildcmp [\#124](https://github.com/doctest/doctest/issues/124)
|
|
||||||
- !!! BREAKING CHANGE \(console output only\) !!! - Emulate the error/warning format emitted by native compiler gcc/clang/msvc when printing test failures in the log [\#123](https://github.com/doctest/doctest/issues/123)
|
|
||||||
- ARM builds: FTBFS on armhf - error: cast from 'const char\*' to 'const [\#118](https://github.com/doctest/doctest/issues/118)
|
|
||||||
|
|
||||||
**Merged pull requests:**
|
|
||||||
|
|
||||||
- Exclude Intel from GCC compiler check [\#132](https://github.com/doctest/doctest/pull/132) ([smcallis](https://github.com/smcallis))
|
|
||||||
- Fix deprecated-declarations warning with GCC-8.0 [\#131](https://github.com/doctest/doctest/pull/131) ([AMS21](https://github.com/AMS21))
|
|
||||||
|
|
||||||
## [1.2.8](https://github.com/doctest/doctest/tree/1.2.8) (2018-03-10)
|
|
||||||
[Full Changelog](https://github.com/doctest/doctest/compare/1.2.7...1.2.8)
|
|
||||||
|
|
||||||
**Closed issues:**
|
|
||||||
|
|
||||||
- ARM64 builds: templated\_test\_cases.cpp test fails [\#119](https://github.com/doctest/doctest/issues/119)
|
|
||||||
|
|
||||||
## [1.2.7](https://github.com/doctest/doctest/tree/1.2.7) (2018-02-06)
|
|
||||||
[Full Changelog](https://github.com/doctest/doctest/compare/1.2.6...1.2.7)
|
|
||||||
|
|
||||||
**Closed issues:**
|
|
||||||
|
|
||||||
- MSan has runtime error: unsigned integer overflow [\#116](https://github.com/doctest/doctest/issues/116)
|
|
||||||
- clang-tidy warning about cert-err58-cpp [\#115](https://github.com/doctest/doctest/issues/115)
|
|
||||||
- Linking errors [\#113](https://github.com/doctest/doctest/issues/113)
|
|
||||||
- inlining function defs [\#111](https://github.com/doctest/doctest/issues/111)
|
|
||||||
- Nullptr issue. [\#110](https://github.com/doctest/doctest/issues/110)
|
|
||||||
- MemorySanitizer: use-of-uninitialized-value [\#109](https://github.com/doctest/doctest/issues/109)
|
|
||||||
- Potential memory leak through scan-build [\#108](https://github.com/doctest/doctest/issues/108)
|
|
||||||
- Warnings raised to error with latest MSVC version [\#107](https://github.com/doctest/doctest/issues/107)
|
|
||||||
- New solution for tests in static libraries ! \(MSVC\) [\#106](https://github.com/doctest/doctest/issues/106)
|
|
||||||
- Command line flags do not work after code formatter/beautifier [\#104](https://github.com/doctest/doctest/issues/104)
|
|
||||||
- Cppcheck 1.81 warnings [\#102](https://github.com/doctest/doctest/issues/102)
|
|
||||||
|
|
||||||
**Merged pull requests:**
|
|
||||||
|
|
||||||
- Fix macros WIN32\_LEAN\_AND\_MEAN typo [\#112](https://github.com/doctest/doctest/pull/112) ([vladimirgamalyan](https://github.com/vladimirgamalyan))
|
|
||||||
- Correct DOCTEST\_NO\_INSTALL logic; do install unless it is set \(\#99\) [\#100](https://github.com/doctest/doctest/pull/100) ([onqtam](https://github.com/onqtam))
|
|
||||||
- Correct DOCTEST\_NO\_INSTALL logic; do install unless it is set [\#99](https://github.com/doctest/doctest/pull/99) ([OdyX](https://github.com/OdyX))
|
|
||||||
|
|
||||||
## [1.2.6](https://github.com/doctest/doctest/tree/1.2.6) (2017-10-29)
|
|
||||||
[Full Changelog](https://github.com/doctest/doctest/compare/1.2.5...1.2.6)
|
|
||||||
|
|
||||||
**Closed issues:**
|
|
||||||
|
|
||||||
- \[bug\] writing an exception translator in a header file results in it being registered multiple times which is suboptimal [\#98](https://github.com/doctest/doctest/issues/98)
|
|
||||||
- Warnings when using something more than /W4 for Visual Studio [\#95](https://github.com/doctest/doctest/issues/95)
|
|
||||||
|
|
||||||
**Merged pull requests:**
|
|
||||||
|
|
||||||
- Added an option to not install Doctest in the CMake scripts [\#96](https://github.com/doctest/doctest/pull/96) ([nm17](https://github.com/nm17))
|
|
||||||
- Adding a defensive check against a null pointer for the current test suite [\#94](https://github.com/doctest/doctest/pull/94) ([Lectem](https://github.com/Lectem))
|
|
||||||
- Remove incomplete copy ctor [\#93](https://github.com/doctest/doctest/pull/93) ([McMartin](https://github.com/McMartin))
|
|
||||||
|
|
||||||
## [1.2.5](https://github.com/doctest/doctest/tree/1.2.5) (2017-10-06)
|
|
||||||
[Full Changelog](https://github.com/doctest/doctest/compare/1.2.4...1.2.5)
|
|
||||||
|
|
||||||
**Closed issues:**
|
|
||||||
|
|
||||||
- Xcode 9 / clang - unknown warning group [\#92](https://github.com/doctest/doctest/issues/92)
|
|
||||||
|
|
||||||
## [1.2.4](https://github.com/doctest/doctest/tree/1.2.4) (2017-09-20)
|
|
||||||
[Full Changelog](https://github.com/doctest/doctest/compare/1.2.3...1.2.4)
|
|
||||||
|
|
||||||
**Closed issues:**
|
|
||||||
|
|
||||||
- \[bug\] test cases can end up in the wrong test suite [\#91](https://github.com/doctest/doctest/issues/91)
|
|
||||||
|
|
||||||
## [1.2.3](https://github.com/doctest/doctest/tree/1.2.3) (2017-09-11)
|
|
||||||
[Full Changelog](https://github.com/doctest/doctest/compare/1.2.2...1.2.3)
|
|
||||||
|
|
||||||
**Closed issues:**
|
|
||||||
|
|
||||||
- \[bug\] Defining a variable T inside a test with DOCTEST\_CONFIG\_DISABLE defined does not compile [\#90](https://github.com/doctest/doctest/issues/90)
|
|
||||||
- \[support\] Using `DOCTEST\_CONFIG\_NO\_SHORT\_MACRO\_NAMES` does not compile using g++ 6.3.0 [\#89](https://github.com/doctest/doctest/issues/89)
|
|
||||||
- \[question\] Why are SUBCASEs executed only once when within a function called multiple times? [\#88](https://github.com/doctest/doctest/issues/88)
|
|
||||||
|
|
||||||
## [1.2.2](https://github.com/doctest/doctest/tree/1.2.2) (2017-09-05)
|
|
||||||
[Full Changelog](https://github.com/doctest/doctest/compare/1.2.1...1.2.2)
|
|
||||||
|
|
||||||
**Closed issues:**
|
|
||||||
|
|
||||||
- \[question\] Differences between doctest and googletest \(gtest\) for uninitialised local variables in test cases [\#86](https://github.com/doctest/doctest/issues/86)
|
|
||||||
- !!! BREAKING CHANGE !!! - remove the custom implementation of std::is\_constructible and optionally use the \<type\_traits\> header because of infinite template recursion issues with GCC [\#85](https://github.com/doctest/doctest/issues/85)
|
|
||||||
- Static Analysis results of doctest [\#83](https://github.com/doctest/doctest/issues/83)
|
|
||||||
- !!! BREAKING CHANGE !!! - catch exceptions as const reference in \<LEVEL\>\_THROWS\_AS [\#81](https://github.com/doctest/doctest/issues/81)
|
|
||||||
- doctest implementation as static library [\#77](https://github.com/doctest/doctest/issues/77)
|
|
||||||
- Provide some easy way to compare structs containing float/doubles [\#73](https://github.com/doctest/doctest/issues/73)
|
|
||||||
|
|
||||||
**Merged pull requests:**
|
|
||||||
|
|
||||||
- Add support for templated scenarios [\#87](https://github.com/doctest/doctest/pull/87) ([Lectem](https://github.com/Lectem))
|
|
||||||
- Prefer if\(MSVC\) in CMakeLists.txt. [\#84](https://github.com/doctest/doctest/pull/84) ([martinmoene](https://github.com/martinmoene))
|
|
||||||
- catch throw\_as exception as const reference [\#82](https://github.com/doctest/doctest/pull/82) ([a4z](https://github.com/a4z))
|
|
||||||
- Added doctest\_with\_main static lib [\#78](https://github.com/doctest/doctest/pull/78) ([ymadzhunkov](https://github.com/ymadzhunkov))
|
|
||||||
|
|
||||||
## [1.2.1](https://github.com/doctest/doctest/tree/1.2.1) (2017-05-24)
|
|
||||||
[Full Changelog](https://github.com/doctest/doctest/compare/1.2.0...1.2.1)
|
|
||||||
|
|
||||||
**Closed issues:**
|
|
||||||
|
|
||||||
- Compile error under MSVC 2015/2017 if \<thread\> included in same file as "doctest.h" [\#72](https://github.com/doctest/doctest/issues/72)
|
|
||||||
|
|
||||||
**Merged pull requests:**
|
|
||||||
|
|
||||||
- docs: TEST\_CASE\_METHOD -\> TEST\_CASE\_FIXTURE [\#71](https://github.com/doctest/doctest/pull/71) ([akrzemi1](https://github.com/akrzemi1))
|
|
||||||
|
|
||||||
## [1.2.0](https://github.com/doctest/doctest/tree/1.2.0) (2017-05-15)
|
|
||||||
[Full Changelog](https://github.com/doctest/doctest/compare/1.1.4...1.2.0)
|
|
||||||
|
|
||||||
**Closed issues:**
|
|
||||||
|
|
||||||
- Further improvements on compile time - disable inlining of functions used in asserts [\#70](https://github.com/doctest/doctest/issues/70)
|
|
||||||
- Improve runtime performance - lazy stringification, more inlining, no statics on the hot path, move semantics for classes such as doctest::String which are used by value, etc. [\#69](https://github.com/doctest/doctest/issues/69)
|
|
||||||
- Add option to show duration of test case execution and add a timeout\(seconds\) decorator - marking them as failed if they exceed it [\#68](https://github.com/doctest/doctest/issues/68)
|
|
||||||
- Add support for test case decorators - label, description, skip, may\_fail, should\_fail, expected\_failures, etc. [\#67](https://github.com/doctest/doctest/issues/67)
|
|
||||||
- Integrate static analysis into the CI builds [\#66](https://github.com/doctest/doctest/issues/66)
|
|
||||||
- Print the test suite name on test case failure [\#65](https://github.com/doctest/doctest/issues/65)
|
|
||||||
- Add signal handlers to handle crashes \(and use SEH under Windows\) - report which test case failed [\#63](https://github.com/doctest/doctest/issues/63)
|
|
||||||
- Add support to Approx for strong typedefs of double [\#62](https://github.com/doctest/doctest/issues/62)
|
|
||||||
- \[question\] Is there a way to always have 0 as the exit code regardless of test results? [\#59](https://github.com/doctest/doctest/issues/59)
|
|
||||||
- Add support for un-parenthesized expressions containing commas in asserts [\#58](https://github.com/doctest/doctest/issues/58)
|
|
||||||
- Add ability to filter subcases with filters [\#57](https://github.com/doctest/doctest/issues/57)
|
|
||||||
- Add option to query if code is being ran inside of a test - doctest::is\_running\_in\_test [\#56](https://github.com/doctest/doctest/issues/56)
|
|
||||||
- Ability for a binary \(executable / shared object\) to use the test runner implementation of another binary - with exported symbols - so tests end up in a single registry [\#55](https://github.com/doctest/doctest/issues/55)
|
|
||||||
- How to force the use of colors in the terminal? [\#54](https://github.com/doctest/doctest/issues/54)
|
|
||||||
- How can I mix production code with the Unit Tests? [\#53](https://github.com/doctest/doctest/issues/53)
|
|
||||||
- add \<= and \>= operators to Approx \(and also maybe \< and \>\) [\#52](https://github.com/doctest/doctest/issues/52)
|
|
||||||
- Add ability to capture variables from test scope [\#48](https://github.com/doctest/doctest/issues/48)
|
|
||||||
- !!! BREAKING CHANGE !!! - Make TEST\_SUITE work with blocks and add TEST\_SUITE\_BEGIN [\#41](https://github.com/doctest/doctest/issues/41)
|
|
||||||
- Add option to print which test suites/cases are run [\#39](https://github.com/doctest/doctest/issues/39)
|
|
||||||
- Add support for templated test cases - parameterized by type [\#38](https://github.com/doctest/doctest/issues/38)
|
|
||||||
- Add custom failure messages with lazy stringification [\#23](https://github.com/doctest/doctest/issues/23)
|
|
||||||
- Add an exception translation mechanism + the ability for users to extend it with custom exception types [\#12](https://github.com/doctest/doctest/issues/12)
|
|
||||||
- Add API for reporting failures [\#9](https://github.com/doctest/doctest/issues/9)
|
|
||||||
|
|
||||||
**Merged pull requests:**
|
|
||||||
|
|
||||||
- Update doctest to work with ARM DS5-compiler [\#64](https://github.com/doctest/doctest/pull/64) ([tomasnilefrost](https://github.com/tomasnilefrost))
|
|
||||||
|
|
||||||
## [1.1.4](https://github.com/doctest/doctest/tree/1.1.4) (2017-02-18)
|
|
||||||
[Full Changelog](https://github.com/doctest/doctest/compare/1.1.3...1.1.4)
|
|
||||||
|
|
||||||
**Closed issues:**
|
|
||||||
|
|
||||||
- Add option --force-colors - for when a tty is not detected for stdout [\#51](https://github.com/doctest/doctest/issues/51)
|
|
||||||
- Issue with using lambdas in tests in gcc [\#49](https://github.com/doctest/doctest/issues/49)
|
|
||||||
- Add the include file to releases [\#47](https://github.com/doctest/doctest/issues/47)
|
|
||||||
|
|
||||||
**Merged pull requests:**
|
|
||||||
|
|
||||||
- Add translation of std::exception for exceptions that terminate a test case [\#46](https://github.com/doctest/doctest/pull/46) ([eliaskosunen](https://github.com/eliaskosunen))
|
|
||||||
|
|
||||||
## [1.1.3](https://github.com/doctest/doctest/tree/1.1.3) (2016-11-15)
|
|
||||||
[Full Changelog](https://github.com/doctest/doctest/compare/1.1.2...1.1.3)
|
|
||||||
|
|
||||||
**Closed issues:**
|
|
||||||
|
|
||||||
- Exception handlers cause warnings when exceptions are disabled [\#44](https://github.com/doctest/doctest/issues/44)
|
|
||||||
|
|
||||||
## [1.1.2](https://github.com/doctest/doctest/tree/1.1.2) (2016-10-10)
|
|
||||||
[Full Changelog](https://github.com/doctest/doctest/compare/1.1.1...1.1.2)
|
|
||||||
|
|
||||||
**Closed issues:**
|
|
||||||
|
|
||||||
- clang warnings when using C++11 or newer [\#42](https://github.com/doctest/doctest/issues/42)
|
|
||||||
- \[support\] identical names for test suites? [\#40](https://github.com/doctest/doctest/issues/40)
|
|
||||||
|
|
||||||
## [1.1.1](https://github.com/doctest/doctest/tree/1.1.1) (2016-09-22)
|
|
||||||
[Full Changelog](https://github.com/doctest/doctest/compare/1.1.0...1.1.1)
|
|
||||||
|
|
||||||
## [1.1.0](https://github.com/doctest/doctest/tree/1.1.0) (2016-09-21)
|
|
||||||
[Full Changelog](https://github.com/doctest/doctest/compare/1.0.0...1.1.0)
|
|
||||||
|
|
||||||
**Closed issues:**
|
|
||||||
|
|
||||||
- char\* comparison uses the contents, not the pointer [\#36](https://github.com/doctest/doctest/issues/36)
|
|
||||||
- add configuration preprocessor identifier for passing by value in assertions instead of by reference [\#35](https://github.com/doctest/doctest/issues/35)
|
|
||||||
- restrict expressions in assertion macros to binary comparisons at most with a static assert [\#34](https://github.com/doctest/doctest/issues/34)
|
|
||||||
- Add clearFilters\(\) to doctest::Context [\#33](https://github.com/doctest/doctest/issues/33)
|
|
||||||
- A way to refrain from polluting “\#define” space for users of tested code? [\#32](https://github.com/doctest/doctest/issues/32)
|
|
||||||
- drop VC++6 support [\#31](https://github.com/doctest/doctest/issues/31)
|
|
||||||
- False positive test [\#30](https://github.com/doctest/doctest/issues/30)
|
|
||||||
- Turn off coloring after tests are finished? [\#28](https://github.com/doctest/doctest/issues/28)
|
|
||||||
- C++11 nullptr [\#27](https://github.com/doctest/doctest/issues/27)
|
|
||||||
- Only one SUBCASE per line is executed [\#25](https://github.com/doctest/doctest/issues/25)
|
|
||||||
- creative formatting of chars [\#24](https://github.com/doctest/doctest/issues/24)
|
|
||||||
- DOCTEST\_BREAK\_INTO\_DEBUGGER undefined under OSX [\#22](https://github.com/doctest/doctest/issues/22)
|
|
||||||
- Tests inside a static library [\#21](https://github.com/doctest/doctest/issues/21)
|
|
||||||
- Add example how to remove doctest options from the command line for the program after the tests run [\#20](https://github.com/doctest/doctest/issues/20)
|
|
||||||
- Single-letter options active even without leading '-' \(dash\) [\#19](https://github.com/doctest/doctest/issues/19)
|
|
||||||
- pointer stringification not working for compilers different from MSVC [\#18](https://github.com/doctest/doctest/issues/18)
|
|
||||||
- Tests that accompany code run and produce output at default [\#17](https://github.com/doctest/doctest/issues/17)
|
|
||||||
- GCC 5.3.1 Compiler warning: sign compare [\#16](https://github.com/doctest/doctest/issues/16)
|
|
||||||
- Slower than Catch in realistic test cases [\#14](https://github.com/doctest/doctest/issues/14)
|
|
||||||
- Rename doctest::detail::Result res; in DOCTEST\_ASSERT\_IMPLEMENT [\#10](https://github.com/doctest/doctest/issues/10)
|
|
||||||
- No red when all tests pass [\#7](https://github.com/doctest/doctest/issues/7)
|
|
||||||
- UNIX line feedings on GitHub please [\#6](https://github.com/doctest/doctest/issues/6)
|
|
||||||
|
|
||||||
**Merged pull requests:**
|
|
||||||
|
|
||||||
- don't show green when tests fail [\#26](https://github.com/doctest/doctest/pull/26) ([ferkulat](https://github.com/ferkulat))
|
|
||||||
- Include "program code" in example [\#15](https://github.com/doctest/doctest/pull/15) ([martinmoene](https://github.com/martinmoene))
|
|
||||||
|
|
||||||
## [1.0.0](https://github.com/doctest/doctest/tree/1.0.0) (2016-05-22)
|
|
||||||
**Merged pull requests:**
|
|
||||||
|
|
||||||
- Reduce the header size for test users [\#3](https://github.com/doctest/doctest/pull/3) ([zah](https://github.com/zah))
|
|
||||||
- Add a Gitter chat badge to README.md [\#1](https://github.com/doctest/doctest/pull/1) ([gitter-badger](https://github.com/gitter-badger))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*
|
|
|
@ -1,158 +0,0 @@
|
||||||
cmake_minimum_required(VERSION 3.0)
|
|
||||||
|
|
||||||
if(POLICY CMP0077)
|
|
||||||
cmake_policy(SET CMP0077 NEW)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
################################################################################
|
|
||||||
## DOCTEST
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/scripts/version.txt ver)
|
|
||||||
project(doctest VERSION ${ver} LANGUAGES CXX)
|
|
||||||
|
|
||||||
# Determine if doctest is built as a subproject (using add_subdirectory) or if it is the main project.
|
|
||||||
set(MAIN_PROJECT OFF)
|
|
||||||
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
|
|
||||||
set(MAIN_PROJECT ON)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
option(DOCTEST_WITH_TESTS "Build tests/examples" ${MAIN_PROJECT})
|
|
||||||
option(DOCTEST_WITH_MAIN_IN_STATIC_LIB "Build a static lib (cmake target) with a default main entry point" ON)
|
|
||||||
option(DOCTEST_NO_INSTALL "Skip the installation process" OFF)
|
|
||||||
option(DOCTEST_USE_STD_HEADERS "Use std headers" OFF)
|
|
||||||
|
|
||||||
add_library(${PROJECT_NAME} INTERFACE)
|
|
||||||
add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
|
|
||||||
|
|
||||||
if(NOT CMAKE_VERSION VERSION_LESS 3.8)
|
|
||||||
target_compile_features(${PROJECT_NAME} INTERFACE cxx_std_11)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(doctest_parts_folder "${CMAKE_CURRENT_SOURCE_DIR}/doctest/parts")
|
|
||||||
set(doctest_folder "${CMAKE_CURRENT_SOURCE_DIR}/") # in order to have the mpi extension files, not included into the doctest.h single header
|
|
||||||
|
|
||||||
if(MAIN_PROJECT)
|
|
||||||
# use a special hidden version of the header which directly includes the 2 parts - proper reporting of file/line locations during dev
|
|
||||||
target_include_directories(${PROJECT_NAME} INTERFACE
|
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/scripts/development_only/>
|
|
||||||
$<BUILD_INTERFACE:${doctest_parts_folder}>
|
|
||||||
$<BUILD_INTERFACE:${doctest_folder}>)
|
|
||||||
|
|
||||||
# add a custom target that assembles the single header when any of the parts are touched
|
|
||||||
add_custom_command(
|
|
||||||
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/doctest/doctest.h
|
|
||||||
DEPENDS
|
|
||||||
${doctest_parts_folder}/doctest_fwd.h
|
|
||||||
${doctest_parts_folder}/doctest.cpp
|
|
||||||
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/scripts/cmake/assemble_single_header.cmake
|
|
||||||
COMMENT "assembling the single header")
|
|
||||||
|
|
||||||
add_custom_target(assemble_single_header ALL DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/doctest/doctest.h)
|
|
||||||
else()
|
|
||||||
target_include_directories(${PROJECT_NAME} INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/>)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# hack to support building on XCode 6 and 7 - propagate the definition to everything
|
|
||||||
if(DEFINED DOCTEST_THREAD_LOCAL)
|
|
||||||
target_compile_definitions(${PROJECT_NAME} INTERFACE
|
|
||||||
DOCTEST_THREAD_LOCAL=${DOCTEST_THREAD_LOCAL})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(DOCTEST_USE_STD_HEADERS)
|
|
||||||
target_compile_definitions(${PROJECT_NAME} INTERFACE DOCTEST_CONFIG_USE_STD_HEADERS)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
################################################################################
|
|
||||||
## TESTS/EXAMPLES/HELPERS
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
if(${DOCTEST_WITH_MAIN_IN_STATIC_LIB})
|
|
||||||
add_library(${PROJECT_NAME}_with_main STATIC EXCLUDE_FROM_ALL ${doctest_parts_folder}/doctest.cpp)
|
|
||||||
target_compile_definitions(${PROJECT_NAME}_with_main PRIVATE
|
|
||||||
DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN)
|
|
||||||
set_target_properties(${PROJECT_NAME}_with_main PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED ON)
|
|
||||||
target_link_libraries(${PROJECT_NAME}_with_main PUBLIC ${PROJECT_NAME})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(MAIN_PROJECT AND DOCTEST_WITH_TESTS)
|
|
||||||
include(scripts/cmake/common.cmake)
|
|
||||||
|
|
||||||
add_subdirectory(examples/all_features)
|
|
||||||
|
|
||||||
# for code coverage we want exactly one binary to be produced and exercised
|
|
||||||
if(NOT DEFINED ENV{CODE_COVERAGE})
|
|
||||||
add_subdirectory(examples/exe_with_static_libs)
|
|
||||||
add_subdirectory(examples/executable_dll_and_plugin)
|
|
||||||
add_subdirectory(examples/combining_the_same_tests_built_differently_in_multiple_shared_objects)
|
|
||||||
add_subdirectory(scripts/playground)
|
|
||||||
add_subdirectory(examples/mpi)
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
################################################################################
|
|
||||||
## PACKAGE SUPPORT
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
set(generated_dir "${CMAKE_CURRENT_BINARY_DIR}/generated")
|
|
||||||
|
|
||||||
if(CMAKE_SYSTEM_NAME STREQUAL Linux)
|
|
||||||
include(GNUInstallDirs)
|
|
||||||
set(include_install_dir ${CMAKE_INSTALL_INCLUDEDIR})
|
|
||||||
set(config_install_dir "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
|
|
||||||
else()
|
|
||||||
set(include_install_dir "include")
|
|
||||||
set(config_install_dir "lib/cmake/${PROJECT_NAME}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
|
|
||||||
set(version_config "${generated_dir}/${PROJECT_NAME}ConfigVersion.cmake")
|
|
||||||
set(project_config "${generated_dir}/${PROJECT_NAME}Config.cmake")
|
|
||||||
set(targets_export_name "${PROJECT_NAME}Targets")
|
|
||||||
set(namespace "${PROJECT_NAME}::")
|
|
||||||
|
|
||||||
include(CMakePackageConfigHelpers)
|
|
||||||
|
|
||||||
# CMake automatically adds an architecture compatibility check to make sure
|
|
||||||
# 32 and 64 bit code is not accidentally mixed. For a header-only library this
|
|
||||||
# is not required. The check can be disabled by temporarily unsetting
|
|
||||||
# CMAKE_SIZEOF_VOID_P. In CMake 3.14 and later this can be achieved more cleanly
|
|
||||||
# with write_basic_package_version_file(ARCH_INDEPENDENT).
|
|
||||||
# TODO: Use this once a newer CMake can be required.
|
|
||||||
set(DOCTEST_SIZEOF_VOID_P ${CMAKE_SIZEOF_VOID_P})
|
|
||||||
unset(CMAKE_SIZEOF_VOID_P)
|
|
||||||
write_basic_package_version_file(
|
|
||||||
"${version_config}" VERSION ${PROJECT_VERSION} COMPATIBILITY SameMajorVersion
|
|
||||||
)
|
|
||||||
set(CMAKE_SIZEOF_VOID_P ${DOCTEST_SIZEOF_VOID_P})
|
|
||||||
|
|
||||||
configure_file("scripts/cmake/Config.cmake.in" "${project_config}" @ONLY)
|
|
||||||
|
|
||||||
if(NOT ${DOCTEST_NO_INSTALL})
|
|
||||||
install(
|
|
||||||
TARGETS ${PROJECT_NAME}
|
|
||||||
EXPORT "${targets_export_name}"
|
|
||||||
INCLUDES DESTINATION "${include_install_dir}"
|
|
||||||
)
|
|
||||||
|
|
||||||
install(
|
|
||||||
FILES "doctest/doctest.h"
|
|
||||||
DESTINATION "${include_install_dir}/doctest"
|
|
||||||
)
|
|
||||||
|
|
||||||
install(
|
|
||||||
FILES "${project_config}" "${version_config}"
|
|
||||||
DESTINATION "${config_install_dir}"
|
|
||||||
)
|
|
||||||
|
|
||||||
install(
|
|
||||||
FILES "scripts/cmake/doctest.cmake" "scripts/cmake/doctestAddTests.cmake"
|
|
||||||
DESTINATION "${config_install_dir}"
|
|
||||||
)
|
|
||||||
|
|
||||||
install(
|
|
||||||
EXPORT "${targets_export_name}"
|
|
||||||
NAMESPACE "${namespace}"
|
|
||||||
DESTINATION "${config_install_dir}"
|
|
||||||
)
|
|
||||||
endif()
|
|
|
@ -1,30 +0,0 @@
|
||||||
## Contributing
|
|
||||||
|
|
||||||
This library is free, and will stay free but needs your support to sustain its development. There are lots of [**new features**](doc/markdown/roadmap.md) and maintenance to do. If you work for a company using **doctest** or have the means to do so, please consider financial support.
|
|
||||||
|
|
||||||
[![Patreon](https://cloud.githubusercontent.com/assets/8225057/5990484/70413560-a9ab-11e4-8942-1a63607c0b00.png)](http://www.patreon.com/onqtam)
|
|
||||||
[![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.me/onqtam/10)
|
|
||||||
|
|
||||||
## Pull requests
|
|
||||||
|
|
||||||
Consider opening an issue for a discussion before making a pull request to make sure the contribution goes smoothly.
|
|
||||||
|
|
||||||
All pull requests should be made against the ```dev``` branch because the ```master``` is the stable one with the latest release.
|
|
||||||
|
|
||||||
If you're going to change something in the library itself - make sure you don't modify ```doctest/doctest.h``` because it's generated from ```doctest/parts/doctest_fwd.h``` and ```doctest/parts/doctest.cpp``` - they get concatenated by CMake - so make sure you do a CMake build after you modify them so the ```assemble_single_header``` target gets built. Also take into consideration how the change affects the code coverage - based on the project in ```examples/all_features```. Also update any relevant examples in the ```examples``` folder.
|
|
||||||
|
|
||||||
This framework has some design goals which must be kept. Make sure you have read the [**features and design goals**](doc/markdown/features.md) page.
|
|
||||||
|
|
||||||
If your changes also change the output of the library - you should also update the reference output for the tests or otherwise the CI builds (```travis``` and ```appveyor```) will fail when they compare the latest output to the outdated reference output (which is committed in the repository). To do this run CMake with the ```DOCTEST_TEST_MODE``` variable set to ```COLLECT``` (making the new reference output) and then run ```ctest``` and commit the changed (or newly created) ```.txt``` files in the ```test_output``` folders too. The default ```DOCTEST_TEST_MODE``` is ```COMPARE```.
|
|
||||||
|
|
||||||
Example: ```cmake -DDOCTEST_TEST_MODE=COLLECT path/to/sources && cmake --build . && ctest```
|
|
||||||
|
|
||||||
Code should be formatted with a recent-enough ```clang-format``` using the config file in the root of the repo (or I will do it...)
|
|
||||||
|
|
||||||
Testing with compilers different from GCC/Clang/MSVC (and more platforms) is something the project would benefit from.
|
|
||||||
|
|
||||||
---------------
|
|
||||||
|
|
||||||
[Home](readme.md#reference)
|
|
||||||
|
|
||||||
<p align="center"><img src="scripts/data/logo/icon_2.svg"></p>
|
|
|
@ -1,21 +0,0 @@
|
||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2016-2021 Viktor Kirilov
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
|
@ -1,139 +0,0 @@
|
||||||
<p align="center"><img src="scripts/data/logo/logo_1.svg"></p>
|
|
||||||
<b>
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
master branch
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
All <a href="https://github.com/onqtam/doctest/actions?query=branch%3Amaster"><img src="https://github.com/onqtam/doctest/workflows/CI/badge.svg?branch=master"></a>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<a href="https://coveralls.io/github/onqtam/doctest?branch=master"><img src="https://coveralls.io/repos/github/onqtam/doctest/badge.svg?branch=master"></a>
|
|
||||||
</td>
|
|
||||||
<!--
|
|
||||||
<td>
|
|
||||||
<a href="https://scan.coverity.com/projects/onqtam-doctest"><img src="https://scan.coverity.com/projects/7865/badge.svg"></a>
|
|
||||||
</td>
|
|
||||||
-->
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
dev branch
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
All <a href="https://github.com/onqtam/doctest/actions?query=branch%3Adev"><img src="https://github.com/onqtam/doctest/workflows/CI/badge.svg?branch=dev"></a>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<a href="https://coveralls.io/github/onqtam/doctest?branch=dev"><img src="https://coveralls.io/repos/github/onqtam/doctest/badge.svg?branch=dev"></a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</b>
|
|
||||||
|
|
||||||
**doctest** is a new C++ testing framework but is by far the fastest both in compile times (by [**orders of magnitude**](doc/markdown/benchmarks.md)) and runtime compared to other feature-rich alternatives. It brings the ability of compiled languages such as [**D**](https://dlang.org/spec/unittest.html) / [**Rust**](https://doc.rust-lang.org/book/second-edition/ch11-00-testing.html) / [**Nim**](https://nim-lang.org/docs/unittest.html) to have tests written directly in the production code thanks to a fast, transparent and flexible test runner with a clean interface.
|
|
||||||
|
|
||||||
[![Standard](https://img.shields.io/badge/c%2B%2B-11/14/17/20-blue.svg)](https://en.wikipedia.org/wiki/C%2B%2B#Standardization)
|
|
||||||
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT)
|
|
||||||
[![download](https://img.shields.io/badge/download%20%20-link-blue.svg)](https://raw.githubusercontent.com/onqtam/doctest/master/doctest/doctest.h)
|
|
||||||
[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/503/badge)](https://bestpractices.coreinfrastructure.org/projects/503)
|
|
||||||
[![Language grade: C/C++](https://img.shields.io/lgtm/grade/cpp/g/onqtam/doctest.svg)](https://lgtm.com/projects/g/onqtam/doctest/context:cpp)
|
|
||||||
[![Chat - Discord](https://img.shields.io/badge/chat-Discord-blue.svg)](https://discord.gg/PGXn9YmyF3)
|
|
||||||
[![Try it online](https://img.shields.io/badge/try%20it-online-orange.svg)](https://godbolt.org/z/4s389Kbfs)
|
|
||||||
<!--
|
|
||||||
[![Language](https://img.shields.io/badge/language-C++-blue.svg)](https://isocpp.org/)
|
|
||||||
[![documentation](https://img.shields.io/badge/documentation%20%20-online-blue.svg)](https://github.com/onqtam/doctest/blob/master/doc/markdown/readme.md#reference)
|
|
||||||
-->
|
|
||||||
|
|
||||||
# [>> doctest is looking for maintainers <<](https://github.com/doctest/doctest/issues/554)
|
|
||||||
|
|
||||||
[<img src="https://cloud.githubusercontent.com/assets/8225057/5990484/70413560-a9ab-11e4-8942-1a63607c0b00.png" align="right">](http://www.patreon.com/onqtam)
|
|
||||||
|
|
||||||
The framework is and will stay free but needs your support to sustain its development. There are lots of <a href="doc/markdown/roadmap.md"><b>new features</b></a> and maintenance to do. If you work for a company using **doctest** or have the means to do so, please consider financial support. Monthly donations via Patreon and one-offs via PayPal.
|
|
||||||
|
|
||||||
[<img src="https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif" align="right">](https://www.paypal.me/onqtam/10)
|
|
||||||
|
|
||||||
A complete example with a self-registering test that compiles to an executable looks like this:
|
|
||||||
|
|
||||||
![cover-example](scripts/data/using_doctest_888px_wide.gif)
|
|
||||||
|
|
||||||
There are many C++ testing frameworks - [Catch](https://github.com/catchorg/Catch2), [Boost.Test](http://www.boost.org/doc/libs/1_64_0/libs/test/doc/html/index.html), [UnitTest++](https://github.com/unittest-cpp/unittest-cpp), [cpputest](https://github.com/cpputest/cpputest), [googletest](https://github.com/google/googletest) and [others](https://en.wikipedia.org/wiki/List_of_unit_testing_frameworks#C.2B.2B).
|
|
||||||
|
|
||||||
The **key** differences between it and other testing frameworks are that it is light and unintrusive:
|
|
||||||
- Ultra light on compile times both in terms of [**including the header**](doc/markdown/benchmarks.md#cost-of-including-the-header) and writing [**thousands of asserts**](doc/markdown/benchmarks.md#cost-of-an-assertion-macro)
|
|
||||||
- Doesn't produce any warnings even on the [**most aggressive**](scripts/cmake/common.cmake#L84) warning levels for **MSVC**/**GCC**/**Clang**
|
|
||||||
- Can remove **everything** testing-related from the binary with the [**```DOCTEST_CONFIG_DISABLE```**](doc/markdown/configuration.md#doctest_config_disable) identifier
|
|
||||||
- [**thread-safe**](doc/markdown/faq.md#is-doctest-thread-aware) - asserts can be used from multiple threads spawned from a single test case - [**example**](examples/all_features/concurrency.cpp)
|
|
||||||
- asserts can be used [**outside of a testing context**](doc/markdown/assertions.md#using-asserts-out-of-a-testing-context) - as a general purpose assert library - [**example**](examples/all_features/asserts_used_outside_of_tests.cpp)
|
|
||||||
- No global namespace pollution (everything is in ```doctest::```) & doesn't drag **any** headers with it
|
|
||||||
- [**Portable**](doc/markdown/features.md#extremely-portable) C++11 (use tag [**1.2.9**](https://github.com/onqtam/doctest/tree/1.2.9) for C++98) with over 100 different CI builds (static analysis, sanitizers..)
|
|
||||||
- binaries (exe/dll) can use the test runner of another binary => tests in a single registry - [**example**](examples/executable_dll_and_plugin/)
|
|
||||||
|
|
||||||
![cost-of-including-the-framework-header](scripts/data/benchmarks/header.png)
|
|
||||||
|
|
||||||
This allows the framework to be used in more ways than any other - tests can be written directly in the production code!
|
|
||||||
|
|
||||||
*Tests can be a form of documentation and should be able to reside near the production code which they test.*
|
|
||||||
|
|
||||||
- This makes the barrier for writing tests **much lower** - you don't have to: **1)** make a separate source file **2)** include a bunch of stuff in it **3)** add it to the build system and **4)** add it to source control - You can just write the tests for a class or a piece of functionality at the bottom of its source file - or even header file!
|
|
||||||
- Tests in the production code can be thought of as documentation/up-to-date comments - showcasing the APIs
|
|
||||||
- Testing internals that are not exposed through the public API and headers is no longer a mind-bending exercise
|
|
||||||
- [**Test-driven development**](https://en.wikipedia.org/wiki/Test-driven_development) in C++ has never been easier!
|
|
||||||
|
|
||||||
The framework can be used just like any other without mixing production code and tests - check out the [**features**](doc/markdown/features.md).
|
|
||||||
|
|
||||||
**doctest** is modeled after [**Catch**](https://github.com/catchorg/Catch2) and some parts of the code have been taken directly - check out [**the differences**](doc/markdown/faq.md#how-is-doctest-different-from-catch).
|
|
||||||
|
|
||||||
[This table](https://github.com/martinmoene/catch-lest-other-comparison) compares **doctest** / [**Catch**](https://github.com/catchorg/Catch2) / [**lest**](https://github.com/martinmoene/lest) which are all very similar.
|
|
||||||
|
|
||||||
Checkout the [**CppCon 2017 talk**](https://cppcon2017.sched.com/event/BgsI/mix-tests-and-production-code-with-doctest-implementing-and-using-the-fastest-modern-c-testing-framework) on [**YouTube**](https://www.youtube.com/watch?v=eH1CxEC29l8) to get a better understanding of how the framework works and read about how to use it in [**the JetBrains article**](https://blog.jetbrains.com/rscpp/better-ways-testing-with-doctest/) - highlighting the unique aspects of the framework! On a short description on how to use the framework along production code you could refer to [**this GitHub issue**](https://github.com/onqtam/doctest/issues/252). There is also an [**older article**](https://accu.org/var/uploads/journals/Overload137.pdf) in the february edition of ACCU Overload 2017.
|
|
||||||
|
|
||||||
[![CppCon 2017 talk about doctest on youtube](scripts/data/youtube-cppcon-talk-thumbnail.png)](https://www.youtube.com/watch?v=eH1CxEC29l8)
|
|
||||||
|
|
||||||
Documentation
|
|
||||||
-------------
|
|
||||||
|
|
||||||
Project:
|
|
||||||
|
|
||||||
- [Features and design goals](doc/markdown/features.md) - the complete list of features
|
|
||||||
- [Roadmap](doc/markdown/roadmap.md) - upcoming features
|
|
||||||
- [Benchmarks](doc/markdown/benchmarks.md) - compile-time and runtime supremacy
|
|
||||||
- [Contributing](CONTRIBUTING.md) - how to make a proper pull request
|
|
||||||
- [Changelog](CHANGELOG.md) - generated changelog based on closed issues/PRs
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
|
|
||||||
- [Tutorial](doc/markdown/tutorial.md) - make sure you have read it before the other parts of the documentation
|
|
||||||
- [Assertion macros](doc/markdown/assertions.md)
|
|
||||||
- [Test cases, subcases and test fixtures](doc/markdown/testcases.md)
|
|
||||||
- [Parameterized test cases](doc/markdown/parameterized-tests.md)
|
|
||||||
- [Command line](doc/markdown/commandline.md)
|
|
||||||
- [Logging macros](doc/markdown/logging.md)
|
|
||||||
- [```main()``` entry point](doc/markdown/main.md)
|
|
||||||
- [Configuration](doc/markdown/configuration.md)
|
|
||||||
- [String conversions](doc/markdown/stringification.md)
|
|
||||||
- [Reporters](doc/markdown/reporters.md)
|
|
||||||
- [Extensions](doc/markdown/extensions.md)
|
|
||||||
- [FAQ](doc/markdown/faq.md)
|
|
||||||
- [Build systems](doc/markdown/build-systems.md)
|
|
||||||
- [Examples](examples)
|
|
||||||
|
|
||||||
Contributing
|
|
||||||
------------
|
|
||||||
|
|
||||||
[<img src="https://cloud.githubusercontent.com/assets/8225057/5990484/70413560-a9ab-11e4-8942-1a63607c0b00.png" align="right">](http://www.patreon.com/onqtam)
|
|
||||||
|
|
||||||
Support the development of the project with donations! There is a list of planned features which are all important and big - see the [**roadmap**](doc/markdown/roadmap.md). I took a break from working in the industry to make open source software so every cent is a big deal.
|
|
||||||
|
|
||||||
[<img src="https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif" align="right">](https://www.paypal.me/onqtam/10)
|
|
||||||
|
|
||||||
If you work for a company using **doctest** or have the means to do so, please consider financial support.
|
|
||||||
|
|
||||||
Contributions in the form of issues and pull requests are welcome as well - check out the [**Contributing**](CONTRIBUTING.md) page.
|
|
||||||
|
|
||||||
Logo
|
|
||||||
------------
|
|
||||||
|
|
||||||
The [logo](scripts/data/logo) is licensed under a Creative Commons Attribution 4.0 International License. Copyright © 2019 [area55git](https://github.com/area55git) [![License: CC BY 4.0](https://licensebuttons.net/l/by/4.0/80x15.png)](https://creativecommons.org/licenses/by/4.0/)
|
|
||||||
|
|
||||||
<p align="center"><img src="scripts/data/logo/icon_2.svg"></p>
|
|
|
@ -1,95 +0,0 @@
|
||||||
# http://www.appveyor.com/docs/appveyor-yml
|
|
||||||
|
|
||||||
notifications:
|
|
||||||
- provider: Email
|
|
||||||
on_build_status_changed: false
|
|
||||||
on_build_failure: false
|
|
||||||
on_build_success: false
|
|
||||||
# gitter
|
|
||||||
- provider: Webhook
|
|
||||||
url: https://webhooks.gitter.im/e/3a78202a235c0325e516
|
|
||||||
on_build_status_changed: true
|
|
||||||
on_build_failure: true
|
|
||||||
on_build_success: false
|
|
||||||
|
|
||||||
clone_depth: 500
|
|
||||||
branches:
|
|
||||||
except:
|
|
||||||
- gh-pages
|
|
||||||
- coverity_scan
|
|
||||||
|
|
||||||
matrix:
|
|
||||||
fast_finish: false
|
|
||||||
|
|
||||||
environment:
|
|
||||||
matrix:
|
|
||||||
- gen: "MinGW Makefiles"
|
|
||||||
- gen: "Visual Studio 14 2015"
|
|
||||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
|
||||||
- gen: "Visual Studio 15 2017"
|
|
||||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
|
||||||
- gen: "Visual Studio 16 2019"
|
|
||||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
|
||||||
|
|
||||||
install:
|
|
||||||
- IF "%gen%" == "MinGW Makefiles" appveyor-retry appveyor DownloadFile http://downloads.sourceforge.net/mingw-w64/x86_64-8.1.0-release-posix-seh-rt_v6-rev0.7z
|
|
||||||
- IF "%gen%" == "MinGW Makefiles" 7z x x86_64-8.1.0-release-posix-seh-rt_v6-rev0.7z -oc:\mingw > nul
|
|
||||||
|
|
||||||
build_script:
|
|
||||||
- cmake --version
|
|
||||||
# workaround for CMake not wanting sh.exe on PATH for MinGW
|
|
||||||
- IF "%gen%" == "MinGW Makefiles" set PATH=%PATH:C:\Program Files\Git\usr\bin;=%
|
|
||||||
- IF "%gen%" == "MinGW Makefiles" set PATH=C:\mingw\mingw64\bin;%PATH%
|
|
||||||
# generate and build everything for debug and release
|
|
||||||
- IF "%gen%" == "MinGW Makefiles" mkdir debug_64
|
|
||||||
- IF "%gen%" == "MinGW Makefiles" cd debug_64
|
|
||||||
- IF "%gen%" == "MinGW Makefiles" cmake .. -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Debug
|
|
||||||
- IF "%gen%" == "MinGW Makefiles" cmake --build .
|
|
||||||
- IF "%gen%" == "MinGW Makefiles" cd ..
|
|
||||||
- IF "%gen%" == "MinGW Makefiles" mkdir release_64
|
|
||||||
- IF "%gen%" == "MinGW Makefiles" cd release_64
|
|
||||||
- IF "%gen%" == "MinGW Makefiles" cmake .. -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release
|
|
||||||
- IF "%gen%" == "MinGW Makefiles" cmake --build .
|
|
||||||
- IF "%gen%" == "MinGW Makefiles" cd ..
|
|
||||||
# adding git to the path again - for the dos2unix tool
|
|
||||||
- IF "%gen%" == "MinGW Makefiles" set PATH=%PATH%;C:\Program Files\Git\usr\bin
|
|
||||||
# execute tests
|
|
||||||
- IF "%gen%" == "MinGW Makefiles" cd debug_64
|
|
||||||
- IF "%gen%" == "MinGW Makefiles" ctest -j2 --output-on-failure
|
|
||||||
- IF "%gen%" == "MinGW Makefiles" cd ..
|
|
||||||
- IF "%gen%" == "MinGW Makefiles" cd release_64
|
|
||||||
- IF "%gen%" == "MinGW Makefiles" ctest -j2 --output-on-failure
|
|
||||||
- IF "%gen%" == "MinGW Makefiles" cd ..
|
|
||||||
- IF "%gen%" == "MinGW Makefiles" appveyor exit
|
|
||||||
# ============= VISUAL STUDIO
|
|
||||||
- mkdir debug_64
|
|
||||||
- cd debug_64
|
|
||||||
- cmake .. -G "%gen%" -A x64
|
|
||||||
- msbuild doctest.sln /p:Configuration=Debug;Platform=x64 /maxcpucount
|
|
||||||
- ctest -C Debug -j2 --output-on-failure
|
|
||||||
- cd ..
|
|
||||||
- mkdir release_64
|
|
||||||
- cd release_64
|
|
||||||
- cmake .. -G "%gen%" -A x64
|
|
||||||
- msbuild doctest.sln /p:Configuration=Release;Platform=x64 /maxcpucount
|
|
||||||
- ctest -C Release -j2 --output-on-failure
|
|
||||||
- cd ..
|
|
||||||
# x86
|
|
||||||
- mkdir debug_86
|
|
||||||
- cd debug_86
|
|
||||||
- cmake .. -G "%gen%" -A Win32
|
|
||||||
- msbuild doctest.sln /p:Configuration=Debug;Platform=Win32 /maxcpucount
|
|
||||||
- ctest -C Debug -j2 --output-on-failure
|
|
||||||
- cd ..
|
|
||||||
- mkdir release_86
|
|
||||||
- cd release_86
|
|
||||||
- cmake .. -G "%gen%" -A Win32
|
|
||||||
- msbuild doctest.sln /p:Configuration=Release;Platform=Win32 /maxcpucount
|
|
||||||
- ctest -C Release -j2 --output-on-failure
|
|
||||||
- cd ..
|
|
||||||
# static code analysis
|
|
||||||
- IF "%gen%" == "Visual Studio 15 2017" mkdir analysis
|
|
||||||
- IF "%gen%" == "Visual Studio 15 2017" cd analysis
|
|
||||||
- IF "%gen%" == "Visual Studio 15 2017" cmake .. -G "%gen%" -A x64
|
|
||||||
- IF "%gen%" == "Visual Studio 15 2017" msbuild doctest.sln /p:Configuration=Debug;Platform=x64 /maxcpucount /p:RunCodeAnalysis=true /p:CodeAnalysisTreatWarningsAsErrors=true
|
|
||||||
- IF "%gen%" == "Visual Studio 15 2017" cd ..
|
|
|
@ -1,173 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<title>assertions</title>
|
|
||||||
<xmp theme="united" style="display:none;">
|
|
||||||
|
|
||||||
## Assertion macros
|
|
||||||
|
|
||||||
Most test frameworks have a large collection of assertion macros to capture all possible conditional forms (```_EQUALS```, ```_NOTEQUALS```, ```_GREATER_THAN``` etc).
|
|
||||||
|
|
||||||
**doctest** is different (but it's like [**Catch**](https://github.com/catchorg/Catch2) in this regard). Because it decomposes comparison expressions most of these forms are reduced to one or two that you will use all the time. That said, there is a rich set of auxiliary macros as well.
|
|
||||||
|
|
||||||
There are 3 levels of assert severity for all assertion macros:
|
|
||||||
|
|
||||||
- ```REQUIRE``` - this level will immediately quit the test case if the assert fails and will mark the test case as failed.
|
|
||||||
- ```CHECK``` - this level will mark the test case as failed if the assert fails but will continue with the test case.
|
|
||||||
- ```WARN``` - this level will only print a message if the assert fails but will not mark the test case as failed.
|
|
||||||
|
|
||||||
The ```CHECK``` level is mostly useful if you have a series of essentially orthogonal assertions and it is useful to see all the results rather than stopping at the first failure.
|
|
||||||
|
|
||||||
All asserts evaluate the expressions only once and if they fail - the values are [**stringified**](stringification.html) properly.
|
|
||||||
|
|
||||||
Since **doctest** is [**thread-safe**](faq.html#is-doctest-thread-aware) all asserts and [**logging**](logging.html) macros can be used in threads spawned from test cases.
|
|
||||||
|
|
||||||
Note that the ```REQUIRE``` level of asserts uses exceptions to end the current test case. It might be dangerous to use this level of asserts inside destructors of user-defined classes - if a destructor is called during stack unwinding due to an exception and a ```REQUIRE``` assert fails then the program will terminate. Also since C++11 all destructors are by default ```noexcept(true)``` unless specified otherwise so such an assert will lead to ```std::terminate()``` being called.
|
|
||||||
|
|
||||||
## Expression decomposing asserts
|
|
||||||
|
|
||||||
These are of the form ```CHECK(expression)``` (Same for ```REQUIRE``` and ```WARN```).
|
|
||||||
|
|
||||||
```expression``` can be a binary comparison like ```a == b``` or just a single thing like ```vec.isEmpty()```.
|
|
||||||
|
|
||||||
If an exception is thrown it is caught, reported, and counted as a failure (unless the assert is of level ```WARN```).
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
```
|
|
||||||
CHECK(flags == state::alive | state::moving);
|
|
||||||
CHECK(thisReturnsTrue());
|
|
||||||
REQUIRE(i < 42);
|
|
||||||
```
|
|
||||||
|
|
||||||
- Negating asserts - ```<LEVEL>_FALSE(expression)``` - evaluates the expression and records the _logical NOT_ of the result.
|
|
||||||
|
|
||||||
These forms exist as a workaround for the fact that ```!``` prefixed expressions cannot be decomposed properly.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```
|
|
||||||
REQUIRE_FALSE(thisReturnsFalse());
|
|
||||||
```
|
|
||||||
|
|
||||||
- Using the [**```DOCTEST_CONFIG_SUPER_FAST_ASSERTS```**](configuration.html#doctest_config_super_fast_asserts) config option can make compilation of asserts up to [**31-63%**](benchmarks.html#cost-of-an-assertion-macro) faster!
|
|
||||||
- These asserts also have a ```_MESSAGE``` form - like ```CHECK_MESSAGE(expression, message)``` which is basically a code block ```{}``` with a scoped [**```INFO()```**](logging.html#info) logging macro together with the ```CHECK``` macro - that way the message will be relevant only to that assert. The binary/unary asserts don't have this variation yet.
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
```
|
|
||||||
INFO("this is relevant to all asserts, and here is some var: ", local);
|
|
||||||
|
|
||||||
CHECK_MESSAGE(a < b, "relevant only to this assert ", other_local, " more text!");
|
|
||||||
|
|
||||||
CHECK(b < c); // here only the first INFO() will be relevant
|
|
||||||
```
|
|
||||||
|
|
||||||
For more information about the ```INFO()``` macro visit the [logging page](logging.html).
|
|
||||||
|
|
||||||
## Binary and unary asserts
|
|
||||||
|
|
||||||
These asserts don't use templates to decompose the comparison expressions for the left and right parts.
|
|
||||||
|
|
||||||
These have the same guarantees as the expression decomposing ones but [**57-68% faster**](benchmarks.html#cost-of-an-assertion-macro) for compilation.
|
|
||||||
|
|
||||||
```<LEVEL>``` is one of 3 possible: ```REQUIRE```/```CHECK```/```WARN```.
|
|
||||||
|
|
||||||
- ```<LEVEL>_EQ(left, right)``` - same as ```<LEVEL>(left == right)```
|
|
||||||
- ```<LEVEL>_NE(left, right)``` - same as ```<LEVEL>(left != right)```
|
|
||||||
- ```<LEVEL>_GT(left, right)``` - same as ```<LEVEL>(left > right)```
|
|
||||||
- ```<LEVEL>_LT(left, right)``` - same as ```<LEVEL>(left < right)```
|
|
||||||
- ```<LEVEL>_GE(left, right)``` - same as ```<LEVEL>(left >= right)```
|
|
||||||
- ```<LEVEL>_LE(left, right)``` - same as ```<LEVEL>(left <= right)```
|
|
||||||
- ```<LEVEL>_UNARY(expr)``` - same as ```<LEVEL>(expr)```
|
|
||||||
- ```<LEVEL>_UNARY_FALSE(expr)``` - same as ```<LEVEL>_FALSE(expr)```
|
|
||||||
|
|
||||||
Using the [**```DOCTEST_CONFIG_SUPER_FAST_ASSERTS```**](configuration.html#doctest_config_super_fast_asserts) config option can make the binary asserts to compile up to [**84-91%**](benchmarks.html#cost-of-an-assertion-macro) faster!
|
|
||||||
|
|
||||||
## Exceptions
|
|
||||||
|
|
||||||
```<LEVEL>``` is one of 3 possible: ```REQUIRE```/```CHECK```/```WARN```.
|
|
||||||
|
|
||||||
- ```<LEVEL>_THROWS(expression)```
|
|
||||||
|
|
||||||
Expects that an exception (of any type) is thrown during evaluation of the expression.
|
|
||||||
|
|
||||||
- ```<LEVEL>_THROWS_AS(expression, exception_type)```
|
|
||||||
|
|
||||||
Expects that an exception of the _specified type_ is thrown during evaluation of the expression.
|
|
||||||
|
|
||||||
Note that ```const``` and ```&``` are added to the exception type if missing (users shouldn't care) - the standard practice for exceptions in C++ is ```Throw by value, catch by (const) reference```.
|
|
||||||
|
|
||||||
```
|
|
||||||
CHECK_THROWS_AS(func(), const std::exception&);
|
|
||||||
CHECK_THROWS_AS(func(), std::exception); // same as above
|
|
||||||
```
|
|
||||||
|
|
||||||
- ```<LEVEL>_THROWS_WITH(expression, c_string)```
|
|
||||||
|
|
||||||
Expects that an exception is thrown during evaluation of the expression and is successfully translated to the _specified c string_ (see [**translating exceptions**](stringification.html#translating-exceptions)).
|
|
||||||
|
|
||||||
```
|
|
||||||
CHECK_THROWS_WITH(func(), "invalid operation!");
|
|
||||||
```
|
|
||||||
|
|
||||||
- ```<LEVEL>_THROWS_WITH_AS(expression, c_string, exception_type)```
|
|
||||||
|
|
||||||
This is a combination of ```<LEVEL>_THROWS_WITH``` and ```<LEVEL>_THROWS_AS```.
|
|
||||||
|
|
||||||
```
|
|
||||||
CHECK_THROWS_WITH_AS(func(), "invalid operation!", std::runtime_error);
|
|
||||||
```
|
|
||||||
|
|
||||||
- ```<LEVEL>_NOTHROW(expression)```
|
|
||||||
|
|
||||||
Expects that no exception is thrown during evaluation of the expression.
|
|
||||||
|
|
||||||
Note that these asserts also have a ```_MESSAGE``` form - like ```CHECK_THROWS_MESSAGE(expression, message)``` - these work identically to the ```_MESSAGE``` form of the normal macros (```CHECK_MESSAGE(a < b, "this shouldn't fail")```) described earlier.
|
|
||||||
|
|
||||||
One may use the [**```DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS```**](configuration.html#doctest_config_void_cast_expressions) config identifier to cast the expression in these asserts to void to avoid warnings or other issues - for example nodiscard statements whose result isn't checked. This will however limit the ability to write entire ```{}``` blocks of code as the expression (or multiple statements) but in that case a simple lambda can be used. This should have been the default behavior from day 1 of the framework...
|
|
||||||
|
|
||||||
## Using asserts out of a testing context
|
|
||||||
|
|
||||||
Asserts can be used outside of a testing context (in code not called from a ```TEST_CASE()```) instead of [```assert()```](https://en.cppreference.com/w/cpp/error/assert).
|
|
||||||
|
|
||||||
A ```doctest::Context``` object still has to be created somewhere and set as the default one using the ```setAsDefaultForAssertsOutOfTestCases()``` method - and then asserts will work. A handler can be registered by calling the ```setAssertHandler()``` method on the context object. If no handler is set then ```std::abort()``` is called on failure.
|
|
||||||
|
|
||||||
The results would be best when using the [**```DOCTEST_CONFIG_SUPER_FAST_ASSERTS```**](configuration.html#doctest_config_super_fast_asserts) config identifier.
|
|
||||||
|
|
||||||
Checkout the [**example**](../../examples/all_features/asserts_used_outside_of_tests.cpp) showcasing how that is done. For more information see the [**issue for the feature request**](https://github.com/onqtam/doctest/issues/114).
|
|
||||||
|
|
||||||
Currently [**logging macros**](logging.html) cannot be used for extra context for asserts outside of a test run. That means that the ```_MESSAGE``` variants of asserts are also not usable - since they are just a packed ```INFO()``` with an assert right after it.
|
|
||||||
|
|
||||||
## Floating point comparisons
|
|
||||||
|
|
||||||
When comparing floating point numbers - especially if at least one of them has been computed - great care must be taken to allow for rounding errors and inexact representations.
|
|
||||||
|
|
||||||
**doctest** provides a way to perform tolerant comparisons of floating point values through the use of a wrapper class called ```doctest::Approx```. ```doctest::Approx``` can be used on either side of a comparison expression. It overloads the comparisons operators to take a relative tolerance into account. Here's a simple example:
|
|
||||||
|
|
||||||
```
|
|
||||||
REQUIRE(performComputation() == doctest::Approx(2.1));
|
|
||||||
```
|
|
||||||
|
|
||||||
By default a small epsilon value (relative - in percentages) is used that covers many simple cases of rounding errors. When this is insufficient the epsilon value (the amount within which a difference either way is ignored) can be specified by calling the ```epsilon()``` method on the ```doctest::Approx``` instance. e.g.:
|
|
||||||
|
|
||||||
```
|
|
||||||
REQUIRE(22.0/7 == doctest::Approx(3.141).epsilon(0.01)); // allow for a 1% error
|
|
||||||
```
|
|
||||||
|
|
||||||
When dealing with very large or very small numbers it can be useful to specify a scale, which can be achieved by calling the ```scale()``` method on the ```doctest::Approx``` instance.
|
|
||||||
|
|
||||||
--------
|
|
||||||
|
|
||||||
- Check out the [**example**](../../examples/all_features/assertion_macros.cpp) which shows many of these macros
|
|
||||||
- Do not wrap assertion macros in ```try```/```catch``` - the REQUIRE macros throw exceptions to end the test case execution!
|
|
||||||
|
|
||||||
---------------
|
|
||||||
|
|
||||||
[Home](readme.html#reference)
|
|
||||||
|
|
||||||
<p align="center"><img src="../../scripts/data/logo/icon_2.svg"></p>
|
|
||||||
|
|
||||||
|
|
||||||
</xmp>
|
|
||||||
<script src="strapdown.js/strapdown.js"></script>
|
|
||||||
</html>
|
|
|
@ -1,212 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<title>benchmarks</title>
|
|
||||||
<xmp theme="united" style="display:none;">
|
|
||||||
|
|
||||||
# Benchmarks
|
|
||||||
|
|
||||||
The benchmarks are done with [**this**](../../scripts/bench/bench.py) script using CMake. There are 3 benchmarking scenarios:
|
|
||||||
|
|
||||||
- [the cost of including the header](#cost-of-including-the-header)
|
|
||||||
- [the cost of an assertion macro](#cost-of-an-assertion-macro)
|
|
||||||
- [runtime speed of lots of asserts](#runtime-benchmarks)
|
|
||||||
|
|
||||||
Compilers used:
|
|
||||||
|
|
||||||
- WINDOWS: Microsoft Visual Studio Community 2017 - Version 15.8.1+28010.2003
|
|
||||||
- WINDOWS: gcc 8.1.0 (x86_64-posix-seh-rev0, Built by MinGW-W64 project)
|
|
||||||
- LINUX: gcc 6.3.0 20170406 (Ubuntu 6.3.0-12ubuntu2)
|
|
||||||
- LINUX: clang 4.0.0-1 (tags/RELEASE_400/rc1) Target: x86_64-pc-linux-gnu
|
|
||||||
|
|
||||||
Environment used (Intel i7 3770k, 16g RAM):
|
|
||||||
|
|
||||||
- Windows 7 - on an SSD
|
|
||||||
- Ubuntu 17.04 in a VirtualBox VM - on a HDD
|
|
||||||
|
|
||||||
**doctest** version: 2.2.0 (released on 2018.12.02)
|
|
||||||
|
|
||||||
[**Catch**](https://github.com/catchorg/Catch2) version: 2.3.0 (released on 2018.07.22)
|
|
||||||
|
|
||||||
# Compile time benchmarks
|
|
||||||
|
|
||||||
## Cost of including the header
|
|
||||||
|
|
||||||
This is a benchmark that is relevant only to single header and header only frameworks - like **doctest** and [**Catch**](https://github.com/catchorg/Catch2).
|
|
||||||
|
|
||||||
The script generates 201 source files and in 200 of them makes a function in the form of ```int f135() { return 135; }``` and in ```main.cpp``` it forward declares all the 200 such dummy functions and accumulates their result to return from the ```main()``` function. This is done to ensure that all source files are built and that the linker doesn't remove/optimize anything.
|
|
||||||
|
|
||||||
- **baseline** - how much time the source files need for a single threaded build with ```msbuild```/```make```
|
|
||||||
- **+ implement** - only in ```main.cpp``` the header is included with a ```#define``` before it so the test runner gets implemented:
|
|
||||||
|
|
||||||
```
|
|
||||||
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
|
|
||||||
#include "doctest.h"
|
|
||||||
```
|
|
||||||
- **+ header everywhere** - the framework header is also included in all the other source files
|
|
||||||
- **+ disabled** - remove everything testing-related from the binary
|
|
||||||
|
|
||||||
| doctest | baseline | + implement | + header everywhere | + disabled |
|
|
||||||
|---------------------|----------|-------------|---------------------|------------|
|
|
||||||
| MSVC Debug | 4.89 | 6.21 | 8.33 | 6.39 |
|
|
||||||
| MSVC Release | 4.38 | 6.39 | 8.71 | 6.02 |
|
|
||||||
| MinGW GCC Debug | 8.12 | 10.86 | 14.73 | 10.17 |
|
|
||||||
| MinGW GCC Release | 8.21 | 11.11 | 15.03 | 10.71 |
|
|
||||||
| Linux GCC Debug | 4.20 | 6.23 | 9.81 | 6.24 |
|
|
||||||
| Linux GCC Release | 4.29 | 6.93 | 11.05 | 6.76 |
|
|
||||||
| Linux Clang Debug | 8.70 | 10.02 | 14.43 | 11.13 |
|
|
||||||
| Linux Clang Release | 9.30 | 11.68 | 16.20 | 11.58 |
|
|
||||||
|
|
||||||
| Catch | baseline | + implement | + header everywhere | + disabled |
|
|
||||||
|---------------------|----------|-------------|---------------------|------------|
|
|
||||||
| MSVC Debug | 4.82 | 7.83 | 88.85 | 88.72 |
|
|
||||||
| MSVC Release | 4.38 | 9.97 | 87.17 | 88.35 |
|
|
||||||
| MinGW GCC Debug | 8.00 | 57.28 | 137.28 | 132.73 |
|
|
||||||
| MinGW GCC Release | 8.38 | 22.94 | 97.17 | 97.22 |
|
|
||||||
| Linux GCC Debug | 4.42 | 15.57 | 97.94 | 97.18 |
|
|
||||||
| Linux GCC Release | 4.50 | 19.59 | 99.48 | 100.75 |
|
|
||||||
| Linux Clang Debug | 8.76 | 15.60 | 107.99 | 110.61 |
|
|
||||||
| Linux Clang Release | 9.32 | 25.75 | 118.67 | 117.11 |
|
|
||||||
|
|
||||||
<img src="../../scripts/data/benchmarks/header.png" width="410" align="right">
|
|
||||||
<img src="../../scripts/data/benchmarks/implement.png" width="410">
|
|
||||||
|
|
||||||
### Conclusion
|
|
||||||
|
|
||||||
#### doctest
|
|
||||||
|
|
||||||
- instantiating the test runner in one source file costs ~1-3 seconds ```implement - baseline```
|
|
||||||
- the inclusion of ```doctest.h``` in one source file costs between 11ms - 23ms ```(header_everywhere - implement) / 200```
|
|
||||||
- including the library everywhere but everything disabled costs around 2 seconds ```disabled - baseline``` for 200 files
|
|
||||||
|
|
||||||
#### [Catch](https://github.com/catchorg/Catch2)
|
|
||||||
|
|
||||||
- instantiating the test runner in one source file costs ~3-50 seconds ```implement - baseline```
|
|
||||||
- the inclusion of ```catch.hpp``` in one source file costs between 380ms - 470ms ```(header_everywhere - implement) / 200```
|
|
||||||
- using the config option to disable the library (**```CATCH_CONFIG_DISABLE```**) has no effect on the header cost
|
|
||||||
|
|
||||||
----------
|
|
||||||
|
|
||||||
So if ```doctest.h``` costs 11ms and ```catch.hpp``` costs 400ms on MSVC - then the **doctest** header is >> **36** << times lighter (for MSVC)!
|
|
||||||
|
|
||||||
----------
|
|
||||||
|
|
||||||
The results are in seconds and are in **no way** intended to bash [**Catch**](https://github.com/catchorg/Catch2) - the **doctest** framework wouldn't exist without it.
|
|
||||||
|
|
||||||
The reason the **doctest** header is so light on compile times is because it forward declares everything and doesn't drag any headers in the source files (except for the source file where the test runner gets implemented). This was a key design decision.
|
|
||||||
|
|
||||||
## Cost of an assertion macro
|
|
||||||
|
|
||||||
The script generates 11 ```.cpp``` files and in 10 of them makes 50 test cases with 100 asserts in them (of the form ```CHECK(a==b)``` where ```a``` and ```b``` are always the same ```int``` variables) - **50k** asserts! The testing framework gets implemented in ```main.cpp```.
|
|
||||||
|
|
||||||
- **baseline** - how much time a single threaded build takes with the header included everywhere - no test cases or asserts!
|
|
||||||
- ```CHECK(a==b)``` - will add ```CHECK()``` asserts which decompose the expression with template machinery
|
|
||||||
|
|
||||||
**doctest** specific:
|
|
||||||
|
|
||||||
- **+fast 1** - will add [**```DOCTEST_CONFIG_SUPER_FAST_ASSERTS```**](configuration.html#doctest_config_super_fast_asserts) to speed up the compilation of the normal asserts ```CHECK(a==b)```
|
|
||||||
- ```CHECK_EQ(a,b)``` - will use ```CHECK_EQ(a,b)``` instead of the expression decomposing ones
|
|
||||||
- **+fast 2** - will add [**```DOCTEST_CONFIG_SUPER_FAST_ASSERTS```**](configuration.html#doctest_config_super_fast_asserts) to speed up the compilation of the binary asserts ```CHECK_EQ(a,b)```
|
|
||||||
- **+disabled** - all test case and assert macros will be disabled with [**```DOCTEST_CONFIG_DISABLE```**](configuration.html#doctest_config_disable)
|
|
||||||
|
|
||||||
[**Catch**](https://github.com/catchorg/Catch2) specific:
|
|
||||||
|
|
||||||
- **+fast** - will add [**```CATCH_CONFIG_FAST_COMPILE```**](https://github.com/catchorg/Catch2/blob/master/docs/configuration.html#catch_config_fast_compile) which speeds up the compilation of the normal asserts ```CHECK(a==b)```
|
|
||||||
- **+disabled** - all test case and assert macros will be disabled with **```CATCH_CONFIG_DISABLE```**
|
|
||||||
|
|
||||||
| doctest | baseline | ```CHECK(a==b)``` | +fast 1 | ```CHECK_EQ(a,b)``` | +fast 2 | +disabled |
|
|
||||||
|---------------------|----------|-------------------|---------|---------------------|---------|-----------|
|
|
||||||
| MSVC Debug | 2.69 | 27.37 | 10.37 | 17.17 | 4.82 | 1.91 |
|
|
||||||
| MSVC Release | 3.15 | 58.73 | 20.73 | 26.07 | 6.43 | 1.83 |
|
|
||||||
| MinGW GCC Debug | 3.78 | 97.29 | 43.05 | 59.86 | 11.88 | 1.67 |
|
|
||||||
| MinGW GCC Release | 4.09 | 286.70 | 95.42 | 156.73 | 18.16 | 2.03 |
|
|
||||||
| Linux GCC Debug | 2.39 | 91.36 | 41.92 | 52.26 | 10.16 | 1.32 |
|
|
||||||
| Linux GCC Release | 3.29 | 257.40 | 97.46 | 128.84 | 19.38 | 1.79 |
|
|
||||||
| Linux Clang Debug | 2.40 | 85.52 | 43.53 | 51.24 | 8.32 | 1.62 |
|
|
||||||
| Linux Clang Release | 3.40 | 160.65 | 79.34 | 81.52 | 11.90 | 1.82 |
|
|
||||||
|
|
||||||
And here is [**Catch**](https://github.com/catchorg/Catch2) which only has normal ```CHECK(a==b)``` asserts:
|
|
||||||
|
|
||||||
| Catch | baseline | ```CHECK(a==b)``` | +fast | +disabled |
|
|
||||||
|---------------------|----------|-------------------|-------|-----------|
|
|
||||||
| MSVC Debug | 8.20 | 31.22 | 25.54 | 8.22 |
|
|
||||||
| MSVC Release | 10.13 | 448.68 | 168.67 | 10.20 |
|
|
||||||
| MinGW GCC Debug | 53.54 | 152.38 | 131.85 | 49.07 |
|
|
||||||
| MinGW GCC Release | 19.26 | 590.16 | 466.69 | 18.99 |
|
|
||||||
| Linux GCC Debug | 15.05 | 117.30 | 95.33 | 14.79 |
|
|
||||||
| Linux GCC Release | 18.77 | 608.94 | 482.73 | 18.96 |
|
|
||||||
| Linux Clang Debug | 12.27 | 94.39 | 77.33 | 12.11 |
|
|
||||||
| Linux Clang Release | 20.75 | 545.84 | 506.02 | 20.15 |
|
|
||||||
|
|
||||||
<img src="../../scripts/data/benchmarks/asserts.png">
|
|
||||||
|
|
||||||
### Conclusion
|
|
||||||
|
|
||||||
**doctest**:
|
|
||||||
|
|
||||||
- is between 0 and 8 times faster than [**Catch**](https://github.com/catchorg/Catch2) when using normal expression decomposing ```CHECK(a==b)``` asserts
|
|
||||||
- asserts of the form ```CHECK_EQ(a,b)``` with no expression decomposition - around 31-63% faster than ```CHECK(a==b)```
|
|
||||||
- the [**```DOCTEST_CONFIG_SUPER_FAST_ASSERTS```**](configuration.html#doctest_config_super_fast_asserts) identifier makes the normal asserts faster by 57-68%
|
|
||||||
- the [**```DOCTEST_CONFIG_SUPER_FAST_ASSERTS```**](configuration.html#doctest_config_super_fast_asserts) identifier makes the binary asserts even faster by another 84-91%
|
|
||||||
- using the [**```DOCTEST_CONFIG_DISABLE```**](configuration.html#doctest_config_disable) identifier the asserts just disappear as if they were never written - even lower than the baseline (because most of the implementation is also gone)
|
|
||||||
|
|
||||||
[**Catch**](https://github.com/catchorg/Catch2):
|
|
||||||
|
|
||||||
- using [**```CATCH_CONFIG_FAST_COMPILE```**](https://github.com/catchorg/Catch2/blob/master/docs/configuration.html#catch_config_fast_compile) results in 10-30% faster build times for asserts (and in one case 73%).
|
|
||||||
- using the **```CATCH_CONFIG_DISABLE```** identifier provides the same great benefits for assert macros as the doctest version ([**```DOCTEST_CONFIG_DISABLE```**](configuration.html#doctest_config_disable)) - but not for the header cost
|
|
||||||
|
|
||||||
## Runtime benchmarks
|
|
||||||
|
|
||||||
The runtime benchmarks consist of a single test case with a loop of 10 million iterations performing the task - a single normal assert (using expression decomposition) or the assert + the logging of the loop iterator ```i```:
|
|
||||||
|
|
||||||
```
|
|
||||||
for(int i = 0; i < 10000000; ++i)
|
|
||||||
CHECK(i == i);
|
|
||||||
```
|
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
```
|
|
||||||
for(int i = 0; i < 10000000; ++i) {
|
|
||||||
INFO(i);
|
|
||||||
CHECK(i == i);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Note that the assert always passes - the goal should be to optimize for the common case - lots of passing test cases and a few that maybe fail.
|
|
||||||
|
|
||||||
| doctest | assert | + info | | Catch | assert | + info |
|
|
||||||
|---------------------|---------|---------|-|---------------------|---------|---------|
|
|
||||||
| MSVC Debug | 4.00 | 11.41 | | MSVC Debug | 5.60 | 213.91 |
|
|
||||||
| MSVC Release | 0.40 | 1.47 | | MSVC Release | 0.76 | 7.60 |
|
|
||||||
| MinGW GCC Debug | 1.05 | 2.93 | | MinGW GCC Debug | 1.17 | 9.54 |
|
|
||||||
| MinGW GCC Release | 0.34 | 1.27 | | MinGW GCC Release | 0.36 | 4.28 |
|
|
||||||
| Linux GCC Debug | 1.24 | 2.34 | | Linux GCC Debug | 1.44 | 9.69 |
|
|
||||||
| Linux GCC Release | 0.29 | 0.52 | | Linux GCC Release | 0.29 | 3.60 |
|
|
||||||
| Linux Clang Debug | 1.15 | 2.38 | | Linux Clang Debug | 1.21 | 9.91 |
|
|
||||||
| Linux Clang Release | 0.28 | 0.50 | | Linux Clang Release | 0.32 | 3.27 |
|
|
||||||
|
|
||||||
<img src="../../scripts/data/benchmarks/runtime_info.png" width="410" align="right">
|
|
||||||
<img src="../../scripts/data/benchmarks/runtime_assert.png" width="410">
|
|
||||||
|
|
||||||
### Conclusion
|
|
||||||
|
|
||||||
**doctest** is around ~20% faster than catch for asserts but a few times faster when also logging variables and context (and in the case of one particular compiler over 18 times faster).
|
|
||||||
|
|
||||||
----------
|
|
||||||
|
|
||||||
The bar charts were generated using [**this google spreadsheet**](https://docs.google.com/spreadsheets/d/1p3MAURUfPzKT7gtJOVuJU2_yVKSqkoD1nbypA1K3618) by pasting the data from the tables.
|
|
||||||
|
|
||||||
If you want a benchmark that is not synthetic - check out [**this blog post**](http://baptiste-wicht.com/posts/2016/09/blazing-fast-unit-test-compilation-with-doctest-11.html) of [**Baptiste Wicht**](https://github.com/wichtounet) who tested the compile times of the asserts in the 1.1 release with his [**Expression Templates Library**](https://github.com/wichtounet/etl)!
|
|
||||||
|
|
||||||
While reading the post - keep in mind that if a part of a process takes 50% of the time and is made 10000 times faster - the overall process would still be only roughly 50% faster.
|
|
||||||
|
|
||||||
---------------
|
|
||||||
|
|
||||||
[Home](readme.html#reference)
|
|
||||||
|
|
||||||
<p align="center"><img src="../../scripts/data/logo/icon_2.svg"></p>
|
|
||||||
|
|
||||||
|
|
||||||
</xmp>
|
|
||||||
<script src="strapdown.js/strapdown.js"></script>
|
|
||||||
</html>
|
|
|
@ -1,93 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<title>build-systems</title>
|
|
||||||
<xmp theme="united" style="display:none;">
|
|
||||||
|
|
||||||
## Build systems
|
|
||||||
|
|
||||||
The latest released version of doctest can be obtained from here: https://raw.githubusercontent.com/onqtam/doctest/master/doctest/doctest.h
|
|
||||||
|
|
||||||
You can substitute ```master``` with ```dev``` or a tag like ```1.2.9``` for a specific version in the URL above.
|
|
||||||
|
|
||||||
### CMake
|
|
||||||
|
|
||||||
- **doctest** is easiest to use as a single file inside your own repository. Then the following minimal example will work:
|
|
||||||
|
|
||||||
```cmake
|
|
||||||
cmake_minimum_required(VERSION 3.0)
|
|
||||||
project(cmake_test VERSION 0.0.1 LANGUAGES CXX)
|
|
||||||
|
|
||||||
# Prepare doctest for other targets to use
|
|
||||||
find_package(doctest REQUIRED)
|
|
||||||
|
|
||||||
# Make test executable
|
|
||||||
add_executable(tests main.cpp)
|
|
||||||
target_compile_features(test PRIVATE cxx_std_17)
|
|
||||||
target_link_libraries(test PRIVATE doctest::doctest)
|
|
||||||
```
|
|
||||||
|
|
||||||
- You can also use the following CMake snippet to automatically fetch the entire **doctest** repository from github and configure it as an external project:
|
|
||||||
|
|
||||||
```cmake
|
|
||||||
include(ExternalProject)
|
|
||||||
find_package(Git REQUIRED)
|
|
||||||
|
|
||||||
ExternalProject_Add(
|
|
||||||
doctest
|
|
||||||
PREFIX ${CMAKE_BINARY_DIR}/doctest
|
|
||||||
GIT_REPOSITORY https://github.com/onqtam/doctest.git
|
|
||||||
TIMEOUT 10
|
|
||||||
UPDATE_COMMAND ${GIT_EXECUTABLE} pull
|
|
||||||
CONFIGURE_COMMAND ""
|
|
||||||
BUILD_COMMAND ""
|
|
||||||
INSTALL_COMMAND ""
|
|
||||||
LOG_DOWNLOAD ON
|
|
||||||
)
|
|
||||||
|
|
||||||
# Expose required variable (DOCTEST_INCLUDE_DIR) to parent scope
|
|
||||||
ExternalProject_Get_Property(doctest source_dir)
|
|
||||||
set(DOCTEST_INCLUDE_DIR ${source_dir}/doctest CACHE INTERNAL "Path to include folder for doctest")
|
|
||||||
```
|
|
||||||
|
|
||||||
And later you'll be able to use the doctest include directory like this:
|
|
||||||
|
|
||||||
```cmake
|
|
||||||
# add it globally
|
|
||||||
include_directories(${DOCTEST_INCLUDE_DIR})
|
|
||||||
|
|
||||||
# or per target
|
|
||||||
target_include_directories(my_target PUBLIC ${DOCTEST_INCLUDE_DIR})
|
|
||||||
```
|
|
||||||
|
|
||||||
- If you have the entire doctest repository available (as a submodule or just as files) you could also include it in your CMake build by using ```add_subdirectory(path/to/doctest)``` and then you could use it like this:
|
|
||||||
|
|
||||||
```cmake
|
|
||||||
add_executable(my_tests src_1.cpp src_2.cpp ...)
|
|
||||||
target_link_libraries(my_tests doctest)
|
|
||||||
```
|
|
||||||
|
|
||||||
- The ```CMakeLists.txt``` file of the doctest repository has ```install()``` commands so you could also use doctest as a package.
|
|
||||||
|
|
||||||
- To discover tests from an executable and register them in ctest you could use [```doctest_discover_tests(<target>)``` from scripts/cmake/doctest.cmake](../../scripts/cmake/doctest.cmake) - read the comments in the file on how to use it. It works just like [the same functionality in Catch](https://github.com/catchorg/Catch2/blob/master/docs/cmake-integration.html#automatic-test-registration).
|
|
||||||
|
|
||||||
### Package managers
|
|
||||||
|
|
||||||
**doctest** is available through the following package managers:
|
|
||||||
|
|
||||||
- vcpkg
|
|
||||||
- hunter
|
|
||||||
- conan
|
|
||||||
- https://bintray.com/bincrafters/public-conan/doctest:bincrafters
|
|
||||||
- https://bintray.com/mmha/conan/doctest%3Ammha
|
|
||||||
- Homebrew (`brew install doctest`)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
[Home](readme.html#reference)
|
|
||||||
|
|
||||||
<p align="center"><img src="../../scripts/data/logo/icon_2.svg"></p>
|
|
||||||
|
|
||||||
|
|
||||||
</xmp>
|
|
||||||
<script src="strapdown.js/strapdown.js"></script>
|
|
||||||
</html>
|
|
|
@ -1,143 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<title>commandline</title>
|
|
||||||
<xmp theme="united" style="display:none;">
|
|
||||||
|
|
||||||
## Command line
|
|
||||||
|
|
||||||
**doctest** works quite nicely without any command line options at all - but for more control a bunch are available.
|
|
||||||
|
|
||||||
**Query flags** - after the result is printed the program quits without executing any test cases (and if the framework is integrated into a client codebase which [**supplies it's own ```main()``` entry point**](main.html) - the program should check the result of ```shouldExit()``` method after calling ```run()``` on a ```doctest::Context``` object and should exit - this is left up to the user).
|
|
||||||
|
|
||||||
**Int/String options** - they require a value after the ```=``` sign - without spaces! For example: ```--order-by=rand```.
|
|
||||||
|
|
||||||
**Bool options** - they expect ```1```/```yes```/```on```/```true``` or ```0```/```no```/```off```/```false``` after the ```=``` sign - but they can also be used like flags and the ```=value``` part can be skipped - then ```true``` is assumed.
|
|
||||||
|
|
||||||
**Filters** - a comma-separated list of wildcards for matching values - where ```*``` means "match any sequence" and ```?``` means "match any one character".
|
|
||||||
To pass patterns with intervals use ```""``` like this: ```--test-case="*no sound*,vaguely named test number ?"```. Patterns that contain a comma can be escaped with ```\``` (example: ```--test-case=this\,test\,has\,commas```).
|
|
||||||
|
|
||||||
All the options can also be set with code (defaults/overrides) if the user [**supplies the ```main()``` function**](main.html).
|
|
||||||
|
|
||||||
| Query Flags | Description |
|
|
||||||
|:------------|-------------|
|
|
||||||
| ```-?``` ```--help``` ```-h``` | Prints a help message listing all these flags/options |
|
|
||||||
| ```-v``` ```--version``` | Prints the version of the **doctest** framework |
|
|
||||||
| ```-c``` ```--count``` | Prints the number of test cases matching the current filters (see below) |
|
|
||||||
| ```-ltc``` ```--list-test-cases``` | Lists all test cases by name which match the current filters (see below) |
|
|
||||||
| ```-lts``` ```--list-test-suites``` | Lists all test suites by name which have at least one test case matching the current filters (see below) |
|
|
||||||
| ```-lr``` ```--list-reporters``` | Lists all registered [**reporters**](reporters.html) |
|
|
||||||
| **Int/String Options** | <hr> |
|
|
||||||
| ```-tc``` ```--test-case=<filters>``` | Filters test cases based on their name. By default all test cases match but if a value is given to this filter like ```--test-case=*math*,*sound*``` then only test cases who match at least one of the patterns in the comma-separated list with wildcards will get executed/counted/listed |
|
|
||||||
| ```-tce``` ```--test-case-exclude=<filters>``` | Same as the ```-test-case=<filters>``` option but if any of the patterns in the comma-separated list of values matches - then the test case is skipped |
|
|
||||||
| ```-sf``` ```--source-file=<filters>``` | Same as ```--test-case=<filters>``` but filters based on the file in which test cases are written |
|
|
||||||
| ```-sfe``` ```--source-file-exclude=<filters>``` | Same as ```--test-case-exclude=<filters>``` but filters based on the file in which test cases are written |
|
|
||||||
| ```-ts``` ```--test-suite=<filters>``` | Same as ```--test-case=<filters>``` but filters based on the test suite in which test cases are in |
|
|
||||||
| ```-tse``` ```--test-suite-exclude=<filters>``` | Same as ```--test-case-exclude=<filters>``` but filters based on the test suite in which test cases are in |
|
|
||||||
| ```-sc``` ```--subcase=<filters>``` | Same as ```--test-case=<filters>``` but filters subcases based on their names. Does not filter test cases (they have to be executed for subcases to be discovered) so you might want to use this together with ```--test-case=<filters>```. |
|
|
||||||
| ```-sce``` ```--subcase-exclude=<filters>``` | Same as ```--test-case-exclude=<filters>``` but filters based on subcase names |
|
|
||||||
| ```-r``` ```--reporters=<filters>``` | List of [**reporters**](reporters.html) to use (default is ```console```) |
|
|
||||||
| ```-o``` ```--out=<string>``` | Output filename |
|
|
||||||
| ```-ob``` ```--order-by=<string>``` | Test cases will be sorted before being executed either by **the file in which they are** / **the test suite they are in** / **their name** / **random**. The possible values of ```<string>``` are ```file```/```suite```/```name```/```rand```/```none```. The default is ```file```. **NOTE: the order produced by the ```file```, ```suite``` and ```name``` options is compiler-dependent and might differ depending on the compiler used.** |
|
|
||||||
| ```-rs``` ```--rand-seed=<int>``` | The seed for random ordering |
|
|
||||||
| ```-f``` ```--first=<int>``` | The **first** test case to execute which passes the current filters - for range-based execution - see [**the example python script**](../../examples/range_based_execution.py) |
|
|
||||||
| ```-l``` ```--last=<int>``` | The **last** test case to execute which passes the current filters - for range-based execution - see [**the example python script**](../../examples/range_based_execution.py) |
|
|
||||||
| ```-aa``` ```--abort-after=<int>``` | The testing framework will stop executing test cases/assertions after this many failed assertions. The default is 0 which means don't stop at all. Note that the framework uses an exception to stop the current test case regardless of the level of the assert (```CHECK```/```REQUIRE```) - so be careful with asserts in destructors... |
|
|
||||||
| ```-scfl``` ```--subcase-filter-levels=<int>``` | Apply subcase filters only for the first ```<int>``` levels of nested subcases and just run the ones nested deeper. Default is a very high number which means *filter any subcase* |
|
|
||||||
| **Bool Options** | <hr> |
|
|
||||||
| ```-s``` ```--success=<bool>``` | To include successful assertions in the output |
|
|
||||||
| ```-cs``` ```--case-sensitive=<bool>``` | Filters being treated as case sensitive |
|
|
||||||
| ```-e``` ```--exit=<bool>``` | Exits after the tests finish - this is meaningful only when the client has [**provided the ```main()``` entry point**](main.html) - the program should check the ```shouldExit()``` method after calling ```run()``` on a ```doctest::Context``` object and should exit - this is left up to the user. The idea is to be able to execute just the tests in a client program and to not continue with it's execution |
|
|
||||||
| ```-d``` ```--duration=<bool>``` | Prints the time each test case took in seconds |
|
|
||||||
| ```-m``` ```--minimal=<bool>``` | Only prints failing tests |
|
|
||||||
| ```-q``` ```--quiet=<bool>``` | Does not print any output |
|
|
||||||
| ```-nt``` ```--no-throw=<bool>``` | Skips [**exceptions-related assertion**](assertions.html#exceptions) checks |
|
|
||||||
| ```-ne``` ```--no-exitcode=<bool>``` | Always returns a successful exit code - even if a test case has failed |
|
|
||||||
| ```-nr``` ```--no-run=<bool>``` | Skips all runtime **doctest** operations (except the test registering which happens before the program enters ```main()```). This is useful if the testing framework is integrated into a client codebase which has [**provided the ```main()``` entry point**](main.html) and the user wants to skip running the tests and just use the program |
|
|
||||||
| ```-ni``` ```--no-intro=<bool>``` | Omits the framework intro in the output |
|
|
||||||
| ```-nv``` ```--no-version=<bool>``` | Omits the framework version in the output |
|
|
||||||
| ```-nc``` ```--no-colors=<bool>``` | Disables colors in the output |
|
|
||||||
| ```-fc``` ```--force-colors=<bool>``` | Forces the use of colors even when a tty cannot be detected |
|
|
||||||
| ```-nb``` ```--no-breaks=<bool>``` | Disables breakpoints in debuggers when an assertion fails |
|
|
||||||
| ```-ns``` ```--no-skip=<bool>``` | Don't skip test cases marked as skip with a decorator |
|
|
||||||
| ```-gfl``` ```--gnu-file-line=<bool>``` | ```:n:``` vs ```(n):``` for line numbers in output (gnu mode is usually for linux tools/IDEs and is with the ```:``` separator) |
|
|
||||||
| ```-npf``` ```--no-path-filenames=<bool>``` | Paths are removed from the output when a filename is printed - useful if you want the same output from the testing framework on different environments |
|
|
||||||
| ```-nln``` ```--no-line-numbers=<bool>``` | Line numbers are replaced with ```0``` in the output when a source location is printed - useful if you want the same output from the testing framework even when test positions change within a source file |
|
|
||||||
| ```-ndo``` ```--no-debug-output=<bool>``` | Disables output in the debug console when a debugger is attached |
|
|
||||||
| | |
|
|
||||||
|
|
||||||
All the flags/options also come with a prefixed version (with ```--dt-``` at the front by default) - for example ```--version``` can be used also with ```--dt-version``` or ```--dt-v```.
|
|
||||||
|
|
||||||
The default prefix is ```--dt-```, but this can be changed by setting the [**```DOCTEST_CONFIG_OPTIONS_PREFIX```**](configuration.html#doctest_config_options_prefix) define.
|
|
||||||
|
|
||||||
All the unprefixed versions listed here can be disabled with the [**```DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS```**](configuration.html#doctest_config_no_unprefixed_options) define.
|
|
||||||
|
|
||||||
This is done for easy interoperability with client command line option handling when the testing framework is integrated within a client codebase - all **doctest** related flags/options can be prefixed so there are no clashes and so that the user can exclude everything starting with ```--dt-``` from their option parsing.
|
|
||||||
|
|
||||||
If there isn't an option to exclude those starting with ```--dt-``` then the ```dt_removed``` helper class might help to filter them out:
|
|
||||||
|
|
||||||
```
|
|
||||||
#define DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
|
|
||||||
#define DOCTEST_CONFIG_IMPLEMENT
|
|
||||||
#include "doctest.h"
|
|
||||||
|
|
||||||
class dt_removed {
|
|
||||||
std::vector<const char*> vec;
|
|
||||||
public:
|
|
||||||
dt_removed(const char** argv_in) {
|
|
||||||
for(; *argv_in; ++argv_in)
|
|
||||||
if(strncmp(*argv_in, "--dt-", strlen("--dt-")) != 0)
|
|
||||||
vec.push_back(*argv_in);
|
|
||||||
vec.push_back(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
int argc() { return static_cast<int>(vec.size()) - 1; }
|
|
||||||
const char** argv() { return &vec[0]; } // Note: non-const char **:
|
|
||||||
};
|
|
||||||
|
|
||||||
int program(int argc, const char** argv);
|
|
||||||
|
|
||||||
int main(int argc, const char** argv) {
|
|
||||||
doctest::Context context(argc, argv);
|
|
||||||
int test_result = context.run(); // run queries, or run tests unless --no-run
|
|
||||||
|
|
||||||
if(context.shouldExit()) // honor query flags and --exit
|
|
||||||
return test_result;
|
|
||||||
|
|
||||||
dt_removed args(argv);
|
|
||||||
int app_result = program(args.argc(), args.argv());
|
|
||||||
|
|
||||||
return test_result + app_result; // combine the 2 results
|
|
||||||
}
|
|
||||||
|
|
||||||
int program(int argc, const char** argv) {
|
|
||||||
printf("Program: %d arguments received:\n", argc - 1);
|
|
||||||
while(*++argv)
|
|
||||||
printf("'%s'\n", *argv);
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
When ran like this:
|
|
||||||
|
|
||||||
```
|
|
||||||
program.exe --dt-test-case=math* --my-option -s --dt-no-breaks
|
|
||||||
```
|
|
||||||
|
|
||||||
Will output this:
|
|
||||||
|
|
||||||
```
|
|
||||||
Program: 2 arguments received:
|
|
||||||
'--my-option'
|
|
||||||
'-s'
|
|
||||||
```
|
|
||||||
|
|
||||||
---------------
|
|
||||||
|
|
||||||
[Home](readme.html#reference)
|
|
||||||
|
|
||||||
<p align="center"><img src="../../scripts/data/logo/icon_2.svg"></p>
|
|
||||||
|
|
||||||
|
|
||||||
</xmp>
|
|
||||||
<script src="strapdown.js/strapdown.js"></script>
|
|
||||||
</html>
|
|
|
@ -1,256 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<title>configuration</title>
|
|
||||||
<xmp theme="united" style="display:none;">
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
**doctest** is designed to "just work" as much as possible. It also allows configuring how it is built with a set of identifiers.
|
|
||||||
|
|
||||||
The identifiers should be defined before the inclusion of the framework header.
|
|
||||||
|
|
||||||
Defining something ```globally``` means for every source file of the binary (executable / shared object).
|
|
||||||
|
|
||||||
- [**```DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN```**](#doctest_config_implement_with_main)
|
|
||||||
- [**```DOCTEST_CONFIG_IMPLEMENT```**](#doctest_config_implement)
|
|
||||||
- [**```DOCTEST_CONFIG_DISABLE```**](#doctest_config_disable)
|
|
||||||
- [**```DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL```**](#doctest_config_implementation_in_dll)
|
|
||||||
- [**```DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES```**](#doctest_config_no_short_macro_names)
|
|
||||||
- [**```DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING```**](#doctest_config_treat_char_star_as_string)
|
|
||||||
- [**```DOCTEST_CONFIG_SUPER_FAST_ASSERTS```**](#doctest_config_super_fast_asserts)
|
|
||||||
- [**```DOCTEST_CONFIG_USE_STD_HEADERS```**](#doctest_config_use_std_headers)
|
|
||||||
- [**```DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS```**](#doctest_config_void_cast_expressions)
|
|
||||||
- [**```DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION```**](#doctest_config_no_comparison_warning_suppression)
|
|
||||||
- [**```DOCTEST_CONFIG_OPTIONS_PREFIX```**](#doctest_config_options_prefix)
|
|
||||||
- [**```DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS```**](#doctest_config_no_unprefixed_options)
|
|
||||||
- [**```DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS```**](#doctest_config_no_try_catch_in_asserts)
|
|
||||||
- [**```DOCTEST_CONFIG_NO_EXCEPTIONS```**](#doctest_config_no_exceptions)
|
|
||||||
- [**```DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS```**](#doctest_config_no_exceptions_but_with_all_asserts)
|
|
||||||
- [**```DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE```**](#doctest_config_assertion_parameters_by_value)
|
|
||||||
- [**```DOCTEST_CONFIG_COLORS_NONE```**](#doctest_config_colors_none)
|
|
||||||
- [**```DOCTEST_CONFIG_COLORS_WINDOWS```**](#doctest_config_colors_windows)
|
|
||||||
- [**```DOCTEST_CONFIG_COLORS_ANSI```**](#doctest_config_colors_ansi)
|
|
||||||
- [**```DOCTEST_CONFIG_WINDOWS_SEH```**](#doctest_config_windows_seh)
|
|
||||||
- [**```DOCTEST_CONFIG_NO_WINDOWS_SEH```**](#doctest_config_no_windows_seh)
|
|
||||||
- [**```DOCTEST_CONFIG_POSIX_SIGNALS```**](#doctest_config_posix_signals)
|
|
||||||
- [**```DOCTEST_CONFIG_NO_POSIX_SIGNALS```**](#doctest_config_no_posix_signals)
|
|
||||||
- [**```DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS```**](#doctest_config_include_type_traits)
|
|
||||||
- [**```DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS```**](#doctest_config_no_multi_lane_atomics)
|
|
||||||
|
|
||||||
For most people the only configuration needed is telling **doctest** which source file should host all the implementation code:
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN```**
|
|
||||||
|
|
||||||
```
|
|
||||||
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
|
|
||||||
#include "doctest.h"
|
|
||||||
```
|
|
||||||
|
|
||||||
This should be defined only in the source file where the library is implemented. It also creates a ```main()``` entry point.
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_IMPLEMENT```**
|
|
||||||
|
|
||||||
If the client wants to [**supply the ```main()``` function**](main.html) (either to set an option with some value from the code or to integrate the framework into their existing project codebase) this identifier should be used.
|
|
||||||
|
|
||||||
This should be defined only in the source file where the library is implemented.
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_DISABLE```**
|
|
||||||
|
|
||||||
One of the most most important configuration option - everything testing-related is removed from the binary - including most of the framework implementation and every test case written anywhere! This is one of the most unique features of **doctest**.
|
|
||||||
|
|
||||||
This should be defined globally.
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL```**
|
|
||||||
|
|
||||||
This will affect the public interface of doctest - all necessary forward declarations for writing tests will be turned into imported symbols. That way the test runner doesn't have to be implemented in the binary (executable / shared object) and can be reused from another binary where it is built and exported.
|
|
||||||
|
|
||||||
To export the test runner from a binary simply use [**```DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL```**](#doctest_config_implementation_in_dll) together with [**```DOCTEST_CONFIG_IMPLEMENT```**](#doctest_config_implement) (or [**```DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN```**](#doctest_config_implement_with_main) but then the other binaries will have to link to the executable) in whatever source file the test runner gets implemented into. Note that this identifier should not be defined in the other source files of the binary which exports the doctest test runner - or there will be linker conflicts - having the same symbols as both imported and exported within the same binary.
|
|
||||||
|
|
||||||
Checkout the [**example**](../../examples/executable_dll_and_plugin/) - it shows how to have the test runner implemented in a dll (and there are even tests in a plugin which is dynamically loaded).
|
|
||||||
|
|
||||||
This should be defined globally in binaries that import the symbols.
|
|
||||||
|
|
||||||
This should be defined only in the source file where the library is implemented for binaries that export the test runner.
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES```**
|
|
||||||
|
|
||||||
This will remove all macros from **doctest** that don't have the **```DOCTEST_```** prefix - like **```CHECK```**, **```TEST_CASE```** and **```SUBCASE```**. Then only the full macro names will be available - **```DOCTEST_CHECK```**, **```DOCTEST_TEST_CASE```** and **```DOCTEST_SUBCASE```**. The user is free to make their own short versions of these macros - [**example**](../../examples/all_features/alternative_macros.cpp).
|
|
||||||
|
|
||||||
This can be defined both globally and in specific source files only.
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING```**
|
|
||||||
|
|
||||||
By default ```char*``` is being treated as a pointer. With this option comparing ```char*``` pointers will switch to using ```strcmp()``` for comparisons and when stringified the string will be printed instead of the pointer value.
|
|
||||||
|
|
||||||
This should be defined globally.
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_SUPER_FAST_ASSERTS```**
|
|
||||||
|
|
||||||
This config option makes the assert macros (except for those dealing with exceptions) compile [**much faster**](benchmarks.html#cost-of-an-assertion-macro)! (31-91% - depending on the type - [**normal**](assertions.html#expression-decomposing-asserts) or [**binary**](assertions.html#binary-and-unary-asserts))
|
|
||||||
|
|
||||||
Each assert is turned into a single function call - the only downside of this is: if an assert fails and a debugger is attached - when it breaks it will be in an internal function - the user will have to go 1 level up in the callstack to see the actual assert.
|
|
||||||
|
|
||||||
It also implies [**```DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS```**](#doctest_config_no_try_catch_in_asserts) (so exceptions thrown during the evaluation of an assert are not caught by the assert itself but by the testing framework - meaning that the test case is immediately aborted).
|
|
||||||
|
|
||||||
This can be defined both globally and in specific source files only.
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_USE_STD_HEADERS```**
|
|
||||||
|
|
||||||
The library by default provides a forward declaration of ```std::ostream``` in order to support the ```operator<<``` [**stringification**](stringification.html) mechanism (also ```std::tuple<>``` and ```std::nullptr_t```). This is forbidden by the standard (even though it works everywhere on all tested compilers). However if the user wishes to be 100% standards compliant - then this configuration option can be used to force the inclusion of the relevant standard headers.
|
|
||||||
|
|
||||||
Also it is possible that some STL implementation of a compiler with niche usage defines them differently - then there will be compilation errors in STL headers and using this option should fix the problem.
|
|
||||||
|
|
||||||
This should be defined globally.
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS```**
|
|
||||||
|
|
||||||
This affects the [asserts dealing with exceptions](assertions.html#exceptions) - the expression is cast to void to avoid problems such as when functions with the ```[[nodiscard]]``` attribute are used but their result isn't checked.
|
|
||||||
|
|
||||||
This can be defined both globally and in specific source files only.
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION```**
|
|
||||||
|
|
||||||
By default the library suppresses warnings about comparing signed and unsigned types, etc.
|
|
||||||
|
|
||||||
- g++/clang ```-Wsign-conversion```
|
|
||||||
- g++/clang ```-Wsign-compare```
|
|
||||||
- msvc ```C4389``` 'operator' : signed/unsigned mismatch
|
|
||||||
- msvc ```C4018``` 'expression' : signed/unsigned mismatch
|
|
||||||
|
|
||||||
You can checkout [**this**](https://github.com/onqtam/doctest/issues/16#issuecomment-246803303) issue to better understand why I suppress these warnings by default.
|
|
||||||
|
|
||||||
This can be defined both globally and in specific source files only.
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_OPTIONS_PREFIX```**
|
|
||||||
|
|
||||||
Defining this as a string will change the prefix of the [**command line**](commandline.html) options to use the given prefix instead of the default ```dt-``` prefix. This can be useful for integrating the testing framework into a client codebase, where a command option prefix like ```selftest-``` might be more clear to users.
|
|
||||||
|
|
||||||
This should be defined only in the source file where the library is implemented (it's relevant only there).
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS```**
|
|
||||||
|
|
||||||
This will disable the short versions of the [**command line**](commandline.html) options and only the versions with ```--dt-``` prefix will be parsed by **doctest** - this is possible for easy interoperability with client command line option handling when the testing framework is integrated within a client codebase - so there are no clashes and so that the user can exclude everything starting with ```--dt-``` from their option parsing.
|
|
||||||
|
|
||||||
This should be defined only in the source file where the library is implemented (it's relevant only there).
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS```**
|
|
||||||
|
|
||||||
This will remove all ```try``` / ```catch``` sections from:
|
|
||||||
|
|
||||||
- the [normal asserts](assertions.html#expression-decomposing-asserts)
|
|
||||||
- the [binary and unary asserts](assertions.html#binary-and-unary-asserts)
|
|
||||||
|
|
||||||
so exceptions thrown while evaluating the expression in an assert will terminate the current test case.
|
|
||||||
|
|
||||||
This can be used for some mild compile time savings but for greater impact look into [**```DOCTEST_CONFIG_SUPER_FAST_ASSERTS```**](configuration.html#doctest_config_super_fast_asserts).
|
|
||||||
|
|
||||||
This can be defined both globally and in specific source files only.
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_NO_EXCEPTIONS```**
|
|
||||||
|
|
||||||
This will remove everything that uses exceptions from the framework - it is also auto detectable if exceptions are disabled for compilers (like with ```-fno-exceptions``` for GCC/Clang).
|
|
||||||
|
|
||||||
What gets changed:
|
|
||||||
|
|
||||||
- asserts that evaluate the expression in a ```try``` / ```catch``` section no longer evaluate in such a context
|
|
||||||
- ```REQUIRE``` macros are gone (undefined)
|
|
||||||
- [exception macros](assertions.html#exceptions) are gone (undefined)
|
|
||||||
- the ```abort-after``` option won't be fully working because an exception is used to terminate test cases
|
|
||||||
|
|
||||||
The ```REQUIRE``` family of asserts uses exceptions to terminate the current test case when they fail. An exception is used instead of a simple ```return;``` because asserts can be used not only in a test case but also in functions called by a test case.
|
|
||||||
|
|
||||||
Also some of the [**logging macros**](logging.html#messages-which-can-optionally-fail-test-cases) which act like a ```REQUIRE``` assert (terminating the test case) - like ```FAIL()``` - start to work differently - like a ```FAIL_CHECK()```.
|
|
||||||
|
|
||||||
[**```DOCTEST_CONFIG_NO_EXCEPTIONS```**](#doctest_config_no_exceptions) implies [**```DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS```**](#doctest_config_no_try_catch_in_asserts)
|
|
||||||
|
|
||||||
If you wish to use asserts that deal with exceptions and only sometimes build without exceptions - check the [**```DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS```**](#doctest_config_no_exceptions_but_with_all_asserts) config option.
|
|
||||||
|
|
||||||
This should be defined globally.
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS```**
|
|
||||||
|
|
||||||
When building with no exceptions (see [**```DOCTEST_CONFIG_NO_EXCEPTIONS```**](#doctest_config_no_exceptions)) ```REQUIRE``` asserts and the ones about dealing with exceptions are gone.
|
|
||||||
|
|
||||||
If however you want your code to use these assertions and only sometimes build without exceptions - then using this config will be of help. The effects of using it are the following:
|
|
||||||
|
|
||||||
- ```REQUIRE``` asserts are not gone - but they act like ```CHECK``` asserts - when one of them fails the whole test case will be marked as failed but will not be exited immediately
|
|
||||||
- the [asserts for dealing with exceptions](assertions.html#exceptions) are turned into a no-op (instead of being totally undefined)
|
|
||||||
|
|
||||||
This can be defined both globally and in specific source files only.
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE```**
|
|
||||||
|
|
||||||
This option forces all doctest asserts to copy by value the expressions they are given instead of binding them to const references. This might be useful to avoid ODR-usage of static constants (which might lead to linker errors with g++/clang):
|
|
||||||
|
|
||||||
```
|
|
||||||
template<typename T> struct type_traits { static const bool value = false; };
|
|
||||||
|
|
||||||
// unless DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE is defined the following assertion
|
|
||||||
// will lead to a linker error if type_traits<int>::value isn't defined in a translation unit
|
|
||||||
CHECK(type_traits<int>::value == false);
|
|
||||||
```
|
|
||||||
|
|
||||||
This can be defined both globally and in specific source files only.
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_COLORS_NONE```**
|
|
||||||
|
|
||||||
This will remove support for colors in the console output of the framework.
|
|
||||||
|
|
||||||
This should be defined only in the source file where the library is implemented (it's relevant only there).
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_COLORS_WINDOWS```**
|
|
||||||
|
|
||||||
This will force the support for colors in the console output to use the Windows APIs and headers.
|
|
||||||
|
|
||||||
This should be defined only in the source file where the library is implemented (it's relevant only there).
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_COLORS_ANSI```**
|
|
||||||
|
|
||||||
This will force the support for colors in the console output to use ANSI escape codes.
|
|
||||||
|
|
||||||
This should be defined only in the source file where the library is implemented (it's relevant only there).
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_WINDOWS_SEH```**
|
|
||||||
|
|
||||||
This will enable SEH handling on Windows. Currently enabled only when compiled with MSVC, because some versions of MinGW do not have the necessary Win32 API support. The user may choose to enable this explicitly - it is known to work with the MinGW-w64 project.
|
|
||||||
|
|
||||||
This should be defined only in the source file where the library is implemented (it's relevant only there).
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_NO_WINDOWS_SEH```**
|
|
||||||
|
|
||||||
This can be used to disable **```DOCTEST_CONFIG_WINDOWS_SEH```** when it is auto-selected by the library.
|
|
||||||
|
|
||||||
This should be defined only in the source file where the library is implemented (it's relevant only there).
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_POSIX_SIGNALS```**
|
|
||||||
|
|
||||||
This will enable the use of signals under UNIX for handling crashes. On by default.
|
|
||||||
|
|
||||||
This should be defined only in the source file where the library is implemented (it's relevant only there).
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_NO_POSIX_SIGNALS```**
|
|
||||||
|
|
||||||
This can be used to disable **```DOCTEST_CONFIG_POSIX_SIGNALS```** when it is auto-selected by the library.
|
|
||||||
|
|
||||||
This should be defined only in the source file where the library is implemented (it's relevant only there).
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS```**
|
|
||||||
|
|
||||||
This can be used to include the ```<type_traits>``` C++11 header. That in turn will enable the ability for the ```Approx``` helper to be used with strong typedefs of ```double``` - check [this](https://github.com/onqtam/doctest/issues/62) or [this](https://github.com/onqtam/doctest/issues/85) issue for more details on that.
|
|
||||||
|
|
||||||
This can be defined both globally and in specific source files only.
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS```**
|
|
||||||
|
|
||||||
This can be used to disable multi lane atomics. Multi lane atomics can speed up highly parallel use of assert statements, but have a small overhead for single threaded applications.
|
|
||||||
|
|
||||||
---------------
|
|
||||||
|
|
||||||
[Home](readme.html#reference)
|
|
||||||
|
|
||||||
<p align="center"><img src="../../scripts/data/logo/icon_2.svg"></p>
|
|
||||||
|
|
||||||
|
|
||||||
</xmp>
|
|
||||||
<script src="strapdown.js/strapdown.js"></script>
|
|
||||||
</html>
|
|
|
@ -1,158 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<title>extensions</title>
|
|
||||||
<xmp theme="united" style="display:none;">
|
|
||||||
|
|
||||||
## Extensions
|
|
||||||
|
|
||||||
The doctest header doesn't include any external or stdlib headers in it's interface part in order to provide the most optimal build times but that means it is limited in what it can provide as functionality => that's when extensions come into play. They are located as header files in [`doctest/extensions`](../../doctest/extensions) and each of them is documented in a section here.
|
|
||||||
|
|
||||||
# [Utils](../../doctest/extensions/doctest_util.h)
|
|
||||||
|
|
||||||
nothing here yet...
|
|
||||||
|
|
||||||
# [Distributed tests with MPI](../../doctest/extensions/doctest_mpi.h)
|
|
||||||
|
|
||||||
[Bruno Maugars and Bérenger Berthoul, ONERA]
|
|
||||||
|
|
||||||
Testing code over distributed processes requires support from the testing framework. **Doctest** support for MPI parallel communication is provided in the ```"doctest/extensions/doctest_mpi.h"``` header.
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
See [**the complete test**](../../examples/mpi/mpi.cpp) and [**the configuration of main()**](../../examples/mpi/main.cpp)
|
|
||||||
|
|
||||||
### MPI_TEST_CASE
|
|
||||||
|
|
||||||
```
|
|
||||||
#include "doctest/extensions/doctest_mpi.h"
|
|
||||||
|
|
||||||
int my_function_to_test(MPI_Comm comm) {
|
|
||||||
int rank;
|
|
||||||
MPI_Comm_rank(comm,&rank);
|
|
||||||
if (rank == 0) {
|
|
||||||
return 10;
|
|
||||||
}
|
|
||||||
return 11;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
MPI_TEST_CASE("test over two processes",2) { // Parallel test on 2 processes
|
|
||||||
int x = my_function_to_test(test_comm);
|
|
||||||
|
|
||||||
MPI_CHECK( 0, x==10 ); // CHECK for rank 0, that x==10
|
|
||||||
MPI_CHECK( 1, x==11 ); // CHECK for rank 1, that x==11
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
An ```MPI_TEST_CASE``` is like a regular ```TEST_CASE```, except it takes a second argument, which is the number of processes needed to run the test. If the number of processes is less than 2, the test will fail. If the number of processes is greater than or equal to 2, it will create a sub-communicator over 2 processes, called ```test_comm```, and execute the test over these processes. Three objects are provided by ```MPI_TEST_CASE```:
|
|
||||||
* ```test_comm```, of type ```MPI_Comm```: the mpi communicator on which the test is running,
|
|
||||||
* ```test_rank``` and ```test_nb_procs```, two ```int``` giving respectively the rank of the current process and the size of the communicator for ```test_comm```. These last two are just here for convenience and could be retrieved from ```test_comm```.
|
|
||||||
|
|
||||||
We always have:
|
|
||||||
|
|
||||||
```
|
|
||||||
MPI_TEST_CASE("my_test",N) {
|
|
||||||
CHECK( test_nb_procs == N );
|
|
||||||
MPI_CHECK( i, test_rank==i ); // for any i<N
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Assertions
|
|
||||||
It is possible to use regular assertions in an ```MPI_TEST_CASE```. MPI-specific assertions are also provided and are all prefixed with ```MPI_``` (```MPI_CHECK```, ```MPI_ASSERT```...). The first argument is the rank for which they are checked, and the second is the usual expression to check.
|
|
||||||
|
|
||||||
## The main entry points and mpi reporters
|
|
||||||
|
|
||||||
You need to launch the unit tests with an ```mpirun``` command:
|
|
||||||
```
|
|
||||||
mpirun -np 2 unit_test_executable.exe
|
|
||||||
```
|
|
||||||
|
|
||||||
```MPI_Init``` should be called before running the unit tests. Also, using the default console reporter will result in each process writing everything in the same place, which is not what we want. Two reporters are provided and can be enabled. A complete ```main()``` would be:
|
|
||||||
|
|
||||||
|
|
||||||
```
|
|
||||||
#define DOCTEST_CONFIG_IMPLEMENT
|
|
||||||
|
|
||||||
#include "doctest/extensions/doctest_mpi.h"
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
|
||||||
MPI_Init(&argc, &argv);
|
|
||||||
|
|
||||||
doctest::Context ctx;
|
|
||||||
ctx.setOption("reporters", "MpiConsoleReporter");
|
|
||||||
ctx.setOption("reporters", "MpiFileReporter");
|
|
||||||
ctx.setOption("force-colors", true);
|
|
||||||
ctx.applyCommandLine(argc, argv);
|
|
||||||
|
|
||||||
int test_result = ctx.run();
|
|
||||||
|
|
||||||
MPI_Finalize();
|
|
||||||
|
|
||||||
return test_result;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### MpiConsoleReporter
|
|
||||||
|
|
||||||
The ```MpiConsoleReporter``` should be substituted to the default reporter. It does the same as the default console reporter for regular assertions, but only outputs on process 0. For MPI test cases, if there is a failure it tells the process that failed
|
|
||||||
|
|
||||||
```
|
|
||||||
[doctest] doctest version is "2.4.0"
|
|
||||||
[doctest] run with "--help" for options
|
|
||||||
===============================================================================
|
|
||||||
[doctest] test cases: 171 | 171 passed | 0 failed | 0 skipped
|
|
||||||
[doctest] assertions: 864 | 864 passed | 0 failed |
|
|
||||||
[doctest] Status: SUCCESS!
|
|
||||||
std_e_mpi_unit_tests
|
|
||||||
[doctest] doctest version is "2.4.0"
|
|
||||||
[doctest] run with "--help" for options
|
|
||||||
===============================================================================
|
|
||||||
path/to/test.cpp:30:
|
|
||||||
TEST CASE: my test case
|
|
||||||
|
|
||||||
On rank [2] : path/to/test.cpp:35: CHECK( x==-1 ) is NOT correct!
|
|
||||||
values: CHECK( 0 == -1 )
|
|
||||||
|
|
||||||
===============================================================================
|
|
||||||
[doctest] test cases: 2 | 2 passed | 0 failed | 0 skipped
|
|
||||||
[doctest] assertions: 2 | 2 passed | 0 failed |
|
|
||||||
[doctest] Status: SUCCESS!
|
|
||||||
===============================================================================
|
|
||||||
[doctest] glob assertions: 5 | 4 passed | 1 failed |
|
|
||||||
===============================================================================
|
|
||||||
[doctest] fail on rank:
|
|
||||||
-> On rank [2] with 1 test failed
|
|
||||||
[doctest] Status: FAILURE!
|
|
||||||
```
|
|
||||||
|
|
||||||
### MpiFileReporter
|
|
||||||
The ```MpiFileReporter``` will just print the result of each process in its own file, named ```doctest_[rank].log```. Only use this reporter as a debug facility if you want to know what is going on exactly when a parallel test case is failing.
|
|
||||||
|
|
||||||
### Other reporters
|
|
||||||
Other reporters (jUnit, XML) are not supported directly, which mean that you can always print the result of each process to its own file, but there is (currently) no equivalent of the ```MpiConsoleReporter``` that will aggregate the results of all processes.
|
|
||||||
|
|
||||||
|
|
||||||
## Note
|
|
||||||
|
|
||||||
This feature is provided to unit-test mpi-distributed code. It is **not** a way to parallelize many unit tests over several processes (for that, see [**the example python script**](../../examples/range_based_execution.py)).
|
|
||||||
|
|
||||||
## TODO
|
|
||||||
|
|
||||||
* Pass ```s``` member variable of ```ConsoleReporter``` as an argument to member functions so we can use them with another object (would help to factorize ```MPIConsoleReporter```)
|
|
||||||
* Only MPI_CHECK tested. MPI_REQUIRE, exception handling: nothing tested
|
|
||||||
* If the number of processes is not enough, prints the correct message, but then deadlocks (comes from ```MPI_Probe``` in ```MpiConsoleReporter```)
|
|
||||||
* [[maybe_unused]] is C++17
|
|
||||||
* More testing, automatic testing
|
|
||||||
* Packaging: create a new target ```mpi_doctest```? (probably cleaner to depend explicitly on MPI for mpi/doctest.h)
|
|
||||||
* Later, maybe: have a general mechanism to represent assertions so we can separate the report format (console, xml, junit...) from the reporting strategy (sequential vs. MPI)
|
|
||||||
|
|
||||||
---------------
|
|
||||||
|
|
||||||
[Home](readme.html#reference)
|
|
||||||
|
|
||||||
<p align="center"><img src="../../scripts/data/logo/icon_2.svg"></p>
|
|
||||||
|
|
||||||
|
|
||||||
</xmp>
|
|
||||||
<script src="strapdown.js/strapdown.js"></script>
|
|
||||||
</html>
|
|
|
@ -1,188 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<title>faq</title>
|
|
||||||
<xmp theme="united" style="display:none;">
|
|
||||||
|
|
||||||
## FAQ
|
|
||||||
|
|
||||||
- [**How is doctest different from Catch?**](#how-is-doctest-different-from-catch)
|
|
||||||
- [**How is doctest different from Google Test?**](#how-is-doctest-different-from-google-test)
|
|
||||||
- [**How to get the best compile-time performance with the framework?**](#how-to-get-the-best-compile-time-performance-with-the-framework)
|
|
||||||
- [**Is doctest thread-aware?**](#is-doctest-thread-aware)
|
|
||||||
- [**Is mocking supported?**](#is-mocking-supported)
|
|
||||||
- [**Why are my tests in a static library not getting registered?**](#why-are-my-tests-in-a-static-library-not-getting-registered)
|
|
||||||
- [**Why is comparing C strings (```char*```) actually comparing pointers?**](#why-is-comparing-c-strings-char-actually-comparing-pointers)
|
|
||||||
- [**How to write tests in header-only libraries?**](#how-to-write-tests-in-header-only-libraries)
|
|
||||||
- [**Does the framework use exceptions?**](#does-the-framework-use-exceptions)
|
|
||||||
- [**Why do I get compiler errors in STL headers when including the doctest header?**](#why-do-i-get-compiler-errors-in-stl-headers-when-including-the-doctest-header)
|
|
||||||
- [**Can different versions of the framework be used within the same binary (executable/dll)?**](#can-different-versions-of-the-framework-be-used-within-the-same-binary-executabledll)
|
|
||||||
- [**Why is doctest using macros?**](#why-is-doctest-using-macros)
|
|
||||||
- [**How to use with multiple files?**](#how-to-use-with-multiple-files)
|
|
||||||
|
|
||||||
### How is **doctest** different from Catch?
|
|
||||||
|
|
||||||
Pros of **doctest**:
|
|
||||||
|
|
||||||
- **doctest** is [**thread-safe**](faq.html#is-doctest-thread-aware)
|
|
||||||
- asserts can be used [**outside of a testing context**](assertions.html#using-asserts-out-of-a-testing-context)
|
|
||||||
- including the **doctest** header is [**over 20 times lighter**](benchmarks.html#cost-of-including-the-header) on compile times than that of [**Catch**](https://github.com/catchorg/Catch2)
|
|
||||||
- the asserts in **doctest** can be [**many times lighter**](benchmarks.html#cost-of-an-assertion-macro) on compile times than those of [**Catch**](https://github.com/catchorg/Catch2)
|
|
||||||
- **doctest** executes tests [**many times faster**](benchmarks.html#runtime-benchmarks) than [**Catch**](https://github.com/catchorg/Catch2)
|
|
||||||
- everything testing-related can be removed from the binary by defining the [**```DOCTEST_CONFIG_DISABLE```**](configuration.html#doctest_config_disable) identifier
|
|
||||||
- doesn't drag any headers when included (except for in the translation unit where the library gets implemented)
|
|
||||||
- 0 warnings even on the [**most aggressive**](../../scripts/cmake/common.cmake#L84) warning levels for MSVC/GCC/Clang
|
|
||||||
- per commit tested with 180+ builds on [**much more compilers**](features.html#extremely-portable) - and through valgrind/sanitizers/analyzers
|
|
||||||
- test cases can be written in headers - the framework will still register the tests only once - no duplicates
|
|
||||||
- binaries (exe/dll) can use the test runner of another binary - so tests end up in a single registry - [**example**](../../examples/executable_dll_and_plugin/)
|
|
||||||
|
|
||||||
Aside from everything mentioned so far doctest has some [**features**](features.html#other-features) (like [**test suites**](testcases.html#test-suites) and [**decorators**](testcases.html#decorators)) which [**Catch**](https://github.com/catchorg/Catch2) doesn't.
|
|
||||||
|
|
||||||
Missing stuff:
|
|
||||||
|
|
||||||
- matchers and generators
|
|
||||||
- micro benchmarking support - nonius is used in [**Catch**](https://github.com/catchorg/Catch2)
|
|
||||||
- other small stuff such as tags - can be easily emulated/migrated from - see below
|
|
||||||
|
|
||||||
But these things (and more!) are planned in the [**roadmap**](roadmap.html)!
|
|
||||||
|
|
||||||
**doctest** can be thought of as a very polished, light, stable and clean subset (or reimplementation) of [**Catch**](https://github.com/catchorg/Catch2) but this might change in the future as more features are added.
|
|
||||||
|
|
||||||
Also checkout [this table](https://github.com/martinmoene/catch-lest-other-comparison) that compares **doctest** / [**Catch**](https://github.com/catchorg/Catch2) / [**lest**](https://github.com/martinmoene/lest).
|
|
||||||
|
|
||||||
A quick and easy way to migrate most of your Catch tests to doctest is to change the ```TEST_CASE``` (if using tags) and ```SECTION``` macros as follows:
|
|
||||||
|
|
||||||
```
|
|
||||||
#include "path/to/doctest.h"
|
|
||||||
|
|
||||||
#define SECTION(name) DOCTEST_SUBCASE(name)
|
|
||||||
|
|
||||||
// only if tags are used: will concatenate them to the test name string literal
|
|
||||||
#undef TEST_CASE
|
|
||||||
#define TEST_CASE(name, tags) DOCTEST_TEST_CASE(tags " " name)
|
|
||||||
|
|
||||||
// catch exposes this by default outside of its namespace
|
|
||||||
using doctest::Approx;
|
|
||||||
```
|
|
||||||
|
|
||||||
### How is **doctest** different from Google Test?
|
|
||||||
|
|
||||||
Here are a couple of differences:
|
|
||||||
|
|
||||||
- the main one is that only doctest from the C++ frameworks is usable next to your production code (speed of compilation, ability to remove the tests from the binary, ability to execute tests/code/both, ability to have tests in multiple shared objects and still a single registry for all of them)
|
|
||||||
- doctest is a single header - Google Test has to be built as a separate static library and linked against.
|
|
||||||
- doctest has the concept of [**Subcases**](https://github.com/onqtam/doctest/blob/master/doc/markdown/tutorial.html#test-cases-and-subcases) which is a much cleaner way to share setup and teardown code between tests compared to fixtures and class inheritance - Google Test is quite verbose!
|
|
||||||
- doctest compiles faster and probably runs faster (although the runtime becomes an issue only when you have millions of asserts)
|
|
||||||
- doctest asserts are thread-safe even on Windows (Google Test uses pthreads so thread-safe asserts are available only on UNIX)
|
|
||||||
- doctest overall has a simpler API
|
|
||||||
|
|
||||||
but there are also some areas in which doctest is lacking:
|
|
||||||
|
|
||||||
- value-parameterized tests
|
|
||||||
- death tests (where you check if calling a certain function doesn’t simply throw but if it crashes the process)
|
|
||||||
- doctest has some integration with mocking libraries but Google Test works perfectly with Google Mock (although doctest should in theory work with it as well)
|
|
||||||
|
|
||||||
The areas where doctest is behind are planned for improvement in the future. There are many other smaller differences - it would be impractical to cover them all.
|
|
||||||
|
|
||||||
### How to get the best compile-time performance with the framework?
|
|
||||||
|
|
||||||
The [**```DOCTEST_CONFIG_SUPER_FAST_ASSERTS```**](configuration.html#doctest_config_super_fast_asserts) config option yields the [**fastest possible**](benchmarks.html#cost-of-an-assertion-macro) compile times (up to 31-91%). Also the expression-decomposing template machinery can be skipped by using the [**binary**](assertions.html#binary-and-unary-asserts) asserts.
|
|
||||||
|
|
||||||
There are only 2 tiny drawbacks of using this config option:
|
|
||||||
|
|
||||||
- there is no ```try/catch``` block in each assert so if an expression is thrown the whole test case ends (but is still caught and reported).
|
|
||||||
- when an assert fails and a debugger is present - the framework will break inside a doctest function so the user will have to go 1 level up in the callstack to see where the actual assert is in the source code.
|
|
||||||
|
|
||||||
These 2 things can be considered negligible and totally worth it if you are dealing mainly with expressions unlikely to throw exceptions and all the tests usually pass (you don't need to navigate often to a failing assert with a debugger attached).
|
|
||||||
|
|
||||||
### Is doctest thread-aware?
|
|
||||||
|
|
||||||
Most macros/functionality is safe to use in a multithreaded context: [**assertion**](assertions.html) and [**logging**](logging.html) macros can be safely used from multiple threads spawned from a single test case. This however does not mean that multiple test cases can be ran in parallel - test cases are still ran serially. [**Subcases**](tutorial.html#test-cases-and-subcases) should also be used only from the test runner thread and all threads spawned in a subcase ought to be joined before the end of that subcase and no new subcases should be entered while other threads with doctest assertions in them are still running - not following these instructions will lead to crashes (example in [**here**](../../examples/all_features/concurrency.cpp)). Also note that logged context in one thread will not be used/printed when asserts from another thread fail - logged context is thread-local.
|
|
||||||
|
|
||||||
There is also an option to run a [**range**](commandline.html) of tests from an executable - so tests can be ran in parallel by invoking the process multiple times with different ranges - see [**the example python script**](../../examples/range_based_execution.py).
|
|
||||||
|
|
||||||
### Is mocking supported?
|
|
||||||
|
|
||||||
**doctest** doesn't support mocking but should be easy to integrate with third-party libraries such as:
|
|
||||||
|
|
||||||
- [trompeloeil](https://github.com/rollbear/trompeloeil) - integration shown [here](https://github.com/rollbear/trompeloeil/blob/master/docs/CookBook.html#adapt_doctest)
|
|
||||||
- [FakeIt](https://github.com/eranpeer/FakeIt) - integration might be similar to that of [catch](https://github.com/eranpeer/FakeIt/tree/master/config/catch) but this has not been looked into
|
|
||||||
|
|
||||||
by using the [**logging**](logging.html#messages-which-can-optionally-fail-test-cases) macros such as ```ADD_FAIL_AT(file, line, message)```
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Not sure how to integrate with these:
|
|
||||||
https://github.com/dascandy/hippomocks
|
|
||||||
https://github.com/tpounds/mockitopp
|
|
||||||
-->
|
|
||||||
|
|
||||||
### Why are my tests in a static library not getting registered?
|
|
||||||
|
|
||||||
This is a [**common problem among libraries with self-registering code**](https://groups.google.com/forum/#!msg/catch-forum/FV0Qo62DvgY/jxEO6c9_q3kJ) and it affects all modern compilers on all platforms.
|
|
||||||
|
|
||||||
The problem is that when a static library is being linked to a binary (executable or dll) - only object files from the static library that define a symbol being required from the binary will get pulled in (this is a linker/dependency optimization).
|
|
||||||
|
|
||||||
A way to solve this in CMake is to use object libraries instead of static libraries - like this:
|
|
||||||
|
|
||||||
```cmake
|
|
||||||
add_library(with_tests OBJECT src_1.cpp src_2.cpp src_3.cpp ...)
|
|
||||||
|
|
||||||
add_library(dll SHARED $<TARGET_OBJECTS:with_tests> dll_src_1.cpp ...)
|
|
||||||
add_executable(exe $<TARGET_OBJECTS:with_tests> exe_src_1.cpp ...)
|
|
||||||
```
|
|
||||||
|
|
||||||
Thanks to [pthom](https://github.com/pthom) for suggesting this.
|
|
||||||
|
|
||||||
As an alternative I have created a CMake function that forces every object file from a static library to be linked into a binary target - it is called [**```doctest_force_link_static_lib_in_target()```**](../../examples/exe_with_static_libs/doctest_force_link_static_lib_in_target.cmake). It is unintrusive - no source file gets changed - everything is done with compiler flags per source files. An example project using it can be found [**here**](../../examples/exe_with_static_libs) - the commented part of the CMakeLists.txt file.
|
|
||||||
|
|
||||||
It doesn't work in 2 scenarios:
|
|
||||||
|
|
||||||
- either the target or the library uses a precompiled header - see [**this**](https://github.com/onqtam/doctest/issues/21#issuecomment-247001423) issue for details
|
|
||||||
- either the target or the library is an imported target (pre-built) and not built within the current cmake tree
|
|
||||||
|
|
||||||
You can also checkout this repository for a different solution: [**pthom/doctest_registerlibrary**](https://github.com/pthom/doctest_registerlibrary).
|
|
||||||
|
|
||||||
A compiler-specific solution for MSVC is to use the [```/OPT:NOREF```](https://msdn.microsoft.com/en-us/library/bxwfs976.aspx) linker flag (thanks to [lectem](https://github.com/Lectem) for [reporting](https://github.com/onqtam/doctest/issues/106) it!). Another option is to look at [```/wholearchive```](https://docs.microsoft.com/en-us/cpp/build/reference/wholearchive-include-all-library-object-files?view=vs-2019) for MSVC.
|
|
||||||
|
|
||||||
### Why is comparing C strings (```char*```) actually comparing pointers?
|
|
||||||
|
|
||||||
**doctest** by default treats ```char*``` as normal pointers. Using the [**```DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING```**](configuration.html#doctest_config_treat_char_star_as_string) changes that.
|
|
||||||
|
|
||||||
### How to write tests in header-only libraries?
|
|
||||||
|
|
||||||
There are 2 options:
|
|
||||||
|
|
||||||
- just include the doctest header in your headers and write the tests - the doctest header should be shipped with your headers and the user will have to implement the doctest runner in one of their source files.
|
|
||||||
- don't include the doctest header and guard your test cases with ```#ifdef DOCTEST_LIBRARY_INCLUDED``` and ```#endif``` - that way your tests will be compiled and registered if the user includes the doctest header before your headers (and they will also have to implement the test runner somewhere).
|
|
||||||
|
|
||||||
Also note that it would be a good idea to add a tag in your test case names (like this: ```TEST_CASE("[the_lib] testing foo")```) so the user can easily filter them out with ```--test-case-exclude=*the_lib*``` if they wish to.
|
|
||||||
|
|
||||||
### Does the framework use exceptions?
|
|
||||||
|
|
||||||
Yes - but they can be disabled - see the [**```DOCTEST_CONFIG_NO_EXCEPTIONS```**](configuration.html#doctest_config_no_exceptions) config identifier.
|
|
||||||
|
|
||||||
### Why do I get compiler errors in STL headers when including the doctest header?
|
|
||||||
|
|
||||||
Try using the [**```DOCTEST_CONFIG_USE_STD_HEADERS```**](configuration.html#doctest_config_use_std_headers) configuration identifier.
|
|
||||||
|
|
||||||
### Can different versions of the framework be used within the same binary (executable/dll)?
|
|
||||||
|
|
||||||
Currently no. Single header libraries like [**stb**](https://github.com/nothings/stb) have this as an option (everything gets declared static - making it with internal linkage) but it isn't very logical for **doctest** - the main point is to write tests in any source file of the project and have the test runner implemented in only one source file.
|
|
||||||
|
|
||||||
### Why is doctest using macros?
|
|
||||||
|
|
||||||
Aren't they evil and not *modern*? - Check out the answer Phil Nash gives to this question [**here**](http://accu.org/index.php/journals/2064) (the creator of [**Catch**](https://github.com/catchorg/Catch2)).
|
|
||||||
|
|
||||||
### How to use with multiple files?
|
|
||||||
|
|
||||||
All you need to do is define either [**```DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN```**](configuration.html#doctest_config_implement_with_main) or [**```DOCTEST_CONFIG_IMPLEMENT```**](configuration.html#doctest_config_implement) in only ONE of the source files just before including the doctest header - in all other source files you just include the header and use the framework. The difference between the two is that one of them provides a `main()` entry point - for more info on that please refer to [`The main() entry point`](main.html).
|
|
||||||
|
|
||||||
---------------
|
|
||||||
|
|
||||||
[Home](readme.html#reference)
|
|
||||||
|
|
||||||
<p align="center"><img src="../../scripts/data/logo/icon_2.svg"></p>
|
|
||||||
|
|
||||||
|
|
||||||
</xmp>
|
|
||||||
<script src="strapdown.js/strapdown.js"></script>
|
|
||||||
</html>
|
|
|
@ -1,95 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<title>features</title>
|
|
||||||
<xmp theme="united" style="display:none;">
|
|
||||||
|
|
||||||
## Features and design goals
|
|
||||||
|
|
||||||
**doctest** has been designed from the start to be as **light** and **unintrusive** as possible. These key features should be kept.
|
|
||||||
|
|
||||||
## Unintrusive (transparent):
|
|
||||||
|
|
||||||
- everything testing-related can be removed from the binary executable by defining the [**```DOCTEST_CONFIG_DISABLE```**](configuration.html#doctest_config_disable) identifier
|
|
||||||
- very small and easy to integrate - single header
|
|
||||||
- **Extremely** low footprint on compile times - [**around 25ms**](benchmarks.html#cost-of-including-the-header) of compile time overhead for including the header in a file
|
|
||||||
- The [**fastest possible**](benchmarks.html#cost-of-an-assertion-macro) assertion macros - 50k asserts can compile for under 30 seconds (even under 10 sec)
|
|
||||||
- doesn't drag any headers when included (except for in the translation unit where the library gets implemented)
|
|
||||||
- everything is in the ```doctest``` namespace (and the implementation details are in a nested ```detail``` namespace)
|
|
||||||
- all macros have prefixes - some by default have unprefixed versions as well but that is optional - see [**configuration**](configuration.html)
|
|
||||||
- 0 warnings even with the most aggressive flags (on all tested compilers!!!)
|
|
||||||
- ```-Weverything -pedantic``` for **clang**
|
|
||||||
- ```-Wall -Wextra -pedantic``` and **>> over 35 <<** other warnings **not** covered by these flags for **GCC**!!! - see [**here**](../../scripts/cmake/common.cmake#L84)
|
|
||||||
- ```/Wall``` for **MSVC** (except for: ```C4514```, ```C4571```, ```C4710```, ```C4711```)
|
|
||||||
- doesn't error on unrecognized [**command line**](commandline.html) options and supports prefixes for interop with client command line parsing
|
|
||||||
- can set options [**procedurally**](main.html) and not deal with passing ```argc```/```argv``` from the command line
|
|
||||||
- doesn't leave warnings disabled after itself
|
|
||||||
|
|
||||||
## Extremely portable:
|
|
||||||
|
|
||||||
**SOME OF THIS IS OUTDATED**
|
|
||||||
|
|
||||||
- Standards compliant **C++11** code - should work with any **C++11** capable compiler (use tag [**1.2.9**](https://github.com/onqtam/doctest/tree/1.2.9) for C++98 and older compilers)
|
|
||||||
- tested with **GCC**: **4.8**, **4.9**, **5**, **6**, **7**, **8**, **9**, **10**
|
|
||||||
- tested with **Clang**: **3.5**, **3.6**, **3.7**, **3.8**, **3.9**, **4**, **5**, **6**, **7**, **8**, **9** (XCode 6+)
|
|
||||||
- tested with **MSVC**: **2015**, **2017**, **2019** (also in 32 bit mode)
|
|
||||||
- per-commit tested on [**travis**](https://travis-ci.org/onqtam/doctest) and [**appveyor**](https://ci.appveyor.com/project/onqtam/doctest) CI services
|
|
||||||
- warnings as errors even on the most aggressive warning levels - see [**here**](../../scripts/cmake/common.cmake#L84)
|
|
||||||
- statically analyzed on the CI - [**Cppcheck**](http://cppcheck.sourceforge.net/) / [**Clang-Tidy**](https://clang.llvm.org/extra/clang-tidy/) / [**Coverity Scan**](https://scan.coverity.com/) / [**OCLint**](http://oclint.org/) / [**Visual Studio Analyzer**](https://docs.microsoft.com/en-us/visualstudio/code-quality/analyzing-c-cpp-code-quality-by-using-code-analysis)
|
|
||||||
- all tests have their output compared to reference output of a previous known good run
|
|
||||||
- all tests built and ran in **Debug**/**Release** modes
|
|
||||||
- all tests ran through **valgrind** under **Linux** (sadly [not under OSX](https://github.com/onqtam/doctest/issues/11))
|
|
||||||
- all tests ran through **address**, **UB** and **thread** sanitizers under **Linux**/**OSX**
|
|
||||||
- tests are ran in more than **150** different configurations on UNIX (Linux + OSX) on **travis** CI
|
|
||||||
- tests are ran in a total of **14** different configurations on Windows on **appveyor** CI
|
|
||||||
|
|
||||||
## Other features:
|
|
||||||
|
|
||||||
- really easy to get started - it's just 1 header file - see the [**tutorial**](tutorial.html)
|
|
||||||
- **very** light, unintrusive and portable - see the sections above - and also the [**benchmarks**](benchmarks.html)
|
|
||||||
- offers a way to remove **everything** testing-related from the binary with the [**```DOCTEST_CONFIG_DISABLE```**](configuration.html#doctest_config_disable) macro
|
|
||||||
- tests are registered automatically - no need to add them to a collection manually
|
|
||||||
- [**Subcases**](tutorial.html#test-cases-and-subcases) - an intuitive way to share common setup and teardown code for test cases (alternative to [**test fixtures**](testcases.html#test-fixtures) which are also supported)
|
|
||||||
- [**templated test cases**](parameterized-tests.html#templated-test-cases---parameterized-by-type) - parameterized by type
|
|
||||||
- supports [**logging macros**](logging.html) for capturing local variables and strings - as a message for when an assert fails - with lazy stringification and no allocations when possible!
|
|
||||||
- crash handling support - uses signals for UNIX and SEH for Windows
|
|
||||||
- [**thread-safe**](faq.html#is-doctest-thread-aware) - asserts (and logging) can be used from multiple threads spawned from a single test case - [**example**](../../examples/all_features/concurrency.cpp)
|
|
||||||
- an extensible [**reporter system**](reporters.html) (can be also used for implementing event listeners)
|
|
||||||
- output from all compilers on all platforms is the same - byte by byte
|
|
||||||
- binaries (exe/dll) can use the test runner of another binary - so tests end up in a single registry - [**example**](../../examples/executable_dll_and_plugin/)
|
|
||||||
- supports [**BDD style**](testcases.html) tests
|
|
||||||
- one core [**assertion macro**](assertions.html) for comparisons - standard C++ operators are used for the comparison (less than, equal, greater than...) - yet the full expression is decomposed and left and right values of the expression are logged
|
|
||||||
- asserts can be used [**outside of a testing context**](assertions.html#using-asserts-out-of-a-testing-context) - [**example**](../../examples/all_features/asserts_used_outside_of_tests.cpp)
|
|
||||||
- assertion macros for [**exceptions**](assertions.html#exceptions) - if something should or shouldn't throw
|
|
||||||
- floating point comparison support - see the [**```Approx()```**](assertions.html#floating-point-comparisons) helper
|
|
||||||
- powerful mechanism for [**stringification**](stringification.html) of user types - including [**exceptions**](stringification.html#translating-exceptions)!
|
|
||||||
- tests can be grouped in [**test suites**](testcases.html#test-suites)
|
|
||||||
- test case [**decorators**](testcases.html#decorators) such as ```description``` / ```skip``` / ```may_fail``` / ```should_fail``` / ```expected_failures``` / ```timeout```
|
|
||||||
- can be used without exceptions and rtti - checkout [**```DOCTEST_CONFIG_NO_EXCEPTIONS```**](configuration.html#doctest_config_no_exceptions)
|
|
||||||
- powerful [**command line**](commandline.html) with lots of options
|
|
||||||
- can report the duration of test cases
|
|
||||||
- tests can be [**filtered**](commandline.html) based on their name/file/test suite using wildcards
|
|
||||||
- can [**filter**](commandline.html) subcases using wildcards and by specifying the nesting levels for which those filters should work
|
|
||||||
- failures can (optionally) break into the debugger on Windows and Mac
|
|
||||||
- integration with the output window of Visual Studio for failing tests
|
|
||||||
- a ```main()``` can be provided when implementing the library with the [**```DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN```**](main.html#doctest_config_implement_with_main) identifier
|
|
||||||
- can write tests in headers - they will still be registered only once in the executable/shared object
|
|
||||||
- [**range-based**](commandline.html) execution of tests within a binary - see the [**example python script**](../../examples/range_based_execution.py)
|
|
||||||
- [**extension headers**](extensions.html) for extra functionality which doesn't need to go into the main `doctest.h` header
|
|
||||||
- colored output in the console
|
|
||||||
- controlling the order of test execution
|
|
||||||
- different ```doctest::Context```s can be created and ran many times within a single execution of the program
|
|
||||||
- ability to query if code is currently being ran in a test - ```doctest::is_running_in_test```
|
|
||||||
- tests can be registered in CTest with the use of [```doctest_discover_tests(<target>)``` from scripts/cmake/doctest.cmake](../../scripts/cmake/doctest.cmake)
|
|
||||||
|
|
||||||
There is a list of planned features which are all important and big - see the [**roadmap**](roadmap.html).
|
|
||||||
|
|
||||||
---------------
|
|
||||||
|
|
||||||
[Home](readme.html#reference)
|
|
||||||
|
|
||||||
<p align="center"><img src="../../scripts/data/logo/icon_2.svg"></p>
|
|
||||||
|
|
||||||
|
|
||||||
</xmp>
|
|
||||||
<script src="strapdown.js/strapdown.js"></script>
|
|
||||||
</html>
|
|
|
@ -1,80 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<title>logging</title>
|
|
||||||
<xmp theme="united" style="display:none;">
|
|
||||||
|
|
||||||
## Logging macros
|
|
||||||
|
|
||||||
Additional messages can be logged during a test case (safely even in [**concurrent threads**](faq.html#is-doctest-thread-aware)).
|
|
||||||
|
|
||||||
## INFO()
|
|
||||||
|
|
||||||
The ```INFO()``` macro allows heterogeneous sequences of expressions to be captured by listing them with commas.
|
|
||||||
|
|
||||||
```
|
|
||||||
INFO("The number is ", i);
|
|
||||||
```
|
|
||||||
|
|
||||||
This message will be relevant to all asserts after it in the current scope or in scopes nested in the current one and will be printed later only if an assert fails.
|
|
||||||
|
|
||||||
The expression is **NOT** evaluated right away - instead it gets lazily evaluated only when needed.
|
|
||||||
|
|
||||||
Some notes:
|
|
||||||
|
|
||||||
- the lazy stringification means the expressions will be evaluated when an assert fails and not at the point of capture - so the value might have changed by then
|
|
||||||
- refer to the [**stringification**](stringification.html) page for information on how to teach doctest to stringify your types
|
|
||||||
|
|
||||||
The lazy evaluation means that in the common case when no asserts fail the code runs super fast. This makes it suitable even in loops - perhaps to log the iteration.
|
|
||||||
|
|
||||||
There is also the **```CAPTURE()```** macro which is a convenience wrapper of **```INFO()```**:
|
|
||||||
|
|
||||||
```
|
|
||||||
CAPTURE(some_variable)
|
|
||||||
```
|
|
||||||
|
|
||||||
This will handle the stringification of the variable name for you (actually it works with any expression, not just variables).
|
|
||||||
|
|
||||||
This would log something like:
|
|
||||||
|
|
||||||
```
|
|
||||||
some_variable := 42
|
|
||||||
```
|
|
||||||
|
|
||||||
## Messages which can optionally fail test cases
|
|
||||||
|
|
||||||
There are a few other macros for logging information:
|
|
||||||
|
|
||||||
- ```MESSAGE(message)```
|
|
||||||
- ```FAIL_CHECK(message)```
|
|
||||||
- ```FAIL(message)```
|
|
||||||
|
|
||||||
```FAIL()``` is like a ```REQUIRE``` assert - fails the test case and exits it. ```FAIL_CHECK()``` acts like a ```CHECK``` assert - fails the test case but continues with the execution. ```MESSAGE()``` just prints a message.
|
|
||||||
|
|
||||||
```
|
|
||||||
FAIL("This is not supposed to happen! some var: ", var);
|
|
||||||
```
|
|
||||||
|
|
||||||
Also there is no lazy stringification here - strings are always constructed and printed.
|
|
||||||
|
|
||||||
There are also a few more intended for use by third party libraries such as mocking frameworks:
|
|
||||||
|
|
||||||
- ```ADD_MESSAGE_AT(file, line, message)```
|
|
||||||
- ```ADD_FAIL_CHECK_AT(file, line, message)```
|
|
||||||
- ```ADD_FAIL_AT(file, line, message)```
|
|
||||||
|
|
||||||
They can be useful when integrating asserts from a different framework with doctest.
|
|
||||||
|
|
||||||
------
|
|
||||||
|
|
||||||
- Check out the [**example**](../../examples/all_features/logging.cpp) which shows how all of these are used.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
[Home](readme.html#reference)
|
|
||||||
|
|
||||||
<p align="center"><img src="../../scripts/data/logo/icon_2.svg"></p>
|
|
||||||
|
|
||||||
|
|
||||||
</xmp>
|
|
||||||
<script src="strapdown.js/strapdown.js"></script>
|
|
||||||
</html>
|
|
|
@ -1,72 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<title>main</title>
|
|
||||||
<xmp theme="united" style="display:none;">
|
|
||||||
|
|
||||||
## The ```main()``` entry point
|
|
||||||
|
|
||||||
The usual way of writing tests in C++ has always been into separate source files from the code they test that form an executable containing only tests. In that scenario the default ```main()``` provided by **doctest** is usually sufficient:
|
|
||||||
|
|
||||||
```
|
|
||||||
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
|
|
||||||
#include "doctest.h"
|
|
||||||
```
|
|
||||||
|
|
||||||
This should be done in exactly one source file and is even a good idea to do this in a separate file with nothing else in it.
|
|
||||||
|
|
||||||
However if you need more control - want to set options with code to the execution context or want to integrate the framework in your production code - then the default ```main()``` just won't do the job. In that case use [**```DOCTEST_CONFIG_IMPLEMENT```**](configuration.html#doctest_config_implement).
|
|
||||||
|
|
||||||
All the [**command line**](commandline.html) options can be set like this (flags cannot because it wouldn't make sense). Filters can only be appended or cleared with the ```addFilter()``` or ```clearFilters()``` method of a ```doctest::Context``` object - the user cannot remove a specific filter with code.
|
|
||||||
|
|
||||||
```
|
|
||||||
#define DOCTEST_CONFIG_IMPLEMENT
|
|
||||||
#include "doctest.h"
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
|
||||||
doctest::Context context;
|
|
||||||
|
|
||||||
// !!! THIS IS JUST AN EXAMPLE SHOWING HOW DEFAULTS/OVERRIDES ARE SET !!!
|
|
||||||
|
|
||||||
// defaults
|
|
||||||
context.addFilter("test-case-exclude", "*math*"); // exclude test cases with "math" in their name
|
|
||||||
context.setOption("abort-after", 5); // stop test execution after 5 failed assertions
|
|
||||||
context.setOption("order-by", "name"); // sort the test cases by their name
|
|
||||||
|
|
||||||
context.applyCommandLine(argc, argv);
|
|
||||||
|
|
||||||
// overrides
|
|
||||||
context.setOption("no-breaks", true); // don't break in the debugger when assertions fail
|
|
||||||
|
|
||||||
int res = context.run(); // run
|
|
||||||
|
|
||||||
if(context.shouldExit()) // important - query flags (and --exit) rely on the user doing this
|
|
||||||
return res; // propagate the result of the tests
|
|
||||||
|
|
||||||
int client_stuff_return_code = 0;
|
|
||||||
// your program - if the testing framework is integrated in your production code
|
|
||||||
|
|
||||||
return res + client_stuff_return_code; // the result from doctest is propagated here as well
|
|
||||||
}
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
Note the call to ```.shouldExit()``` on the context - that is very important - it will be set when a query flag has been used (or the ```--no-run``` option is set to ```true```) and it is the user's responsibility to exit the application in a normal way.
|
|
||||||
|
|
||||||
### Dealing with shared objects (DLLs)
|
|
||||||
|
|
||||||
The framework can be used separately in binaries (executables / shared objects) with each having it's own test runner - this way even different versions of doctest can be used - but there will be no simple way to execute the tests from all loaded binaries and have the results aggregated and summarized.
|
|
||||||
|
|
||||||
There is also an option to have the test runner (implementation) built in a binary and shared with others (so there is a single test registry) by exporting it's public symbols (the ones needed for writing tests by the user - all the forward declarations of the framework).
|
|
||||||
|
|
||||||
For more info on that checkout the [**```DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL```**](configuration.html#doctest_config_implementation_in_dll) config identifier and [**this example**](../../examples/executable_dll_and_plugin/).
|
|
||||||
|
|
||||||
---------------
|
|
||||||
|
|
||||||
[Home](readme.html#reference)
|
|
||||||
|
|
||||||
<p align="center"><img src="../../scripts/data/logo/icon_2.svg"></p>
|
|
||||||
|
|
||||||
|
|
||||||
</xmp>
|
|
||||||
<script src="strapdown.js/strapdown.js"></script>
|
|
||||||
</html>
|
|
|
@ -1,187 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<title>parameterized-tests</title>
|
|
||||||
<xmp theme="united" style="display:none;">
|
|
||||||
|
|
||||||
## Parameterized test cases
|
|
||||||
|
|
||||||
Test cases can be parameterized easily by type and indirectly by value.
|
|
||||||
|
|
||||||
## Value-parameterized test cases
|
|
||||||
|
|
||||||
There will be proper support for this in the future. For now there are 2 ways of doing data-driven testing in doctest:
|
|
||||||
|
|
||||||
- extracting the asserts in a helper function and calling it with a user-constructed array of data:
|
|
||||||
|
|
||||||
```
|
|
||||||
void doChecks(int data) {
|
|
||||||
// do asserts with data
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("test name") {
|
|
||||||
std::vector<int> data {1, 2, 3, 4, 5, 6};
|
|
||||||
|
|
||||||
for(auto& i : data) {
|
|
||||||
CAPTURE(i); // log the current input data
|
|
||||||
doChecks(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
This has several drawbacks:
|
|
||||||
- in case of an exception (or a ```REQUIRE``` assert failing) the entire test case ends and the checks are not done for the rest of the input data
|
|
||||||
- the user has to manually log the data with calls to ```CAPTURE()``` ( or ```INFO()```)
|
|
||||||
- more boilerplate - doctest should supply primitives for generating data but currently doesnt - so the user has to write their own data generation
|
|
||||||
|
|
||||||
- using subcases to initialize data differently:
|
|
||||||
|
|
||||||
```
|
|
||||||
TEST_CASE("test name") {
|
|
||||||
int data;
|
|
||||||
SUBCASE("") { data = 1; }
|
|
||||||
SUBCASE("") { data = 2; }
|
|
||||||
|
|
||||||
CAPTURE(data);
|
|
||||||
|
|
||||||
// do asserts with data
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
This has the following drawbacks:
|
|
||||||
- doesn't scale well - it is very impractical to write such code for more than a few different inputs
|
|
||||||
- the user has to manually log the data with calls to ```CAPTURE()``` (or ```INFO()```)
|
|
||||||
|
|
||||||
--------------------------------
|
|
||||||
|
|
||||||
There is however an easy way to encapsulate this into a macro (written with C++14 for simplicity):
|
|
||||||
|
|
||||||
```
|
|
||||||
#include <algorithm>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#define DOCTEST_VALUE_PARAMETERIZED_DATA(data, data_container) \
|
|
||||||
static size_t _doctest_subcase_idx = 0; \
|
|
||||||
std::for_each(data_container.begin(), data_container.end(), [&](const auto& in) { \
|
|
||||||
DOCTEST_SUBCASE((std::string(#data_container "[") + \
|
|
||||||
std::to_string(_doctest_subcase_idx++) + "]").c_str()) { data = in; } \
|
|
||||||
}); \
|
|
||||||
_doctest_subcase_idx = 0
|
|
||||||
```
|
|
||||||
|
|
||||||
and now this can be used as follows:
|
|
||||||
|
|
||||||
```
|
|
||||||
TEST_CASE("test name") {
|
|
||||||
int data;
|
|
||||||
std::list<int> data_container = {1, 2, 3, 4}; // must be iterable - std::vector<> would work as well
|
|
||||||
|
|
||||||
DOCTEST_VALUE_PARAMETERIZED_DATA(data, data_container);
|
|
||||||
|
|
||||||
printf("%d\n", data);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
and will print the 4 numbers by re-entering the test case 3 times (after the first entry) - just like subcases work:
|
|
||||||
|
|
||||||
```
|
|
||||||
1
|
|
||||||
2
|
|
||||||
3
|
|
||||||
4
|
|
||||||
```
|
|
||||||
|
|
||||||
The big limitation of this approach is that the macro cannot be used with other subcases at the same code block {} indentation level (will act weird) - it can only be used within a subcase.
|
|
||||||
|
|
||||||
Stay tuned for proper value-parameterization in doctest!
|
|
||||||
|
|
||||||
## Templated test cases - parameterized by type
|
|
||||||
|
|
||||||
Suppose you have multiple implementations of the same interface and want to make sure that all of them satisfy some common requirements. Or, you may have defined several types that are supposed to conform to the same "concept" and you want to verify it. In both cases, you want the same test logic repeated for different types.
|
|
||||||
|
|
||||||
While you can write one ```TEST_CASE``` for each type you want to test (and you may even factor the test logic into a function template that you invoke from the test case), it's tedious and doesn't scale: if you want ```M``` tests over ```N``` types, you'll end up writing ```M * N``` tests.
|
|
||||||
|
|
||||||
Templated tests allow you to repeat the same test logic over a list of types. You only need to write the test logic once.
|
|
||||||
|
|
||||||
There are 2 ways to do it:
|
|
||||||
|
|
||||||
- directly pass the list of types to the templated test case
|
|
||||||
|
|
||||||
```
|
|
||||||
TEST_CASE_TEMPLATE("signed integers stuff", T, char, short, int, long long int) {
|
|
||||||
T var = T();
|
|
||||||
--var;
|
|
||||||
CHECK(var == -1);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
- define the templated test case with a specific unique name (identifier) for later instantiation
|
|
||||||
|
|
||||||
```
|
|
||||||
TEST_CASE_TEMPLATE_DEFINE("signed integer stuff", T, test_id) {
|
|
||||||
T var = T();
|
|
||||||
--var;
|
|
||||||
CHECK(var == -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE_TEMPLATE_INVOKE(test_id, char, short, int, long long int);
|
|
||||||
|
|
||||||
TEST_CASE_TEMPLATE_APPLY(test_id, std::tuple<float, double>);
|
|
||||||
```
|
|
||||||
If you are designing an interface or concept, you can define a suite of type-parameterized tests to verify properties that any valid implementation of the interface/concept should have. Then, the author of each implementation can just instantiate the test suite with their type to verify that it conforms to the requirements, without having to write similar tests repeatedly.
|
|
||||||
|
|
||||||
|
|
||||||
A test case named ```signed integers stuff``` instantiated for type ```int``` will yield the following test case name:
|
|
||||||
|
|
||||||
```
|
|
||||||
signed integers stuff<int>
|
|
||||||
```
|
|
||||||
|
|
||||||
By default all primitive types (fundamental - ```int```, ```bool```, ```float```...) have stringification provided by the library. For all other types the user will have to use the ```TYPE_TO_STRING(type)``` macro - like this:
|
|
||||||
|
|
||||||
```
|
|
||||||
TYPE_TO_STRING(std::vector<int>);
|
|
||||||
```
|
|
||||||
|
|
||||||
The ```TYPE_TO_STRING``` macro has an effect only in the current source file and thus needs to be used in some header if the same type will be used in separate source files for templated test cases.
|
|
||||||
|
|
||||||
Other testing frameworks use the header ```<typeinfo>``` in addition to demangling to get the string for types automatically but doctest cannot afford to include any header in it's forward declaration part (the public one) of the header - so the user has to teach the framework for each type. This is done to achieve [maximal compile time performance](benchmarks.html).
|
|
||||||
|
|
||||||
Some notes:
|
|
||||||
|
|
||||||
- types are NOT filtered for uniqueness - the same templated test case can be instantiated multiple times for the same type - preventing that is left up to the user
|
|
||||||
- you don't need to provide stringification for every type as that plays a role only in the test case name - the default is ```<>``` - the tests will still work and be distinct
|
|
||||||
- if you need parameterization on more than 1 type you can package multiple types in a single one like this:
|
|
||||||
|
|
||||||
```
|
|
||||||
template <typename first, typename second>
|
|
||||||
struct TypePair
|
|
||||||
{
|
|
||||||
typedef first A;
|
|
||||||
typedef second B;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define pairs \
|
|
||||||
TypePair<int, char>, \
|
|
||||||
TypePair<char, int>
|
|
||||||
|
|
||||||
TEST_CASE_TEMPLATE("multiple types", T, pairs) {
|
|
||||||
typedef typename T::A T1;
|
|
||||||
typedef typename T::B T2;
|
|
||||||
// use T1 and T2 types
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
------
|
|
||||||
|
|
||||||
- Check out the [**example**](../../examples/all_features/templated_test_cases.cpp) which shows how all of these are used.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
[Home](readme.html#reference)
|
|
||||||
|
|
||||||
<p align="center"><img src="../../scripts/data/logo/icon_2.svg"></p>
|
|
||||||
|
|
||||||
|
|
||||||
</xmp>
|
|
||||||
<script src="strapdown.js/strapdown.js"></script>
|
|
||||||
</html>
|
|
|
@ -1,46 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<title>readme</title>
|
|
||||||
<xmp theme="united" style="display:none;">
|
|
||||||
|
|
||||||
Reference
|
|
||||||
=======
|
|
||||||
|
|
||||||
Project:
|
|
||||||
|
|
||||||
- [Features and design goals](features.html) - the complete list of features
|
|
||||||
- [Roadmap](roadmap.html) - upcoming features
|
|
||||||
- [Benchmarks](benchmarks.html) - compile-time and runtime supremacy
|
|
||||||
- [Contributing](../../CONTRIBUTING.html) - how to make a proper pull request
|
|
||||||
- [Changelog](../../CHANGELOG.html) - generated changelog based on closed issues/PRs
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
|
|
||||||
- [Tutorial](tutorial.html) - make sure you have read it before the other parts of the documentation
|
|
||||||
- [Assertion macros](assertions.html)
|
|
||||||
- [Test cases, subcases and test fixtures](testcases.html)
|
|
||||||
- [Parameterized test cases](parameterized-tests.html)
|
|
||||||
- [Logging macros](logging.html)
|
|
||||||
- [Command line](commandline.html)
|
|
||||||
- [```main()``` entry point](main.html)
|
|
||||||
- [Configuration](configuration.html)
|
|
||||||
- [String conversions](stringification.html)
|
|
||||||
- [Reporters](reporters.html)
|
|
||||||
- [Extensions](extensions.html)
|
|
||||||
- [FAQ](faq.html)
|
|
||||||
- [Build systems](build-systems.html)
|
|
||||||
- [Examples](../../examples)
|
|
||||||
|
|
||||||
This library is free, and will stay free but needs your support to sustain its development. There are lots of [**new features**](roadmap.html) and maintenance to do. If you work for a company using **doctest** or have the means to do so, please consider financial support.
|
|
||||||
|
|
||||||
[![Patreon](https://cloud.githubusercontent.com/assets/8225057/5990484/70413560-a9ab-11e4-8942-1a63607c0b00.png)](http://www.patreon.com/onqtam)
|
|
||||||
[![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.me/onqtam/10)
|
|
||||||
|
|
||||||
------------
|
|
||||||
|
|
||||||
<p align="center"><img src="../../scripts/data/logo/icon_2.svg"></p>
|
|
||||||
|
|
||||||
|
|
||||||
</xmp>
|
|
||||||
<script src="strapdown.js/strapdown.js"></script>
|
|
||||||
</html>
|
|
|
@ -1,116 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<title>reporters</title>
|
|
||||||
<xmp theme="united" style="display:none;">
|
|
||||||
|
|
||||||
## Reporters
|
|
||||||
|
|
||||||
Doctest has a modular reporter/listener system with which users can write their own reporters and register them. The reporter interface can also be used for "listening" to events.
|
|
||||||
|
|
||||||
You can list all registered reporters/listeners with ```--list-reporters```. There are a few implemented reporters in the framework:
|
|
||||||
- ```console``` - streaming - writes normal lines of text with coloring if a capable terminal is detected
|
|
||||||
- ```xml``` - streaming - writes in xml format tailored to doctest
|
|
||||||
- ```junit``` - buffering - writes in JUnit-compatible xml - for more information look [here](https://github.com/onqtam/doctest/issues/318) and [here](https://github.com/onqtam/doctest/issues/376).
|
|
||||||
|
|
||||||
Streaming means that results are delivered progressively and not at the end of the test run.
|
|
||||||
|
|
||||||
The output is by default written to ```stdout``` but can be redirected with the use of the ```--out=<filename>``` [**command line option**](commandline.html).
|
|
||||||
|
|
||||||
Example how to define your own reporter:
|
|
||||||
|
|
||||||
```
|
|
||||||
#include <doctest/doctest.h>
|
|
||||||
|
|
||||||
#include <mutex>
|
|
||||||
|
|
||||||
using namespace doctest;
|
|
||||||
|
|
||||||
struct MyXmlReporter : public IReporter
|
|
||||||
{
|
|
||||||
// caching pointers/references to objects of these types - safe to do
|
|
||||||
std::ostream& stdout_stream;
|
|
||||||
const ContextOptions& opt;
|
|
||||||
const TestCaseData* tc;
|
|
||||||
std::mutex mutex;
|
|
||||||
|
|
||||||
// constructor has to accept the ContextOptions by ref as a single argument
|
|
||||||
MyXmlReporter(const ContextOptions& in)
|
|
||||||
: stdout_stream(*in.cout)
|
|
||||||
, opt(in) {}
|
|
||||||
|
|
||||||
void report_query(const QueryData& /*in*/) override {}
|
|
||||||
|
|
||||||
void test_run_start() override {}
|
|
||||||
|
|
||||||
void test_run_end(const TestRunStats& /*in*/) override {}
|
|
||||||
|
|
||||||
void test_case_start(const TestCaseData& in) override { tc = ∈ }
|
|
||||||
|
|
||||||
// called when a test case is reentered because of unfinished subcases
|
|
||||||
void test_case_reenter(const TestCaseData& /*in*/) override {}
|
|
||||||
|
|
||||||
void test_case_end(const CurrentTestCaseStats& /*in*/) override {}
|
|
||||||
|
|
||||||
void test_case_exception(const TestCaseException& /*in*/) override {}
|
|
||||||
|
|
||||||
void subcase_start(const SubcaseSignature& /*in*/) override {
|
|
||||||
std::lock_guard<std::mutex> lock(mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
void subcase_end() override {
|
|
||||||
std::lock_guard<std::mutex> lock(mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
void log_assert(const AssertData& in) override {
|
|
||||||
// don't include successful asserts by default - this is done here
|
|
||||||
// instead of in the framework itself because doctest doesn't know
|
|
||||||
// if/when a reporter/listener cares about successful results
|
|
||||||
if(!in.m_failed && !opt.success)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// make sure there are no races - this is done here instead of in the
|
|
||||||
// framework itself because doctest doesn't know if reporters/listeners
|
|
||||||
// care about successful asserts and thus doesn't lock a mutex unnecessarily
|
|
||||||
std::lock_guard<std::mutex> lock(mutex);
|
|
||||||
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
|
|
||||||
void log_message(const MessageData& /*in*/) override {
|
|
||||||
// messages too can be used in a multi-threaded context - like asserts
|
|
||||||
std::lock_guard<std::mutex> lock(mutex);
|
|
||||||
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
|
|
||||||
void test_case_skipped(const TestCaseData& /*in*/) override {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// "1" is the priority - used for ordering when multiple reporters are used
|
|
||||||
REGISTER_REPORTER("my_xml", 1, MyXmlReporter);
|
|
||||||
|
|
||||||
// registering the same class as a reporter and as a listener is nonsense but it's possible
|
|
||||||
REGISTER_LISTENER("my_listener", 1, MyXmlReporter);
|
|
||||||
```
|
|
||||||
|
|
||||||
Custom `IReporter` implementations must be registered with one of:
|
|
||||||
|
|
||||||
* `REGISTER_REPORTER`, for when the new reporter is an option that users may choose at run-time.
|
|
||||||
* `REGISTER_LISTENER`, for when the reporter is actually a listener and must always be executed, regardless of which reporters have been chosen at run-time.
|
|
||||||
|
|
||||||
Multiple reporters can be used at the same time - just specify them through the ```--reporters=...``` [**command line filtering option**](commandline.html) using commas to separate them like this: ```--reporters=myReporter,xml``` and their order of execution will be based on their priority - that is the number "1" in the case of the example reporter above (lower means earlier - the default console/xml reporters from the framework have 0 as their priority and negative numbers are accepted as well).
|
|
||||||
|
|
||||||
All registered listeners (```REGISTER_LISTENER```) will be executed before any reporter - they do not need to be specified and cannot be filtered through the command line.
|
|
||||||
|
|
||||||
When implementing a reporter users are advised to follow the comments from the example above and look at the few implemented reporters in the framework itself. Also check out the [**example**](../../examples/all_features/reporters_and_listeners.cpp).
|
|
||||||
|
|
||||||
---------------
|
|
||||||
|
|
||||||
[Home](readme.html#reference)
|
|
||||||
|
|
||||||
<p align="center"><img src="../../scripts/data/logo/icon_2.svg"></p>
|
|
||||||
|
|
||||||
|
|
||||||
</xmp>
|
|
||||||
<script src="strapdown.js/strapdown.js"></script>
|
|
||||||
</html>
|
|
|
@ -1,173 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<title>roadmap</title>
|
|
||||||
<xmp theme="united" style="display:none;">
|
|
||||||
|
|
||||||
## Roadmap
|
|
||||||
|
|
||||||
This library is free, and will stay free but needs your support to sustain its development. There are lots of [**new features**](roadmap.html) and maintenance to do. If you work for a company using **doctest** or have the means to do so, please consider financial support.
|
|
||||||
|
|
||||||
[![Patreon](https://cloud.githubusercontent.com/assets/8225057/5990484/70413560-a9ab-11e4-8942-1a63607c0b00.png)](http://www.patreon.com/onqtam)
|
|
||||||
[![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.me/onqtam/10)
|
|
||||||
|
|
||||||
Planned features for future releases - order changes constantly... Also look through the [**issues**](https://github.com/onqtam/doctest/issues).
|
|
||||||
|
|
||||||
### For 2.5:
|
|
||||||
|
|
||||||
- https://github.com/onqtam/doctest/issues/208
|
|
||||||
- reporters:
|
|
||||||
- ability to redirect the stdout/stderr from test cases and capture it - like Catch does it
|
|
||||||
- xUnit/TeamCity reporter
|
|
||||||
- compact reporter
|
|
||||||
- matchers - should investigate what they are - look at google test/mock and Catch (also predicates and boost test)
|
|
||||||
- header with extensions
|
|
||||||
- demangling with the use of the cxxabi header
|
|
||||||
- stringification of types from std, also enums with the help of traits as discussed in #121
|
|
||||||
- esoteric reporters
|
|
||||||
- convolution support for the assertion macros (with a predicate)
|
|
||||||
- Value-Parameterized test cases
|
|
||||||
- generators? - look at Catch - and investigate what they are (also SUBCASEs can be while() loops instead of if() statements! that might be useful...)
|
|
||||||
- look at property based testing
|
|
||||||
- [rapidcheck](https://github.com/emil-e/rapidcheck)
|
|
||||||
- [autocheck](https://github.com/thejohnfreeman/autocheck)
|
|
||||||
- [CppQuickCheck](https://github.com/grogers0/CppQuickCheck)
|
|
||||||
- proper conan package - https://github.com/onqtam/doctest/issues/103
|
|
||||||
- IDE integration
|
|
||||||
- https://blogs.msdn.microsoft.com/vcblog/2017/05/10/unit-testing-and-the-future-announcing-the-test-adapter-for-google-test/
|
|
||||||
- https://www.reddit.com/r/cpp/comments/65c0f1/run_cpp_unit_tests_from_xcode_and_visual_studio/
|
|
||||||
- https://github.com/k-brac/CUTI
|
|
||||||
- https://github.com/csoltenborn/GoogleTestAdapter
|
|
||||||
- MSTest
|
|
||||||
- http://accu.org/index.php/journals/1851
|
|
||||||
- https://msdn.microsoft.com/en-us/library/hh270865.aspx
|
|
||||||
- https://msdn.microsoft.com/en-us/library/hh598953.aspx
|
|
||||||
- https://blogs.msdn.microsoft.com/vcblog/2017/04/19/cpp-testing-in-visual-studio/
|
|
||||||
- https://msdn.microsoft.com/en-us/library/hh419385.aspx
|
|
||||||
- XCode - https://github.com/catchorg/Catch2/pull/454
|
|
||||||
- CLion
|
|
||||||
- https://www.jetbrains.com/clion/features/unit-testing.html
|
|
||||||
- https://blog.jetbrains.com/clion/2017/03/clion-2017-1-released/#catch
|
|
||||||
|
|
||||||
### For 2.6:
|
|
||||||
|
|
||||||
- log levels - like in [boost test](http://www.boost.org/doc/libs/1_63_0/libs/test/doc/html/boost_test/utf_reference/rt_param_reference/log_level.html)
|
|
||||||
- running tests a [few times](https://github.com/google/googletest/blob/master/googletest/docs/AdvancedGuide.html#repeating-the-tests)
|
|
||||||
- test execution in [separate processes](https://github.com/catchorg/Catch2/issues/853) - ```fork()``` for UNIX and [this](https://github.com/nemequ/munit/issues/2) for Windows
|
|
||||||
- killing a test that exceeds a time limit (will perhaps require threading or processes)
|
|
||||||
- [symbolizer](https://github.com/facebook/folly/tree/master/folly/experimental/symbolizer) - for a stack trace - when an assertion fails - and it's in a user function with some deep callstack away from the current test case - how to know the exact code path that lead to the failing assert
|
|
||||||
- ability to make the framework not capture unexpected exceptions - as requested [here](https://github.com/onqtam/doctest/issues/12#issuecomment-235334585)
|
|
||||||
- add Approx ability to compare with absolute epsilon - [Catch PR](https://github.com/catchorg/Catch2/pull/538)
|
|
||||||
- ability to customize the colors in the console output (may also use styles - based on [this](https://github.com/agauniyal/rang) or [this](https://github.com/ikalnytskyi/termcolor))
|
|
||||||
- implement breaking into the debugger under linux - see [here](https://github.com/catchorg/Catch2/pull/585) and [here](https://github.com/scottt/debugbreak)
|
|
||||||
- better testing of the library
|
|
||||||
- unit test the String class
|
|
||||||
- should unit test internals - currently even if a bug is caught by different output it's very difficult to track the reason
|
|
||||||
- should test stuff that should not compile
|
|
||||||
- https://github.com/ldionne/dyno/blob/master/cmake/CompileFailTest.cmake
|
|
||||||
- see slide 38 here - https://github.com/boostcon/cppnow_presentations_2017/blob/master/05-19-2017_friday/effective_cmake__daniel_pfeifer__cppnow_05-19-2017.pdf
|
|
||||||
- should test crash handling
|
|
||||||
- should test more config options
|
|
||||||
- don't cheat for maxing out code coverage (see [coverage_maxout.cpp](../../examples/all_features/coverage_maxout.cpp))
|
|
||||||
- should test C++11 stuff - perhaps inspect the CMAKE_CXX_FLAGS for -std=c++11 on the CI and add more targets/tests
|
|
||||||
- test tricky stuff like expressions with commas in asserts
|
|
||||||
|
|
||||||
### For 3.0:
|
|
||||||
|
|
||||||
- use modules - use ```std::string``` and whatever else comes from the standard - no more hand rolled traits and classes
|
|
||||||
- minimize the use of the preprocessor
|
|
||||||
- remove backwards-compatible macros for the fast asserts
|
|
||||||
|
|
||||||
### Things that are being considered but not part of the roadmap yet:
|
|
||||||
|
|
||||||
- add ability to print a diff for strings/values instead of the whole 2 versions (gtest does that)
|
|
||||||
- add LIKELY & friends for the conditions of asserts - look at BOOST_LIKELY, ppk_assert, foonathan/debug_assert, etc
|
|
||||||
- ability for users to register their own command line options and access them later on
|
|
||||||
- fix this: https://github.com/catchorg/Catch2/issues/1292
|
|
||||||
- FakeIt mocking integration - like [catch](https://github.com/eranpeer/FakeIt/tree/master/config/catch) (also checkout [this](https://github.com/ujiro99/doctest-sample))
|
|
||||||
- look into https://github.com/cpp-testing/GUnit - https://www.youtube.com/watch?v=NVrZjT5lW5o
|
|
||||||
- consider the following 2 properties for the MSVC static code analyzer: EnableCppCoreCheck, EnableExperimentalCppCoreCheck
|
|
||||||
- rpm package? like this: https://github.com/vietjtnguyen/argagg/blob/master/packaging/rpm/argagg.spec
|
|
||||||
- get the current test case/section path - https://github.com/catchorg/Catch2/issues/522
|
|
||||||
- when no assertion is encountered in a test case it should fail - and should also add a SUCCEED() call
|
|
||||||
- failure reporting should print out previous SECTIONs for data-driven testing - as requested [here](https://github.com/catchorg/Catch2/issues/734)
|
|
||||||
- ```Bitwise()``` class that has overloaded operators for comparison - to be used to check objects bitwise against each other
|
|
||||||
- detect floating point exceptions
|
|
||||||
- checkpoint/passpoint - like in [boost test](http://www.boost.org/doc/libs/1_63_0/libs/test/doc/html/boost_test/test_output/test_tools_support_for_logging/checkpoints.html) (also make all assert/subcase/logging macros to act as passpoints and print the last one on crashes or exceptions)
|
|
||||||
- queries for the current test case - name (and probably decorators)
|
|
||||||
- support for LibIdentify
|
|
||||||
- add CHECKED_IF & friends: https://github.com/catchorg/Catch2/issues/1278
|
|
||||||
- support for running tests in parallel in multiple threads
|
|
||||||
- death tests - as in [google test](https://github.com/google/googletest/blob/master/docs/advanced.html#death-tests)
|
|
||||||
- config options
|
|
||||||
- test case name uniqueness - reject the ones with identical names
|
|
||||||
- command line options
|
|
||||||
- ability to specify ASC/DESC for the order option
|
|
||||||
- global timeout option (per test or per entire session?)
|
|
||||||
- command line error handling/reporting
|
|
||||||
- option to not print context info when the --success option is used
|
|
||||||
- ability for the user to extend the command line - as requested [here](https://github.com/catchorg/Catch2/issues/622)
|
|
||||||
- option to list files in which there are test cases who match the current filters
|
|
||||||
- option for filters to switch from "match any" to "match all" mode
|
|
||||||
- option to list test suites and test cases in a tree view
|
|
||||||
- add a "wait key" option (before and after tests) - as requested [here](https://github.com/catchorg/Catch2/issues/477#issuecomment-256417686)
|
|
||||||
- decorators for test cases and test suites- like in boost test
|
|
||||||
- depends_on
|
|
||||||
- precondition
|
|
||||||
- fixture
|
|
||||||
- label (tag) - with the ability to have multiple labels (tags) for a test case and also the ability to list them
|
|
||||||
- run X times (should also multiply with (or just override) the global test run times)
|
|
||||||
- throw an exception when incompatible decorators are given in the same list of decorators - like may_fail and should_fail
|
|
||||||
- setup / teardown support
|
|
||||||
- global setup / teardown - can be currently achieved by providing a custom main function
|
|
||||||
- per test suite (block? only? and not all blocks of the same test suite?)
|
|
||||||
- as decorators
|
|
||||||
- see how it's done in boost test - with the fixture decorator
|
|
||||||
- perhaps for fixtures in addition to the constructor / destructor - since throwing in the destructor might terminate the program
|
|
||||||
- or just ignore all of this this - it would require globals or classes and inheritance - and we already have subcases
|
|
||||||
- doctest in a GUI environment? with no console? APIs for attaching a console? querying if there is one? [investigate...](https://github.com/catchorg/Catch2/blob/master/docs/configuration.html#stdout)
|
|
||||||
- runtime performance
|
|
||||||
- look at this: https://github.com/catchorg/Catch2/issues/1086
|
|
||||||
- startup - the set holding all registered tests should use a specialized allocator to minimize program startup time
|
|
||||||
- optimize the mutex lock:
|
|
||||||
- http://preshing.com/20111124/always-use-a-lightweight-mutex/
|
|
||||||
- http://preshing.com/20120226/roll-your-own-lightweight-mutex/
|
|
||||||
- ability to provide a temp folder that is cleared between each test case
|
|
||||||
- make the _MESSAGE assert macros work with variadic arguments - and maybe write the ones for binary/unary asserts as well
|
|
||||||
- move from operator "<<" to "<=" for capturing the left operand when decomposing binary expressions with templates
|
|
||||||
- think about silencing warnings about unused variables when DOCTEST_CONFIG_DISABLE is used - see commit 6b61e8aa3818c5ea100cedc1bb48a60ea10df6e8 or issue #61
|
|
||||||
- also this: ```(void)(true ? (void)0 : ((void)(expression)))```
|
|
||||||
- think about optionally using ```<typeinfo>``` and libcxxabi for demangling so users don't have to use ```TYPE_TO_STRING()```
|
|
||||||
- handle more complex expressions - ```CHECK(foo() == 1 || bar() == 2);```
|
|
||||||
- add [[noreturn]] to MessageBuilder::react() - and actually make a separate function (react2) for the FAIL() case
|
|
||||||
- think about using a string view of some sorts
|
|
||||||
- benchmark against google test and boost test
|
|
||||||
|
|
||||||
### Things that are very unlikely to enter the roadmap:
|
|
||||||
|
|
||||||
- rethink static code analysis suppressions - users shouldn't have to use the same flags for code which uses doctest macros/types
|
|
||||||
- move the "react()" part (the one that throws for REQUIRE asserts - or for when "abort-after=<int>" is reached) to a function call in the while() part of the asserts
|
|
||||||
- stop using underscores for the beginning of identifiers - the anonymous variables - against the standard...
|
|
||||||
- templated fixture test cases
|
|
||||||
- test with missed warning flags for GCC
|
|
||||||
- https://github.com/Barro/compiler-warnings
|
|
||||||
- https://stackoverflow.com/a/34971392/3162383
|
|
||||||
- utf8 / unicode ???
|
|
||||||
- https://github.com/catchorg/Catch2/pull/903
|
|
||||||
- handle ```wchar``` strings???
|
|
||||||
- hierarchical test suites - using a stack for the pushed ones
|
|
||||||
- ability to specify the width of the terminal in terms of characters (for example 60 - less than 80 - the default)
|
|
||||||
- ability to re-run only newly compiled tests based on time stamps using ```__DATE__``` and ```__TIME__``` - stored in some file
|
|
||||||
- add underscores to all preprocessor identifiers not intended for use by the user
|
|
||||||
- put everything from the ```detail``` namespace also in a nested anonymous namespace to make them with internal linkage
|
|
||||||
- ability to put everything from doctest into an anonymous namespace - to allow the use of multiple different versions of **doctest** within the same binary (executable/dll) - like the [**stb**](https://github.com/nothings/stb) libraries can
|
|
||||||
|
|
||||||
---------------
|
|
||||||
|
|
||||||
[Home](readme.html#reference)
|
|
||||||
|
|
||||||
<p align="center"><img src="../../scripts/data/logo/icon_2.svg"></p>
|
|
||||||
|
|
||||||
|
|
||||||
</xmp>
|
|
||||||
<script src="strapdown.js/strapdown.js"></script>
|
|
||||||
</html>
|
|
|
@ -1,24 +0,0 @@
|
||||||
lbesson.bitbucket.org/md/
|
|
||||||
=========================
|
|
||||||
|
|
||||||
[StrapDown.js](https://lbesson.bitbucket.org/md/index.html)
|
|
||||||
is an awesome tool to write nice-looking webpages in pure Markdown, with no server side compilation (as the page you are reading).
|
|
||||||
|
|
||||||
### More details
|
|
||||||
More details on http://lbesson.bitbucket.org/md/index.html,
|
|
||||||
with example and all.
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
# About
|
|
||||||
### Hacked by [Lilian Besson](https://bitbucket.org/lbesson).
|
|
||||||
|
|
||||||
### Languages
|
|
||||||
- JavaScript;
|
|
||||||
- HTML 5 and CSS 3.
|
|
||||||
|
|
||||||
### License
|
|
||||||
This project is released under the **GPLv3 license**, for more details,
|
|
||||||
take a look at the [LICENSE](http://besson.qc.to/LICENSE.html) file in the source.
|
|
||||||
|
|
||||||
*Basically, that allow you to use all or part of the project for you own business.*
|
|
|
@ -1,154 +0,0 @@
|
||||||
<!DOCTYPE html><html><head><meta charset="utf-8"/><title>StrapDown.js on lbesson.bitbucket.org/md</title></head><body><xmp theme="cyborg">
|
|
||||||
# StrapDown.js
|
|
||||||
**StrapDown.js** is an awesome **on-the-fly** [Markdown](https://en.wikipedia.org/wiki/Markdown)
|
|
||||||
to [HTML](https://en.wikipedia.org/wiki/HTML) [text processor](https://en.wikipedia.org/wiki/Compiler).
|
|
||||||
|
|
||||||
## Features
|
|
||||||
- *Directly write your documents in Markdown*, and let the browser do the boring *compilation* steps,
|
|
||||||
- no need for CSS, theming or painless styling : *StrapDown.js* is already *friggin' beautiful*, and *responsive*,
|
|
||||||
- *quick* and *secure*, thanks to *bitbucket* and its SSL (even if the certificate is not valid for [lbesson.bitbucket.org](https://lbesson.bitbucket.org), it is still secure),
|
|
||||||
- an almost perfect support for text-only browsers : pure Markdown is simpler to read than complicated HTML full of javascript,
|
|
||||||
- no external dependencies other than itself,
|
|
||||||
- no spying, no logging, no leaking of your pages (only [Google Analytics](http://besson.qc.to/beacon.html) with the default template, and [rum.js from bitbucket hosting server](https://confluence.atlassian.com/display/BITBUCKET/Publishing+a+Website+on+Bitbucket#PublishingaWebsiteonBitbucket-TechnicalFeaturesandLimitationsofthisFeature)).
|
|
||||||
|
|
||||||
- And, the last but not the least, *experimental* embedding of the even awesomer [SquirtFR](https://lbesson.bitbucket.org/squirt) bookmarklet to read *as quickly as Lucky Luke*.
|
|
||||||
|
|
||||||
## Defaults ?
|
|
||||||
- It might get slow for *long* pages (3000 lines seem to be too much),
|
|
||||||
- a reduced support for browsers *without javascript* or *with javascript disabled* (the pages are still readable, but really ugly),
|
|
||||||
- hosted on bitbucket, which is wonderful but might not be always available (~ 3 hours of maintenance every 6 months).
|
|
||||||
|
|
||||||
Concretly, bitbucket is always *up*, *secured* and *quick* (ooh, and bitbucket is also awesome, completely free, and awesome too). Yeah, *bitbucket is so awesome* that I had to say it twice, you read it correctly.
|
|
||||||
|
|
||||||
But if you prefer, feel free to download [StrapDown.js.zip](https://bitbucket.org/lbesson/lbesson.bitbucket.org/downloads/StrapDown.js.zip) and embed it on your own server.
|
|
||||||
|
|
||||||
> ## A quick "thank you" to the initial project
|
|
||||||
> My version of StrapDown.js is a fork of [strapdownjs.com](http://strapdownjs.com), a cool project that kinda seems dead by now.
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
## How to start using StrapDown.js ?
|
|
||||||
**Just follow this short tutorial** :
|
|
||||||
|
|
||||||
### [Default template to use](example0.html) *(you can click this to see it)*
|
|
||||||
Create an empty file, save it to *mytext.html*
|
|
||||||
(yes, *.html* as HTML, but you will write in Markdown in no time),
|
|
||||||
and then copy and paste the following 5 lines :
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
<!DOCTYPE html><html><head><title>A StrapDown.js template</title></head><body><textarea theme="cyborg">
|
|
||||||
### Write here in Markdown rather than in HTML
|
|
||||||
> This document is empty right now. Fill it out with awesome content !
|
|
||||||
|
|
||||||
</textarea><script type="text/javascript" src="//lbesson.bitbucket.org/md/strapdown.js?src=example0"></script></body></html>
|
|
||||||
```
|
|
||||||
|
|
||||||
### [A first example](example1.html) *(you can click this to see it)*
|
|
||||||
There we use some markup.
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
<!DOCTYPE html><html><head><meta charset="utf-8"/><title>« My first test with StrapDown.js »</title></head><body><textarea theme="cyborg">
|
|
||||||
# This is a Markdown document
|
|
||||||
You can now write your web page in Markdown.
|
|
||||||
|
|
||||||
You opened a `textarea` tag, but a `xmp` tag works as well.
|
|
||||||
|
|
||||||
And, yes, it is **as simple** as **one** HTML line at the beginning and **one** HTML line at the end of this document.
|
|
||||||
</textarea><script type="text/javascript" src="//lbesson.bitbucket.org/md/strapdown.js?src=example1"></script></body></html>
|
|
||||||
```
|
|
||||||
|
|
||||||
### [A second example](example2.html) *(you can click this to see it)*
|
|
||||||
There we embed two images, and describe a little more how cool is StrapDown.js !
|
|
||||||
We also use another theme (*united*).
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
<!DOCTYPE html><html><head><title>Awesome second example with StrapDown.js</title></head><body><textarea theme="united">
|
|
||||||
# This is a Markdown document
|
|
||||||
You can now write your web page in Markdown.
|
|
||||||
You opened a `textarea` tag, but a `xmp` tag works as well.
|
|
||||||
And, yes, it is **as simple** as **one** HTML line at the beginning and **one** HTML line at the end of this document.
|
|
||||||
|
|
||||||
## What to say more
|
|
||||||
Feel free to use it, redistribute it etc, *under the condition of the GPLv3 License*.
|
|
||||||
|
|
||||||
## Only for textual, simple documents
|
|
||||||
StrapDown.js is *awesome* to quickly build nice-looking web page,
|
|
||||||
but it might not be efficient for anything more complicated, as it is really not designed for it.
|
|
||||||
|
|
||||||
## Add a picture ?
|
|
||||||
With Markdown syntax, it's easy : ![GA|Analytics](https://ga-beacon.appspot.com/UA-38514290-14/example2.html "Thanks to ga-beacon").
|
|
||||||
|
|
||||||
### An other one ?
|
|
||||||
Alright, here comes the mighty Cthulhu ![Logo Squirt](../squirt/images/logo.png "Logo Cthulhu")
|
|
||||||
|
|
||||||
### A last one, because it's dangerous to go alone :
|
|
||||||
|
|
||||||
![Logo Take this from dotcore](../squirt/images/takethis.jpg "Logo «Take this» from dotcore")
|
|
||||||
|
|
||||||
## Add anything you want, it *might* work
|
|
||||||
For instance, you can add use Google Analytics to monitor the page's activity,
|
|
||||||
with including a piece of Javascript code, before *or* after closing the *textarea* tag.
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
|
||||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
|
||||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
|
||||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
|
||||||
ga('create','UA-38514290-14','lbesson.bitbucket.org'); ga('send','pageview');
|
|
||||||
</script>
|
|
||||||
<noscript>
|
|
||||||
The previous parapraph was supposed to include Google Analytics web monitoring tool,
|
|
||||||
but hey, you are browsing without JavaScript enabled, what can I do for it ? <br/>
|
|
||||||
Maybe you are using a text-only browser (w3m, links, elinks ? I love elinks !),
|
|
||||||
or a 19th-century IE, or maybe you disabled JavaScript globally (which is kinda stupid) or site-by-site (with NoScript, as I do, which is brilliant, and safer).
|
|
||||||
</noscript>
|
|
||||||
|
|
||||||
## That's it
|
|
||||||
This was a brief overview, to show the basic use of [StrapDown.js](index.html).
|
|
||||||
</textarea><script type="text/javascript" src="//lbesson.bitbucket.org/md/strapdown.js?src=example2"></script></body></html>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Themes
|
|
||||||
Only two themes from [strapdownjs.com]() are pretty enough to be included :
|
|
||||||
|
|
||||||
- [cyborg](http://bootswatch.com/cyborg) for a demo,
|
|
||||||
- [united](http://bootswatch.com/united) for a demo.
|
|
||||||
|
|
||||||
More will soon be availables !
|
|
||||||
|
|
||||||
### Printing to a nice looking PDF
|
|
||||||
Rather than use the built-in "Print to a PDF" function
|
|
||||||
of your browser, you should consider using [StrapDown2PDF](strapdown2pdf.html).
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
# Cloning
|
|
||||||
As of now, StrapDown.js does **not** have it own git repository.
|
|
||||||
And I don't want to, because it is cleaner to let it live on http://lbesson.bitbucket.org/md.
|
|
||||||
|
|
||||||
But, there, you can download this not up-to-date version of the *md* subdir of my [lbesson.bitbucket.org](https://bitbucket.org/lbesson/lbesson.bitbucket.org/src/master/md/) repository :
|
|
||||||
[StrapDown.js.zip](https://bitbucket.org/lbesson/lbesson.bitbucket.org/downloads/StrapDown.js.zip)
|
|
||||||
(and [its PGP signature](https://bitbucket.org/lbesson/lbesson.bitbucket.org/downloads/StrapDown.js.zip.asc).)
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
# Future features
|
|
||||||
- Maybe host it on a *CDN*,
|
|
||||||
- More themes,
|
|
||||||
- Hack something to force using local cached version of the script and stylesheets rather than download them every time ?
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
# About
|
|
||||||
### Hacked by [Lilian Besson](https://bitbucket.org/lbesson)
|
|
||||||
|
|
||||||
### Languages
|
|
||||||
- JavaScript;
|
|
||||||
- CSS 3.
|
|
||||||
|
|
||||||
### License
|
|
||||||
This project is released under the **GPLv3 license**, for more details,
|
|
||||||
take a look at the [LICENSE](http://besson.qc.to/LICENSE.html) file in the source.
|
|
||||||
|
|
||||||
*Basically, that allow you to use all or part of the project for you own business.*
|
|
||||||
</xmp><script type="text/javascript" src="strapdown.js"></script><img alt="GA|Analytics" style="visibility: hidden; display: none;" src="https://ga-beacon.appspot.com/UA-38514290-14/md/index.html?pixel"/></body></html>
|
|
|
@ -1,96 +0,0 @@
|
||||||
/**
|
|
||||||
* StrapDown.js - an on-the-fly markdown parser
|
|
||||||
* Copyright (C) 2014, Lilian Besson. (GPLv3 Licensed)
|
|
||||||
* https://lbesson.bitbucket.org/md/
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This chunk is to fix Bootstrap so that the Markdown output looks good
|
|
||||||
*/
|
|
||||||
|
|
||||||
body {
|
|
||||||
padding-top: 60px;
|
|
||||||
padding-bottom: 40px;
|
|
||||||
font-size: 15px;
|
|
||||||
line-height: 150%;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*xmp, textarea {
|
|
||||||
display: none;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
h1,h2,h3,h4 {
|
|
||||||
margin: 15px 0;
|
|
||||||
}
|
|
||||||
pre {
|
|
||||||
margin: 20px 0;
|
|
||||||
}
|
|
||||||
img {
|
|
||||||
margin: 10px 0;
|
|
||||||
}
|
|
||||||
.navbar {
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
.table {
|
|
||||||
width: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This chunk is for Google's Code Prettify:
|
|
||||||
* http://google-code-prettify.googlecode.com
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Pretty printing styles. Used with prettify.js. */
|
|
||||||
/* SPAN elements with the classes below are added by prettyprint. */
|
|
||||||
.pln { color: #000 } /* plain text */
|
|
||||||
|
|
||||||
@media screen {
|
|
||||||
.str { color: #080 } /* string content */
|
|
||||||
.kwd { color: #008 } /* a keyword */
|
|
||||||
.com { color: #800 } /* a comment */
|
|
||||||
.typ { color: #606 } /* a type name */
|
|
||||||
.lit { color: #066 } /* a literal value */
|
|
||||||
/* punctuation, lisp open bracket, lisp close bracket */
|
|
||||||
.pun, .opn, .clo { color: #660 }
|
|
||||||
.tag { color: #008 } /* a markup tag name */
|
|
||||||
.atn { color: #606 } /* a markup attribute name */
|
|
||||||
.atv { color: #080 } /* a markup attribute value */
|
|
||||||
.dec, .var { color: #606 } /* a declaration; a variable name */
|
|
||||||
.fun { color: red } /* a function name */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Use higher contrast and text-weight for printable form. */
|
|
||||||
@media print, projection {
|
|
||||||
.str { color: #060 }
|
|
||||||
.kwd { color: #006; font-weight: bold }
|
|
||||||
.com { color: #600; font-style: italic }
|
|
||||||
.typ { color: #404; font-weight: bold }
|
|
||||||
.lit { color: #044 }
|
|
||||||
.pun, .opn, .clo { color: #440 }
|
|
||||||
.tag { color: #006; font-weight: bold }
|
|
||||||
.atn { color: #404 }
|
|
||||||
.atv { color: #060 }
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Put a border around prettyprinted code snippets. */
|
|
||||||
pre.prettyprint { padding: 2px; border: 1px solid #888 }
|
|
||||||
|
|
||||||
/* Specify class=linenums on a pre to get line numbering */
|
|
||||||
ol.linenums { margin-top: 0; margin-bottom: 0 } /* IE indents via margin-left */
|
|
||||||
li.L0, li.L1, li.L2, li.L3, li.L5, li.L6, li.L7, li.L8 { list-style-type: none }
|
|
||||||
/* Alternate shading for lines */
|
|
||||||
li.L1, li.L3, li.L5, li.L7, li.L9 { background: #eee }
|
|
||||||
|
|
||||||
/* Fix for (C) banner on top */
|
|
||||||
#headline-copyrights {
|
|
||||||
float:right;
|
|
||||||
margin-right:5px;
|
|
||||||
text-align:right;
|
|
||||||
font-size: 70%;
|
|
||||||
}
|
|
||||||
/* Fix for Squirt banner on top */
|
|
||||||
#headline-squirt {
|
|
||||||
float: right;
|
|
||||||
text-align:right;
|
|
||||||
font-size: 70%;
|
|
||||||
}
|
|
|
@ -1,476 +0,0 @@
|
||||||
/**
|
|
||||||
* StrapDown.js - an on-the-fly markdown parser
|
|
||||||
* Copyright (C) 2014, Lilian Besson. (GPLv3 Licensed)
|
|
||||||
* https://lbesson.bitbucket.org/md/
|
|
||||||
* Version: 0.4.1
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* marked - a markdown parser
|
|
||||||
* Copyright (c) 2011-2013, Christopher Jeffrey. (MIT Licensed)
|
|
||||||
* https://github.com/chjj/marked
|
|
||||||
*/
|
|
||||||
;(function(){var block={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:noop,hr:/^( *[-*_]){3,} *(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,nptable:noop,lheading:/^([^\n]+)\n *(=|-){3,} *\n*/,blockquote:/^( *>[^\n]+(\n[^\n]+)*\n*)+/,list:/^( *)(bull) [\s\S]+?(?:hr|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:/^ *(?:comment|closed|closing) *(?:\n{2,}|\s*$)/,def:/^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,table:noop,paragraph:/^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,text:/^[^\n]+/};block.bullet=/(?:[*+-]|\d+\.)/;block.item=/^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;block.item=replace(block.item,'gm')
|
|
||||||
(/bull/g,block.bullet)
|
|
||||||
();block.list=replace(block.list)
|
|
||||||
(/bull/g,block.bullet)
|
|
||||||
('hr',/\n+(?=(?: *[-*_]){3,} *(?:\n+|$))/)
|
|
||||||
();block._tag='(?!(?:'
|
|
||||||
+'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code'
|
|
||||||
+'|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo'
|
|
||||||
+'|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|@)\\b';block.html=replace(block.html)
|
|
||||||
('comment',/<!--[\s\S]*?-->/)
|
|
||||||
('closed',/<(tag)[\s\S]+?<\/\1>/)
|
|
||||||
('closing',/<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)
|
|
||||||
(/tag/g,block._tag)
|
|
||||||
();block.paragraph=replace(block.paragraph)
|
|
||||||
('hr',block.hr)
|
|
||||||
('heading',block.heading)
|
|
||||||
('lheading',block.lheading)
|
|
||||||
('blockquote',block.blockquote)
|
|
||||||
('tag','<'+block._tag)
|
|
||||||
('def',block.def)
|
|
||||||
();block.normal=merge({},block);block.gfm=merge({},block.normal,{fences:/^ *(`{3,}|~{3,}) *(\w+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/,paragraph:/^/});block.gfm.paragraph=replace(block.paragraph)
|
|
||||||
('(?!','(?!'+block.gfm.fences.source.replace('\\1','\\2')+'|')
|
|
||||||
();block.tables=merge({},block.gfm,{nptable:/^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,table:/^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/});function Lexer(options){this.tokens=[];this.tokens.links={};this.options=options||marked.defaults;this.rules=block.normal;if(this.options.gfm){if(this.options.tables){this.rules=block.tables;}else{this.rules=block.gfm;}}}
|
|
||||||
Lexer.rules=block;Lexer.lex=function(src,options){var lexer=new Lexer(options);return lexer.lex(src);};Lexer.prototype.lex=function(src){src=src.replace(/\r\n|\r/g,'\n').replace(/\t/g,' ').replace(/\u00a0/g,' ').replace(/\u2424/g,'\n');return this.token(src,true);};Lexer.prototype.token=function(src,top){var src=src.replace(/^ +$/gm,''),next,loose,cap,bull,b,item,space,i,l;while(src){if(cap=this.rules.newline.exec(src)){src=src.substring(cap[0].length);if(cap[0].length>1){this.tokens.push({type:'space'});}}
|
|
||||||
if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);cap=cap[0].replace(/^ {4}/gm,'');this.tokens.push({type:'code',text:!this.options.pedantic?cap.replace(/\n+$/,''):cap});continue;}
|
|
||||||
if(cap=this.rules.fences.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:'code',lang:cap[2],text:cap[3]});continue;}
|
|
||||||
if(cap=this.rules.heading.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:'heading',depth:cap[1].length,text:cap[2]});continue;}
|
|
||||||
if(top&&(cap=this.rules.nptable.exec(src))){src=src.substring(cap[0].length);item={type:'table',header:cap[1].replace(/^ *| *\| *$/g,'').split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,'').split(/ *\| */),cells:cap[3].replace(/\n$/,'').split('\n')};for(i=0;i<item.align.length;i++){if(/^ *-+: *$/.test(item.align[i])){item.align[i]='right';}else if(/^ *:-+: *$/.test(item.align[i])){item.align[i]='center';}else if(/^ *:-+ *$/.test(item.align[i])){item.align[i]='left';}else{item.align[i]=null;}}
|
|
||||||
for(i=0;i<item.cells.length;i++){item.cells[i]=item.cells[i].split(/ *\| */);}
|
|
||||||
this.tokens.push(item);continue;}
|
|
||||||
if(cap=this.rules.lheading.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:'heading',depth:cap[2]==='='?1:2,text:cap[1]});continue;}
|
|
||||||
if(cap=this.rules.hr.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:'hr'});continue;}
|
|
||||||
if(cap=this.rules.blockquote.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:'blockquote_start'});cap=cap[0].replace(/^ *> ?/gm,'');this.token(cap,top);this.tokens.push({type:'blockquote_end'});continue;}
|
|
||||||
if(cap=this.rules.list.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:'list_start',ordered:isFinite(cap[2])});cap=cap[0].match(this.rules.item);if(this.options.smartLists){bull=block.bullet.exec(cap[0])[0];}
|
|
||||||
next=false;l=cap.length;i=0;for(;i<l;i++){item=cap[i];space=item.length;item=item.replace(/^ *([*+-]|\d+\.) +/,'');if(~item.indexOf('\n ')){space-=item.length;item=!this.options.pedantic?item.replace(new RegExp('^ {1,'+space+'}','gm'),''):item.replace(/^ {1,4}/gm,'');}
|
|
||||||
if(this.options.smartLists&&i!==l-1){b=block.bullet.exec(cap[i+1])[0];if(bull!==b&&!(bull[1]==='.'&&b[1]==='.')){src=cap.slice(i+1).join('\n')+src;i=l-1;}}
|
|
||||||
loose=next||/\n\n(?!\s*$)/.test(item);if(i!==l-1){next=item[item.length-1]==='\n';if(!loose)loose=next;}
|
|
||||||
this.tokens.push({type:loose?'loose_item_start':'list_item_start'});this.token(item,false);this.tokens.push({type:'list_item_end'});}
|
|
||||||
this.tokens.push({type:'list_end'});continue;}
|
|
||||||
if(cap=this.rules.html.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:this.options.sanitize?'paragraph':'html',pre:cap[1]==='pre',text:cap[0]});continue;}
|
|
||||||
if(top&&(cap=this.rules.def.exec(src))){src=src.substring(cap[0].length);this.tokens.links[cap[1].toLowerCase()]={href:cap[2],title:cap[3]};continue;}
|
|
||||||
if(top&&(cap=this.rules.table.exec(src))){src=src.substring(cap[0].length);item={type:'table',header:cap[1].replace(/^ *| *\| *$/g,'').split(/ *\| */),align:cap[2].replace(/^ *|\| *$/g,'').split(/ *\| */),cells:cap[3].replace(/(?: *\| *)?\n$/,'').split('\n')};for(i=0;i<item.align.length;i++){if(/^ *-+: *$/.test(item.align[i])){item.align[i]='right';}else if(/^ *:-+: *$/.test(item.align[i])){item.align[i]='center';}else if(/^ *:-+ *$/.test(item.align[i])){item.align[i]='left';}else{item.align[i]=null;}}
|
|
||||||
for(i=0;i<item.cells.length;i++){item.cells[i]=item.cells[i].replace(/^ *\| *| *\| *$/g,'').split(/ *\| */);}
|
|
||||||
this.tokens.push(item);continue;}
|
|
||||||
if(top&&(cap=this.rules.paragraph.exec(src))){src=src.substring(cap[0].length);this.tokens.push({type:'paragraph',text:cap[1][cap[1].length-1]==='\n'?cap[1].slice(0,-1):cap[1]});continue;}
|
|
||||||
if(cap=this.rules.text.exec(src)){src=src.substring(cap[0].length);this.tokens.push({type:'text',text:cap[0]});continue;}
|
|
||||||
if(src){throw new
|
|
||||||
Error('Infinite loop on byte: '+src.charCodeAt(0));}}
|
|
||||||
return this.tokens;};var inline={escape:/^\\([\\`*{}\[\]()#+\-.!_>])/,autolink:/^<([^ >]+(@|:\/)[^ >]+)>/,url:noop,tag:/^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,link:/^!?\[(inside)\]\(href\)/,reflink:/^!?\[(inside)\]\s*\[([^\]]*)\]/,nolink:/^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,strong:/^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,em:/^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,code:/^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,br:/^ {2,}\n(?!\s*$)/,del:noop,text:/^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/};inline._inside=/(?:\[[^\]]*\]|[^\]]|\](?=[^\[]*\]))*/;inline._href=/\s*<?([^\s]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;inline.link=replace(inline.link)
|
|
||||||
('inside',inline._inside)
|
|
||||||
('href',inline._href)
|
|
||||||
();inline.reflink=replace(inline.reflink)
|
|
||||||
('inside',inline._inside)
|
|
||||||
();inline.normal=merge({},inline);inline.pedantic=merge({},inline.normal,{strong:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,em:/^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/});inline.gfm=merge({},inline.normal,{escape:replace(inline.escape)('])','~|])')(),url:/^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,del:/^~~(?=\S)([\s\S]*?\S)~~/,text:replace(inline.text)
|
|
||||||
(']|','~]|')
|
|
||||||
('|','|https?://|')
|
|
||||||
()});inline.breaks=merge({},inline.gfm,{br:replace(inline.br)('{2,}','*')(),text:replace(inline.gfm.text)('{2,}','*')()});function InlineLexer(links,options){this.options=options||marked.defaults;this.links=links;this.rules=inline.normal;if(!this.links){throw new
|
|
||||||
Error('Tokens array requires a `links` property.');}
|
|
||||||
if(this.options.gfm){if(this.options.breaks){this.rules=inline.breaks;}else{this.rules=inline.gfm;}}else if(this.options.pedantic){this.rules=inline.pedantic;}}
|
|
||||||
InlineLexer.rules=inline;InlineLexer.output=function(src,links,opt){var inline=new InlineLexer(links,opt);return inline.output(src);};InlineLexer.prototype.output=function(src){var out='',link,text,href,cap;while(src){if(cap=this.rules.escape.exec(src)){src=src.substring(cap[0].length);out+=cap[1];continue;}
|
|
||||||
if(cap=this.rules.autolink.exec(src)){src=src.substring(cap[0].length);if(cap[2]==='@'){text=cap[1][6]===':'?this.mangle(cap[1].substring(7)):this.mangle(cap[1]);href=this.mangle('mailto:')+text;}else{text=escape(cap[1]);href=text;}
|
|
||||||
out+='<a href="'
|
|
||||||
+href
|
|
||||||
+'">'
|
|
||||||
+text
|
|
||||||
+'</a>';continue;}
|
|
||||||
if(cap=this.rules.url.exec(src)){src=src.substring(cap[0].length);text=escape(cap[1]);href=text;out+='<a href="'
|
|
||||||
+href
|
|
||||||
+'">'
|
|
||||||
+text
|
|
||||||
+'</a>';continue;}
|
|
||||||
if(cap=this.rules.tag.exec(src)){src=src.substring(cap[0].length);out+=this.options.sanitize?escape(cap[0]):cap[0];continue;}
|
|
||||||
if(cap=this.rules.link.exec(src)){src=src.substring(cap[0].length);out+=this.outputLink(cap,{href:cap[2],title:cap[3]});continue;}
|
|
||||||
if((cap=this.rules.reflink.exec(src))||(cap=this.rules.nolink.exec(src))){src=src.substring(cap[0].length);link=(cap[2]||cap[1]).replace(/\s+/g,' ');link=this.links[link.toLowerCase()];if(!link||!link.href){out+=cap[0][0];src=cap[0].substring(1)+src;continue;}
|
|
||||||
out+=this.outputLink(cap,link);continue;}
|
|
||||||
if(cap=this.rules.strong.exec(src)){src=src.substring(cap[0].length);out+='<strong>'
|
|
||||||
+this.output(cap[2]||cap[1])
|
|
||||||
+'</strong>';continue;}
|
|
||||||
if(cap=this.rules.em.exec(src)){src=src.substring(cap[0].length);out+='<em>'
|
|
||||||
+this.output(cap[2]||cap[1])
|
|
||||||
+'</em>';continue;}
|
|
||||||
if(cap=this.rules.code.exec(src)){src=src.substring(cap[0].length);out+='<code>'
|
|
||||||
+escape(cap[2],true)
|
|
||||||
+'</code>';continue;}
|
|
||||||
if(cap=this.rules.br.exec(src)){src=src.substring(cap[0].length);out+='<br>';continue;}
|
|
||||||
if(cap=this.rules.del.exec(src)){src=src.substring(cap[0].length);out+='<del>'
|
|
||||||
+this.output(cap[1])
|
|
||||||
+'</del>';continue;}
|
|
||||||
if(cap=this.rules.text.exec(src)){src=src.substring(cap[0].length);out+=escape(cap[0]);continue;}
|
|
||||||
if(src){throw new
|
|
||||||
Error('Infinite loop on byte: '+src.charCodeAt(0));}}
|
|
||||||
return out;};InlineLexer.prototype.outputLink=function(cap,link){if(cap[0][0]!=='!'){return'<a href="'
|
|
||||||
+escape(link.href)
|
|
||||||
+'"'
|
|
||||||
+(link.title?' title="'
|
|
||||||
+escape(link.title)
|
|
||||||
+'"':'')
|
|
||||||
+'>'
|
|
||||||
+this.output(cap[1])
|
|
||||||
+'</a>';}else{return'<img src="'
|
|
||||||
+escape(link.href)
|
|
||||||
+'" alt="'
|
|
||||||
+escape(cap[1])
|
|
||||||
+'"'
|
|
||||||
+(link.title?' title="'
|
|
||||||
+escape(link.title)
|
|
||||||
+'"':'')
|
|
||||||
+'>';}};InlineLexer.prototype.mangle=function(text){var out='',l=text.length,i=0,ch;for(;i<l;i++){ch=text.charCodeAt(i);if(Math.random()>0.5){ch='x'+ch.toString(16);}
|
|
||||||
out+='&#'+ch+';';}
|
|
||||||
return out;};function Parser(options){this.tokens=[];this.token=null;this.options=options||marked.defaults;}
|
|
||||||
Parser.parse=function(src,options){var parser=new Parser(options);return parser.parse(src);};Parser.prototype.parse=function(src){this.inline=new InlineLexer(src.links,this.options);this.tokens=src.reverse();var out='';while(this.next()){out+=this.tok();}
|
|
||||||
return out;};Parser.prototype.next=function(){return this.token=this.tokens.pop();};Parser.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0;};Parser.prototype.parseText=function(){var body=this.token.text;while(this.peek().type==='text'){body+='\n'+this.next().text;}
|
|
||||||
return this.inline.output(body);};Parser.prototype.tok=function(){switch(this.token.type){case'space':{return'';}
|
|
||||||
case'hr':{return'<hr>\n';}
|
|
||||||
case'heading':{return'<h'
|
|
||||||
+this.token.depth
|
|
||||||
+'>'
|
|
||||||
+this.inline.output(this.token.text)
|
|
||||||
+'</h'
|
|
||||||
+this.token.depth
|
|
||||||
+'>\n';}
|
|
||||||
case'code':{if(this.options.highlight){var code=this.options.highlight(this.token.text,this.token.lang);if(code!=null&&code!==this.token.text){this.token.escaped=true;this.token.text=code;}}
|
|
||||||
if(!this.token.escaped){this.token.text=escape(this.token.text,true);}
|
|
||||||
return'<pre><code'
|
|
||||||
+(this.token.lang?' class="'
|
|
||||||
+this.options.langPrefix
|
|
||||||
+this.token.lang
|
|
||||||
+'"':'')
|
|
||||||
+'>'
|
|
||||||
+this.token.text
|
|
||||||
+'</code></pre>\n';}
|
|
||||||
case'table':{var body='',heading,i,row,cell,j;body+='<thead>\n<tr>\n';for(i=0;i<this.token.header.length;i++){heading=this.inline.output(this.token.header[i]);body+=this.token.align[i]?'<th align="'+this.token.align[i]+'">'+heading+'</th>\n':'<th>'+heading+'</th>\n';}
|
|
||||||
body+='</tr>\n</thead>\n';body+='<tbody>\n'
|
|
||||||
for(i=0;i<this.token.cells.length;i++){row=this.token.cells[i];body+='<tr>\n';for(j=0;j<row.length;j++){cell=this.inline.output(row[j]);body+=this.token.align[j]?'<td align="'+this.token.align[j]+'">'+cell+'</td>\n':'<td>'+cell+'</td>\n';}
|
|
||||||
body+='</tr>\n';}
|
|
||||||
body+='</tbody>\n';return'<table>\n'
|
|
||||||
+body
|
|
||||||
+'</table>\n';}
|
|
||||||
case'blockquote_start':{var body='';while(this.next().type!=='blockquote_end'){body+=this.tok();}
|
|
||||||
return'<blockquote>\n'
|
|
||||||
+body
|
|
||||||
+'</blockquote>\n';}
|
|
||||||
case'list_start':{var type=this.token.ordered?'ol':'ul',body='';while(this.next().type!=='list_end'){body+=this.tok();}
|
|
||||||
return'<'
|
|
||||||
+type
|
|
||||||
+'>\n'
|
|
||||||
+body
|
|
||||||
+'</'
|
|
||||||
+type
|
|
||||||
+'>\n';}
|
|
||||||
case'list_item_start':{var body='';while(this.next().type!=='list_item_end'){body+=this.token.type==='text'?this.parseText():this.tok();}
|
|
||||||
return'<li>'
|
|
||||||
+body
|
|
||||||
+'</li>\n';}
|
|
||||||
case'loose_item_start':{var body='';while(this.next().type!=='list_item_end'){body+=this.tok();}
|
|
||||||
return'<li>'
|
|
||||||
+body
|
|
||||||
+'</li>\n';}
|
|
||||||
case'html':{return!this.token.pre&&!this.options.pedantic?this.inline.output(this.token.text):this.token.text;}
|
|
||||||
case'paragraph':{return'<p>'
|
|
||||||
+this.inline.output(this.token.text)
|
|
||||||
+'</p>\n';}
|
|
||||||
case'text':{return'<p>'
|
|
||||||
+this.parseText()
|
|
||||||
+'</p>\n';}}};function escape(html,encode){return html.replace(!encode?/&(?!#?\w+;)/g:/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"').replace(/'/g,''');}
|
|
||||||
function replace(regex,opt){regex=regex.source;opt=opt||'';return function self(name,val){if(!name)return new RegExp(regex,opt);val=val.source||val;val=val.replace(/(^|[^\[])\^/g,'$1');regex=regex.replace(name,val);return self;};}
|
|
||||||
function noop(){}
|
|
||||||
noop.exec=noop;function merge(obj){var i=1,target,key;for(;i<arguments.length;i++){target=arguments[i];for(key in target){if(Object.prototype.hasOwnProperty.call(target,key)){obj[key]=target[key];}}}
|
|
||||||
return obj;}
|
|
||||||
function marked(src,opt){try{if(opt)opt=merge({},marked.defaults,opt);return Parser.parse(Lexer.lex(src,opt),opt);}catch(e){e.message+='\nPlease report this to https://github.com/chjj/marked.';if((opt||marked.defaults).silent){return'An error occured:\n'+e.message;}
|
|
||||||
throw e;}}
|
|
||||||
marked.options=marked.setOptions=function(opt){merge(marked.defaults,opt);return marked;};marked.defaults={gfm:true,tables:true,breaks:false,pedantic:false,sanitize:false,smartLists:false,silent:false,highlight:null,langPrefix:'lang-'};marked.Parser=Parser;marked.parser=Parser.parse;marked.Lexer=Lexer;marked.lexer=Lexer.lex;marked.InlineLexer=InlineLexer;marked.inlineLexer=InlineLexer.output;marked.parse=marked;if(typeof exports==='object'){module.exports=marked;}else if(typeof define==='function'&&define.amd){define(function(){return marked;});}else{this.marked=marked;}}).call(function(){return this||(typeof window!=='undefined'?window:global);}());
|
|
||||||
// Copyright (C) 2006 Google Inc.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
window['PR_SHOULD_USE_CONTINUATION']=true;var prettyPrintOne;var prettyPrint;(function(){var win=window;var FLOW_CONTROL_KEYWORDS=["break,continue,do,else,for,if,return,while"];var C_KEYWORDS=[FLOW_CONTROL_KEYWORDS,"auto,case,char,const,default,"+"double,enum,extern,float,goto,int,long,register,short,signed,sizeof,"+"static,struct,switch,typedef,union,unsigned,void,volatile"];var COMMON_KEYWORDS=[C_KEYWORDS,"catch,class,delete,false,import,"+"new,operator,private,protected,public,this,throw,true,try,typeof"];var CPP_KEYWORDS=[COMMON_KEYWORDS,"alignof,align_union,asm,axiom,bool,"+"concept,concept_map,const_cast,constexpr,decltype,"+"dynamic_cast,explicit,export,friend,inline,late_check,"+"mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,"+"template,typeid,typename,using,virtual,where"];var JAVA_KEYWORDS=[COMMON_KEYWORDS,"abstract,boolean,byte,extends,final,finally,implements,import,"+"instanceof,null,native,package,strictfp,super,synchronized,throws,"+"transient"];var CSHARP_KEYWORDS=[JAVA_KEYWORDS,"as,base,by,checked,decimal,delegate,descending,dynamic,event,"+"fixed,foreach,from,group,implicit,in,interface,internal,into,is,let,"+"lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,"+"sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,"+"var,virtual,where"];var COFFEE_KEYWORDS="all,and,by,catch,class,else,extends,false,finally,"+"for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,"+"throw,true,try,unless,until,when,while,yes";var JSCRIPT_KEYWORDS=[COMMON_KEYWORDS,"debugger,eval,export,function,get,null,set,undefined,var,with,"+"Infinity,NaN"];var PERL_KEYWORDS="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,"+"goto,if,import,last,local,my,next,no,our,print,package,redo,require,"+"sub,undef,unless,until,use,wantarray,while,BEGIN,END";var PYTHON_KEYWORDS=[FLOW_CONTROL_KEYWORDS,"and,as,assert,class,def,del,"+"elif,except,exec,finally,from,global,import,in,is,lambda,"+"nonlocal,not,or,pass,print,raise,try,with,yield,"+"False,True,None"];var RUBY_KEYWORDS=[FLOW_CONTROL_KEYWORDS,"alias,and,begin,case,class,"+"def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,"+"rescue,retry,self,super,then,true,undef,unless,until,when,yield,"+"BEGIN,END"];var SH_KEYWORDS=[FLOW_CONTROL_KEYWORDS,"case,done,elif,esac,eval,fi,"+"function,in,local,set,then,until"];var ALL_KEYWORDS=[CPP_KEYWORDS,CSHARP_KEYWORDS,JSCRIPT_KEYWORDS,PERL_KEYWORDS+
|
|
||||||
PYTHON_KEYWORDS,RUBY_KEYWORDS,SH_KEYWORDS];var C_TYPES=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)\b/;var PR_STRING='str';var PR_KEYWORD='kwd';var PR_COMMENT='com';var PR_TYPE='typ';var PR_LITERAL='lit';var PR_PUNCTUATION='pun';var PR_PLAIN='pln';var PR_TAG='tag';var PR_DECLARATION='dec';var PR_SOURCE='src';var PR_ATTRIB_NAME='atn';var PR_ATTRIB_VALUE='atv';var PR_NOCODE='nocode';var REGEXP_PRECEDER_PATTERN='(?:^^\\.?|[+-]|[!=]=?=?|\\#|%=?|&&?=?|\\(|\\*=?|[+\\-]=|->|\\/=?|::?|<<?=?|>>?>?=?|,|;|\\?|@|\\[|~|{|\\^\\^?=?|\\|\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*';function combinePrefixPatterns(regexs){var capturedGroupIndex=0;var needToFoldCase=false;var ignoreCase=false;for(var i=0,n=regexs.length;i<n;++i){var regex=regexs[i];if(regex.ignoreCase){ignoreCase=true;}else if(/[a-z]/i.test(regex.source.replace(/\\u[0-9a-f]{4}|\\x[0-9a-f]{2}|\\[^ux]/gi,''))){needToFoldCase=true;ignoreCase=false;break;}}
|
|
||||||
var escapeCharToCodeUnit={'b':8,'t':9,'n':0xa,'v':0xb,'f':0xc,'r':0xd};function decodeEscape(charsetPart){var cc0=charsetPart.charCodeAt(0);if(cc0!==92){return cc0;}
|
|
||||||
var c1=charsetPart.charAt(1);cc0=escapeCharToCodeUnit[c1];if(cc0){return cc0;}else if('0'<=c1&&c1<='7'){return parseInt(charsetPart.substring(1),8);}else if(c1==='u'||c1==='x'){return parseInt(charsetPart.substring(2),16);}else{return charsetPart.charCodeAt(1);}}
|
|
||||||
function encodeEscape(charCode){if(charCode<0x20){return(charCode<0x10?'\\x0':'\\x')+charCode.toString(16);}
|
|
||||||
var ch=String.fromCharCode(charCode);return(ch==='\\'||ch==='-'||ch===']'||ch==='^')?"\\"+ch:ch;}
|
|
||||||
function caseFoldCharset(charSet){var charsetParts=charSet.substring(1,charSet.length-1).match(new RegExp('\\\\u[0-9A-Fa-f]{4}'
|
|
||||||
+'|\\\\x[0-9A-Fa-f]{2}'
|
|
||||||
+'|\\\\[0-3][0-7]{0,2}'
|
|
||||||
+'|\\\\[0-7]{1,2}'
|
|
||||||
+'|\\\\[\\s\\S]'
|
|
||||||
+'|-'
|
|
||||||
+'|[^-\\\\]','g'));var ranges=[];var inverse=charsetParts[0]==='^';var out=['['];if(inverse){out.push('^');}
|
|
||||||
for(var i=inverse?1:0,n=charsetParts.length;i<n;++i){var p=charsetParts[i];if(/\\[bdsw]/i.test(p)){out.push(p);}else{var start=decodeEscape(p);var end;if(i+2<n&&'-'===charsetParts[i+1]){end=decodeEscape(charsetParts[i+2]);i+=2;}else{end=start;}
|
|
||||||
ranges.push([start,end]);if(!(end<65||start>122)){if(!(end<65||start>90)){ranges.push([Math.max(65,start)|32,Math.min(end,90)|32]);}
|
|
||||||
if(!(end<97||start>122)){ranges.push([Math.max(97,start)&~32,Math.min(end,122)&~32]);}}}}
|
|
||||||
ranges.sort(function(a,b){return(a[0]-b[0])||(b[1]-a[1]);});var consolidatedRanges=[];var lastRange=[];for(var i=0;i<ranges.length;++i){var range=ranges[i];if(range[0]<=lastRange[1]+1){lastRange[1]=Math.max(lastRange[1],range[1]);}else{consolidatedRanges.push(lastRange=range);}}
|
|
||||||
for(var i=0;i<consolidatedRanges.length;++i){var range=consolidatedRanges[i];out.push(encodeEscape(range[0]));if(range[1]>range[0]){if(range[1]+1>range[0]){out.push('-');}
|
|
||||||
out.push(encodeEscape(range[1]));}}
|
|
||||||
out.push(']');return out.join('');}
|
|
||||||
function allowAnywhereFoldCaseAndRenumberGroups(regex){var parts=regex.source.match(new RegExp('(?:'
|
|
||||||
+'\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]'
|
|
||||||
+'|\\\\u[A-Fa-f0-9]{4}'
|
|
||||||
+'|\\\\x[A-Fa-f0-9]{2}'
|
|
||||||
+'|\\\\[0-9]+'
|
|
||||||
+'|\\\\[^ux0-9]'
|
|
||||||
+'|\\(\\?[:!=]'
|
|
||||||
+'|[\\(\\)\\^]'
|
|
||||||
+'|[^\\x5B\\x5C\\(\\)\\^]+'
|
|
||||||
+')','g'));var n=parts.length;var capturedGroups=[];for(var i=0,groupIndex=0;i<n;++i){var p=parts[i];if(p==='('){++groupIndex;}else if('\\'===p.charAt(0)){var decimalValue=+p.substring(1);if(decimalValue){if(decimalValue<=groupIndex){capturedGroups[decimalValue]=-1;}else{parts[i]=encodeEscape(decimalValue);}}}}
|
|
||||||
for(var i=1;i<capturedGroups.length;++i){if(-1===capturedGroups[i]){capturedGroups[i]=++capturedGroupIndex;}}
|
|
||||||
for(var i=0,groupIndex=0;i<n;++i){var p=parts[i];if(p==='('){++groupIndex;if(!capturedGroups[groupIndex]){parts[i]='(?:';}}else if('\\'===p.charAt(0)){var decimalValue=+p.substring(1);if(decimalValue&&decimalValue<=groupIndex){parts[i]='\\'+capturedGroups[decimalValue];}}}
|
|
||||||
for(var i=0;i<n;++i){if('^'===parts[i]&&'^'!==parts[i+1]){parts[i]='';}}
|
|
||||||
if(regex.ignoreCase&&needToFoldCase){for(var i=0;i<n;++i){var p=parts[i];var ch0=p.charAt(0);if(p.length>=2&&ch0==='['){parts[i]=caseFoldCharset(p);}else if(ch0!=='\\'){parts[i]=p.replace(/[a-zA-Z]/g,function(ch){var cc=ch.charCodeAt(0);return'['+String.fromCharCode(cc&~32,cc|32)+']';});}}}
|
|
||||||
return parts.join('');}
|
|
||||||
var rewritten=[];for(var i=0,n=regexs.length;i<n;++i){var regex=regexs[i];if(regex.global||regex.multiline){throw new Error(''+regex);}
|
|
||||||
rewritten.push('(?:'+allowAnywhereFoldCaseAndRenumberGroups(regex)+')');}
|
|
||||||
return new RegExp(rewritten.join('|'),ignoreCase?'gi':'g');}
|
|
||||||
function extractSourceSpans(node,isPreformatted){var nocode=/(?:^|\s)nocode(?:\s|$)/;var chunks=[];var length=0;var spans=[];var k=0;function walk(node){switch(node.nodeType){case 1:if(nocode.test(node.className)){return;}
|
|
||||||
for(var child=node.firstChild;child;child=child.nextSibling){walk(child);}
|
|
||||||
var nodeName=node.nodeName.toLowerCase();if('br'===nodeName||'li'===nodeName){chunks[k]='\n';spans[k<<1]=length++;spans[(k++<<1)|1]=node;}
|
|
||||||
break;case 3:case 4:var text=node.nodeValue;if(text.length){if(!isPreformatted){text=text.replace(/[ \t\r\n]+/g,' ');}else{text=text.replace(/\r\n?/g,'\n');}
|
|
||||||
chunks[k]=text;spans[k<<1]=length;length+=text.length;spans[(k++<<1)|1]=node;}
|
|
||||||
break;}}
|
|
||||||
walk(node);return{sourceCode:chunks.join('').replace(/\n$/,''),spans:spans};}
|
|
||||||
function appendDecorations(basePos,sourceCode,langHandler,out){if(!sourceCode){return;}
|
|
||||||
var job={sourceCode:sourceCode,basePos:basePos};langHandler(job);out.push.apply(out,job.decorations);}
|
|
||||||
var notWs=/\S/;function childContentWrapper(element){var wrapper=undefined;for(var c=element.firstChild;c;c=c.nextSibling){var type=c.nodeType;wrapper=(type===1)?(wrapper?element:c):(type===3)?(notWs.test(c.nodeValue)?element:wrapper):wrapper;}
|
|
||||||
return wrapper===element?undefined:wrapper;}
|
|
||||||
function createSimpleLexer(shortcutStylePatterns,fallthroughStylePatterns){var shortcuts={};var tokenizer;(function(){var allPatterns=shortcutStylePatterns.concat(fallthroughStylePatterns);var allRegexs=[];var regexKeys={};for(var i=0,n=allPatterns.length;i<n;++i){var patternParts=allPatterns[i];var shortcutChars=patternParts[3];if(shortcutChars){for(var c=shortcutChars.length;--c>=0;){shortcuts[shortcutChars.charAt(c)]=patternParts;}}
|
|
||||||
var regex=patternParts[1];var k=''+regex;if(!regexKeys.hasOwnProperty(k)){allRegexs.push(regex);regexKeys[k]=null;}}
|
|
||||||
allRegexs.push(/[\0-\uffff]/);tokenizer=combinePrefixPatterns(allRegexs);})();var nPatterns=fallthroughStylePatterns.length;var decorate=function(job){var sourceCode=job.sourceCode,basePos=job.basePos;var decorations=[basePos,PR_PLAIN];var pos=0;var tokens=sourceCode.match(tokenizer)||[];var styleCache={};for(var ti=0,nTokens=tokens.length;ti<nTokens;++ti){var token=tokens[ti];var style=styleCache[token];var match=void 0;var isEmbedded;if(typeof style==='string'){isEmbedded=false;}else{var patternParts=shortcuts[token.charAt(0)];if(patternParts){match=token.match(patternParts[1]);style=patternParts[0];}else{for(var i=0;i<nPatterns;++i){patternParts=fallthroughStylePatterns[i];match=token.match(patternParts[1]);if(match){style=patternParts[0];break;}}
|
|
||||||
if(!match){style=PR_PLAIN;}}
|
|
||||||
isEmbedded=style.length>=5&&'lang-'===style.substring(0,5);if(isEmbedded&&!(match&&typeof match[1]==='string')){isEmbedded=false;style=PR_SOURCE;}
|
|
||||||
if(!isEmbedded){styleCache[token]=style;}}
|
|
||||||
var tokenStart=pos;pos+=token.length;if(!isEmbedded){decorations.push(basePos+tokenStart,style);}else{var embeddedSource=match[1];var embeddedSourceStart=token.indexOf(embeddedSource);var embeddedSourceEnd=embeddedSourceStart+embeddedSource.length;if(match[2]){embeddedSourceEnd=token.length-match[2].length;embeddedSourceStart=embeddedSourceEnd-embeddedSource.length;}
|
|
||||||
var lang=style.substring(5);appendDecorations(basePos+tokenStart,token.substring(0,embeddedSourceStart),decorate,decorations);appendDecorations(basePos+tokenStart+embeddedSourceStart,embeddedSource,langHandlerForExtension(lang,embeddedSource),decorations);appendDecorations(basePos+tokenStart+embeddedSourceEnd,token.substring(embeddedSourceEnd),decorate,decorations);}}
|
|
||||||
job.decorations=decorations;};return decorate;}
|
|
||||||
function sourceDecorator(options){var shortcutStylePatterns=[],fallthroughStylePatterns=[];if(options['tripleQuotedStrings']){shortcutStylePatterns.push([PR_STRING,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,'\'"']);}else if(options['multiLineStrings']){shortcutStylePatterns.push([PR_STRING,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,'\'"`']);}else{shortcutStylePatterns.push([PR_STRING,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,'"\'']);}
|
|
||||||
if(options['verbatimStrings']){fallthroughStylePatterns.push([PR_STRING,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null]);}
|
|
||||||
var hc=options['hashComments'];if(hc){if(options['cStyleComments']){if(hc>1){shortcutStylePatterns.push([PR_COMMENT,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,'#']);}else{shortcutStylePatterns.push([PR_COMMENT,/^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\b|[^\r\n]*)/,null,'#']);}
|
|
||||||
fallthroughStylePatterns.push([PR_STRING,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h(?:h|pp|\+\+)?|[a-z]\w*)>/,null]);}else{shortcutStylePatterns.push([PR_COMMENT,/^#[^\r\n]*/,null,'#']);}}
|
|
||||||
if(options['cStyleComments']){fallthroughStylePatterns.push([PR_COMMENT,/^\/\/[^\r\n]*/,null]);fallthroughStylePatterns.push([PR_COMMENT,/^\/\*[\s\S]*?(?:\*\/|$)/,null]);}
|
|
||||||
if(options['regexLiterals']){var REGEX_LITERAL=('/(?=[^/*])'
|
|
||||||
+'(?:[^/\\x5B\\x5C]'
|
|
||||||
+'|\\x5C[\\s\\S]'
|
|
||||||
+'|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+'
|
|
||||||
+'/');fallthroughStylePatterns.push(['lang-regex',new RegExp('^'+REGEXP_PRECEDER_PATTERN+'('+REGEX_LITERAL+')')]);}
|
|
||||||
var types=options['types'];if(types){fallthroughStylePatterns.push([PR_TYPE,types]);}
|
|
||||||
var keywords=(""+options['keywords']).replace(/^ | $/g,'');if(keywords.length){fallthroughStylePatterns.push([PR_KEYWORD,new RegExp('^(?:'+keywords.replace(/[\s,]+/g,'|')+')\\b'),null]);}
|
|
||||||
shortcutStylePatterns.push([PR_PLAIN,/^\s+/,null,' \r\n\t\xA0']);var punctuation=/^.[^\s\w\.$@\'\"\`\/\\]*/;fallthroughStylePatterns.push([PR_LITERAL,/^@[a-z_$][a-z_$@0-9]*/i,null],[PR_TYPE,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[PR_PLAIN,/^[a-z_$][a-z_$@0-9]*/i,null],[PR_LITERAL,new RegExp('^(?:'
|
|
||||||
+'0x[a-f0-9]+'
|
|
||||||
+'|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)'
|
|
||||||
+'(?:e[+\\-]?\\d+)?'
|
|
||||||
+')'
|
|
||||||
+'[a-z]*','i'),null,'0123456789'],[PR_PLAIN,/^\\[\s\S]?/,null],[PR_PUNCTUATION,punctuation,null]);return createSimpleLexer(shortcutStylePatterns,fallthroughStylePatterns);}
|
|
||||||
var decorateSource=sourceDecorator({'keywords':ALL_KEYWORDS,'hashComments':true,'cStyleComments':true,'multiLineStrings':true,'regexLiterals':true});function numberLines(node,opt_startLineNum,isPreformatted){var nocode=/(?:^|\s)nocode(?:\s|$)/;var lineBreak=/\r\n?|\n/;var document=node.ownerDocument;var li=document.createElement('li');while(node.firstChild){li.appendChild(node.firstChild);}
|
|
||||||
var listItems=[li];function walk(node){switch(node.nodeType){case 1:if(nocode.test(node.className)){break;}
|
|
||||||
if('br'===node.nodeName){breakAfter(node);if(node.parentNode){node.parentNode.removeChild(node);}}else{for(var child=node.firstChild;child;child=child.nextSibling){walk(child);}}
|
|
||||||
break;case 3:case 4:if(isPreformatted){var text=node.nodeValue;var match=text.match(lineBreak);if(match){var firstLine=text.substring(0,match.index);node.nodeValue=firstLine;var tail=text.substring(match.index+match[0].length);if(tail){var parent=node.parentNode;parent.insertBefore(document.createTextNode(tail),node.nextSibling);}
|
|
||||||
breakAfter(node);if(!firstLine){node.parentNode.removeChild(node);}}}
|
|
||||||
break;}}
|
|
||||||
function breakAfter(lineEndNode){while(!lineEndNode.nextSibling){lineEndNode=lineEndNode.parentNode;if(!lineEndNode){return;}}
|
|
||||||
function breakLeftOf(limit,copy){var rightSide=copy?limit.cloneNode(false):limit;var parent=limit.parentNode;if(parent){var parentClone=breakLeftOf(parent,1);var next=limit.nextSibling;parentClone.appendChild(rightSide);for(var sibling=next;sibling;sibling=next){next=sibling.nextSibling;parentClone.appendChild(sibling);}}
|
|
||||||
return rightSide;}
|
|
||||||
var copiedListItem=breakLeftOf(lineEndNode.nextSibling,0);for(var parent;(parent=copiedListItem.parentNode)&&parent.nodeType===1;){copiedListItem=parent;}
|
|
||||||
listItems.push(copiedListItem);}
|
|
||||||
for(var i=0;i<listItems.length;++i){walk(listItems[i]);}
|
|
||||||
if(opt_startLineNum===(opt_startLineNum|0)){listItems[0].setAttribute('value',opt_startLineNum);}
|
|
||||||
var ol=document.createElement('ol');ol.className='linenums';var offset=Math.max(0,((opt_startLineNum-1))|0)||0;for(var i=0,n=listItems.length;i<n;++i){li=listItems[i];li.className='L'+((i+offset)%10);if(!li.firstChild){li.appendChild(document.createTextNode('\xA0'));}
|
|
||||||
ol.appendChild(li);}
|
|
||||||
node.appendChild(ol);}
|
|
||||||
function recombineTagsAndDecorations(job){var isIE8OrEarlier=/\bMSIE\s(\d+)/.exec(navigator.userAgent);isIE8OrEarlier=isIE8OrEarlier&&+isIE8OrEarlier[1]<=8;var newlineRe=/\n/g;var source=job.sourceCode;var sourceLength=source.length;var sourceIndex=0;var spans=job.spans;var nSpans=spans.length;var spanIndex=0;var decorations=job.decorations;var nDecorations=decorations.length;var decorationIndex=0;decorations[nDecorations]=sourceLength;var decPos,i;for(i=decPos=0;i<nDecorations;){if(decorations[i]!==decorations[i+2]){decorations[decPos++]=decorations[i++];decorations[decPos++]=decorations[i++];}else{i+=2;}}
|
|
||||||
nDecorations=decPos;for(i=decPos=0;i<nDecorations;){var startPos=decorations[i];var startDec=decorations[i+1];var end=i+2;while(end+2<=nDecorations&&decorations[end+1]===startDec){end+=2;}
|
|
||||||
decorations[decPos++]=startPos;decorations[decPos++]=startDec;i=end;}
|
|
||||||
nDecorations=decorations.length=decPos;var sourceNode=job.sourceNode;var oldDisplay;if(sourceNode){oldDisplay=sourceNode.style.display;sourceNode.style.display='none';}
|
|
||||||
try{var decoration=null;while(spanIndex<nSpans){var spanStart=spans[spanIndex];var spanEnd=spans[spanIndex+2]||sourceLength;var decEnd=decorations[decorationIndex+2]||sourceLength;var end=Math.min(spanEnd,decEnd);var textNode=spans[spanIndex+1];var styledText;if(textNode.nodeType!==1&&(styledText=source.substring(sourceIndex,end))){if(isIE8OrEarlier){styledText=styledText.replace(newlineRe,'\r');}
|
|
||||||
textNode.nodeValue=styledText;var document=textNode.ownerDocument;var span=document.createElement('span');span.className=decorations[decorationIndex+1];var parentNode=textNode.parentNode;parentNode.replaceChild(span,textNode);span.appendChild(textNode);if(sourceIndex<spanEnd){spans[spanIndex+1]=textNode=document.createTextNode(source.substring(end,spanEnd));parentNode.insertBefore(textNode,span.nextSibling);}}
|
|
||||||
sourceIndex=end;if(sourceIndex>=spanEnd){spanIndex+=2;}
|
|
||||||
if(sourceIndex>=decEnd){decorationIndex+=2;}}}finally{if(sourceNode){sourceNode.style.display=oldDisplay;}}}
|
|
||||||
var langHandlerRegistry={};function registerLangHandler(handler,fileExtensions){for(var i=fileExtensions.length;--i>=0;){var ext=fileExtensions[i];if(!langHandlerRegistry.hasOwnProperty(ext)){langHandlerRegistry[ext]=handler;}else if(win['console']){console['warn']('cannot override language handler %s',ext);}}}
|
|
||||||
function langHandlerForExtension(extension,source){if(!(extension&&langHandlerRegistry.hasOwnProperty(extension))){extension=/^\s*</.test(source)?'default-markup':'default-code';}
|
|
||||||
return langHandlerRegistry[extension];}
|
|
||||||
registerLangHandler(decorateSource,['default-code']);registerLangHandler(createSimpleLexer([],[[PR_PLAIN,/^[^<?]+/],[PR_DECLARATION,/^<!\w[^>]*(?:>|$)/],[PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],['lang-',/^<\?([\s\S]+?)(?:\?>|$)/],['lang-',/^<%([\s\S]+?)(?:%>|$)/],[PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],['lang-',/^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],['lang-js',/^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],['lang-css',/^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],['lang-in.tag',/^(<\/?[a-z][^<>]*>)/i]]),['default-markup','htm','html','mxml','xhtml','xml','xsl']);registerLangHandler(createSimpleLexer([[PR_PLAIN,/^[\s]+/,null,' \t\r\n'],[PR_ATTRIB_VALUE,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,'\"\'']],[[PR_TAG,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[PR_ATTRIB_NAME,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],['lang-uq.val',/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[PR_PUNCTUATION,/^[=<>\/]+/],['lang-js',/^on\w+\s*=\s*\"([^\"]+)\"/i],['lang-js',/^on\w+\s*=\s*\'([^\']+)\'/i],['lang-js',/^on\w+\s*=\s*([^\"\'>\s]+)/i],['lang-css',/^style\s*=\s*\"([^\"]+)\"/i],['lang-css',/^style\s*=\s*\'([^\']+)\'/i],['lang-css',/^style\s*=\s*([^\"\'>\s]+)/i]]),['in.tag']);registerLangHandler(createSimpleLexer([],[[PR_ATTRIB_VALUE,/^[\s\S]+/]]),['uq.val']);registerLangHandler(sourceDecorator({'keywords':CPP_KEYWORDS,'hashComments':true,'cStyleComments':true,'types':C_TYPES}),['c','cc','cpp','cxx','cyc','m']);registerLangHandler(sourceDecorator({'keywords':'null,true,false'}),['json']);registerLangHandler(sourceDecorator({'keywords':CSHARP_KEYWORDS,'hashComments':true,'cStyleComments':true,'verbatimStrings':true,'types':C_TYPES}),['cs']);registerLangHandler(sourceDecorator({'keywords':JAVA_KEYWORDS,'cStyleComments':true}),['java']);registerLangHandler(sourceDecorator({'keywords':SH_KEYWORDS,'hashComments':true,'multiLineStrings':true}),['bsh','csh','sh']);registerLangHandler(sourceDecorator({'keywords':PYTHON_KEYWORDS,'hashComments':true,'multiLineStrings':true,'tripleQuotedStrings':true}),['cv','py']);registerLangHandler(sourceDecorator({'keywords':PERL_KEYWORDS,'hashComments':true,'multiLineStrings':true,'regexLiterals':true}),['perl','pl','pm']);registerLangHandler(sourceDecorator({'keywords':RUBY_KEYWORDS,'hashComments':true,'multiLineStrings':true,'regexLiterals':true}),['rb']);registerLangHandler(sourceDecorator({'keywords':JSCRIPT_KEYWORDS,'cStyleComments':true,'regexLiterals':true}),['js']);registerLangHandler(sourceDecorator({'keywords':COFFEE_KEYWORDS,'hashComments':3,'cStyleComments':true,'multilineStrings':true,'tripleQuotedStrings':true,'regexLiterals':true}),['coffee']);registerLangHandler(createSimpleLexer([],[[PR_STRING,/^[\s\S]+/]]),['regex']);function applyDecorator(job){var opt_langExtension=job.langExtension;try{var sourceAndSpans=extractSourceSpans(job.sourceNode,job.pre);var source=sourceAndSpans.sourceCode;job.sourceCode=source;job.spans=sourceAndSpans.spans;job.basePos=0;langHandlerForExtension(opt_langExtension,source)(job);recombineTagsAndDecorations(job);}catch(e){if(win['console']){console['log'](e&&e['stack']?e['stack']:e);}}}
|
|
||||||
function prettyPrintOne(sourceCodeHtml,opt_langExtension,opt_numberLines){var container=document.createElement('pre');container.innerHTML=sourceCodeHtml;if(opt_numberLines){numberLines(container,opt_numberLines,true);}
|
|
||||||
var job={langExtension:opt_langExtension,numberLines:opt_numberLines,sourceNode:container,pre:1};applyDecorator(job);return container.innerHTML;}
|
|
||||||
function prettyPrint(opt_whenDone){function byTagName(tn){return document.getElementsByTagName(tn);}
|
|
||||||
var codeSegments=[byTagName('pre'),byTagName('code'),byTagName('xmp')];var elements=[];for(var i=0;i<codeSegments.length;++i){for(var j=0,n=codeSegments[i].length;j<n;++j){elements.push(codeSegments[i][j]);}}
|
|
||||||
codeSegments=null;var clock=Date;if(!clock['now']){clock={'now':function(){return+(new Date);}};}
|
|
||||||
var k=0;var prettyPrintingJob;var langExtensionRe=/\blang(?:uage)?-([\w.]+)(?!\S)/;var prettyPrintRe=/\bprettyprint\b/;var prettyPrintedRe=/\bprettyprinted\b/;var preformattedTagNameRe=/pre|xmp/i;var codeRe=/^code$/i;var preCodeXmpRe=/^(?:pre|code|xmp)$/i;function doWork(){var endTime=(win['PR_SHOULD_USE_CONTINUATION']?clock['now']()+250:Infinity);for(;k<elements.length&&clock['now']()<endTime;k++){var cs=elements[k];var className=cs.className;if(prettyPrintRe.test(className)&&!prettyPrintedRe.test(className)){var nested=false;for(var p=cs.parentNode;p;p=p.parentNode){var tn=p.tagName;if(preCodeXmpRe.test(tn)&&p.className&&prettyPrintRe.test(p.className)){nested=true;break;}}
|
|
||||||
if(!nested){cs.className+=' prettyprinted';var langExtension=className.match(langExtensionRe);var wrapper;if(!langExtension&&(wrapper=childContentWrapper(cs))&&codeRe.test(wrapper.tagName)){langExtension=wrapper.className.match(langExtensionRe);}
|
|
||||||
if(langExtension){langExtension=langExtension[1];}
|
|
||||||
var preformatted;if(preformattedTagNameRe.test(cs.tagName)){preformatted=1;}else{var currentStyle=cs['currentStyle'];var whitespace=(currentStyle?currentStyle['whiteSpace']:(document.defaultView&&document.defaultView.getComputedStyle)?document.defaultView.getComputedStyle(cs,null).getPropertyValue('white-space'):0);preformatted=whitespace&&'pre'===whitespace.substring(0,3);}
|
|
||||||
var lineNums=cs.className.match(/\blinenums\b(?::(\d+))?/);lineNums=lineNums?lineNums[1]&&lineNums[1].length?+lineNums[1]:true:false;if(lineNums){numberLines(cs,lineNums,preformatted);}
|
|
||||||
prettyPrintingJob={langExtension:langExtension,sourceNode:cs,numberLines:lineNums,pre:preformatted};applyDecorator(prettyPrintingJob);}}}
|
|
||||||
if(k<elements.length){setTimeout(doWork,250);}else if(opt_whenDone){opt_whenDone();}}
|
|
||||||
doWork();}
|
|
||||||
var PR=win['PR']={'createSimpleLexer':createSimpleLexer,'registerLangHandler':registerLangHandler,'sourceDecorator':sourceDecorator,'PR_ATTRIB_NAME':PR_ATTRIB_NAME,'PR_ATTRIB_VALUE':PR_ATTRIB_VALUE,'PR_COMMENT':PR_COMMENT,'PR_DECLARATION':PR_DECLARATION,'PR_KEYWORD':PR_KEYWORD,'PR_LITERAL':PR_LITERAL,'PR_NOCODE':PR_NOCODE,'PR_PLAIN':PR_PLAIN,'PR_PUNCTUATION':PR_PUNCTUATION,'PR_SOURCE':PR_SOURCE,'PR_STRING':PR_STRING,'PR_TAG':PR_TAG,'PR_TYPE':PR_TYPE,'prettyPrintOne':win['prettyPrintOne']=prettyPrintOne,'prettyPrint':win['prettyPrint']=prettyPrint};if(typeof define==="function"&&define['amd']){define("google-code-prettify",[],function(){return PR;});}})();
|
|
||||||
;(function(window, document) {
|
|
||||||
|
|
||||||
// Hide body until we're done fiddling with the DOM (FIXED")
|
|
||||||
document.body.style.display = 'none';
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Shims for IE < 9
|
|
||||||
//
|
|
||||||
|
|
||||||
document.head = document.getElementsByTagName('head')[0];
|
|
||||||
|
|
||||||
if (!('getElementsByClassName' in document)) {
|
|
||||||
document.getElementsByClassName = function(name) {
|
|
||||||
function getElementsByClassName(node, classname) {
|
|
||||||
var a = [];
|
|
||||||
var re = new RegExp('(^| )'+classname+'( |$)');
|
|
||||||
var els = node.getElementsByTagName("*");
|
|
||||||
for(var i=0,j=els.length; i<j; i++)
|
|
||||||
if(re.test(els[i].className))a.push(els[i]);
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
return getElementsByClassName(document.body, name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Get user elements we need
|
|
||||||
//
|
|
||||||
|
|
||||||
var markdownEl = document.getElementsByTagName('xmp')[0] || document.getElementsByTagName('pre')[0] || document.getElementsByTagName('textarea')[0],
|
|
||||||
titleEl = document.getElementsByTagName('title')[0],
|
|
||||||
scriptEls = document.getElementsByTagName('script'),
|
|
||||||
navbarEl = document.getElementsByClassName('navbar')[0];
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// <head> stuff
|
|
||||||
//
|
|
||||||
|
|
||||||
// Use <meta> viewport so that Bootstrap is actually responsive on mobile
|
|
||||||
var metaEl = document.createElement('meta');
|
|
||||||
metaEl.name = 'viewport';
|
|
||||||
metaEl.content = 'width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0';
|
|
||||||
if (document.head.firstChild)
|
|
||||||
document.head.insertBefore(metaEl, document.head.firstChild);
|
|
||||||
else
|
|
||||||
document.head.appendChild(metaEl);
|
|
||||||
|
|
||||||
// Get origin of script
|
|
||||||
var origin = '';
|
|
||||||
for (var i = 0; i < scriptEls.length; i++) {
|
|
||||||
if (scriptEls[i].src.match('strapdown')) {
|
|
||||||
origin = scriptEls[i].src;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var originBase = origin.substr(0, origin.lastIndexOf('/'));
|
|
||||||
|
|
||||||
// Get theme
|
|
||||||
var theme = markdownEl.getAttribute('theme') || 'bootstrap';
|
|
||||||
theme = theme.toLowerCase();
|
|
||||||
|
|
||||||
// Stylesheets
|
|
||||||
var linkEl = document.createElement('link');
|
|
||||||
linkEl.rel = 'stylesheet';
|
|
||||||
linkEl.href = originBase + '/themes/'+theme+'.min.css?md';
|
|
||||||
document.head.appendChild(linkEl);
|
|
||||||
|
|
||||||
var linkEl = document.createElement('link');
|
|
||||||
linkEl.rel = 'stylesheet';
|
|
||||||
linkEl.href = originBase + '/strapdown.css?md';
|
|
||||||
document.head.appendChild(linkEl);
|
|
||||||
|
|
||||||
var linkEl = document.createElement('link');
|
|
||||||
linkEl.rel = 'stylesheet';
|
|
||||||
linkEl.href = originBase + '/themes/bootstrap-responsive.min.css?md';
|
|
||||||
document.head.appendChild(linkEl);
|
|
||||||
|
|
||||||
// Favicon
|
|
||||||
var linkEl = document.createElement('link');
|
|
||||||
linkEl.rel = 'shortcut icon';
|
|
||||||
linkEl.href = originBase + '/favicon.png?md';
|
|
||||||
// linkEl.href = 'https://ga-beacon.appspot.com/UA-38514290-15/strapdown?pixel';
|
|
||||||
document.head.appendChild(linkEl);
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// <body> stuff
|
|
||||||
//
|
|
||||||
|
|
||||||
var markdown = markdownEl.textContent || markdownEl.innerText;
|
|
||||||
|
|
||||||
var newNode = document.createElement('div');
|
|
||||||
newNode.className = 'container';
|
|
||||||
newNode.id = 'content';
|
|
||||||
document.body.replaceChild(newNode, markdownEl);
|
|
||||||
|
|
||||||
// Insert navbar if there's none
|
|
||||||
// FIXME be sure THIS is good.
|
|
||||||
var newNode = document.createElement('div');
|
|
||||||
newNode.className = 'navbar navbar-fixed-top';
|
|
||||||
if (!navbarEl && titleEl) {
|
|
||||||
newNode.innerHTML = '<div class="navbar-inner"> <div class="container"> <div id="headline" class="brand"> </div> '
|
|
||||||
/* // @HARDLY: dont want
|
|
||||||
+ '<div id="headline-copyrights" class="brand">(Powered by '
|
|
||||||
+ '<a title="http://lbo.k.vu/md" href="https://lbesson.bitbucket.org/md/index.html?src=strapdown.js">StrapDown.js</a> v0.4.1 '
|
|
||||||
+ 'with theme <a title="More information on this theme on bootswatch.com !" href="http://bootswatch.com/'+theme+'">'+theme+'</a>, '
|
|
||||||
+ 'hosted on <a href="https://bitbucket.org/">BitBucket</a>)</div> '
|
|
||||||
+ '<div id="headline-squirt" class="brand"> <a title="Check https://lbesson.bitbucket.org/squirt/ for more informations" '
|
|
||||||
+ 'href="javascript:(function(){sq=window.sq;if(sq&&sq.closed){window.sq.closed&&window.document.dispatchEvent(new Event(\'squirt.again\'));}else{sq=window.sq||{};sq.version=\'0.4\';sq.host=\'https://lbesson.bitbucket.org/squirt\';sq.j=document.createElement(\'script\');sq.j.src=sq.host+\'/squirt.js?src=strapdown.js\';document.body.appendChild(sq.j);}})();" '
|
|
||||||
+ '>Use Squirt?</a></div> '
|
|
||||||
*/
|
|
||||||
+ '</div> </div>';
|
|
||||||
document.body.insertBefore(newNode, document.body.firstChild);
|
|
||||||
var title = titleEl.innerHTML;
|
|
||||||
var headlineEl = document.getElementById('headline');
|
|
||||||
if (headlineEl)
|
|
||||||
headlineEl.innerHTML = title;
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Markdown!
|
|
||||||
//
|
|
||||||
|
|
||||||
// Generate Markdown
|
|
||||||
var html = marked(markdown);
|
|
||||||
document.getElementById('content').innerHTML = html;
|
|
||||||
|
|
||||||
// Prettify
|
|
||||||
var codeEls = document.getElementsByTagName('code');
|
|
||||||
for (var i=0, ii=codeEls.length; i<ii; i++) {
|
|
||||||
var codeEl = codeEls[i];
|
|
||||||
var lang = codeEl.className;
|
|
||||||
codeEl.className = 'prettyprint lang-' + lang;
|
|
||||||
}
|
|
||||||
prettyPrint();
|
|
||||||
|
|
||||||
// Style tables
|
|
||||||
var tableEls = document.getElementsByTagName('table');
|
|
||||||
for (var i=0, ii=tableEls.length; i<ii; i++) {
|
|
||||||
var tableEl = tableEls[i];
|
|
||||||
tableEl.className = 'table table-striped table-bordered';
|
|
||||||
}
|
|
||||||
|
|
||||||
// All done - show body
|
|
||||||
document.body.style.display = '';
|
|
||||||
|
|
||||||
/* // @HARDLY: dont want
|
|
||||||
// Experimental ga-beacon auto web request
|
|
||||||
var linkEl = document.createElement('img');
|
|
||||||
linkEl.alt = 'GA|Analytics';
|
|
||||||
linkEl.style = 'visibility: hidden; display: none;';
|
|
||||||
linkEl.src = 'https://ga-beacon.appspot.com/UA-38514290-14/strapdown.js?pixel';
|
|
||||||
document.body.appendChild(linkEl);
|
|
||||||
*/
|
|
||||||
|
|
||||||
})(window, document);
|
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,945 +0,0 @@
|
||||||
/*!
|
|
||||||
* Bootstrap v2.3.2
|
|
||||||
*
|
|
||||||
* Copyright 2012 Twitter, Inc
|
|
||||||
* Licensed under the Apache License v2.0
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Designed and built with all the love in the world @twitter by @mdo and @fat.
|
|
||||||
*/
|
|
||||||
/*@import url('https://fonts.googleapis.com/css?family=Droid+Sans:400,700');*/
|
|
||||||
|
|
||||||
article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block;}
|
|
||||||
audio,canvas,video{display:inline-block;*display:inline;*zoom:1;}
|
|
||||||
audio:not([controls]){display:none;}
|
|
||||||
html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;}
|
|
||||||
a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;}
|
|
||||||
a:hover,a:active{outline:0;}
|
|
||||||
sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline;}
|
|
||||||
sup{top:-0.5em;}
|
|
||||||
sub{bottom:-0.25em;}
|
|
||||||
img{max-width:100%;width:auto\9;height:auto;vertical-align:middle;border:0;-ms-interpolation-mode:bicubic;}
|
|
||||||
#map_canvas img{max-width:none;}
|
|
||||||
button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle;}
|
|
||||||
button,input{*overflow:visible;line-height:normal;}
|
|
||||||
button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0;}
|
|
||||||
button,input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button;}
|
|
||||||
input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield;}
|
|
||||||
input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none;}
|
|
||||||
textarea{overflow:auto;vertical-align:top;}
|
|
||||||
.clearfix{*zoom:1;}.clearfix:before,.clearfix:after{display:table;content:"";line-height:0;}
|
|
||||||
.clearfix:after{clear:both;}
|
|
||||||
.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0;}
|
|
||||||
.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;}
|
|
||||||
body{margin:0;font-family:'Droid Sans',sans-serif;font-size:14px;line-height:20px;color:#999999;background-color:#060606;}
|
|
||||||
a{color:#33b5e5;text-decoration:none;}
|
|
||||||
a:hover{color:#ffffff;text-decoration:underline;}
|
|
||||||
.img-rounded{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;}
|
|
||||||
.img-polaroid{padding:4px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0, 0, 0, 0.2);-webkit-box-shadow:0 1px 3px rgba(0, 0, 0, 0.1);-moz-box-shadow:0 1px 3px rgba(0, 0, 0, 0.1);box-shadow:0 1px 3px rgba(0, 0, 0, 0.1);}
|
|
||||||
.img-circle{-webkit-border-radius:500px;-moz-border-radius:500px;border-radius:500px;}
|
|
||||||
.row{margin-left:-20px;*zoom:1;}.row:before,.row:after{display:table;content:"";line-height:0;}
|
|
||||||
.row:after{clear:both;}
|
|
||||||
[class*="span"]{float:left;min-height:1px;margin-left:20px;}
|
|
||||||
.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px;}
|
|
||||||
.span12{width:940px;}
|
|
||||||
.span11{width:860px;}
|
|
||||||
.span10{width:780px;}
|
|
||||||
.span9{width:700px;}
|
|
||||||
.span8{width:620px;}
|
|
||||||
.span7{width:540px;}
|
|
||||||
.span6{width:460px;}
|
|
||||||
.span5{width:380px;}
|
|
||||||
.span4{width:300px;}
|
|
||||||
.span3{width:220px;}
|
|
||||||
.span2{width:140px;}
|
|
||||||
.span1{width:60px;}
|
|
||||||
.offset12{margin-left:980px;}
|
|
||||||
.offset11{margin-left:900px;}
|
|
||||||
.offset10{margin-left:820px;}
|
|
||||||
.offset9{margin-left:740px;}
|
|
||||||
.offset8{margin-left:660px;}
|
|
||||||
.offset7{margin-left:580px;}
|
|
||||||
.offset6{margin-left:500px;}
|
|
||||||
.offset5{margin-left:420px;}
|
|
||||||
.offset4{margin-left:340px;}
|
|
||||||
.offset3{margin-left:260px;}
|
|
||||||
.offset2{margin-left:180px;}
|
|
||||||
.offset1{margin-left:100px;}
|
|
||||||
.row-fluid{width:100%;*zoom:1;}.row-fluid:before,.row-fluid:after{display:table;content:"";line-height:0;}
|
|
||||||
.row-fluid:after{clear:both;}
|
|
||||||
.row-fluid [class*="span"]{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;float:left;margin-left:2.127659574468085%;*margin-left:2.074468085106383%;}
|
|
||||||
.row-fluid [class*="span"]:first-child{margin-left:0;}
|
|
||||||
.row-fluid .span12{width:100%;*width:99.94680851063829%;}
|
|
||||||
.row-fluid .span11{width:91.48936170212765%;*width:91.43617021276594%;}
|
|
||||||
.row-fluid .span10{width:82.97872340425532%;*width:82.92553191489361%;}
|
|
||||||
.row-fluid .span9{width:74.46808510638297%;*width:74.41489361702126%;}
|
|
||||||
.row-fluid .span8{width:65.95744680851064%;*width:65.90425531914893%;}
|
|
||||||
.row-fluid .span7{width:57.44680851063829%;*width:57.39361702127659%;}
|
|
||||||
.row-fluid .span6{width:48.93617021276595%;*width:48.88297872340425%;}
|
|
||||||
.row-fluid .span5{width:40.42553191489362%;*width:40.37234042553192%;}
|
|
||||||
.row-fluid .span4{width:31.914893617021278%;*width:31.861702127659576%;}
|
|
||||||
.row-fluid .span3{width:23.404255319148934%;*width:23.351063829787233%;}
|
|
||||||
.row-fluid .span2{width:14.893617021276595%;*width:14.840425531914894%;}
|
|
||||||
.row-fluid .span1{width:6.382978723404255%;*width:6.329787234042553%;}
|
|
||||||
.row-fluid .offset12{margin-left:104.25531914893617%;*margin-left:104.14893617021275%;}
|
|
||||||
.row-fluid .offset12:first-child{margin-left:102.12765957446808%;*margin-left:102.02127659574467%;}
|
|
||||||
.row-fluid .offset11{margin-left:95.74468085106382%;*margin-left:95.6382978723404%;}
|
|
||||||
.row-fluid .offset11:first-child{margin-left:93.61702127659574%;*margin-left:93.51063829787232%;}
|
|
||||||
.row-fluid .offset10{margin-left:87.23404255319149%;*margin-left:87.12765957446807%;}
|
|
||||||
.row-fluid .offset10:first-child{margin-left:85.1063829787234%;*margin-left:84.99999999999999%;}
|
|
||||||
.row-fluid .offset9{margin-left:78.72340425531914%;*margin-left:78.61702127659572%;}
|
|
||||||
.row-fluid .offset9:first-child{margin-left:76.59574468085106%;*margin-left:76.48936170212764%;}
|
|
||||||
.row-fluid .offset8{margin-left:70.2127659574468%;*margin-left:70.10638297872339%;}
|
|
||||||
.row-fluid .offset8:first-child{margin-left:68.08510638297872%;*margin-left:67.9787234042553%;}
|
|
||||||
.row-fluid .offset7{margin-left:61.70212765957446%;*margin-left:61.59574468085106%;}
|
|
||||||
.row-fluid .offset7:first-child{margin-left:59.574468085106375%;*margin-left:59.46808510638297%;}
|
|
||||||
.row-fluid .offset6{margin-left:53.191489361702125%;*margin-left:53.085106382978715%;}
|
|
||||||
.row-fluid .offset6:first-child{margin-left:51.063829787234035%;*margin-left:50.95744680851063%;}
|
|
||||||
.row-fluid .offset5{margin-left:44.68085106382979%;*margin-left:44.57446808510638%;}
|
|
||||||
.row-fluid .offset5:first-child{margin-left:42.5531914893617%;*margin-left:42.4468085106383%;}
|
|
||||||
.row-fluid .offset4{margin-left:36.170212765957444%;*margin-left:36.06382978723405%;}
|
|
||||||
.row-fluid .offset4:first-child{margin-left:34.04255319148936%;*margin-left:33.93617021276596%;}
|
|
||||||
.row-fluid .offset3{margin-left:27.659574468085104%;*margin-left:27.5531914893617%;}
|
|
||||||
.row-fluid .offset3:first-child{margin-left:25.53191489361702%;*margin-left:25.425531914893618%;}
|
|
||||||
.row-fluid .offset2{margin-left:19.148936170212764%;*margin-left:19.04255319148936%;}
|
|
||||||
.row-fluid .offset2:first-child{margin-left:17.02127659574468%;*margin-left:16.914893617021278%;}
|
|
||||||
.row-fluid .offset1{margin-left:10.638297872340425%;*margin-left:10.53191489361702%;}
|
|
||||||
.row-fluid .offset1:first-child{margin-left:8.51063829787234%;*margin-left:8.404255319148938%;}
|
|
||||||
[class*="span"].hide,.row-fluid [class*="span"].hide{display:none;}
|
|
||||||
[class*="span"].pull-right,.row-fluid [class*="span"].pull-right{float:right;}
|
|
||||||
.container{margin-right:auto;margin-left:auto;*zoom:1;}.container:before,.container:after{display:table;content:"";line-height:0;}
|
|
||||||
.container:after{clear:both;}
|
|
||||||
.container-fluid{padding-right:20px;padding-left:20px;*zoom:1;}.container-fluid:before,.container-fluid:after{display:table;content:"";line-height:0;}
|
|
||||||
.container-fluid:after{clear:both;}
|
|
||||||
p{margin:0 0 10px;}
|
|
||||||
.lead{margin-bottom:20px;font-size:21px;font-weight:200;line-height:30px;}
|
|
||||||
small{font-size:85%;}
|
|
||||||
strong{font-weight:bold;}
|
|
||||||
em{font-style:italic;}
|
|
||||||
cite{font-style:normal;}
|
|
||||||
.muted{color:#adafae;}
|
|
||||||
.text-warning{color:#a47e3c;}
|
|
||||||
.text-error{color:#b94a48;}
|
|
||||||
.text-info{color:#0099cc;}
|
|
||||||
.text-success{color:#468847;}
|
|
||||||
h1,h2,h3,h4,h5,h6{margin:10px 0;font-family:inherit;font-weight:normal;line-height:1;color:#ffffff;text-rendering:optimizelegibility;}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:normal;line-height:1;color:#adafae;}
|
|
||||||
h1{font-size:36px;line-height:40px;}
|
|
||||||
h2{font-size:30px;line-height:40px;}
|
|
||||||
h3{font-size:24px;line-height:40px;}
|
|
||||||
h4{font-size:18px;line-height:20px;}
|
|
||||||
h5{font-size:14px;line-height:20px;}
|
|
||||||
h6{font-size:12px;line-height:20px;}
|
|
||||||
h1 small{font-size:24px;}
|
|
||||||
h2 small{font-size:18px;}
|
|
||||||
h3 small{font-size:14px;}
|
|
||||||
h4 small{font-size:14px;}
|
|
||||||
.page-header{padding-bottom:9px;margin:20px 0 30px;border-bottom:1px solid #eeeeee;}
|
|
||||||
ul,ol{padding:0;margin:0 0 10px 25px;}
|
|
||||||
ul ul,ul ol,ol ol,ol ul{margin-bottom:0;}
|
|
||||||
li{line-height:20px;}
|
|
||||||
ul.unstyled,ol.unstyled{margin-left:0;list-style:none;}
|
|
||||||
dl{margin-bottom:20px;}
|
|
||||||
dt,dd{line-height:20px;}
|
|
||||||
dt{font-weight:bold;}
|
|
||||||
dd{margin-left:10px;}
|
|
||||||
.dl-horizontal{*zoom:1;}.dl-horizontal:before,.dl-horizontal:after{display:table;content:"";line-height:0;}
|
|
||||||
.dl-horizontal:after{clear:both;}
|
|
||||||
.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
|
|
||||||
.dl-horizontal dd{margin-left:180px;}
|
|
||||||
hr{margin:20px 0;border:0;border-top:1px solid #999999;border-bottom:1px solid #ffffff;}
|
|
||||||
abbr[title]{cursor:help;border-bottom:1px dotted #adafae;}
|
|
||||||
abbr.initialism{font-size:90%;text-transform:uppercase;}
|
|
||||||
blockquote{padding:0 0 0 15px;margin:0 0 20px;border-left:5px solid #eeeeee;}blockquote p{margin-bottom:0;font-size:16px;font-weight:300;line-height:25px;}
|
|
||||||
blockquote small{display:block;line-height:20px;color:#adafae;}blockquote small:before{content:'\2014 \00A0';}
|
|
||||||
blockquote.pull-right{float:right;padding-right:15px;padding-left:0;border-right:5px solid #eeeeee;border-left:0;}blockquote.pull-right p,blockquote.pull-right small{text-align:right;}
|
|
||||||
blockquote.pull-right small:before{content:'';}
|
|
||||||
blockquote.pull-right small:after{content:'\00A0 \2014';}
|
|
||||||
q:before,q:after,blockquote:before,blockquote:after{content:"";}
|
|
||||||
address{display:block;margin-bottom:20px;font-style:normal;line-height:20px;}
|
|
||||||
code,pre{padding:0 3px 2px;font-family:Menlo,Monaco,Consolas,"Courier New",monospace;font-size:18px;color:#282828;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}
|
|
||||||
code{padding:2px 4px;color:#d14;background-color:#f7f7f9;border:1px solid #e1e1e8;}
|
|
||||||
pre{display:block;padding:9.5px;margin:0 0 10px;font-size:90%;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre;white-space:pre-wrap;background-color:#f5f5f5;border:1px solid #ccc;border:1px solid rgba(0, 0, 0, 0.15);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}pre.prettyprint{margin-bottom:20px;}
|
|
||||||
pre code{padding:0;color:inherit;background-color:transparent;border:0;}
|
|
||||||
.pre-scrollable{max-height:340px;overflow-y:scroll;}
|
|
||||||
form{margin:0 0 20px;}
|
|
||||||
fieldset{padding:0;margin:0;border:0;}
|
|
||||||
legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:40px;color:#282828;border:0;border-bottom:1px solid #e5e5e5;}legend small{font-size:15px;color:#adafae;}
|
|
||||||
label,input,button,select,textarea{font-size:14px;font-weight:normal;line-height:20px;}
|
|
||||||
input,button,select,textarea{font-family:'Droid Sans',sans-serif;}
|
|
||||||
label{display:block;margin-bottom:5px;}
|
|
||||||
select,textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{display:inline-block;height:20px;padding:4px 6px;margin-bottom:9px;font-size:14px;line-height:20px;color:#999999;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}
|
|
||||||
input,textarea,.uneditable-input{width:206px;}
|
|
||||||
textarea{height:auto;}
|
|
||||||
textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{background-color:#cccccc;border:1px solid #bbbbbb;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-webkit-transition:border linear .2s, box-shadow linear .2s;-moz-transition:border linear .2s, box-shadow linear .2s;-o-transition:border linear .2s, box-shadow linear .2s;transition:border linear .2s, box-shadow linear .2s;}textarea:focus,input[type="text"]:focus,input[type="password"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="date"]:focus,input[type="month"]:focus,input[type="time"]:focus,input[type="week"]:focus,input[type="number"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="color"]:focus,.uneditable-input:focus{border-color:rgba(82, 168, 236, 0.8);outline:0;outline:thin dotted \9;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);}
|
|
||||||
input[type="radio"],input[type="checkbox"]{margin:4px 0 0;*margin-top:0;margin-top:1px \9;line-height:normal;cursor:pointer;}
|
|
||||||
input[type="file"],input[type="image"],input[type="submit"],input[type="reset"],input[type="button"],input[type="radio"],input[type="checkbox"]{width:auto;}
|
|
||||||
select,input[type="file"]{height:30px;*margin-top:4px;line-height:30px;}
|
|
||||||
select{width:220px;border:1px solid #bbbbbb;background-color:#cccccc;}
|
|
||||||
select[multiple],select[size]{height:auto;}
|
|
||||||
select:focus,input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;}
|
|
||||||
.uneditable-input,.uneditable-textarea{color:#adafae;background-color:#c9c9c9;border-color:#bbbbbb;-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);-moz-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);cursor:not-allowed;}
|
|
||||||
.uneditable-input{overflow:hidden;white-space:nowrap;}
|
|
||||||
.uneditable-textarea{width:auto;height:auto;}
|
|
||||||
input:-moz-placeholder,textarea:-moz-placeholder{color:#adafae;}
|
|
||||||
input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#adafae;}
|
|
||||||
input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#adafae;}
|
|
||||||
.radio,.checkbox{min-height:18px;padding-left:18px;}
|
|
||||||
.radio input[type="radio"],.checkbox input[type="checkbox"]{float:left;margin-left:-18px;}
|
|
||||||
.controls>.radio:first-child,.controls>.checkbox:first-child{padding-top:5px;}
|
|
||||||
.radio.inline,.checkbox.inline{display:inline-block;padding-top:5px;margin-bottom:0;vertical-align:middle;}
|
|
||||||
.radio.inline+.radio.inline,.checkbox.inline+.checkbox.inline{margin-left:10px;}
|
|
||||||
.input-mini{width:60px;}
|
|
||||||
.input-small{width:90px;}
|
|
||||||
.input-medium{width:150px;}
|
|
||||||
.input-large{width:210px;}
|
|
||||||
.input-xlarge{width:270px;}
|
|
||||||
.input-xxlarge{width:530px;}
|
|
||||||
input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"]{float:none;margin-left:0;}
|
|
||||||
.input-append input[class*="span"],.input-append .uneditable-input[class*="span"],.input-prepend input[class*="span"],.input-prepend .uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"],.row-fluid .input-prepend [class*="span"],.row-fluid .input-append [class*="span"]{display:inline-block;}
|
|
||||||
input,textarea,.uneditable-input{margin-left:0;}
|
|
||||||
.controls-row [class*="span"]+[class*="span"]{margin-left:20px;}
|
|
||||||
input.span12, textarea.span12, .uneditable-input.span12{width:926px;}
|
|
||||||
input.span11, textarea.span11, .uneditable-input.span11{width:846px;}
|
|
||||||
input.span10, textarea.span10, .uneditable-input.span10{width:766px;}
|
|
||||||
input.span9, textarea.span9, .uneditable-input.span9{width:686px;}
|
|
||||||
input.span8, textarea.span8, .uneditable-input.span8{width:606px;}
|
|
||||||
input.span7, textarea.span7, .uneditable-input.span7{width:526px;}
|
|
||||||
input.span6, textarea.span6, .uneditable-input.span6{width:446px;}
|
|
||||||
input.span5, textarea.span5, .uneditable-input.span5{width:366px;}
|
|
||||||
input.span4, textarea.span4, .uneditable-input.span4{width:286px;}
|
|
||||||
input.span3, textarea.span3, .uneditable-input.span3{width:206px;}
|
|
||||||
input.span2, textarea.span2, .uneditable-input.span2{width:126px;}
|
|
||||||
input.span1, textarea.span1, .uneditable-input.span1{width:46px;}
|
|
||||||
.controls-row{*zoom:1;}.controls-row:before,.controls-row:after{display:table;content:"";line-height:0;}
|
|
||||||
.controls-row:after{clear:both;}
|
|
||||||
.controls-row [class*="span"]{float:left;}
|
|
||||||
input[disabled],select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{cursor:not-allowed;background-color:#eeeeee;}
|
|
||||||
input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"][readonly],input[type="checkbox"][readonly]{background-color:transparent;}
|
|
||||||
.control-group.warning>label,.control-group.warning .help-block,.control-group.warning .help-inline{color:#a47e3c;}
|
|
||||||
.control-group.warning .checkbox,.control-group.warning .radio,.control-group.warning input,.control-group.warning select,.control-group.warning textarea{color:#a47e3c;}
|
|
||||||
.control-group.warning input,.control-group.warning select,.control-group.warning textarea{border-color:#a47e3c;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);}.control-group.warning input:focus,.control-group.warning select:focus,.control-group.warning textarea:focus{border-color:#7f612e;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ceae78;-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ceae78;box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ceae78;}
|
|
||||||
.control-group.warning .input-prepend .add-on,.control-group.warning .input-append .add-on{color:#a47e3c;background-color:#eeeeee;border-color:#a47e3c;}
|
|
||||||
.control-group.error>label,.control-group.error .help-block,.control-group.error .help-inline{color:#b94a48;}
|
|
||||||
.control-group.error .checkbox,.control-group.error .radio,.control-group.error input,.control-group.error select,.control-group.error textarea{color:#b94a48;}
|
|
||||||
.control-group.error input,.control-group.error select,.control-group.error textarea{border-color:#b94a48;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);}.control-group.error input:focus,.control-group.error select:focus,.control-group.error textarea:focus{border-color:#953b39;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;}
|
|
||||||
.control-group.error .input-prepend .add-on,.control-group.error .input-append .add-on{color:#b94a48;background-color:#eeeeee;border-color:#b94a48;}
|
|
||||||
.control-group.success>label,.control-group.success .help-block,.control-group.success .help-inline{color:#468847;}
|
|
||||||
.control-group.success .checkbox,.control-group.success .radio,.control-group.success input,.control-group.success select,.control-group.success textarea{color:#468847;}
|
|
||||||
.control-group.success input,.control-group.success select,.control-group.success textarea{border-color:#468847;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);}.control-group.success input:focus,.control-group.success select:focus,.control-group.success textarea:focus{border-color:#356635;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;}
|
|
||||||
.control-group.success .input-prepend .add-on,.control-group.success .input-append .add-on{color:#468847;background-color:#eeeeee;border-color:#468847;}
|
|
||||||
.control-group.info>label,.control-group.info .help-block,.control-group.info .help-inline{color:#0099cc;}
|
|
||||||
.control-group.info .checkbox,.control-group.info .radio,.control-group.info input,.control-group.info select,.control-group.info textarea{color:#0099cc;}
|
|
||||||
.control-group.info input,.control-group.info select,.control-group.info textarea{border-color:#0099cc;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);}.control-group.info input:focus,.control-group.info select:focus,.control-group.info textarea:focus{border-color:#007399;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #33ccff;-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #33ccff;box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #33ccff;}
|
|
||||||
.control-group.info .input-prepend .add-on,.control-group.info .input-append .add-on{color:#0099cc;background-color:#eeeeee;border-color:#0099cc;}
|
|
||||||
input:focus:required:invalid,textarea:focus:required:invalid,select:focus:required:invalid{color:#b94a48;border-color:#ee5f5b;}input:focus:required:invalid:focus,textarea:focus:required:invalid:focus,select:focus:required:invalid:focus{border-color:#e9322d;-webkit-box-shadow:0 0 6px #f8b9b7;-moz-box-shadow:0 0 6px #f8b9b7;box-shadow:0 0 6px #f8b9b7;}
|
|
||||||
.form-actions{padding:19px 20px 20px;margin-top:20px;margin-bottom:20px;background-color:transparent;border-top:1px solid #e5e5e5;*zoom:1;}.form-actions:before,.form-actions:after{display:table;content:"";line-height:0;}
|
|
||||||
.form-actions:after{clear:both;}
|
|
||||||
.help-block,.help-inline{color:#bfbfbf;}
|
|
||||||
.help-block{display:block;margin-bottom:10px;}
|
|
||||||
.help-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle;padding-left:5px;}
|
|
||||||
.input-append,.input-prepend{margin-bottom:5px;font-size:0;white-space:nowrap;}.input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input{position:relative;margin-bottom:0;*margin-left:0;font-size:14px;vertical-align:top;-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0;}.input-append input:focus,.input-prepend input:focus,.input-append select:focus,.input-prepend select:focus,.input-append .uneditable-input:focus,.input-prepend .uneditable-input:focus{z-index:2;}
|
|
||||||
.input-append .add-on,.input-prepend .add-on{display:inline-block;width:auto;height:20px;min-width:16px;padding:4px 5px;font-size:14px;font-weight:normal;line-height:20px;text-align:center;text-shadow:0 1px 0 #ffffff;background-color:#eeeeee;border:1px solid #ccc;}
|
|
||||||
.input-append .add-on,.input-prepend .add-on,.input-append .btn,.input-prepend .btn{vertical-align:top;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
|
|
||||||
.input-append .active,.input-prepend .active{background-color:#bbff33;border-color:#669900;}
|
|
||||||
.input-prepend .add-on,.input-prepend .btn{margin-right:-1px;}
|
|
||||||
.input-prepend .add-on:first-child,.input-prepend .btn:first-child{-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px;}
|
|
||||||
.input-append input,.input-append select,.input-append .uneditable-input{-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px;}
|
|
||||||
.input-append .add-on,.input-append .btn{margin-left:-1px;}
|
|
||||||
.input-append .add-on:last-child,.input-append .btn:last-child{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0;}
|
|
||||||
.input-prepend.input-append input,.input-prepend.input-append select,.input-prepend.input-append .uneditable-input{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
|
|
||||||
.input-prepend.input-append .add-on:first-child,.input-prepend.input-append .btn:first-child{margin-right:-1px;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px;}
|
|
||||||
.input-prepend.input-append .add-on:last-child,.input-prepend.input-append .btn:last-child{margin-left:-1px;-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0;}
|
|
||||||
input.search-query{padding-right:14px;padding-right:4px \9;padding-left:14px;padding-left:4px \9;margin-bottom:0;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px;}
|
|
||||||
.form-search .input-append .search-query,.form-search .input-prepend .search-query{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
|
|
||||||
.form-search .input-append .search-query{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px;}
|
|
||||||
.form-search .input-append .btn{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0;}
|
|
||||||
.form-search .input-prepend .search-query{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0;}
|
|
||||||
.form-search .input-prepend .btn{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px;}
|
|
||||||
.form-search input,.form-inline input,.form-horizontal input,.form-search textarea,.form-inline textarea,.form-horizontal textarea,.form-search select,.form-inline select,.form-horizontal select,.form-search .help-inline,.form-inline .help-inline,.form-horizontal .help-inline,.form-search .uneditable-input,.form-inline .uneditable-input,.form-horizontal .uneditable-input,.form-search .input-prepend,.form-inline .input-prepend,.form-horizontal .input-prepend,.form-search .input-append,.form-inline .input-append,.form-horizontal .input-append{display:inline-block;*display:inline;*zoom:1;margin-bottom:0;vertical-align:middle;}
|
|
||||||
.form-search .hide,.form-inline .hide,.form-horizontal .hide{display:none;}
|
|
||||||
.form-search label,.form-inline label,.form-search .btn-group,.form-inline .btn-group{display:inline-block;}
|
|
||||||
.form-search .input-append,.form-inline .input-append,.form-search .input-prepend,.form-inline .input-prepend{margin-bottom:0;}
|
|
||||||
.form-search .radio,.form-search .checkbox,.form-inline .radio,.form-inline .checkbox{padding-left:0;margin-bottom:0;vertical-align:middle;}
|
|
||||||
.form-search .radio input[type="radio"],.form-search .checkbox input[type="checkbox"],.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:left;margin-right:3px;margin-left:0;}
|
|
||||||
.control-group{margin-bottom:10px;}
|
|
||||||
legend+.control-group{margin-top:20px;-webkit-margin-top-collapse:separate;}
|
|
||||||
.form-horizontal .control-group{margin-bottom:20px;*zoom:1;}.form-horizontal .control-group:before,.form-horizontal .control-group:after{display:table;content:"";line-height:0;}
|
|
||||||
.form-horizontal .control-group:after{clear:both;}
|
|
||||||
.form-horizontal .control-label{float:left;width:160px;padding-top:5px;text-align:right;}
|
|
||||||
.form-horizontal .controls{*display:inline-block;*padding-left:20px;margin-left:180px;*margin-left:0;}.form-horizontal .controls:first-child{*padding-left:180px;}
|
|
||||||
.form-horizontal .help-block{margin-bottom:0;}
|
|
||||||
.form-horizontal input+.help-block,.form-horizontal select+.help-block,.form-horizontal textarea+.help-block{margin-top:10px;}
|
|
||||||
.form-horizontal .form-actions{padding-left:180px;}
|
|
||||||
table{max-width:100%;background-color:transparent;border-collapse:collapse;border-spacing:0;}
|
|
||||||
.table{width:100%;margin-bottom:20px;}.table th,.table td{padding:8px;line-height:20px;text-align:left;vertical-align:top;border-top:1px solid #222222;}
|
|
||||||
.table th{font-weight:bold;}
|
|
||||||
.table thead th{vertical-align:bottom;}
|
|
||||||
.table caption+thead tr:first-child th,.table caption+thead tr:first-child td,.table colgroup+thead tr:first-child th,.table colgroup+thead tr:first-child td,.table thead:first-child tr:first-child th,.table thead:first-child tr:first-child td{border-top:0;}
|
|
||||||
.table tbody+tbody{border-top:2px solid #222222;}
|
|
||||||
.table-condensed th,.table-condensed td{padding:4px 5px;}
|
|
||||||
.table-bordered{border:1px solid #222222;border-collapse:separate;*border-collapse:collapse;border-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}.table-bordered th,.table-bordered td{border-left:1px solid #222222;}
|
|
||||||
.table-bordered caption+thead tr:first-child th,.table-bordered caption+tbody tr:first-child th,.table-bordered caption+tbody tr:first-child td,.table-bordered colgroup+thead tr:first-child th,.table-bordered colgroup+tbody tr:first-child th,.table-bordered colgroup+tbody tr:first-child td,.table-bordered thead:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child td{border-top:0;}
|
|
||||||
.table-bordered thead:first-child tr:first-child th:first-child,.table-bordered tbody:first-child tr:first-child td:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px;}
|
|
||||||
.table-bordered thead:first-child tr:first-child th:last-child,.table-bordered tbody:first-child tr:first-child td:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px;}
|
|
||||||
.table-bordered thead:last-child tr:last-child th:first-child,.table-bordered tbody:last-child tr:last-child td:first-child,.table-bordered tfoot:last-child tr:last-child td:first-child{-webkit-border-radius:0 0 0 4px;-moz-border-radius:0 0 0 4px;border-radius:0 0 0 4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px;}
|
|
||||||
.table-bordered thead:last-child tr:last-child th:last-child,.table-bordered tbody:last-child tr:last-child td:last-child,.table-bordered tfoot:last-child tr:last-child td:last-child{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px;}
|
|
||||||
.table-bordered caption+thead tr:first-child th:first-child,.table-bordered caption+tbody tr:first-child td:first-child,.table-bordered colgroup+thead tr:first-child th:first-child,.table-bordered colgroup+tbody tr:first-child td:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px;}
|
|
||||||
.table-bordered caption+thead tr:first-child th:last-child,.table-bordered caption+tbody tr:first-child td:last-child,.table-bordered colgroup+thead tr:first-child th:last-child,.table-bordered colgroup+tbody tr:first-child td:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topleft:4px;}
|
|
||||||
.table-striped tbody tr:nth-child(odd) td,.table-striped tbody tr:nth-child(odd) th{background-color:rgba(100, 100, 100, 0.1);}
|
|
||||||
.table-hover tbody tr:hover td,.table-hover tbody tr:hover th{background-color:#282828;}
|
|
||||||
table [class*=span],.row-fluid table [class*=span]{display:table-cell;float:none;margin-left:0;}
|
|
||||||
.table .span1{float:none;width:44px;margin-left:0;}
|
|
||||||
.table .span2{float:none;width:124px;margin-left:0;}
|
|
||||||
.table .span3{float:none;width:204px;margin-left:0;}
|
|
||||||
.table .span4{float:none;width:284px;margin-left:0;}
|
|
||||||
.table .span5{float:none;width:364px;margin-left:0;}
|
|
||||||
.table .span6{float:none;width:444px;margin-left:0;}
|
|
||||||
.table .span7{float:none;width:524px;margin-left:0;}
|
|
||||||
.table .span8{float:none;width:604px;margin-left:0;}
|
|
||||||
.table .span9{float:none;width:684px;margin-left:0;}
|
|
||||||
.table .span10{float:none;width:764px;margin-left:0;}
|
|
||||||
.table .span11{float:none;width:844px;margin-left:0;}
|
|
||||||
.table .span12{float:none;width:924px;margin-left:0;}
|
|
||||||
.table .span13{float:none;width:1004px;margin-left:0;}
|
|
||||||
.table .span14{float:none;width:1084px;margin-left:0;}
|
|
||||||
.table .span15{float:none;width:1164px;margin-left:0;}
|
|
||||||
.table .span16{float:none;width:1244px;margin-left:0;}
|
|
||||||
.table .span17{float:none;width:1324px;margin-left:0;}
|
|
||||||
.table .span18{float:none;width:1404px;margin-left:0;}
|
|
||||||
.table .span19{float:none;width:1484px;margin-left:0;}
|
|
||||||
.table .span20{float:none;width:1564px;margin-left:0;}
|
|
||||||
.table .span21{float:none;width:1644px;margin-left:0;}
|
|
||||||
.table .span22{float:none;width:1724px;margin-left:0;}
|
|
||||||
.table .span23{float:none;width:1804px;margin-left:0;}
|
|
||||||
.table .span24{float:none;width:1884px;margin-left:0;}
|
|
||||||
.table tbody tr.success td{background-color:#eeeeee;}
|
|
||||||
.table tbody tr.error td{background-color:#eeeeee;}
|
|
||||||
.table tbody tr.warning td{background-color:#eeeeee;}
|
|
||||||
.table tbody tr.info td{background-color:#eeeeee;}
|
|
||||||
.table-hover tbody tr.success:hover td{background-color:#e1e1e1;}
|
|
||||||
.table-hover tbody tr.error:hover td{background-color:#e1e1e1;}
|
|
||||||
.table-hover tbody tr.warning:hover td{background-color:#e1e1e1;}
|
|
||||||
.table-hover tbody tr.info:hover td{background-color:#e1e1e1;}
|
|
||||||
[class^="icon-"],[class*=" icon-"]{display:inline-block;width:14px;height:14px;*margin-right:.3em;line-height:14px;vertical-align:text-top;background-image:url("../img/glyphicons-halflings.png");background-position:14px 14px;background-repeat:no-repeat;margin-top:1px;}
|
|
||||||
.icon-white,.nav-tabs>.active>a>[class^="icon-"],.nav-tabs>.active>a>[class*=" icon-"],.nav-pills>.active>a>[class^="icon-"],.nav-pills>.active>a>[class*=" icon-"],.nav-list>.active>a>[class^="icon-"],.nav-list>.active>a>[class*=" icon-"],.navbar-inverse .nav>.active>a>[class^="icon-"],.navbar-inverse .nav>.active>a>[class*=" icon-"],.dropdown-menu>li>a:hover>[class^="icon-"],.dropdown-menu>li>a:hover>[class*=" icon-"],.dropdown-menu>.active>a>[class^="icon-"],.dropdown-menu>.active>a>[class*=" icon-"]{background-image:url("../img/glyphicons-halflings-white.png");}
|
|
||||||
.icon-glass{background-position:0 0;}
|
|
||||||
.icon-music{background-position:-24px 0;}
|
|
||||||
.icon-search{background-position:-48px 0;}
|
|
||||||
.icon-envelope{background-position:-72px 0;}
|
|
||||||
.icon-heart{background-position:-96px 0;}
|
|
||||||
.icon-star{background-position:-120px 0;}
|
|
||||||
.icon-star-empty{background-position:-144px 0;}
|
|
||||||
.icon-user{background-position:-168px 0;}
|
|
||||||
.icon-film{background-position:-192px 0;}
|
|
||||||
.icon-th-large{background-position:-216px 0;}
|
|
||||||
.icon-th{background-position:-240px 0;}
|
|
||||||
.icon-th-list{background-position:-264px 0;}
|
|
||||||
.icon-ok{background-position:-288px 0;}
|
|
||||||
.icon-remove{background-position:-312px 0;}
|
|
||||||
.icon-zoom-in{background-position:-336px 0;}
|
|
||||||
.icon-zoom-out{background-position:-360px 0;}
|
|
||||||
.icon-off{background-position:-384px 0;}
|
|
||||||
.icon-signal{background-position:-408px 0;}
|
|
||||||
.icon-cog{background-position:-432px 0;}
|
|
||||||
.icon-trash{background-position:-456px 0;}
|
|
||||||
.icon-home{background-position:0 -24px;}
|
|
||||||
.icon-file{background-position:-24px -24px;}
|
|
||||||
.icon-time{background-position:-48px -24px;}
|
|
||||||
.icon-road{background-position:-72px -24px;}
|
|
||||||
.icon-download-alt{background-position:-96px -24px;}
|
|
||||||
.icon-download{background-position:-120px -24px;}
|
|
||||||
.icon-upload{background-position:-144px -24px;}
|
|
||||||
.icon-inbox{background-position:-168px -24px;}
|
|
||||||
.icon-play-circle{background-position:-192px -24px;}
|
|
||||||
.icon-repeat{background-position:-216px -24px;}
|
|
||||||
.icon-refresh{background-position:-240px -24px;}
|
|
||||||
.icon-list-alt{background-position:-264px -24px;}
|
|
||||||
.icon-lock{background-position:-287px -24px;}
|
|
||||||
.icon-flag{background-position:-312px -24px;}
|
|
||||||
.icon-headphones{background-position:-336px -24px;}
|
|
||||||
.icon-volume-off{background-position:-360px -24px;}
|
|
||||||
.icon-volume-down{background-position:-384px -24px;}
|
|
||||||
.icon-volume-up{background-position:-408px -24px;}
|
|
||||||
.icon-qrcode{background-position:-432px -24px;}
|
|
||||||
.icon-barcode{background-position:-456px -24px;}
|
|
||||||
.icon-tag{background-position:0 -48px;}
|
|
||||||
.icon-tags{background-position:-25px -48px;}
|
|
||||||
.icon-book{background-position:-48px -48px;}
|
|
||||||
.icon-bookmark{background-position:-72px -48px;}
|
|
||||||
.icon-print{background-position:-96px -48px;}
|
|
||||||
.icon-camera{background-position:-120px -48px;}
|
|
||||||
.icon-font{background-position:-144px -48px;}
|
|
||||||
.icon-bold{background-position:-167px -48px;}
|
|
||||||
.icon-italic{background-position:-192px -48px;}
|
|
||||||
.icon-text-height{background-position:-216px -48px;}
|
|
||||||
.icon-text-width{background-position:-240px -48px;}
|
|
||||||
.icon-align-left{background-position:-264px -48px;}
|
|
||||||
.icon-align-center{background-position:-288px -48px;}
|
|
||||||
.icon-align-right{background-position:-312px -48px;}
|
|
||||||
.icon-align-justify{background-position:-336px -48px;}
|
|
||||||
.icon-list{background-position:-360px -48px;}
|
|
||||||
.icon-indent-left{background-position:-384px -48px;}
|
|
||||||
.icon-indent-right{background-position:-408px -48px;}
|
|
||||||
.icon-facetime-video{background-position:-432px -48px;}
|
|
||||||
.icon-picture{background-position:-456px -48px;}
|
|
||||||
.icon-pencil{background-position:0 -72px;}
|
|
||||||
.icon-map-marker{background-position:-24px -72px;}
|
|
||||||
.icon-adjust{background-position:-48px -72px;}
|
|
||||||
.icon-tint{background-position:-72px -72px;}
|
|
||||||
.icon-edit{background-position:-96px -72px;}
|
|
||||||
.icon-share{background-position:-120px -72px;}
|
|
||||||
.icon-check{background-position:-144px -72px;}
|
|
||||||
.icon-move{background-position:-168px -72px;}
|
|
||||||
.icon-step-backward{background-position:-192px -72px;}
|
|
||||||
.icon-fast-backward{background-position:-216px -72px;}
|
|
||||||
.icon-backward{background-position:-240px -72px;}
|
|
||||||
.icon-play{background-position:-264px -72px;}
|
|
||||||
.icon-pause{background-position:-288px -72px;}
|
|
||||||
.icon-stop{background-position:-312px -72px;}
|
|
||||||
.icon-forward{background-position:-336px -72px;}
|
|
||||||
.icon-fast-forward{background-position:-360px -72px;}
|
|
||||||
.icon-step-forward{background-position:-384px -72px;}
|
|
||||||
.icon-eject{background-position:-408px -72px;}
|
|
||||||
.icon-chevron-left{background-position:-432px -72px;}
|
|
||||||
.icon-chevron-right{background-position:-456px -72px;}
|
|
||||||
.icon-plus-sign{background-position:0 -96px;}
|
|
||||||
.icon-minus-sign{background-position:-24px -96px;}
|
|
||||||
.icon-remove-sign{background-position:-48px -96px;}
|
|
||||||
.icon-ok-sign{background-position:-72px -96px;}
|
|
||||||
.icon-question-sign{background-position:-96px -96px;}
|
|
||||||
.icon-info-sign{background-position:-120px -96px;}
|
|
||||||
.icon-screenshot{background-position:-144px -96px;}
|
|
||||||
.icon-remove-circle{background-position:-168px -96px;}
|
|
||||||
.icon-ok-circle{background-position:-192px -96px;}
|
|
||||||
.icon-ban-circle{background-position:-216px -96px;}
|
|
||||||
.icon-arrow-left{background-position:-240px -96px;}
|
|
||||||
.icon-arrow-right{background-position:-264px -96px;}
|
|
||||||
.icon-arrow-up{background-position:-289px -96px;}
|
|
||||||
.icon-arrow-down{background-position:-312px -96px;}
|
|
||||||
.icon-share-alt{background-position:-336px -96px;}
|
|
||||||
.icon-resize-full{background-position:-360px -96px;}
|
|
||||||
.icon-resize-small{background-position:-384px -96px;}
|
|
||||||
.icon-plus{background-position:-408px -96px;}
|
|
||||||
.icon-minus{background-position:-433px -96px;}
|
|
||||||
.icon-asterisk{background-position:-456px -96px;}
|
|
||||||
.icon-exclamation-sign{background-position:0 -120px;}
|
|
||||||
.icon-gift{background-position:-24px -120px;}
|
|
||||||
.icon-leaf{background-position:-48px -120px;}
|
|
||||||
.icon-fire{background-position:-72px -120px;}
|
|
||||||
.icon-eye-open{background-position:-96px -120px;}
|
|
||||||
.icon-eye-close{background-position:-120px -120px;}
|
|
||||||
.icon-warning-sign{background-position:-144px -120px;}
|
|
||||||
.icon-plane{background-position:-168px -120px;}
|
|
||||||
.icon-calendar{background-position:-192px -120px;}
|
|
||||||
.icon-random{background-position:-216px -120px;width:16px;}
|
|
||||||
.icon-comment{background-position:-240px -120px;}
|
|
||||||
.icon-magnet{background-position:-264px -120px;}
|
|
||||||
.icon-chevron-up{background-position:-288px -120px;}
|
|
||||||
.icon-chevron-down{background-position:-313px -119px;}
|
|
||||||
.icon-retweet{background-position:-336px -120px;}
|
|
||||||
.icon-shopping-cart{background-position:-360px -120px;}
|
|
||||||
.icon-folder-close{background-position:-384px -120px;}
|
|
||||||
.icon-folder-open{background-position:-408px -120px;width:16px;}
|
|
||||||
.icon-resize-vertical{background-position:-432px -119px;}
|
|
||||||
.icon-resize-horizontal{background-position:-456px -118px;}
|
|
||||||
.icon-hdd{background-position:0 -144px;}
|
|
||||||
.icon-bullhorn{background-position:-24px -144px;}
|
|
||||||
.icon-bell{background-position:-48px -144px;}
|
|
||||||
.icon-certificate{background-position:-72px -144px;}
|
|
||||||
.icon-thumbs-up{background-position:-96px -144px;}
|
|
||||||
.icon-thumbs-down{background-position:-120px -144px;}
|
|
||||||
.icon-hand-right{background-position:-144px -144px;}
|
|
||||||
.icon-hand-left{background-position:-168px -144px;}
|
|
||||||
.icon-hand-up{background-position:-192px -144px;}
|
|
||||||
.icon-hand-down{background-position:-216px -144px;}
|
|
||||||
.icon-circle-arrow-right{background-position:-240px -144px;}
|
|
||||||
.icon-circle-arrow-left{background-position:-264px -144px;}
|
|
||||||
.icon-circle-arrow-up{background-position:-288px -144px;}
|
|
||||||
.icon-circle-arrow-down{background-position:-312px -144px;}
|
|
||||||
.icon-globe{background-position:-336px -144px;}
|
|
||||||
.icon-wrench{background-position:-360px -144px;}
|
|
||||||
.icon-tasks{background-position:-384px -144px;}
|
|
||||||
.icon-filter{background-position:-408px -144px;}
|
|
||||||
.icon-briefcase{background-position:-432px -144px;}
|
|
||||||
.icon-fullscreen{background-position:-456px -144px;}
|
|
||||||
.dropup,.dropdown{position:relative;}
|
|
||||||
.dropdown-toggle{*margin-bottom:-3px;}
|
|
||||||
.dropdown-toggle:active,.open .dropdown-toggle{outline:0;}
|
|
||||||
.caret{display:inline-block;width:0;height:0;vertical-align:top;border-top:4px solid #000000;border-right:4px solid transparent;border-left:4px solid transparent;content:"";}
|
|
||||||
.dropdown .caret{margin-top:8px;margin-left:2px;}
|
|
||||||
.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;background-color:#ffffff;border:1px solid #ccc;border:1px solid rgba(0, 0, 0, 0.2);*border-right-width:2px;*border-bottom-width:2px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);-moz-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box;}.dropdown-menu.pull-right{right:0;left:auto;}
|
|
||||||
.dropdown-menu .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:transparent;border-bottom:1px solid #222222;}
|
|
||||||
.dropdown-menu a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:20px;color:#999999;white-space:nowrap;}
|
|
||||||
.dropdown-menu li>a:hover,.dropdown-menu li>a:focus,.dropdown-submenu:hover>a{text-decoration:none;color:#ffffff;background-color:#33b5e5;background-color:#2ab2e4;background-image:-moz-linear-gradient(top, #33b5e5, #1dade2);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#33b5e5), to(#1dade2));background-image:-webkit-linear-gradient(top, #33b5e5, #1dade2);background-image:-o-linear-gradient(top, #33b5e5, #1dade2);background-image:linear-gradient(to bottom, #33b5e5, #1dade2);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff33b5e5', endColorstr='#ff1dade2', GradientType=0);}
|
|
||||||
.dropdown-menu .active>a,.dropdown-menu .active>a:hover{color:#ffffff;text-decoration:none;outline:0;background-color:#33b5e5;background-color:#2ab2e4;background-image:-moz-linear-gradient(top, #33b5e5, #1dade2);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#33b5e5), to(#1dade2));background-image:-webkit-linear-gradient(top, #33b5e5, #1dade2);background-image:-o-linear-gradient(top, #33b5e5, #1dade2);background-image:linear-gradient(to bottom, #33b5e5, #1dade2);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff33b5e5', endColorstr='#ff1dade2', GradientType=0);}
|
|
||||||
.dropdown-menu .disabled>a,.dropdown-menu .disabled>a:hover{color:#adafae;}
|
|
||||||
.dropdown-menu .disabled>a:hover{text-decoration:none;background-color:transparent;cursor:default;}
|
|
||||||
.open{*z-index:1000;}.open >.dropdown-menu{display:block;}
|
|
||||||
.pull-right>.dropdown-menu{right:0;left:auto;}
|
|
||||||
.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid #000000;content:"";}
|
|
||||||
.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px;}
|
|
||||||
.dropdown-submenu{position:relative;}
|
|
||||||
.dropdown-submenu>.dropdown-menu{top:0;left:100%;margin-top:-6px;margin-left:-1px;-webkit-border-radius:0 6px 6px 6px;-moz-border-radius:0 6px 6px 6px;border-radius:0 6px 6px 6px;}
|
|
||||||
.dropdown-submenu:hover>.dropdown-menu{display:block;}
|
|
||||||
.dropdown-submenu>a:after{display:block;content:" ";float:right;width:0;height:0;border-color:transparent;border-style:solid;border-width:5px 0 5px 5px;border-left-color:#cccccc;margin-top:5px;margin-right:-10px;}
|
|
||||||
.dropdown-submenu:hover>a:after{border-left-color:#ffffff;}
|
|
||||||
.dropdown .dropdown-menu .nav-header{padding-left:20px;padding-right:20px;}
|
|
||||||
.typeahead{margin-top:2px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}
|
|
||||||
.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#131517;border:1px solid #030303;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);}.well blockquote{border-color:#ddd;border-color:rgba(0, 0, 0, 0.15);}
|
|
||||||
.well-large{padding:24px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;}
|
|
||||||
.well-small{padding:9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}
|
|
||||||
.fade{opacity:0;-webkit-transition:opacity 0.15s linear;-moz-transition:opacity 0.15s linear;-o-transition:opacity 0.15s linear;transition:opacity 0.15s linear;}.fade.in{opacity:1;}
|
|
||||||
.collapse{position:relative;height:0;overflow:hidden;-webkit-transition:height 0.35s ease;-moz-transition:height 0.35s ease;-o-transition:height 0.35s ease;transition:height 0.35s ease;}.collapse.in{height:auto;}
|
|
||||||
.close{float:right;font-size:20px;font-weight:bold;line-height:20px;color:#000000;text-shadow:0 1px 0 #ffffff;opacity:0.2;filter:alpha(opacity=20);}.close:hover{color:#000000;text-decoration:none;cursor:pointer;opacity:0.4;filter:alpha(opacity=40);}
|
|
||||||
button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none;}
|
|
||||||
.btn{display:inline-block;*display:inline;*zoom:1;padding:4px 14px;margin-bottom:0;font-size:14px;line-height:20px;*line-height:20px;text-align:center;vertical-align:middle;cursor:pointer;color:#282828;text-shadow:0 1px 1px rgba(255, 255, 255, 0.75);background-color:#616161;background-image:-moz-linear-gradient(top, #666666, #595959);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#666666), to(#595959));background-image:-webkit-linear-gradient(top, #666666, #595959);background-image:-o-linear-gradient(top, #666666, #595959);background-image:linear-gradient(to bottom, #666666, #595959);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff666666', endColorstr='#ff595959', GradientType=0);border-color:#595959 #595959 #333333;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#595959;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);border:1px solid rgba(0, 0, 0, 0);*border:0;border-bottom-color:rgba(0, 0, 0, 0);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;*margin-left:.3em;-webkit-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);}.btn:hover,.btn:active,.btn.active,.btn.disabled,.btn[disabled]{color:#282828;background-color:#595959;*background-color:#4d4d4d;}
|
|
||||||
.btn:active,.btn.active{background-color:#404040 \9;}
|
|
||||||
.btn:first-child{*margin-left:0;}
|
|
||||||
.btn:hover{color:#282828;text-decoration:none;background-color:#e6e6e6;*background-color:#d9d9d9;background-position:0 -15px;-webkit-transition:background-position 0.1s linear;-moz-transition:background-position 0.1s linear;-o-transition:background-position 0.1s linear;transition:background-position 0.1s linear;}
|
|
||||||
.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;}
|
|
||||||
.btn.active,.btn:active{background-color:#e6e6e6;background-color:#d9d9d9 \9;background-image:none;outline:0;-webkit-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);}
|
|
||||||
.btn.disabled,.btn[disabled]{cursor:default;background-color:#e6e6e6;background-image:none;opacity:0.65;filter:alpha(opacity=65);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
|
|
||||||
.btn-large{padding:9px 14px;font-size:16px;line-height:normal;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;}
|
|
||||||
.btn-large [class^="icon-"]{margin-top:2px;}
|
|
||||||
.btn-small{padding:3px 9px;font-size:12px;line-height:18px;}
|
|
||||||
.btn-small [class^="icon-"]{margin-top:0;}
|
|
||||||
.btn-mini{padding:2px 6px;font-size:11px;line-height:17px;}
|
|
||||||
.btn-block{display:block;width:100%;padding-left:0;padding-right:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;}
|
|
||||||
.btn-block+.btn-block{margin-top:5px;}
|
|
||||||
input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%;}
|
|
||||||
.btn-primary.active,.btn-warning.active,.btn-danger.active,.btn-success.active,.btn-info.active,.btn-inverse.active{color:rgba(255, 255, 255, 0.75);}
|
|
||||||
.btn{border-color:#c5c5c5;border-color:rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.15) rgba(0, 0, 0, 0.25);}
|
|
||||||
.btn-primary{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#008ab8;background-image:-moz-linear-gradient(top, #0099cc, #007399);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#0099cc), to(#007399));background-image:-webkit-linear-gradient(top, #0099cc, #007399);background-image:-o-linear-gradient(top, #0099cc, #007399);background-image:linear-gradient(to bottom, #0099cc, #007399);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0099cc', endColorstr='#ff007399', GradientType=0);border-color:#007399 #007399 #00394d;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#007399;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-primary:hover,.btn-primary:active,.btn-primary.active,.btn-primary.disabled,.btn-primary[disabled]{color:#ffffff;background-color:#007399;*background-color:#006080;}
|
|
||||||
.btn-primary:active,.btn-primary.active{background-color:#004d66 \9;}
|
|
||||||
.btn-warning{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#ff9d2e;background-image:-moz-linear-gradient(top, #ffac4d, #ff8800);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ffac4d), to(#ff8800));background-image:-webkit-linear-gradient(top, #ffac4d, #ff8800);background-image:-o-linear-gradient(top, #ffac4d, #ff8800);background-image:linear-gradient(to bottom, #ffac4d, #ff8800);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffac4d', endColorstr='#ffff8800', GradientType=0);border-color:#ff8800 #ff8800 #b35f00;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#ff8800;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-warning:hover,.btn-warning:active,.btn-warning.active,.btn-warning.disabled,.btn-warning[disabled]{color:#ffffff;background-color:#ff8800;*background-color:#e67a00;}
|
|
||||||
.btn-warning:active,.btn-warning.active{background-color:#cc6d00 \9;}
|
|
||||||
.btn-danger{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#eb0000;background-image:-moz-linear-gradient(top, #ff0000, #cc0000);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ff0000), to(#cc0000));background-image:-webkit-linear-gradient(top, #ff0000, #cc0000);background-image:-o-linear-gradient(top, #ff0000, #cc0000);background-image:linear-gradient(to bottom, #ff0000, #cc0000);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff0000', endColorstr='#ffcc0000', GradientType=0);border-color:#cc0000 #cc0000 #800000;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#cc0000;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-danger:hover,.btn-danger:active,.btn-danger.active,.btn-danger.disabled,.btn-danger[disabled]{color:#ffffff;background-color:#cc0000;*background-color:#b30000;}
|
|
||||||
.btn-danger:active,.btn-danger.active{background-color:#990000 \9;}
|
|
||||||
.btn-success{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#7ab800;background-image:-moz-linear-gradient(top, #88cc00, #669900);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#88cc00), to(#669900));background-image:-webkit-linear-gradient(top, #88cc00, #669900);background-image:-o-linear-gradient(top, #88cc00, #669900);background-image:linear-gradient(to bottom, #88cc00, #669900);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff88cc00', endColorstr='#ff669900', GradientType=0);border-color:#669900 #669900 #334d00;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#669900;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-success:hover,.btn-success:active,.btn-success.active,.btn-success.disabled,.btn-success[disabled]{color:#ffffff;background-color:#669900;*background-color:#558000;}
|
|
||||||
.btn-success:active,.btn-success.active{background-color:#446600 \9;}
|
|
||||||
.btn-info{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#292929;background-image:-moz-linear-gradient(top, #333333, #191919);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#333333), to(#191919));background-image:-webkit-linear-gradient(top, #333333, #191919);background-image:-o-linear-gradient(top, #333333, #191919);background-image:linear-gradient(to bottom, #333333, #191919);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff333333', endColorstr='#ff191919', GradientType=0);border-color:#191919 #191919 #000000;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#191919;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-info:hover,.btn-info:active,.btn-info.active,.btn-info.disabled,.btn-info[disabled]{color:#ffffff;background-color:#191919;*background-color:#0d0d0d;}
|
|
||||||
.btn-info:active,.btn-info.active{background-color:#000000 \9;}
|
|
||||||
.btn-inverse{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#9f3fcf;background-image:-moz-linear-gradient(top, #a347d1, #9933cc);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#a347d1), to(#9933cc));background-image:-webkit-linear-gradient(top, #a347d1, #9933cc);background-image:-o-linear-gradient(top, #a347d1, #9933cc);background-image:linear-gradient(to bottom, #a347d1, #9933cc);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffa347d1', endColorstr='#ff9933cc', GradientType=0);border-color:#9933cc #9933cc #6b248f;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#9933cc;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-inverse:hover,.btn-inverse:active,.btn-inverse.active,.btn-inverse.disabled,.btn-inverse[disabled]{color:#ffffff;background-color:#9933cc;*background-color:#8a2eb8;}
|
|
||||||
.btn-inverse:active,.btn-inverse.active{background-color:#7a29a3 \9;}
|
|
||||||
button.btn,input[type="submit"].btn{*padding-top:3px;*padding-bottom:3px;}button.btn::-moz-focus-inner,input[type="submit"].btn::-moz-focus-inner{padding:0;border:0;}
|
|
||||||
button.btn.btn-large,input[type="submit"].btn.btn-large{*padding-top:7px;*padding-bottom:7px;}
|
|
||||||
button.btn.btn-small,input[type="submit"].btn.btn-small{*padding-top:3px;*padding-bottom:3px;}
|
|
||||||
button.btn.btn-mini,input[type="submit"].btn.btn-mini{*padding-top:1px;*padding-bottom:1px;}
|
|
||||||
.btn-link,.btn-link:active,.btn-link[disabled]{background-color:transparent;background-image:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
|
|
||||||
.btn-link{border-color:transparent;cursor:pointer;color:#33b5e5;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
|
|
||||||
.btn-link:hover{color:#ffffff;text-decoration:underline;background-color:transparent;}
|
|
||||||
.btn-link[disabled]:hover{color:#282828;text-decoration:none;}
|
|
||||||
.btn-group{position:relative;font-size:0;vertical-align:middle;white-space:nowrap;*margin-left:.3em;}.btn-group:first-child{*margin-left:0;}
|
|
||||||
.btn-group+.btn-group{margin-left:5px;}
|
|
||||||
.btn-toolbar{font-size:0;margin-top:10px;margin-bottom:10px;}.btn-toolbar .btn-group{display:inline-block;*display:inline;*zoom:1;}
|
|
||||||
.btn-toolbar .btn+.btn,.btn-toolbar .btn-group+.btn,.btn-toolbar .btn+.btn-group{margin-left:5px;}
|
|
||||||
.btn-group>.btn{position:relative;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
|
|
||||||
.btn-group>.btn+.btn{margin-left:-1px;}
|
|
||||||
.btn-group>.btn,.btn-group>.dropdown-menu{font-size:14px;}
|
|
||||||
.btn-group>.btn-mini{font-size:11px;}
|
|
||||||
.btn-group>.btn-small{font-size:12px;}
|
|
||||||
.btn-group>.btn-large{font-size:16px;}
|
|
||||||
.btn-group>.btn:first-child{margin-left:0;-webkit-border-top-left-radius:4px;-moz-border-radius-topleft:4px;border-top-left-radius:4px;-webkit-border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px;border-bottom-left-radius:4px;}
|
|
||||||
.btn-group>.btn:last-child,.btn-group>.dropdown-toggle{-webkit-border-top-right-radius:4px;-moz-border-radius-topright:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px;border-bottom-right-radius:4px;}
|
|
||||||
.btn-group>.btn.large:first-child{margin-left:0;-webkit-border-top-left-radius:6px;-moz-border-radius-topleft:6px;border-top-left-radius:6px;-webkit-border-bottom-left-radius:6px;-moz-border-radius-bottomleft:6px;border-bottom-left-radius:6px;}
|
|
||||||
.btn-group>.btn.large:last-child,.btn-group>.large.dropdown-toggle{-webkit-border-top-right-radius:6px;-moz-border-radius-topright:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;-moz-border-radius-bottomright:6px;border-bottom-right-radius:6px;}
|
|
||||||
.btn-group>.btn:hover,.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active{z-index:2;}
|
|
||||||
.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0;}
|
|
||||||
.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px;-webkit-box-shadow:inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 1px 0 0 rgba(255, 255, 255, 0.125), inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);*padding-top:5px;*padding-bottom:5px;}
|
|
||||||
.btn-group>.btn-mini+.dropdown-toggle{padding-left:5px;padding-right:5px;*padding-top:2px;*padding-bottom:2px;}
|
|
||||||
.btn-group>.btn-small+.dropdown-toggle{*padding-top:5px;*padding-bottom:4px;}
|
|
||||||
.btn-group>.btn-large+.dropdown-toggle{padding-left:12px;padding-right:12px;*padding-top:7px;*padding-bottom:7px;}
|
|
||||||
.btn-group.open .dropdown-toggle{background-image:none;-webkit-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);}
|
|
||||||
.btn-group.open .btn.dropdown-toggle{background-color:#595959;}
|
|
||||||
.btn-group.open .btn-primary.dropdown-toggle{background-color:#007399;}
|
|
||||||
.btn-group.open .btn-warning.dropdown-toggle{background-color:#ff8800;}
|
|
||||||
.btn-group.open .btn-danger.dropdown-toggle{background-color:#cc0000;}
|
|
||||||
.btn-group.open .btn-success.dropdown-toggle{background-color:#669900;}
|
|
||||||
.btn-group.open .btn-info.dropdown-toggle{background-color:#191919;}
|
|
||||||
.btn-group.open .btn-inverse.dropdown-toggle{background-color:#9933cc;}
|
|
||||||
.btn .caret{margin-top:8px;margin-left:0;}
|
|
||||||
.btn-mini .caret,.btn-small .caret,.btn-large .caret{margin-top:6px;}
|
|
||||||
.btn-large .caret{border-left-width:5px;border-right-width:5px;border-top-width:5px;}
|
|
||||||
.dropup .btn-large .caret{border-bottom:5px solid #000000;border-top:0;}
|
|
||||||
.btn-primary .caret,.btn-warning .caret,.btn-danger .caret,.btn-info .caret,.btn-success .caret,.btn-inverse .caret{border-top-color:#ffffff;border-bottom-color:#ffffff;}
|
|
||||||
.btn-group-vertical{display:inline-block;*display:inline;*zoom:1;}
|
|
||||||
.btn-group-vertical .btn{display:block;float:none;width:100%;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
|
|
||||||
.btn-group-vertical .btn+.btn{margin-left:0;margin-top:-1px;}
|
|
||||||
.btn-group-vertical .btn:first-child{-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0;}
|
|
||||||
.btn-group-vertical .btn:last-child{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px;}
|
|
||||||
.btn-group-vertical .btn-large:first-child{-webkit-border-radius:6px 6px 0 0;-moz-border-radius:6px 6px 0 0;border-radius:6px 6px 0 0;}
|
|
||||||
.btn-group-vertical .btn-large:last-child{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;}
|
|
||||||
.alert{padding:8px 35px 8px 14px;margin-bottom:20px;text-shadow:0 1px 0 rgba(255, 255, 255, 0.5);background-color:#eeeeee;border:1px solid transparent;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;color:#a47e3c;}
|
|
||||||
.alert h4{margin:0;}
|
|
||||||
.alert .close{position:relative;top:-2px;right:-21px;line-height:20px;}
|
|
||||||
.alert-success{background-color:#eeeeee;border-color:#e1e1e1;color:#468847;}
|
|
||||||
.alert-danger,.alert-error{background-color:#eeeeee;border-color:#e6e6e6;color:#b94a48;}
|
|
||||||
.alert-info{background-color:#eeeeee;border-color:#dcdcdc;color:#0099cc;}
|
|
||||||
.alert-block{padding-top:14px;padding-bottom:14px;}
|
|
||||||
.alert-block>p,.alert-block>ul{margin-bottom:0;}
|
|
||||||
.alert-block p+p{margin-top:5px;}
|
|
||||||
.nav{margin-left:0;margin-bottom:20px;list-style:none;}
|
|
||||||
.nav>li>a{display:block;}
|
|
||||||
.nav>li>a:hover{text-decoration:none;background-color:#eeeeee;}
|
|
||||||
.nav>.pull-right{float:right;}
|
|
||||||
.nav-header{display:block;padding:3px 15px;font-size:11px;font-weight:bold;line-height:20px;color:#adafae;text-shadow:0 1px 0 rgba(255, 255, 255, 0.5);text-transform:uppercase;}
|
|
||||||
.nav li+.nav-header{margin-top:9px;}
|
|
||||||
.nav-list{padding-left:15px;padding-right:15px;margin-bottom:0;}
|
|
||||||
.nav-list>li>a,.nav-list .nav-header{margin-left:-15px;margin-right:-15px;text-shadow:0 1px 0 rgba(255, 255, 255, 0.5);}
|
|
||||||
.nav-list>li>a{padding:3px 15px;}
|
|
||||||
.nav-list>.active>a,.nav-list>.active>a:hover{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.2);background-color:#33b5e5;}
|
|
||||||
.nav-list [class^="icon-"]{margin-right:2px;}
|
|
||||||
.nav-list .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #ffffff;}
|
|
||||||
.nav-tabs,.nav-pills{*zoom:1;}.nav-tabs:before,.nav-pills:before,.nav-tabs:after,.nav-pills:after{display:table;content:"";line-height:0;}
|
|
||||||
.nav-tabs:after,.nav-pills:after{clear:both;}
|
|
||||||
.nav-tabs>li,.nav-pills>li{float:left;}
|
|
||||||
.nav-tabs>li>a,.nav-pills>li>a{padding-right:12px;padding-left:12px;margin-right:2px;line-height:14px;}
|
|
||||||
.nav-tabs{border-bottom:1px solid #ddd;}
|
|
||||||
.nav-tabs>li{margin-bottom:-1px;}
|
|
||||||
.nav-tabs>li>a{padding-top:8px;padding-bottom:8px;line-height:20px;border:1px solid transparent;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0;}.nav-tabs>li>a:hover{border-color:#eeeeee #eeeeee #dddddd;}
|
|
||||||
.nav-tabs>.active>a,.nav-tabs>.active>a:hover{color:#999999;background-color:#ffffff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default;}
|
|
||||||
.nav-pills>li>a{padding-top:8px;padding-bottom:8px;margin-top:2px;margin-bottom:2px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;}
|
|
||||||
.nav-pills>.active>a,.nav-pills>.active>a:hover{color:#ffffff;background-color:#33b5e5;}
|
|
||||||
.nav-stacked>li{float:none;}
|
|
||||||
.nav-stacked>li>a{margin-right:0;}
|
|
||||||
.nav-tabs.nav-stacked{border-bottom:0;}
|
|
||||||
.nav-tabs.nav-stacked>li>a{border:1px solid #ddd;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
|
|
||||||
.nav-tabs.nav-stacked>li:first-child>a{-webkit-border-top-right-radius:4px;-moz-border-radius-topright:4px;border-top-right-radius:4px;-webkit-border-top-left-radius:4px;-moz-border-radius-topleft:4px;border-top-left-radius:4px;}
|
|
||||||
.nav-tabs.nav-stacked>li:last-child>a{-webkit-border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px;border-bottom-right-radius:4px;-webkit-border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px;border-bottom-left-radius:4px;}
|
|
||||||
.nav-tabs.nav-stacked>li>a:hover{border-color:#ddd;z-index:2;}
|
|
||||||
.nav-pills.nav-stacked>li>a{margin-bottom:3px;}
|
|
||||||
.nav-pills.nav-stacked>li:last-child>a{margin-bottom:1px;}
|
|
||||||
.nav-tabs .dropdown-menu{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;}
|
|
||||||
.nav-pills .dropdown-menu{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;}
|
|
||||||
.nav .dropdown-toggle .caret{border-top-color:#33b5e5;border-bottom-color:#33b5e5;margin-top:6px;}
|
|
||||||
.nav .dropdown-toggle:hover .caret{border-top-color:#ffffff;border-bottom-color:#ffffff;}
|
|
||||||
.nav-tabs .dropdown-toggle .caret{margin-top:8px;}
|
|
||||||
.nav .active .dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff;}
|
|
||||||
.nav-tabs .active .dropdown-toggle .caret{border-top-color:#999999;border-bottom-color:#999999;}
|
|
||||||
.nav>.dropdown.active>a:hover{cursor:pointer;}
|
|
||||||
.nav-tabs .open .dropdown-toggle,.nav-pills .open .dropdown-toggle,.nav>li.dropdown.open.active>a:hover{color:#ffffff;background-color:#adafae;border-color:#adafae;}
|
|
||||||
.nav li.dropdown.open .caret,.nav li.dropdown.open.active .caret,.nav li.dropdown.open a:hover .caret{border-top-color:#ffffff;border-bottom-color:#ffffff;opacity:1;filter:alpha(opacity=100);}
|
|
||||||
.tabs-stacked .open>a:hover{border-color:#adafae;}
|
|
||||||
.tabbable{*zoom:1;}.tabbable:before,.tabbable:after{display:table;content:"";line-height:0;}
|
|
||||||
.tabbable:after{clear:both;}
|
|
||||||
.tab-content{overflow:auto;}
|
|
||||||
.tabs-below>.nav-tabs,.tabs-right>.nav-tabs,.tabs-left>.nav-tabs{border-bottom:0;}
|
|
||||||
.tab-content>.tab-pane,.pill-content>.pill-pane{display:none;}
|
|
||||||
.tab-content>.active,.pill-content>.active{display:block;}
|
|
||||||
.tabs-below>.nav-tabs{border-top:1px solid #ddd;}
|
|
||||||
.tabs-below>.nav-tabs>li{margin-top:-1px;margin-bottom:0;}
|
|
||||||
.tabs-below>.nav-tabs>li>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px;}.tabs-below>.nav-tabs>li>a:hover{border-bottom-color:transparent;border-top-color:#ddd;}
|
|
||||||
.tabs-below>.nav-tabs>.active>a,.tabs-below>.nav-tabs>.active>a:hover{border-color:transparent #ddd #ddd #ddd;}
|
|
||||||
.tabs-left>.nav-tabs>li,.tabs-right>.nav-tabs>li{float:none;}
|
|
||||||
.tabs-left>.nav-tabs>li>a,.tabs-right>.nav-tabs>li>a{min-width:74px;margin-right:0;margin-bottom:3px;}
|
|
||||||
.tabs-left>.nav-tabs{float:left;margin-right:19px;border-right:1px solid #ddd;}
|
|
||||||
.tabs-left>.nav-tabs>li>a{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px;}
|
|
||||||
.tabs-left>.nav-tabs>li>a:hover{border-color:#eeeeee #dddddd #eeeeee #eeeeee;}
|
|
||||||
.tabs-left>.nav-tabs .active>a,.tabs-left>.nav-tabs .active>a:hover{border-color:#ddd transparent #ddd #ddd;*border-right-color:#ffffff;}
|
|
||||||
.tabs-right>.nav-tabs{float:right;margin-left:19px;border-left:1px solid #ddd;}
|
|
||||||
.tabs-right>.nav-tabs>li>a{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0;}
|
|
||||||
.tabs-right>.nav-tabs>li>a:hover{border-color:#eeeeee #eeeeee #eeeeee #dddddd;}
|
|
||||||
.tabs-right>.nav-tabs .active>a,.tabs-right>.nav-tabs .active>a:hover{border-color:#ddd #ddd #ddd transparent;*border-left-color:#ffffff;}
|
|
||||||
.nav>.disabled>a{color:#adafae;}
|
|
||||||
.nav>.disabled>a:hover{text-decoration:none;background-color:transparent;cursor:default;}
|
|
||||||
.navbar{overflow:visible;margin-bottom:20px;color:#adafae;*position:relative;*z-index:2;}
|
|
||||||
.navbar-inner{min-height:40px;padding-left:20px;padding-right:20px;background-color:#020202;background-image:-moz-linear-gradient(top, #020202, #020202);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#020202), to(#020202));background-image:-webkit-linear-gradient(top, #020202, #020202);background-image:-o-linear-gradient(top, #020202, #020202);background-image:linear-gradient(to bottom, #020202, #020202);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff020202', endColorstr='#ff020202', GradientType=0);border:1px solid #000000;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 4px rgba(0, 0, 0, 0.065);-moz-box-shadow:0 1px 4px rgba(0, 0, 0, 0.065);box-shadow:0 1px 4px rgba(0, 0, 0, 0.065);*zoom:1;}.navbar-inner:before,.navbar-inner:after{display:table;content:"";line-height:0;}
|
|
||||||
.navbar-inner:after{clear:both;}
|
|
||||||
.navbar .container{width:auto;}
|
|
||||||
.nav-collapse.collapse{height:auto;}
|
|
||||||
.navbar .brand{float:left;display:block;padding:10px 20px 10px;margin-left:-20px;font-size:20px;font-weight:200;color:#adafae;text-shadow:0 1px 0 #020202;}.navbar .brand:hover{text-decoration:none;}
|
|
||||||
.navbar-text{margin-bottom:0;line-height:40px;}
|
|
||||||
.navbar-link{color:#adafae;}.navbar-link:hover{color:#ffffff;}
|
|
||||||
.navbar .divider-vertical{height:40px;margin:0 9px;border-left:1px solid #020202;border-right:1px solid #020202;}
|
|
||||||
.navbar .btn,.navbar .btn-group{margin-top:5px;}
|
|
||||||
.navbar .btn-group .btn,.navbar .input-prepend .btn,.navbar .input-append .btn{margin-top:0;}
|
|
||||||
.navbar-form{margin-bottom:0;*zoom:1;}.navbar-form:before,.navbar-form:after{display:table;content:"";line-height:0;}
|
|
||||||
.navbar-form:after{clear:both;}
|
|
||||||
.navbar-form input,.navbar-form select,.navbar-form .radio,.navbar-form .checkbox{margin-top:5px;}
|
|
||||||
.navbar-form input,.navbar-form select,.navbar-form .btn{display:inline-block;margin-bottom:0;}
|
|
||||||
.navbar-form input[type="image"],.navbar-form input[type="checkbox"],.navbar-form input[type="radio"]{margin-top:3px;}
|
|
||||||
.navbar-form .input-append,.navbar-form .input-prepend{margin-top:6px;white-space:nowrap;}.navbar-form .input-append input,.navbar-form .input-prepend input{margin-top:0;}
|
|
||||||
.navbar-search{position:relative;float:left;margin-top:5px;margin-bottom:0;}.navbar-search .search-query{margin-bottom:0;padding:4px 14px;font-family:'Droid Sans',sans-serif;font-size:13px;font-weight:normal;line-height:1;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px;}
|
|
||||||
.navbar-static-top{position:static;width:100%;margin-bottom:0;}.navbar-static-top .navbar-inner{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
|
|
||||||
.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030;margin-bottom:0;}
|
|
||||||
.navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{border-width:0 0 1px;}
|
|
||||||
.navbar-fixed-bottom .navbar-inner{border-width:1px 0 0;}
|
|
||||||
.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding-left:0;padding-right:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
|
|
||||||
.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px;}
|
|
||||||
.navbar-fixed-top{top:0;}
|
|
||||||
.navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{-webkit-box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.1), 0 1px 10px rgba(0, 0, 0, 0.1);-moz-box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.1), 0 1px 10px rgba(0, 0, 0, 0.1);box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.1), 0 1px 10px rgba(0, 0, 0, 0.1);}
|
|
||||||
.navbar-fixed-bottom{bottom:0;}.navbar-fixed-bottom .navbar-inner{-webkit-box-shadow:inset 0 1px 0 rgba(0, 0, 0, 0.1), 0 -1px 10px rgba(0, 0, 0, 0.1);-moz-box-shadow:inset 0 1px 0 rgba(0, 0, 0, 0.1), 0 -1px 10px rgba(0, 0, 0, 0.1);box-shadow:inset 0 1px 0 rgba(0, 0, 0, 0.1), 0 -1px 10px rgba(0, 0, 0, 0.1);}
|
|
||||||
.navbar .nav{position:relative;left:0;display:block;float:left;margin:0 10px 0 0;}
|
|
||||||
.navbar .nav.pull-right{float:right;margin-right:0;}
|
|
||||||
.navbar .nav>li{float:left;}
|
|
||||||
.navbar .nav>li>a{float:none;padding:10px 15px 10px;color:#adafae;text-decoration:none;text-shadow:0 1px 0 #020202;}
|
|
||||||
.navbar .nav .dropdown-toggle .caret{margin-top:8px;}
|
|
||||||
.navbar .nav>li>a:focus,.navbar .nav>li>a:hover{background-color:transparent;color:#ffffff;text-decoration:none;}
|
|
||||||
.navbar .nav>.active>a,.navbar .nav>.active>a:hover,.navbar .nav>.active>a:focus{color:#ffffff;text-decoration:none;background-color:#020202;-webkit-box-shadow:inset 0 3px 8px rgba(0, 0, 0, 0.125);-moz-box-shadow:inset 0 3px 8px rgba(0, 0, 0, 0.125);box-shadow:inset 0 3px 8px rgba(0, 0, 0, 0.125);}
|
|
||||||
.navbar .btn-navbar{display:none;float:right;padding:7px 10px;margin-left:5px;margin-right:5px;color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#000000;background-image:-moz-linear-gradient(top, #000000, #000000);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#000000), to(#000000));background-image:-webkit-linear-gradient(top, #000000, #000000);background-image:-o-linear-gradient(top, #000000, #000000);background-image:linear-gradient(to bottom, #000000, #000000);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff000000', endColorstr='#ff000000', GradientType=0);border-color:#000000 #000000 #000000;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#000000;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);-webkit-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);-moz-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.075);}.navbar .btn-navbar:hover,.navbar .btn-navbar:active,.navbar .btn-navbar.active,.navbar .btn-navbar.disabled,.navbar .btn-navbar[disabled]{color:#ffffff;background-color:#000000;*background-color:#000000;}
|
|
||||||
.navbar .btn-navbar:active,.navbar .btn-navbar.active{background-color:#000000 \9;}
|
|
||||||
.navbar .btn-navbar .icon-bar{display:block;width:18px;height:2px;background-color:#f5f5f5;-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;-webkit-box-shadow:0 1px 0 rgba(0, 0, 0, 0.25);-moz-box-shadow:0 1px 0 rgba(0, 0, 0, 0.25);box-shadow:0 1px 0 rgba(0, 0, 0, 0.25);}
|
|
||||||
.btn-navbar .icon-bar+.icon-bar{margin-top:3px;}
|
|
||||||
.navbar .nav>li>.dropdown-menu:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:rgba(0, 0, 0, 0.2);position:absolute;top:-7px;left:9px;}
|
|
||||||
.navbar .nav>li>.dropdown-menu:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #ffffff;position:absolute;top:-6px;left:10px;}
|
|
||||||
.navbar-fixed-bottom .nav>li>.dropdown-menu:before{border-top:7px solid #ccc;border-top-color:rgba(0, 0, 0, 0.2);border-bottom:0;bottom:-7px;top:auto;}
|
|
||||||
.navbar-fixed-bottom .nav>li>.dropdown-menu:after{border-top:6px solid #ffffff;border-bottom:0;bottom:-6px;top:auto;}
|
|
||||||
.navbar .nav li.dropdown.open>.dropdown-toggle,.navbar .nav li.dropdown.active>.dropdown-toggle,.navbar .nav li.dropdown.open.active>.dropdown-toggle{background-color:#020202;color:#ffffff;}
|
|
||||||
.navbar .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#adafae;border-bottom-color:#adafae;}
|
|
||||||
.navbar .nav li.dropdown.open>.dropdown-toggle .caret,.navbar .nav li.dropdown.active>.dropdown-toggle .caret,.navbar .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#ffffff;border-bottom-color:#ffffff;}
|
|
||||||
.navbar .pull-right>li>.dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right{left:auto;right:0;}.navbar .pull-right>li>.dropdown-menu:before,.navbar .nav>li>.dropdown-menu.pull-right:before{left:auto;right:12px;}
|
|
||||||
.navbar .pull-right>li>.dropdown-menu:after,.navbar .nav>li>.dropdown-menu.pull-right:after{left:auto;right:13px;}
|
|
||||||
.navbar .pull-right>li>.dropdown-menu .dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right .dropdown-menu{left:auto;right:100%;margin-left:0;margin-right:-1px;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px;}
|
|
||||||
.navbar-inverse{color:#eeeeee;}.navbar-inverse .navbar-inner{background-color:#252a30;background-image:-moz-linear-gradient(top, #252a30, #252a30);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#252a30), to(#252a30));background-image:-webkit-linear-gradient(top, #252a30, #252a30);background-image:-o-linear-gradient(top, #252a30, #252a30);background-image:linear-gradient(to bottom, #252a30, #252a30);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff252a30', endColorstr='#ff252a30', GradientType=0);border-color:transparent;}
|
|
||||||
.navbar-inverse .brand,.navbar-inverse .nav>li>a{color:#eeeeee;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);}.navbar-inverse .brand:hover,.navbar-inverse .nav>li>a:hover{color:#ffffff;}
|
|
||||||
.navbar-inverse .nav>li>a:focus,.navbar-inverse .nav>li>a:hover{background-color:#000000;color:#ffffff;}
|
|
||||||
.navbar-inverse .nav .active>a,.navbar-inverse .nav .active>a:hover,.navbar-inverse .nav .active>a:focus{color:#ffffff;background-color:#000000;}
|
|
||||||
.navbar-inverse .navbar-link{color:#eeeeee;}.navbar-inverse .navbar-link:hover{color:#ffffff;}
|
|
||||||
.navbar-inverse .divider-vertical{border-left-color:#252a30;border-right-color:#252a30;}
|
|
||||||
.navbar-inverse .nav li.dropdown.open>.dropdown-toggle,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle{background-color:#000000;color:#ffffff;}
|
|
||||||
.navbar-inverse .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#eeeeee;border-bottom-color:#eeeeee;}
|
|
||||||
.navbar-inverse .nav li.dropdown.open>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#ffffff;border-bottom-color:#ffffff;}
|
|
||||||
.navbar-inverse .navbar-search .search-query{color:#ffffff;background-color:#5d6978;border-color:#252a30;-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);-moz-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0 rgba(255, 255, 255, 0.15);-webkit-transition:none;-moz-transition:none;-o-transition:none;transition:none;}.navbar-inverse .navbar-search .search-query:-moz-placeholder{color:#ffffff;}
|
|
||||||
.navbar-inverse .navbar-search .search-query:-ms-input-placeholder{color:#ffffff;}
|
|
||||||
.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder{color:#ffffff;}
|
|
||||||
.navbar-inverse .navbar-search .search-query:focus,.navbar-inverse .navbar-search .search-query.focused{padding:5px 15px;color:#282828;text-shadow:0 1px 0 #ffffff;background-color:#ffffff;border:0;-webkit-box-shadow:0 0 3px rgba(0, 0, 0, 0.15);-moz-box-shadow:0 0 3px rgba(0, 0, 0, 0.15);box-shadow:0 0 3px rgba(0, 0, 0, 0.15);outline:0;}
|
|
||||||
.navbar-inverse .btn-navbar{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#1a1d22;background-image:-moz-linear-gradient(top, #1a1d22, #1a1d22);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#1a1d22), to(#1a1d22));background-image:-webkit-linear-gradient(top, #1a1d22, #1a1d22);background-image:-o-linear-gradient(top, #1a1d22, #1a1d22);background-image:linear-gradient(to bottom, #1a1d22, #1a1d22);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff1a1d22', endColorstr='#ff1a1d22', GradientType=0);border-color:#1a1d22 #1a1d22 #000000;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#1a1d22;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.navbar-inverse .btn-navbar:hover,.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active,.navbar-inverse .btn-navbar.disabled,.navbar-inverse .btn-navbar[disabled]{color:#ffffff;background-color:#1a1d22;*background-color:#0f1113;}
|
|
||||||
.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active{background-color:#040405 \9;}
|
|
||||||
.breadcrumb{padding:8px 15px;margin:0 0 20px;list-style:none;background-color:#f5f5f5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}.breadcrumb li{display:inline-block;*display:inline;*zoom:1;text-shadow:0 1px 0 #ffffff;}
|
|
||||||
.breadcrumb .divider{padding:0 5px;color:#ccc;}
|
|
||||||
.breadcrumb .active{color:#adafae;}
|
|
||||||
.pagination{height:40px;margin:20px 0;}
|
|
||||||
.pagination ul{display:inline-block;*display:inline;*zoom:1;margin-left:0;margin-bottom:0;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:0 1px 2px rgba(0, 0, 0, 0.05);}
|
|
||||||
.pagination ul>li{display:inline;}
|
|
||||||
.pagination ul>li>a,.pagination ul>li>span{float:left;padding:0 14px;line-height:38px;text-decoration:none;background-color:#060606;border:1px solid #dddddd;border-left-width:0;}
|
|
||||||
.pagination ul>li>a:hover,.pagination ul>.active>a,.pagination ul>.active>span{background-color:#f5f5f5;}
|
|
||||||
.pagination ul>.active>a,.pagination ul>.active>span{color:#adafae;cursor:default;}
|
|
||||||
.pagination ul>.disabled>span,.pagination ul>.disabled>a,.pagination ul>.disabled>a:hover{color:#adafae;background-color:transparent;cursor:default;}
|
|
||||||
.pagination ul>li:first-child>a,.pagination ul>li:first-child>span{border-left-width:1px;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px;}
|
|
||||||
.pagination ul>li:last-child>a,.pagination ul>li:last-child>span{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0;}
|
|
||||||
.pagination-centered{text-align:center;}
|
|
||||||
.pagination-right{text-align:right;}
|
|
||||||
.pager{margin:20px 0;list-style:none;text-align:center;*zoom:1;}.pager:before,.pager:after{display:table;content:"";line-height:0;}
|
|
||||||
.pager:after{clear:both;}
|
|
||||||
.pager li{display:inline;}
|
|
||||||
.pager a,.pager span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px;}
|
|
||||||
.pager a:hover{text-decoration:none;background-color:#f5f5f5;}
|
|
||||||
.pager .next a,.pager .next span{float:right;}
|
|
||||||
.pager .previous a{float:left;}
|
|
||||||
.pager .disabled a,.pager .disabled a:hover,.pager .disabled span{color:#adafae;background-color:#fff;cursor:default;}
|
|
||||||
.modal-open .modal .dropdown-menu{z-index:2050;}
|
|
||||||
.modal-open .modal .dropdown.open{*z-index:2050;}
|
|
||||||
.modal-open .modal .popover{z-index:2060;}
|
|
||||||
.modal-open .modal .tooltip{z-index:2070;}
|
|
||||||
.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000000;}.modal-backdrop.fade{opacity:0;}
|
|
||||||
.modal-backdrop,.modal-backdrop.fade.in{opacity:0.8;filter:alpha(opacity=80);}
|
|
||||||
.modal{position:fixed;top:50%;left:50%;z-index:1050;overflow:auto;width:560px;margin:-250px 0 0 -280px;background-color:#ffffff;border:1px solid #999;border:1px solid rgba(0, 0, 0, 0.3);*border:1px solid #999;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-moz-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box;}.modal.fade{-webkit-transition:opacity .3s linear, top .3s ease-out;-moz-transition:opacity .3s linear, top .3s ease-out;-o-transition:opacity .3s linear, top .3s ease-out;transition:opacity .3s linear, top .3s ease-out;top:-25%;}
|
|
||||||
.modal.fade.in{top:50%;}
|
|
||||||
.modal-header{padding:9px 15px;border-bottom:1px solid #eee;}.modal-header .close{margin-top:2px;}
|
|
||||||
.modal-header h3{margin:0;line-height:30px;}
|
|
||||||
.modal-body{overflow-y:auto;max-height:400px;padding:15px;}
|
|
||||||
.modal-form{margin-bottom:0;}
|
|
||||||
.modal-footer{padding:14px 15px 15px;margin-bottom:0;text-align:right;background-color:#f5f5f5;border-top:1px solid #ddd;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;-webkit-box-shadow:inset 0 1px 0 #ffffff;-moz-box-shadow:inset 0 1px 0 #ffffff;box-shadow:inset 0 1px 0 #ffffff;*zoom:1;}.modal-footer:before,.modal-footer:after{display:table;content:"";line-height:0;}
|
|
||||||
.modal-footer:after{clear:both;}
|
|
||||||
.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0;}
|
|
||||||
.modal-footer .btn-group .btn+.btn{margin-left:-1px;}
|
|
||||||
.tooltip{position:absolute;z-index:1020;display:block;visibility:visible;padding:5px;font-size:11px;opacity:0;filter:alpha(opacity=0);}.tooltip.in{opacity:0.8;filter:alpha(opacity=80);}
|
|
||||||
.tooltip.top{margin-top:-3px;}
|
|
||||||
.tooltip.right{margin-left:3px;}
|
|
||||||
.tooltip.bottom{margin-top:3px;}
|
|
||||||
.tooltip.left{margin-left:-3px;}
|
|
||||||
.tooltip-inner{max-width:200px;padding:3px 8px;color:#ffffff;text-align:center;text-decoration:none;background-color:#000000;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}
|
|
||||||
.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid;}
|
|
||||||
.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000000;}
|
|
||||||
.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000000;}
|
|
||||||
.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000000;}
|
|
||||||
.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000000;}
|
|
||||||
.popover{position:absolute;top:0;left:0;z-index:1010;display:none;width:236px;padding:1px;background-color:#ffffff;-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0, 0, 0, 0.2);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);-moz-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);}.popover.top{margin-bottom:10px;}
|
|
||||||
.popover.right{margin-left:10px;}
|
|
||||||
.popover.bottom{margin-top:10px;}
|
|
||||||
.popover.left{margin-right:10px;}
|
|
||||||
.popover-title{margin:0;padding:8px 14px;font-size:14px;font-weight:normal;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0;}
|
|
||||||
.popover-content{padding:9px 14px;}.popover-content p,.popover-content ul,.popover-content ol{margin-bottom:0;}
|
|
||||||
.popover .arrow,.popover .arrow:after{position:absolute;display:inline-block;width:0;height:0;border-color:transparent;border-style:solid;}
|
|
||||||
.popover .arrow:after{content:"";z-index:-1;}
|
|
||||||
.popover.top .arrow{bottom:-10px;left:50%;margin-left:-10px;border-width:10px 10px 0;border-top-color:#ffffff;}.popover.top .arrow:after{border-width:11px 11px 0;border-top-color:rgba(0, 0, 0, 0.25);bottom:-1px;left:-11px;}
|
|
||||||
.popover.right .arrow{top:50%;left:-10px;margin-top:-10px;border-width:10px 10px 10px 0;border-right-color:#ffffff;}.popover.right .arrow:after{border-width:11px 11px 11px 0;border-right-color:rgba(0, 0, 0, 0.25);bottom:-11px;left:-1px;}
|
|
||||||
.popover.bottom .arrow{top:-10px;left:50%;margin-left:-10px;border-width:0 10px 10px;border-bottom-color:#ffffff;}.popover.bottom .arrow:after{border-width:0 11px 11px;border-bottom-color:rgba(0, 0, 0, 0.25);top:-1px;left:-11px;}
|
|
||||||
.popover.left .arrow{top:50%;right:-10px;margin-top:-10px;border-width:10px 0 10px 10px;border-left-color:#ffffff;}.popover.left .arrow:after{border-width:11px 0 11px 11px;border-left-color:rgba(0, 0, 0, 0.25);bottom:-11px;right:-1px;}
|
|
||||||
.thumbnails{margin-left:-20px;list-style:none;*zoom:1;}.thumbnails:before,.thumbnails:after{display:table;content:"";line-height:0;}
|
|
||||||
.thumbnails:after{clear:both;}
|
|
||||||
.row-fluid .thumbnails{margin-left:0;}
|
|
||||||
.thumbnails>li{float:left;margin-bottom:20px;margin-left:20px;}
|
|
||||||
.thumbnail{display:block;padding:4px;line-height:20px;border:1px solid #ddd;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 3px rgba(0, 0, 0, 0.055);-moz-box-shadow:0 1px 3px rgba(0, 0, 0, 0.055);box-shadow:0 1px 3px rgba(0, 0, 0, 0.055);-webkit-transition:all 0.2s ease-in-out;-moz-transition:all 0.2s ease-in-out;-o-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out;}
|
|
||||||
a.thumbnail:hover{border-color:#33b5e5;-webkit-box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);-moz-box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);}
|
|
||||||
.thumbnail>img{display:block;max-width:100%;margin-left:auto;margin-right:auto;}
|
|
||||||
.thumbnail .caption{padding:9px;color:#999999;}
|
|
||||||
.label,.badge{font-size:11.844px;font-weight:bold;line-height:14px;color:#ffffff;vertical-align:baseline;white-space:nowrap;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#adafae;}
|
|
||||||
.label{padding:1px 4px 2px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}
|
|
||||||
.badge{padding:1px 9px 2px;-webkit-border-radius:9px;-moz-border-radius:9px;border-radius:9px;}
|
|
||||||
a.label:hover,a.badge:hover{color:#ffffff;text-decoration:none;cursor:pointer;}
|
|
||||||
.label-important,.badge-important{background-color:#b94a48;}
|
|
||||||
.label-important[href],.badge-important[href]{background-color:#953b39;}
|
|
||||||
.label-warning,.badge-warning{background-color:#ff8800;}
|
|
||||||
.label-warning[href],.badge-warning[href]{background-color:#cc6d00;}
|
|
||||||
.label-success,.badge-success{background-color:#468847;}
|
|
||||||
.label-success[href],.badge-success[href]{background-color:#356635;}
|
|
||||||
.label-info,.badge-info{background-color:#0099cc;}
|
|
||||||
.label-info[href],.badge-info[href]{background-color:#007399;}
|
|
||||||
.label-inverse,.badge-inverse{background-color:#282828;}
|
|
||||||
.label-inverse[href],.badge-inverse[href]{background-color:#0e0e0e;}
|
|
||||||
.btn .label,.btn .badge{position:relative;top:-1px;}
|
|
||||||
.btn-mini .label,.btn-mini .badge{top:0;}
|
|
||||||
@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0;} to{background-position:0 0;}}@-moz-keyframes progress-bar-stripes{from{background-position:40px 0;} to{background-position:0 0;}}@-ms-keyframes progress-bar-stripes{from{background-position:40px 0;} to{background-position:0 0;}}@-o-keyframes progress-bar-stripes{from{background-position:0 0;} to{background-position:40px 0;}}@keyframes progress-bar-stripes{from{background-position:40px 0;} to{background-position:0 0;}}.progress{overflow:hidden;height:20px;margin-bottom:20px;background-color:#f7f7f7;background-image:-moz-linear-gradient(top, #f5f5f5, #f9f9f9);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9));background-image:-webkit-linear-gradient(top, #f5f5f5, #f9f9f9);background-image:-o-linear-gradient(top, #f5f5f5, #f9f9f9);background-image:linear-gradient(to bottom, #f5f5f5, #f9f9f9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0);-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1);-moz-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1);box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}
|
|
||||||
.progress .bar{width:0%;height:100%;color:#ffffff;float:left;font-size:12px;text-align:center;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#0e90d2;background-image:-moz-linear-gradient(top, #149bdf, #0480be);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be));background-image:-webkit-linear-gradient(top, #149bdf, #0480be);background-image:-o-linear-gradient(top, #149bdf, #0480be);background-image:linear-gradient(to bottom, #149bdf, #0480be);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.15);-moz-box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.15);box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-transition:width 0.6s ease;-moz-transition:width 0.6s ease;-o-transition:width 0.6s ease;transition:width 0.6s ease;}
|
|
||||||
.progress .bar+.bar{-webkit-box-shadow:inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);-moz-box-shadow:inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);box-shadow:inset 1px 0 0 rgba(0, 0, 0, 0.15), inset 0 -1px 0 rgba(0, 0, 0, 0.15);}
|
|
||||||
.progress-striped .bar{background-color:#149bdf;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);-webkit-background-size:40px 40px;-moz-background-size:40px 40px;-o-background-size:40px 40px;background-size:40px 40px;}
|
|
||||||
.progress.active .bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-moz-animation:progress-bar-stripes 2s linear infinite;-ms-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite;}
|
|
||||||
.progress-danger .bar,.progress .bar-danger{background-color:#dd514c;background-image:-moz-linear-gradient(top, #ee5f5b, #c43c35);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ee5f5b), to(#c43c35));background-image:-webkit-linear-gradient(top, #ee5f5b, #c43c35);background-image:-o-linear-gradient(top, #ee5f5b, #c43c35);background-image:linear-gradient(to bottom, #ee5f5b, #c43c35);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b', endColorstr='#ffc43c35', GradientType=0);}
|
|
||||||
.progress-danger.progress-striped .bar,.progress-striped .bar-danger{background-color:#ee5f5b;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);}
|
|
||||||
.progress-success .bar,.progress .bar-success{background-color:#5eb95e;background-image:-moz-linear-gradient(top, #62c462, #57a957);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#62c462), to(#57a957));background-image:-webkit-linear-gradient(top, #62c462, #57a957);background-image:-o-linear-gradient(top, #62c462, #57a957);background-image:linear-gradient(to bottom, #62c462, #57a957);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462', endColorstr='#ff57a957', GradientType=0);}
|
|
||||||
.progress-success.progress-striped .bar,.progress-striped .bar-success{background-color:#62c462;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);}
|
|
||||||
.progress-info .bar,.progress .bar-info{background-color:#4bb1cf;background-image:-moz-linear-gradient(top, #5bc0de, #339bb9);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#5bc0de), to(#339bb9));background-image:-webkit-linear-gradient(top, #5bc0de, #339bb9);background-image:-o-linear-gradient(top, #5bc0de, #339bb9);background-image:linear-gradient(to bottom, #5bc0de, #339bb9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff339bb9', GradientType=0);}
|
|
||||||
.progress-info.progress-striped .bar,.progress-striped .bar-info{background-color:#5bc0de;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);}
|
|
||||||
.progress-warning .bar,.progress .bar-warning{background-color:#ff9d2e;background-image:-moz-linear-gradient(top, #ffac4d, #ff8800);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ffac4d), to(#ff8800));background-image:-webkit-linear-gradient(top, #ffac4d, #ff8800);background-image:-o-linear-gradient(top, #ffac4d, #ff8800);background-image:linear-gradient(to bottom, #ffac4d, #ff8800);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffac4d', endColorstr='#ffff8800', GradientType=0);}
|
|
||||||
.progress-warning.progress-striped .bar,.progress-striped .bar-warning{background-color:#ffac4d;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);}
|
|
||||||
.accordion{margin-bottom:20px;}
|
|
||||||
.accordion-group{margin-bottom:2px;border:1px solid #e5e5e5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}
|
|
||||||
.accordion-heading{border-bottom:0;}
|
|
||||||
.accordion-heading .accordion-toggle{display:block;padding:8px 15px;}
|
|
||||||
.accordion-toggle{cursor:pointer;}
|
|
||||||
.accordion-inner{padding:9px 15px;border-top:1px solid #e5e5e5;}
|
|
||||||
.carousel{position:relative;margin-bottom:20px;line-height:1;}
|
|
||||||
.carousel-inner{overflow:hidden;width:100%;position:relative;}
|
|
||||||
.carousel .item{display:none;position:relative;-webkit-transition:0.6s ease-in-out left;-moz-transition:0.6s ease-in-out left;-o-transition:0.6s ease-in-out left;transition:0.6s ease-in-out left;}
|
|
||||||
.carousel .item>img{display:block;line-height:1;}
|
|
||||||
.carousel .active,.carousel .next,.carousel .prev{display:block;}
|
|
||||||
.carousel .active{left:0;}
|
|
||||||
.carousel .next,.carousel .prev{position:absolute;top:0;width:100%;}
|
|
||||||
.carousel .next{left:100%;}
|
|
||||||
.carousel .prev{left:-100%;}
|
|
||||||
.carousel .next.left,.carousel .prev.right{left:0;}
|
|
||||||
.carousel .active.left{left:-100%;}
|
|
||||||
.carousel .active.right{left:100%;}
|
|
||||||
.carousel-control{position:absolute;top:40%;left:15px;width:40px;height:40px;margin-top:-20px;font-size:60px;font-weight:100;line-height:30px;color:#ffffff;text-align:center;background:#020202;border:3px solid #ffffff;-webkit-border-radius:23px;-moz-border-radius:23px;border-radius:23px;opacity:0.5;filter:alpha(opacity=50);}.carousel-control.right{left:auto;right:15px;}
|
|
||||||
.carousel-control:hover{color:#ffffff;text-decoration:none;opacity:0.9;filter:alpha(opacity=90);}
|
|
||||||
.carousel-caption{position:absolute;left:0;right:0;bottom:0;padding:15px;background:#282828;background:rgba(0, 0, 0, 0.75);}
|
|
||||||
.carousel-caption h4,.carousel-caption p{color:#ffffff;line-height:20px;}
|
|
||||||
.carousel-caption h4{margin:0 0 5px;}
|
|
||||||
.carousel-caption p{margin-bottom:0;}
|
|
||||||
.hero-unit{padding:60px;margin-bottom:30px;background-color:#131517;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;}.hero-unit h1{margin-bottom:0;font-size:60px;line-height:1;color:inherit;letter-spacing:-1px;}
|
|
||||||
.hero-unit p{font-size:18px;font-weight:200;line-height:30px;color:inherit;}
|
|
||||||
.pull-right{float:right;}
|
|
||||||
.pull-left{float:left;}
|
|
||||||
.hide{display:none;}
|
|
||||||
.show{display:block;}
|
|
||||||
.invisible{visibility:hidden;}
|
|
||||||
.affix{position:fixed;}
|
|
||||||
label,input,button,select,textarea,.navbar .search-query:-moz-placeholder,.navbar .search-query::-webkit-input-placeholder{font-family:'Droid Sans',sans-serif;color:#999999;}
|
|
||||||
code,pre{background-color:#eeeeee;}
|
|
||||||
blockquote{border-left:5px solid #33b5e5;}blockquote.pull-right{border-right:5px solid #33b5e5;}
|
|
||||||
html{min-height:100%;}
|
|
||||||
body{min-height:100%;background-color:#121417;background-image:-moz-linear-gradient(top, #060606, #060606);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#060606), to(#060606));background-image:-webkit-linear-gradient(top, #060606, #060606);background-image:-o-linear-gradient(top, #060606, #060606);background-image:linear-gradient(to bottom, #060606, #060606);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff060606', endColorstr='#ff252a30', GradientType=0);}
|
|
||||||
.page-header{border-bottom:2px solid #33b5e5;}
|
|
||||||
.navbar{font-size:16px;}.navbar .navbar-inner{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;border-bottom:2px solid #33b5e5;}
|
|
||||||
.navbar .brand{padding:12px 20px 11px;color:#eeeeee;font-weight:normal;text-shadow:none;}
|
|
||||||
.navbar li{line-height:19px;}
|
|
||||||
.navbar .nav>li>a{padding:13px 10px 8px;border-bottom:3px solid transparent;border-left:1px solid rgba(255, 255, 255, 0.1);}.navbar .nav>li>a:hover{border-bottom:3px solid #33b5e5;}
|
|
||||||
.navbar .nav>.active>a{border-bottom:3px solid #33b5e5;}
|
|
||||||
.navbar .nav .active>a,.navbar .nav .active>a:hover,.navbar .nav .active>a:focus{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
|
|
||||||
.navbar .nav>li>.dropdown-menu::before,.navbar .nav>li>.dropdown-menu::after{display:none;}
|
|
||||||
.navbar .dropdown-menu li>a:hover,.navbar .dropdown-menu li>a:focus,.navbar .dropdown-submenu:hover>a{background-image:none;}
|
|
||||||
.navbar .navbar-text{margin-left:15px;margin-right:15px;line-height:43px;}
|
|
||||||
.navbar .search-query,.navbar .search-query:focus,.navbar .search-query.focused{color:#adafae;text-shadow:none;background-color:#222;-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;}.navbar .search-query:-moz-placeholder,.navbar .search-query:focus:-moz-placeholder,.navbar .search-query.focused:-moz-placeholder{color:#999999;}
|
|
||||||
.navbar .search-query:-ms-input-placeholder,.navbar .search-query:focus:-ms-input-placeholder,.navbar .search-query.focused:-ms-input-placeholder{color:#999999;}
|
|
||||||
.navbar .search-query::-webkit-input-placeholder,.navbar .search-query:focus::-webkit-input-placeholder,.navbar .search-query.focused::-webkit-input-placeholder{color:#999999;}
|
|
||||||
.navbar-inverse .navbar-inner{border:none;border-bottom:3px solid #000000;}
|
|
||||||
.navbar-inverse .brand:hover{border-bottom:none;background-color:#000000;}
|
|
||||||
.navbar-inverse .nav li>a:hover{border-bottom-color:transparent;}
|
|
||||||
.navbar-inverse .nav .active>a{border-bottom-color:transparent;}
|
|
||||||
@media (max-width:979px){.navbar .nav-collapse .nav li>a{border:none;color:#eeeeee;font-weight:normal;text-shadow:none;}.navbar .nav-collapse .nav li>a:hover{border:none;background-color:#33b5e5;} .navbar .nav-collapse .nav .active>a{border:none;background-color:#33b5e5;} .navbar .nav-collapse .dropdown-menu a:hover{background-color:#33b5e5;} .navbar .nav-collapse .navbar-form,.navbar .nav-collapse .navbar-search{border-top:none;border-bottom:none;} .navbar .nav-collapse .nav-header{color:rgba(128, 128, 128, 0.6);} .navbar-inverse .nav-collapse .nav li>a:hover{background-color:#111;} .navbar-inverse .nav-collapse .nav .active>a{background-color:#111;} .navbar-inverse .nav-collapse .nav li.dropdown.open>.dropdown-toggle,.navbar-inverse .nav-collapse .nav li.dropdown.active>.dropdown-toggle,.navbar-inverse .nav-collapse .nav li.dropdown.open.active>.dropdown-toggle{background-color:#111;}}div.subnav{position:static;background-color:#020202;background-image:none;border:0;}div.subnav.subnav-fixed{position:relative;left:-1px;top:auto;}
|
|
||||||
div.subnav .nav>li>a,div.subnav .nav .active a{background-color:#020202;border-left:1px solid #222;border-right:0;color:#eeeeee;}
|
|
||||||
div.subnav .nav li.nav-header{text-shadow:none;}
|
|
||||||
div.subnav .nav>li>a:hover,div.subnav .nav>li.active>a:hover,div.subnav .nav>li:first-child>a:hover{background:transparent;border-bottom:2px solid #33b5e5;border-left:1px solid #222;color:#ffffff;}
|
|
||||||
div.subnav .nav .open .dropdown-toggle{border:0;border-left:1px solid #222;border-bottom:2px solid #33b5e5;background-color:#060606;}
|
|
||||||
div.subnav .nav .open .dropdown-menu{background-color:#020202;border-left:solid 1px rgba(255, 255, 255, 0.1);}div.subnav .nav .open .dropdown-menu li>a:hover{border-bottom:0;background:#33b5e5;}
|
|
||||||
.nav-tabs{border-bottom:1px solid #222;}.nav-tabs li>a:hover,.nav-tabs li.active>a,.nav-tabs li.active>a:hover{border:1px solid #222;background-color:#33b5e5;color:#ffffff;}
|
|
||||||
.nav-tabs .open .dropdown-toggle{background-color:#060606 !important;border:1px solid #222;}
|
|
||||||
.nav-tabs .dropdown-menu li>a:hover{border:none;}
|
|
||||||
.nav-pills li>a:hover{background-color:#33b5e5;color:#ffffff;}
|
|
||||||
.nav-pills .open .dropdown-toggle{background-color:#060606;}
|
|
||||||
.nav-pills .dropdown-menu li>a:hover{border:none;}
|
|
||||||
.nav-list li>a{text-shadow:none;}
|
|
||||||
.nav-list li>a:hover{background-color:#33b5e5;color:#ffffff;}
|
|
||||||
.nav-list .nav-header{text-shadow:none;}
|
|
||||||
.nav-list .divider{background-color:transparent;border-bottom:1px solid #222;}
|
|
||||||
.nav-stacked li>a{border:1px solid #222 !important;}
|
|
||||||
.nav-stacked li>a:hover,.nav-stacked li.active>a{background-color:#33b5e5;color:#ffffff;}
|
|
||||||
.tabbable .nav-tabs,.tabbable .nav-tabs li.active>a{border-color:#222;}
|
|
||||||
.breadcrumb{background-color:transparent;background-image:none;border-width:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;font-size:14px;}.breadcrumb li{text-shadow:none;}
|
|
||||||
.breadcrumb li>a{color:#33b5e5;text-shadow:none;}
|
|
||||||
.pagination ul{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
|
|
||||||
.pagination ul>li>a,.pagination ul>li>span{border:0;font-size:14px;}
|
|
||||||
.pagination ul>li>a:hover{background-color:#33b5e5;color:#ffffff;}
|
|
||||||
.pagination ul>.active>a,.pagination ul>.active>span{background-color:#33b5e5;color:#ffffff;}
|
|
||||||
.pagination ul>.disabled>a,.pagination ul>.disabled>a:hover,.pagination ul>.disabled>span,.pagination ul>.disabled>span:hover{background-color:rgba(0, 0, 0, 0.2);}
|
|
||||||
.pager a{background-color:#060606;border:none;}.pager a:hover{background-color:#33b5e5;}
|
|
||||||
.pager .disabled a,.pager .disabled a:hover{background-color:#060606;}
|
|
||||||
.btn{-webkit-box-shadow:1px 1px 2px #111111;-moz-box-shadow:1px 1px 2px #111111;box-shadow:1px 1px 2px #111111;color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#5c5c5c;background-image:-moz-linear-gradient(top, #666666, #4d4d4d);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#666666), to(#4d4d4d));background-image:-webkit-linear-gradient(top, #666666, #4d4d4d);background-image:-o-linear-gradient(top, #666666, #4d4d4d);background-image:linear-gradient(to bottom, #666666, #4d4d4d);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff666666', endColorstr='#ff4d4d4d', GradientType=0);border-color:#4d4d4d #4d4d4d #262626;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#4d4d4d;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);color:#ffffff;text-shadow:none;}.btn:hover,.btn:active,.btn.active,.btn.disabled,.btn[disabled]{color:#ffffff;background-color:#4d4d4d;*background-color:#404040;}
|
|
||||||
.btn:active,.btn.active{background-color:#333333 \9;}
|
|
||||||
.btn:hover{text-shadow:none;color:#ffffff;}
|
|
||||||
.btn-primary{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#008ab8;background-image:-moz-linear-gradient(top, #0099cc, #007399);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#0099cc), to(#007399));background-image:-webkit-linear-gradient(top, #0099cc, #007399);background-image:-o-linear-gradient(top, #0099cc, #007399);background-image:linear-gradient(to bottom, #0099cc, #007399);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0099cc', endColorstr='#ff007399', GradientType=0);border-color:#007399 #007399 #00394d;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#007399;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-primary:hover,.btn-primary:active,.btn-primary.active,.btn-primary.disabled,.btn-primary[disabled]{color:#ffffff;background-color:#007399;*background-color:#006080;}
|
|
||||||
.btn-primary:active,.btn-primary.active{background-color:#004d66 \9;}
|
|
||||||
.btn-warning{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#ff961f;background-image:-moz-linear-gradient(top, #ffa033, #ff8800);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ffa033), to(#ff8800));background-image:-webkit-linear-gradient(top, #ffa033, #ff8800);background-image:-o-linear-gradient(top, #ffa033, #ff8800);background-image:linear-gradient(to bottom, #ffa033, #ff8800);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffa033', endColorstr='#ffff8800', GradientType=0);border-color:#ff8800 #ff8800 #b35f00;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#ff8800;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-warning:hover,.btn-warning:active,.btn-warning.active,.btn-warning.disabled,.btn-warning[disabled]{color:#ffffff;background-color:#ff8800;*background-color:#e67a00;}
|
|
||||||
.btn-warning:active,.btn-warning.active{background-color:#cc6d00 \9;}
|
|
||||||
.btn-danger{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#eb0000;background-image:-moz-linear-gradient(top, #ff0000, #cc0000);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ff0000), to(#cc0000));background-image:-webkit-linear-gradient(top, #ff0000, #cc0000);background-image:-o-linear-gradient(top, #ff0000, #cc0000);background-image:linear-gradient(to bottom, #ff0000, #cc0000);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffff0000', endColorstr='#ffcc0000', GradientType=0);border-color:#cc0000 #cc0000 #800000;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#cc0000;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-danger:hover,.btn-danger:active,.btn-danger.active,.btn-danger.disabled,.btn-danger[disabled]{color:#ffffff;background-color:#cc0000;*background-color:#b30000;}
|
|
||||||
.btn-danger:active,.btn-danger.active{background-color:#990000 \9;}
|
|
||||||
.btn-success{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#7ab800;background-image:-moz-linear-gradient(top, #88cc00, #669900);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#88cc00), to(#669900));background-image:-webkit-linear-gradient(top, #88cc00, #669900);background-image:-o-linear-gradient(top, #88cc00, #669900);background-image:linear-gradient(to bottom, #88cc00, #669900);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff88cc00', endColorstr='#ff669900', GradientType=0);border-color:#669900 #669900 #334d00;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#669900;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-success:hover,.btn-success:active,.btn-success.active,.btn-success.disabled,.btn-success[disabled]{color:#ffffff;background-color:#669900;*background-color:#558000;}
|
|
||||||
.btn-success:active,.btn-success.active{background-color:#446600 \9;}
|
|
||||||
.btn-info{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#292929;background-image:-moz-linear-gradient(top, #333333, #191919);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#333333), to(#191919));background-image:-webkit-linear-gradient(top, #333333, #191919);background-image:-o-linear-gradient(top, #333333, #191919);background-image:linear-gradient(to bottom, #333333, #191919);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff333333', endColorstr='#ff191919', GradientType=0);border-color:#191919 #191919 #000000;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#191919;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-info:hover,.btn-info:active,.btn-info.active,.btn-info.disabled,.btn-info[disabled]{color:#ffffff;background-color:#191919;*background-color:#0d0d0d;}
|
|
||||||
.btn-info:active,.btn-info.active{background-color:#000000 \9;}
|
|
||||||
.btn-inverse{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#9f3fcf;background-image:-moz-linear-gradient(top, #a347d1, #9933cc);background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#a347d1), to(#9933cc));background-image:-webkit-linear-gradient(top, #a347d1, #9933cc);background-image:-o-linear-gradient(top, #a347d1, #9933cc);background-image:linear-gradient(to bottom, #a347d1, #9933cc);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffa347d1', endColorstr='#ff9933cc', GradientType=0);border-color:#9933cc #9933cc #6b248f;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);*background-color:#9933cc;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);}.btn-inverse:hover,.btn-inverse:active,.btn-inverse.active,.btn-inverse.disabled,.btn-inverse[disabled]{color:#ffffff;background-color:#9933cc;*background-color:#8a2eb8;}
|
|
||||||
.btn-inverse:active,.btn-inverse.active{background-color:#7a29a3 \9;}
|
|
||||||
.btn .caret{border-top:4px solid black;opacity:0.3;}
|
|
||||||
.btn-group>.dropdown-menu>li>a:hover{border-bottom:0;}
|
|
||||||
.btn.disabled,.btn[disabled]{background-color:#adafae;}
|
|
||||||
input,textarea,select{border-width:2px;-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;}
|
|
||||||
legend,label{color:#999999;border-bottom:0px solid #222;}
|
|
||||||
input,textarea,select,.uneditable-input{color:#282828;}
|
|
||||||
input[disabled],select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly],.uneditable-input{background-color:#555;border-color:#444;}
|
|
||||||
input:focus,textarea:focus,input.focused,textarea.focused{border-color:#52a8ec;outline:0;outline:thin dotted \9;}
|
|
||||||
input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus,select:focus{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;}
|
|
||||||
.form-actions{border-top:1px solid #222;}
|
|
||||||
.table{-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;}.table tbody tr.success td{background-color:#669900;color:#ffffff;}
|
|
||||||
.table tbody tr.error td{background-color:#cc0000;color:#ffffff;}
|
|
||||||
.table tbody tr.info td{background-color:#33b5e5;color:#ffffff;}
|
|
||||||
.dropdown-menu{background-color:#191A1A;-webkit-box-shadow:0 2px 4px rgba(0, 0, 0, 0.8);-moz-box-shadow:0 2px 4px rgba(0, 0, 0, 0.8);box-shadow:0 2px 4px rgba(0, 0, 0, 0.8);}
|
|
||||||
.dropdown-menu li>a:hover{background-color:#33b5e5;}
|
|
||||||
.alert,.alert .alert-heading,.alert-success,.alert-success .alert-heading,.alert-danger,.alert-error,.alert-danger .alert-heading,.alert-error .alert-heading,.alert-info,.alert-info .alert-heading{color:#eeeeee;text-shadow:none;border:none;}
|
|
||||||
.label{color:#eeeeee;}
|
|
||||||
.label,.alert{background-color:#666666;}
|
|
||||||
.label:hover{background-color:#4d4d4d;}
|
|
||||||
.label-important,.alert-danger,.alert-error{background-color:#cc0000;}
|
|
||||||
.label-important:hover{background-color:#990000;}
|
|
||||||
.label-warning{background-color:#cc6d00;}
|
|
||||||
.label-warning:hover{background-color:#995200;}
|
|
||||||
.label-success,.alert-success{background-color:#5c8a00;}
|
|
||||||
.label-success:hover{background-color:#3a5700;}
|
|
||||||
.label-info,.alert-info{background-color:#007399;}
|
|
||||||
.label-info:hover{background-color:#004d66;}
|
|
||||||
.well,.hero-unit{-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;}
|
|
||||||
.well,.hero-unit{border-top:solid 1px #353535;-webkit-box-shadow:0 2px 4px rgba(0, 0, 0, 0.8);-moz-box-shadow:0 2px 4px rgba(0, 0, 0, 0.8);box-shadow:0 2px 4px rgba(0, 0, 0, 0.8);}
|
|
||||||
.thumbnail{border-color:#222;}
|
|
||||||
.progress{background-color:#060606;background-image:none;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
|
|
||||||
.modal{-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;border-top:solid 1px #353535;background-color:#282828;}
|
|
||||||
.modal-header{border-bottom:1px solid #222;}
|
|
||||||
.modal-footer{background-color:#282828;border-top:1px solid #222;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
|
|
||||||
.footer{border-top:1px solid #222;}
|
|
||||||
@media (max-width:768px){div.subnav .nav>li+li>a,div.subnav .nav>li:first-child>a{border-top:1px solid #222;border-left:1px solid #222;} .subnav .nav>li+li>a:hover,.subnav .nav>li:first-child>a:hover{border-bottom:0;background-color:#33b5e5;}}.pull-right{float:right;}
|
|
||||||
.pull-left{float:left;}
|
|
||||||
.hide{display:none;}
|
|
||||||
.show{display:block;}
|
|
||||||
.invisible{visibility:hidden;}
|
|
||||||
.affix{position:fixed;}
|
|
||||||
|
|
||||||
body{font-size: 130%;}
|
|
File diff suppressed because one or more lines are too long
|
@ -1,105 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<title>stringification</title>
|
|
||||||
<xmp theme="united" style="display:none;">
|
|
||||||
|
|
||||||
## String conversions
|
|
||||||
|
|
||||||
**doctest** needs to be able to convert types you use in assertions and logging expressions into strings (for logging and reporting purposes).
|
|
||||||
Most built-in types are supported out of the box but there are three ways that you can tell **doctest** how to convert your own types (or other, third-party types) into strings.
|
|
||||||
|
|
||||||
For stringifying enums checkout [this issue](https://github.com/onqtam/doctest/issues/121).
|
|
||||||
|
|
||||||
## ```operator<<``` overload for ```std::ostream```
|
|
||||||
|
|
||||||
This is the standard way of providing string conversions in C++ - and the chances are you may already provide this for your own purposes. If you're not familiar with this idiom it involves writing a free function of the form:
|
|
||||||
|
|
||||||
```
|
|
||||||
std::ostream& operator<< (std::ostream& os, const T& value) {
|
|
||||||
os << convertMyTypeToString(value);
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
(where ```T``` is your type and ```convertMyTypeToString``` is where you'll write whatever code is necessary to make your type printable - it doesn't have to be in another function).
|
|
||||||
|
|
||||||
You should put this function in the same namespace as your type.
|
|
||||||
|
|
||||||
Alternatively you may prefer to write it as a member function:
|
|
||||||
|
|
||||||
```
|
|
||||||
std::ostream& T::operator<<(std::ostream& os) const {
|
|
||||||
os << convertMyTypeToString(*this);
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## ```doctest::toString``` overload
|
|
||||||
|
|
||||||
If you don't want to provide an ```operator<<``` overload, or you want to convert your type differently for testing purposes, you can provide an overload for ```toString()``` for your type which returns ```doctest::String```.
|
|
||||||
|
|
||||||
```
|
|
||||||
namespace user {
|
|
||||||
struct udt {};
|
|
||||||
|
|
||||||
doctest::String toString(const udt& value) {
|
|
||||||
return convertMyTypeToString(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Note that the function must be in the same namespace as your type. If the type is not in any namespace - then the overload should be in the global namespace as well. ```convertMyTypeToString``` is where you'll write whatever code is necessary to make your type printable.
|
|
||||||
|
|
||||||
## ```doctest::StringMaker<T>``` specialisation
|
|
||||||
|
|
||||||
There are some cases where overloading ```toString``` does not work as expected. Specialising ```StringMaker<T>``` gives you more precise and reliable control - but at the cost of slightly more code and complexity:
|
|
||||||
|
|
||||||
```
|
|
||||||
namespace doctest {
|
|
||||||
template<> struct StringMaker<T> {
|
|
||||||
static String convert(const T& value) {
|
|
||||||
return convertMyTypeToString(value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Translating exceptions
|
|
||||||
|
|
||||||
By default all exceptions deriving from ```std::exception``` will be translated to strings by calling the ```what()``` method (also C strings). For exception types that do not derive from ```std::exception``` - or if ```what()``` does not return a suitable string - use ```REGISTER_EXCEPTION_TRANSLATOR```. This defines a function that takes your exception type and returns a ```doctest::String```. It can appear anywhere in the code - it doesn't have to be in the same translation unit. For example:
|
|
||||||
|
|
||||||
```
|
|
||||||
REGISTER_EXCEPTION_TRANSLATOR(MyType& ex) {
|
|
||||||
return doctest::String(ex.message());
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Note that the exception may be accepted without a reference but it is considered bad practice in C++.
|
|
||||||
|
|
||||||
An alternative way to register an exception translator is to do the following in some function - before executing any tests:
|
|
||||||
|
|
||||||
```
|
|
||||||
// adding a lambda - the signature required is `doctest::String(exception_type)`
|
|
||||||
doctest::registerExceptionTranslator<int>([](int in){ return doctest::toString(in); });
|
|
||||||
```
|
|
||||||
|
|
||||||
The order of registering exception translators can be controlled - simply call the explicit function in the required order or list the exception translators with the macro in a top-to-bottom fashion in a single translation unit - everything that auto-registers in doctest works in a top-to-bottom way for a single translation unit (source file).
|
|
||||||
|
|
||||||
You could also [override the translation mechanism](https://github.com/catchorg/Catch2/issues/539#issuecomment-454549904) for exceptions deriving from ```std::exception```.
|
|
||||||
|
|
||||||
------
|
|
||||||
|
|
||||||
- Check out the [**example**](../../examples/all_features/stringification.cpp) which shows how to stringify ```std::vector<T>``` and other types/exceptions.
|
|
||||||
- Note that the type ```String``` is used when specializing ```StringMaker<T>``` or overloading ```toString()``` - it is the string type **doctest** works with. ```std::string``` is not an option because doctest would have to include the ```<string>``` header.
|
|
||||||
- To support the ```operator<<(std::ostream&...``` stringification the library has to offer a forward declaration of ```std::ostream``` and that is what the library does - but it is forbidden by the standard. It currently works everywhere - on all tested compilers - but if the user wishes to be 100% standards compliant - then the [**```DOCTEST_CONFIG_USE_STD_HEADERS```**](configuration.html#doctest_config_use_std_headers) identifier can be used to force the inclusion of ```<iosfwd>```. The reason the header is not included by default is that on MSVC (for example) it drags a whole bunch of stuff with it - and after the preprocessor is finished the translation unit has grown to 42k lines of C++ code - while Clang and the libc++ are so well implemented that including ```<iosfwd>``` there results in 400 lines of code.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
[Home](readme.html#reference)
|
|
||||||
|
|
||||||
<p align="center"><img src="../../scripts/data/logo/icon_2.svg"></p>
|
|
||||||
|
|
||||||
|
|
||||||
</xmp>
|
|
||||||
<script src="strapdown.js/strapdown.js"></script>
|
|
||||||
</html>
|
|
|
@ -1,182 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<title>testcases</title>
|
|
||||||
<xmp theme="united" style="display:none;">
|
|
||||||
|
|
||||||
## Test cases
|
|
||||||
|
|
||||||
While **doctest** fully supports the traditional, xUnit, style of class-based fixtures containing test case methods this is not the preferred style. Instead **doctest** provides a powerful mechanism for nesting subcases within a test case. For a more detailed discussion and examples see the [**tutorial**](tutorial.html#test-cases-and-subcases).
|
|
||||||
|
|
||||||
Test cases and subcases are very easy to use in practice:
|
|
||||||
|
|
||||||
* **TEST_CASE(** _test name_ **)**
|
|
||||||
* **SUBCASE(** _subcase name_ **)**
|
|
||||||
|
|
||||||
_test name_ and _subcase name_ are free form, quoted, strings. Test names don't have to be unique within the **doctest** executable. They should also be string literals.
|
|
||||||
|
|
||||||
It is possible to write test cases inside of class bodies in C++17 with the help of ```TEST_CASE_CLASS()``` - used just like ```TEST_CASE()``` - making testing private parts of classes easier.
|
|
||||||
|
|
||||||
Keep in mind that even though **doctest** is [**thread-safe**](faq.html#is-doctest-thread-aware) - using subcases has to be done only in the main test runner thread.
|
|
||||||
|
|
||||||
Test cases can also be parameterized - see the [**documentation**](parameterized-tests.html)
|
|
||||||
|
|
||||||
Test cases and subcases can be filtered through the use of the [**command line**](commandline.html)
|
|
||||||
|
|
||||||
## BDD-style test cases
|
|
||||||
|
|
||||||
In addition to **doctest**'s take on the classic style of test cases, **doctest** supports an alternative syntax that allow tests to be written as "executable specifications" (one of the early goals of [Behaviour Driven Development](http://dannorth.net/introducing-bdd/)). This set of macros map on to ```TEST_CASE```s and ```SUBCASE```s, with a little internal support to make them smoother to work with.
|
|
||||||
|
|
||||||
* **SCENARIO(** _scenario name_ **)**
|
|
||||||
|
|
||||||
This macro maps onto ```TEST_CASE``` and works in the same way, except that the test case name will be prefixed by "Scenario: "
|
|
||||||
|
|
||||||
* **SCENARIO_TEMPLATE(** _scenario name_, _type_, _list of types_ **)**
|
|
||||||
|
|
||||||
This macro maps onto ```TEST_CASE_TEMPLATE``` and works in the same way, except that the test case name will be prefixed by "Scenario: "
|
|
||||||
|
|
||||||
* **SCENARIO_TEMPLATE_DEFINE(** _scenario name_, _type_, _id_ **)**
|
|
||||||
|
|
||||||
This macro maps onto ```TEST_CASE_TEMPLATE_DEFINE``` and works in the same way, except that the test case name will be prefixed by "Scenario: "
|
|
||||||
|
|
||||||
* **GIVEN(** _something_ **)**
|
|
||||||
* **WHEN(** _something_ **)**
|
|
||||||
* **THEN(** _something_ **)**
|
|
||||||
|
|
||||||
These macros map onto ```SUBCASE```s except that the subcase names are the _something_s prefixed by "given: ", "when: " or "then: " respectively.
|
|
||||||
|
|
||||||
* **AND_WHEN(** _something_ **)**
|
|
||||||
* **AND_THEN(** _something_ **)**
|
|
||||||
|
|
||||||
Similar to ```WHEN``` and ```THEN``` except that the prefixes start with "and ". These are used to chain ```WHEN```s and ```THEN```s together.
|
|
||||||
|
|
||||||
When any of these macros are used the console reporter recognises them and formats the test case header such that the Givens, Whens and Thens are aligned to aid readability.
|
|
||||||
|
|
||||||
Other than the additional prefixes and the formatting in the console reporter these macros behave exactly as ```TEST_CASE```s and ```SUBCASE```s. As such there is nothing enforcing the correct sequencing of these macros - that's up to the programmer!
|
|
||||||
|
|
||||||
Note that when using the [`--test-case=<filters>`](https://github.com/onqtam/doctest/blob/master/doc/markdown/commandline.html) command line option (or `--subcase=<filters>`) you will have to pass the prefix `Scenario: ` as well.
|
|
||||||
|
|
||||||
## Test fixtures
|
|
||||||
|
|
||||||
Although **doctest** allows you to group tests together as subcases within a test case, it can still be convenient, sometimes, to group them using a more traditional test fixture. **doctest** fully supports this too. You define the test fixture as a simple structure:
|
|
||||||
|
|
||||||
```
|
|
||||||
class UniqueTestsFixture {
|
|
||||||
private:
|
|
||||||
static int uniqueID;
|
|
||||||
protected:
|
|
||||||
DBConnection conn;
|
|
||||||
public:
|
|
||||||
UniqueTestsFixture() : conn(DBConnection::createConnection("myDB")) {}
|
|
||||||
protected:
|
|
||||||
int getID() {
|
|
||||||
return ++uniqueID;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
int UniqueTestsFixture::uniqueID = 0;
|
|
||||||
|
|
||||||
TEST_CASE_FIXTURE(UniqueTestsFixture, "Create Employee/No Name") {
|
|
||||||
REQUIRE_THROWS(conn.executeSQL("INSERT INTO employee (id, name) VALUES (?, ?)", getID(), ""));
|
|
||||||
}
|
|
||||||
TEST_CASE_FIXTURE(UniqueTestsFixture, "Create Employee/Normal") {
|
|
||||||
REQUIRE(conn.executeSQL("INSERT INTO employee (id, name) VALUES (?, ?)", getID(), "Joe Bloggs"));
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The two test cases here will create uniquely-named derived classes of UniqueTestsFixture and thus can access the `getID()` protected method and `conn` member variables. This ensures that both the test cases are able to create a DBConnection using the same method (DRY principle) and that any ID's created are unique such that the order that tests are executed does not matter.
|
|
||||||
|
|
||||||
## Test suites
|
|
||||||
|
|
||||||
Test cases can be grouped into test suites. This is done with ```TEST_SUITE()``` or ```TEST_SUITE_BEGIN()``` / ```TEST_SUITE_END()```.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
```
|
|
||||||
TEST_CASE("") {} // not part of any test suite
|
|
||||||
|
|
||||||
TEST_SUITE("math") {
|
|
||||||
TEST_CASE("") {} // part of the math test suite
|
|
||||||
TEST_CASE("") {} // part of the math test suite
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_SUITE_BEGIN("utils");
|
|
||||||
|
|
||||||
TEST_CASE("") {} // part of the utils test suite
|
|
||||||
|
|
||||||
TEST_SUITE_END();
|
|
||||||
|
|
||||||
TEST_CASE("") {} // not part of any test suite
|
|
||||||
```
|
|
||||||
|
|
||||||
Then test cases from specific test suites can be executed with the help of filters - check out the [**command line**](commandline.html)
|
|
||||||
|
|
||||||
## Decorators
|
|
||||||
|
|
||||||
Test cases can be *decorated* with additional attributes like this:
|
|
||||||
|
|
||||||
```
|
|
||||||
TEST_CASE("name"
|
|
||||||
* doctest::description("shouldn't take more than 500ms")
|
|
||||||
* doctest::timeout(0.5)) {
|
|
||||||
// asserts
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Multiple decorators can be used at the same time. These are the currently supported decorators:
|
|
||||||
|
|
||||||
- **```skip(bool = true)```** - marks the test case to be skipped from execution - unless the ```--no-skip``` option is used
|
|
||||||
- **```no_breaks(bool = true)```** - no breaking into the debugger for asserts in the test case - useful in combination with `may_fail`/`should_fail`/`expected_failures`
|
|
||||||
- **```no_output(bool = true)```** - no output from asserts in the test case - useful in combination with `may_fail`/`should_fail`/`expected_failures`
|
|
||||||
- **```may_fail(bool = true)```** - doesn't fail the test if any given assertion fails (but still reports it) - this can be useful to flag a work-in-progress, or a known issue that you don't want to immediately fix but still want to track in the your tests
|
|
||||||
- **```should_fail(bool = true)```** - like **```may_fail()```** but fails the test if it passes - this can be useful if you want to be notified of accidental, or third-party, fixes
|
|
||||||
- **```expected_failures(int)```** - defines the number of assertions that are expected to fail within the test case - reported as failure when the number of failed assertions is different than the declared expected number of failures
|
|
||||||
- **```timeout(double)```** - fails the test case if its execution exceeds this limit (in seconds) - but doesn't terminate it - that would require subprocess support
|
|
||||||
- **```test_suite("name")```** - can be used on test cases to override (or just set) the test suite they are in
|
|
||||||
- **```description("text")```** - a description of the test case
|
|
||||||
|
|
||||||
The values that the decorators take are computed while registering the test cases (during global initialization) - before entering ```main()``` and not just before running them.
|
|
||||||
|
|
||||||
Decorators can also be applied to test suite blocks and all test cases in that block inherit them:
|
|
||||||
|
|
||||||
```
|
|
||||||
TEST_SUITE("some TS" * doctest::description("all tests will have this")) {
|
|
||||||
TEST_CASE("has a description from the surrounding test suite") {
|
|
||||||
// asserts
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TEST_SUITE("some TS") {
|
|
||||||
TEST_CASE("no description even though in the same test suite as the one above") {
|
|
||||||
// asserts
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Test cases can override the decorators that they inherit from their surrounding test suite:
|
|
||||||
|
|
||||||
```
|
|
||||||
TEST_SUITE("not longer than 500ms" * doctest::timeout(0.5)) {
|
|
||||||
TEST_CASE("500ms limit") {
|
|
||||||
// asserts
|
|
||||||
}
|
|
||||||
TEST_CASE("200ms limit" * doctest::timeout(0.2)) {
|
|
||||||
// asserts
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
------
|
|
||||||
|
|
||||||
- Check out the [**subcases and BDD example**](../../examples/all_features/subcases.cpp)
|
|
||||||
- Check out the [**assertion macros example**](../../examples/all_features/assertion_macros.cpp) to see how test suites are used
|
|
||||||
- Tests are registered from top to bottom of each processed cpp after the headers have been preprocessed and included but there is no ordering between cpp files.
|
|
||||||
|
|
||||||
---------------
|
|
||||||
|
|
||||||
[Home](readme.html#reference)
|
|
||||||
|
|
||||||
<p align="center"><img src="../../scripts/data/logo/icon_2.svg"></p>
|
|
||||||
|
|
||||||
|
|
||||||
</xmp>
|
|
||||||
<script src="strapdown.js/strapdown.js"></script>
|
|
||||||
</html>
|
|
|
@ -1,215 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<title>tutorial</title>
|
|
||||||
<xmp theme="united" style="display:none;">
|
|
||||||
|
|
||||||
## Tutorial
|
|
||||||
|
|
||||||
To get started with **doctest** all you need is to download the [**latest version**](https://raw.githubusercontent.com/onqtam/doctest/master/doctest/doctest.h) which is just a single header and include it in your source files (or add this repository as a git submodule).
|
|
||||||
|
|
||||||
This tutorial assumes you can use the header directly: ```#include "doctest.h"``` - so it is either in the same folder with your test source files or you have set up the include paths to it in your build system properly.
|
|
||||||
|
|
||||||
[TDD](https://en.wikipedia.org/wiki/Test-driven_development) is not discussed in this tutorial.
|
|
||||||
|
|
||||||
## A simple example
|
|
||||||
|
|
||||||
Suppose we have a ```factorial()``` function that we want to test:
|
|
||||||
|
|
||||||
```
|
|
||||||
int factorial(int number) { return number <= 1 ? number : factorial(number - 1) * number; }
|
|
||||||
```
|
|
||||||
|
|
||||||
A complete compiling example with a self-registering test looks like this:
|
|
||||||
|
|
||||||
```
|
|
||||||
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
|
|
||||||
#include "doctest.h"
|
|
||||||
|
|
||||||
int factorial(int number) { return number <= 1 ? number : factorial(number - 1) * number; }
|
|
||||||
|
|
||||||
TEST_CASE("testing the factorial function") {
|
|
||||||
CHECK(factorial(1) == 1);
|
|
||||||
CHECK(factorial(2) == 2);
|
|
||||||
CHECK(factorial(3) == 6);
|
|
||||||
CHECK(factorial(10) == 3628800);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
This will compile to a complete executable which responds to command line arguments. If you just run it with no arguments it will execute all test cases (in this case - just one), report any failures, report a summary of how many tests passed and failed and returns 0 on success and 1 if anything failed (useful if you just want a yes/no answer to: "did it work").
|
|
||||||
|
|
||||||
If you run this as written it will pass. Everything is good. Right? Well there is still a bug here. We missed to check if ```factorial(0) == 1``` so lets add that check as well:
|
|
||||||
|
|
||||||
```
|
|
||||||
TEST_CASE("testing the factorial function") {
|
|
||||||
CHECK(factorial(0) == 1);
|
|
||||||
CHECK(factorial(1) == 1);
|
|
||||||
CHECK(factorial(2) == 2);
|
|
||||||
CHECK(factorial(3) == 6);
|
|
||||||
CHECK(factorial(10) == 3628800);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Now we get a failure - something like:
|
|
||||||
|
|
||||||
```
|
|
||||||
test.cpp(7) FAILED!
|
|
||||||
CHECK( factorial(0) == 1 )
|
|
||||||
with expansion:
|
|
||||||
CHECK( 0 == 1 )
|
|
||||||
```
|
|
||||||
|
|
||||||
Note that we get the actual return value of ```factorial(0)``` printed for us (0) - even though we used a natural expression with the ```==``` operator. That lets us immediately see what the problem is.
|
|
||||||
|
|
||||||
Let's change the factorial function to:
|
|
||||||
|
|
||||||
```
|
|
||||||
int factorial(int number) { return number > 1 ? factorial(number - 1) * number : 1; }
|
|
||||||
```
|
|
||||||
|
|
||||||
Now all the tests pass.
|
|
||||||
|
|
||||||
Of course there are still more issues to do deal with. For example we'll hit problems when the return value starts to exceed the range of an int. With factorials that can happen quite quickly. You might want to add tests for such cases and decide how to handle them. We'll stop short of doing that here.
|
|
||||||
|
|
||||||
## What did we do here?
|
|
||||||
|
|
||||||
Although this was a simple test it's been enough to demonstrate a few things about how **doctest** is used.
|
|
||||||
|
|
||||||
1. All we did was ```#define``` one identifier and ```#include``` one header and we got everything - even an implementation of ```main()``` that will respond to command line arguments. You can only use that ```#define``` in one source file for (hopefully) obvious reasons. Once you have more than one file with unit tests in you'll just ```#include "doctest.h"``` and go. Usually it's a good idea to have a dedicated implementation file that just has ```#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN``` and ```#include "doctest.h"```. You can also provide your own implementation of main and drive **doctest** yourself - see [**supplying your own ```main()```**](main.html).
|
|
||||||
2. We introduce test cases with the ```TEST_CASE``` macro. It takes one argument - a free form test name (for more see [**Test cases and subcases**](testcases.html)). The test name doesn't have to be unique. You can run sets of tests by specifying a wildcarded test name or a tag expression. See the [**command line**](commandline.html) docs for more information on running tests.
|
|
||||||
3. The name is just a string. We haven't had to declare a function or method - or explicitly register the test case anywhere. Behind the scenes a function with a generated name is defined for you and automatically registered using static registry classes. By abstracting the function name away we can name our tests without the constraints of identifier names.
|
|
||||||
4. We write our individual test assertions using the ```CHECK()``` macro. Rather than a separate macro for each type of condition (equal, less than, greater than, etc.) we express the condition naturally using C++ syntax. Behind the scenes a simple expression template captures the left-hand-side and right-hand-side of the expression so we can display the values in our test report. There are other [**assertion macros**](assertions.html) not covered in this tutorial - but because of this technique the number of them is drastically reduced.
|
|
||||||
|
|
||||||
## Test cases and subcases
|
|
||||||
|
|
||||||
Most test frameworks have a class-based fixture mechanism - test cases map to methods on a class and common setup and teardown can be performed in ```setup()``` and ```teardown()``` methods (or constructor/ destructor in languages like C++ that support deterministic destruction).
|
|
||||||
|
|
||||||
While **doctest** fully supports this way of working there are a few problems with the approach. In particular the way your code must be split up and the blunt granularity of it may cause problems. You can only have one setup/ teardown pair across a set of methods but sometimes you want slightly different setup in each method or you may even want several levels of setup (a concept which we will clarify later on in this tutorial). It was [**problems like these**](http://jamesnewkirk.typepad.com/posts/2007/09/why-you-should-.html) that led James Newkirk who led the team that built NUnit to start again from scratch and build [**xUnit**](http://jamesnewkirk.typepad.com/posts/2007/09/announcing-xuni.html)).
|
|
||||||
|
|
||||||
**doctest** takes a different approach (to both NUnit and xUnit) that is a more natural fit for C++ and the C family of languages.
|
|
||||||
|
|
||||||
This is best explained through an example:
|
|
||||||
|
|
||||||
```
|
|
||||||
TEST_CASE("vectors can be sized and resized") {
|
|
||||||
std::vector<int> v(5);
|
|
||||||
|
|
||||||
REQUIRE(v.size() == 5);
|
|
||||||
REQUIRE(v.capacity() >= 5);
|
|
||||||
|
|
||||||
SUBCASE("adding to the vector increases it's size") {
|
|
||||||
v.push_back(1);
|
|
||||||
|
|
||||||
CHECK(v.size() == 6);
|
|
||||||
CHECK(v.capacity() >= 6);
|
|
||||||
}
|
|
||||||
SUBCASE("reserving increases just the capacity") {
|
|
||||||
v.reserve(6);
|
|
||||||
|
|
||||||
CHECK(v.size() == 5);
|
|
||||||
CHECK(v.capacity() >= 6);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
For each ```SUBCASE()``` the ```TEST_CASE()``` is executed from the start - so as we enter each subcase we know that the size is 5 and the capacity is at least 5. We enforce those requirements with the ```REQUIRE()``` macros at the top level so we can be confident in them. If a ```CHECK()``` fails - the test is marked as failed but the execution continues - but if a ```REQUIRE()``` fails - execution of the test stops.
|
|
||||||
|
|
||||||
This works because the ```SUBCASE()``` macro contains an if statement that calls back into **doctest** to see if the subcase should be executed. One leaf subcase is executed on each run through a ```TEST_CASE()```. The other subcases are skipped. Next time the next subcase is executed and so on until no new subcases are encountered.
|
|
||||||
|
|
||||||
So far so good - this is already an improvement on the setup/teardown approach because now we see our setup code inline and use the stack. The power of subcases really shows when we start nesting them like in the example below:
|
|
||||||
|
|
||||||
<table><tr><td>
|
|
||||||
Code
|
|
||||||
</td><td>
|
|
||||||
Output
|
|
||||||
</td></tr><tr><td>
|
|
||||||
<pre lang="c++">
|
|
||||||
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
|
|
||||||
#include "doctest.h"
|
|
||||||
<br>
|
|
||||||
#include <iostream>
|
|
||||||
using namespace std;
|
|
||||||
<br>
|
|
||||||
TEST_CASE("lots of nested subcases") {
|
|
||||||
cout << endl << "root" << endl;
|
|
||||||
SUBCASE("") {
|
|
||||||
cout << "1" << endl;
|
|
||||||
SUBCASE("") { cout << "1.1" << endl; }
|
|
||||||
}
|
|
||||||
SUBCASE("") {
|
|
||||||
cout << "2" << endl;
|
|
||||||
SUBCASE("") { cout << "2.1" << endl; }
|
|
||||||
SUBCASE("") {
|
|
||||||
cout << "2.2" << endl;
|
|
||||||
SUBCASE("") {
|
|
||||||
cout << "2.2.1" << endl;
|
|
||||||
SUBCASE("") { cout << "2.2.1.1" << endl; }
|
|
||||||
SUBCASE("") { cout << "2.2.1.2" << endl; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SUBCASE("") { cout << "2.3" << endl; }
|
|
||||||
SUBCASE("") { cout << "2.4" << endl; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</pre>
|
|
||||||
</td><td width="400">
|
|
||||||
<pre lang="">
|
|
||||||
root
|
|
||||||
1
|
|
||||||
1.1<br>
|
|
||||||
root
|
|
||||||
2
|
|
||||||
2.1<br>
|
|
||||||
root
|
|
||||||
2
|
|
||||||
2.2
|
|
||||||
2.2.1
|
|
||||||
2.2.1.1<br>
|
|
||||||
root
|
|
||||||
2
|
|
||||||
2.2
|
|
||||||
2.2.1
|
|
||||||
2.2.1.2<br>
|
|
||||||
root
|
|
||||||
2
|
|
||||||
2.3<br>
|
|
||||||
root
|
|
||||||
2
|
|
||||||
2.4
|
|
||||||
</pre>
|
|
||||||
</td></tr></table>
|
|
||||||
|
|
||||||
Subcases can be nested to an arbitrary depth (limited only by your stack size). Each leaf subcase (a subcase that contains no nested subcases) will be executed exactly once on a separate path of execution from any other leaf subcase (so no leaf subcase can interfere with another). A fatal failure in a parent subcase will prevent nested subcases from running - but then that's the idea.
|
|
||||||
|
|
||||||
Keep in mind that even though **doctest** is [**thread-safe**](faq.html#is-doctest-thread-aware) - using subcases has to be done only in the main test runner thread and all threads spawned in a subcase ought to be joined before the end of that subcase and no new subcases should be entered while other threads with doctest assertions in them are still running.
|
|
||||||
|
|
||||||
## Scaling up
|
|
||||||
|
|
||||||
To keep the tutorial simple we put all our code in a single file. This is fine to get started - and makes jumping into **doctest** even quicker and easier. This is not really the best approach when you start writing more real-world tests.
|
|
||||||
|
|
||||||
The requirement is that the following block of code ([**or equivalent**](main.html)):
|
|
||||||
|
|
||||||
```
|
|
||||||
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
|
|
||||||
#include "doctest.h"
|
|
||||||
```
|
|
||||||
|
|
||||||
appears in _exactly_ one translation unit (source file). Use as many additional source files as you need for your tests - partitioned however makes most sense for your way of working. Each additional file needs only to ```#include "doctest.h"``` - do not repeat the ```#define```!
|
|
||||||
|
|
||||||
In fact it is usually a good idea to put the block with the ```#define``` in it's own source file.
|
|
||||||
|
|
||||||
## Next steps
|
|
||||||
|
|
||||||
This has been a brief introduction to get you up and running with **doctest** and to point out some of the key differences between **doctest** and other frameworks you may already be familiar with. This will get you going quite far already and you are now in a position to dive in and write some tests.
|
|
||||||
|
|
||||||
Of course there is more to learn - see the ever-growing [**reference**](readme.html#reference) section for what's available.
|
|
||||||
|
|
||||||
---------------
|
|
||||||
|
|
||||||
[Home](readme.html#reference)
|
|
||||||
|
|
||||||
<p align="center"><img src="../../scripts/data/logo/icon_2.svg"></p>
|
|
||||||
|
|
||||||
|
|
||||||
</xmp>
|
|
||||||
<script src="strapdown.js/strapdown.js"></script>
|
|
||||||
</html>
|
|
|
@ -1,163 +0,0 @@
|
||||||
## Assertion macros
|
|
||||||
|
|
||||||
Most test frameworks have a large collection of assertion macros to capture all possible conditional forms (```_EQUALS```, ```_NOTEQUALS```, ```_GREATER_THAN``` etc).
|
|
||||||
|
|
||||||
**doctest** is different (but it's like [**Catch**](https://github.com/catchorg/Catch2) in this regard). Because it decomposes comparison expressions most of these forms are reduced to one or two that you will use all the time. That said, there is a rich set of auxiliary macros as well.
|
|
||||||
|
|
||||||
There are 3 levels of assert severity for all assertion macros:
|
|
||||||
|
|
||||||
- ```REQUIRE``` - this level will immediately quit the test case if the assert fails and will mark the test case as failed.
|
|
||||||
- ```CHECK``` - this level will mark the test case as failed if the assert fails but will continue with the test case.
|
|
||||||
- ```WARN``` - this level will only print a message if the assert fails but will not mark the test case as failed.
|
|
||||||
|
|
||||||
The ```CHECK``` level is mostly useful if you have a series of essentially orthogonal assertions and it is useful to see all the results rather than stopping at the first failure.
|
|
||||||
|
|
||||||
All asserts evaluate the expressions only once and if they fail - the values are [**stringified**](stringification.md) properly.
|
|
||||||
|
|
||||||
Since **doctest** is [**thread-safe**](faq.md#is-doctest-thread-aware) all asserts and [**logging**](logging.md) macros can be used in threads spawned from test cases.
|
|
||||||
|
|
||||||
Note that the ```REQUIRE``` level of asserts uses exceptions to end the current test case. It might be dangerous to use this level of asserts inside destructors of user-defined classes - if a destructor is called during stack unwinding due to an exception and a ```REQUIRE``` assert fails then the program will terminate. Also since C++11 all destructors are by default ```noexcept(true)``` unless specified otherwise so such an assert will lead to ```std::terminate()``` being called.
|
|
||||||
|
|
||||||
## Expression decomposing asserts
|
|
||||||
|
|
||||||
These are of the form ```CHECK(expression)``` (Same for ```REQUIRE``` and ```WARN```).
|
|
||||||
|
|
||||||
```expression``` can be a binary comparison like ```a == b``` or just a single thing like ```vec.isEmpty()```.
|
|
||||||
|
|
||||||
If an exception is thrown it is caught, reported, and counted as a failure (unless the assert is of level ```WARN```).
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
```c++
|
|
||||||
CHECK(flags == state::alive | state::moving);
|
|
||||||
CHECK(thisReturnsTrue());
|
|
||||||
REQUIRE(i < 42);
|
|
||||||
```
|
|
||||||
|
|
||||||
- Negating asserts - ```<LEVEL>_FALSE(expression)``` - evaluates the expression and records the _logical NOT_ of the result.
|
|
||||||
|
|
||||||
These forms exist as a workaround for the fact that ```!``` prefixed expressions cannot be decomposed properly.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```c++
|
|
||||||
REQUIRE_FALSE(thisReturnsFalse());
|
|
||||||
```
|
|
||||||
|
|
||||||
- Using the [**```DOCTEST_CONFIG_SUPER_FAST_ASSERTS```**](configuration.md#doctest_config_super_fast_asserts) config option can make compilation of asserts up to [**31-63%**](benchmarks.md#cost-of-an-assertion-macro) faster!
|
|
||||||
- These asserts also have a ```_MESSAGE``` form - like ```CHECK_MESSAGE(expression, message)``` which is basically a code block ```{}``` with a scoped [**```INFO()```**](logging.md#info) logging macro together with the ```CHECK``` macro - that way the message will be relevant only to that assert. The binary/unary asserts don't have this variation yet.
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
```c++
|
|
||||||
INFO("this is relevant to all asserts, and here is some var: ", local);
|
|
||||||
|
|
||||||
CHECK_MESSAGE(a < b, "relevant only to this assert ", other_local, " more text!");
|
|
||||||
|
|
||||||
CHECK(b < c); // here only the first INFO() will be relevant
|
|
||||||
```
|
|
||||||
|
|
||||||
For more information about the ```INFO()``` macro visit the [logging page](logging.md).
|
|
||||||
|
|
||||||
## Binary and unary asserts
|
|
||||||
|
|
||||||
These asserts don't use templates to decompose the comparison expressions for the left and right parts.
|
|
||||||
|
|
||||||
These have the same guarantees as the expression decomposing ones but [**57-68% faster**](benchmarks.md#cost-of-an-assertion-macro) for compilation.
|
|
||||||
|
|
||||||
```<LEVEL>``` is one of 3 possible: ```REQUIRE```/```CHECK```/```WARN```.
|
|
||||||
|
|
||||||
- ```<LEVEL>_EQ(left, right)``` - same as ```<LEVEL>(left == right)```
|
|
||||||
- ```<LEVEL>_NE(left, right)``` - same as ```<LEVEL>(left != right)```
|
|
||||||
- ```<LEVEL>_GT(left, right)``` - same as ```<LEVEL>(left > right)```
|
|
||||||
- ```<LEVEL>_LT(left, right)``` - same as ```<LEVEL>(left < right)```
|
|
||||||
- ```<LEVEL>_GE(left, right)``` - same as ```<LEVEL>(left >= right)```
|
|
||||||
- ```<LEVEL>_LE(left, right)``` - same as ```<LEVEL>(left <= right)```
|
|
||||||
- ```<LEVEL>_UNARY(expr)``` - same as ```<LEVEL>(expr)```
|
|
||||||
- ```<LEVEL>_UNARY_FALSE(expr)``` - same as ```<LEVEL>_FALSE(expr)```
|
|
||||||
|
|
||||||
Using the [**```DOCTEST_CONFIG_SUPER_FAST_ASSERTS```**](configuration.md#doctest_config_super_fast_asserts) config option can make the binary asserts to compile up to [**84-91%**](benchmarks.md#cost-of-an-assertion-macro) faster!
|
|
||||||
|
|
||||||
## Exceptions
|
|
||||||
|
|
||||||
```<LEVEL>``` is one of 3 possible: ```REQUIRE```/```CHECK```/```WARN```.
|
|
||||||
|
|
||||||
- ```<LEVEL>_THROWS(expression)```
|
|
||||||
|
|
||||||
Expects that an exception (of any type) is thrown during evaluation of the expression.
|
|
||||||
|
|
||||||
- ```<LEVEL>_THROWS_AS(expression, exception_type)```
|
|
||||||
|
|
||||||
Expects that an exception of the _specified type_ is thrown during evaluation of the expression.
|
|
||||||
|
|
||||||
Note that ```const``` and ```&``` are added to the exception type if missing (users shouldn't care) - the standard practice for exceptions in C++ is ```Throw by value, catch by (const) reference```.
|
|
||||||
|
|
||||||
```c++
|
|
||||||
CHECK_THROWS_AS(func(), const std::exception&);
|
|
||||||
CHECK_THROWS_AS(func(), std::exception); // same as above
|
|
||||||
```
|
|
||||||
|
|
||||||
- ```<LEVEL>_THROWS_WITH(expression, c_string)```
|
|
||||||
|
|
||||||
Expects that an exception is thrown during evaluation of the expression and is successfully translated to the _specified c string_ (see [**translating exceptions**](stringification.md#translating-exceptions)).
|
|
||||||
|
|
||||||
```c++
|
|
||||||
CHECK_THROWS_WITH(func(), "invalid operation!");
|
|
||||||
```
|
|
||||||
|
|
||||||
- ```<LEVEL>_THROWS_WITH_AS(expression, c_string, exception_type)```
|
|
||||||
|
|
||||||
This is a combination of ```<LEVEL>_THROWS_WITH``` and ```<LEVEL>_THROWS_AS```.
|
|
||||||
|
|
||||||
```c++
|
|
||||||
CHECK_THROWS_WITH_AS(func(), "invalid operation!", std::runtime_error);
|
|
||||||
```
|
|
||||||
|
|
||||||
- ```<LEVEL>_NOTHROW(expression)```
|
|
||||||
|
|
||||||
Expects that no exception is thrown during evaluation of the expression.
|
|
||||||
|
|
||||||
Note that these asserts also have a ```_MESSAGE``` form - like ```CHECK_THROWS_MESSAGE(expression, message)``` - these work identically to the ```_MESSAGE``` form of the normal macros (```CHECK_MESSAGE(a < b, "this shouldn't fail")```) described earlier.
|
|
||||||
|
|
||||||
One may use the [**```DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS```**](configuration.md#doctest_config_void_cast_expressions) config identifier to cast the expression in these asserts to void to avoid warnings or other issues - for example nodiscard statements whose result isn't checked. This will however limit the ability to write entire ```{}``` blocks of code as the expression (or multiple statements) but in that case a simple lambda can be used. This should have been the default behavior from day 1 of the framework...
|
|
||||||
|
|
||||||
## Using asserts out of a testing context
|
|
||||||
|
|
||||||
Asserts can be used outside of a testing context (in code not called from a ```TEST_CASE()```) instead of [```assert()```](https://en.cppreference.com/w/cpp/error/assert).
|
|
||||||
|
|
||||||
A ```doctest::Context``` object still has to be created somewhere and set as the default one using the ```setAsDefaultForAssertsOutOfTestCases()``` method - and then asserts will work. A handler can be registered by calling the ```setAssertHandler()``` method on the context object. If no handler is set then ```std::abort()``` is called on failure.
|
|
||||||
|
|
||||||
The results would be best when using the [**```DOCTEST_CONFIG_SUPER_FAST_ASSERTS```**](configuration.md#doctest_config_super_fast_asserts) config identifier.
|
|
||||||
|
|
||||||
Checkout the [**example**](../../examples/all_features/asserts_used_outside_of_tests.cpp) showcasing how that is done. For more information see the [**issue for the feature request**](https://github.com/onqtam/doctest/issues/114).
|
|
||||||
|
|
||||||
Currently [**logging macros**](logging.md) cannot be used for extra context for asserts outside of a test run. That means that the ```_MESSAGE``` variants of asserts are also not usable - since they are just a packed ```INFO()``` with an assert right after it.
|
|
||||||
|
|
||||||
## Floating point comparisons
|
|
||||||
|
|
||||||
When comparing floating point numbers - especially if at least one of them has been computed - great care must be taken to allow for rounding errors and inexact representations.
|
|
||||||
|
|
||||||
**doctest** provides a way to perform tolerant comparisons of floating point values through the use of a wrapper class called ```doctest::Approx```. ```doctest::Approx``` can be used on either side of a comparison expression. It overloads the comparisons operators to take a relative tolerance into account. Here's a simple example:
|
|
||||||
|
|
||||||
```c++
|
|
||||||
REQUIRE(performComputation() == doctest::Approx(2.1));
|
|
||||||
```
|
|
||||||
|
|
||||||
By default a small epsilon value (relative - in percentages) is used that covers many simple cases of rounding errors. When this is insufficient the epsilon value (the amount within which a difference either way is ignored) can be specified by calling the ```epsilon()``` method on the ```doctest::Approx``` instance. e.g.:
|
|
||||||
|
|
||||||
```c++
|
|
||||||
REQUIRE(22.0/7 == doctest::Approx(3.141).epsilon(0.01)); // allow for a 1% error
|
|
||||||
```
|
|
||||||
|
|
||||||
When dealing with very large or very small numbers it can be useful to specify a scale, which can be achieved by calling the ```scale()``` method on the ```doctest::Approx``` instance.
|
|
||||||
|
|
||||||
--------
|
|
||||||
|
|
||||||
- Check out the [**example**](../../examples/all_features/assertion_macros.cpp) which shows many of these macros
|
|
||||||
- Do not wrap assertion macros in ```try```/```catch``` - the REQUIRE macros throw exceptions to end the test case execution!
|
|
||||||
|
|
||||||
---------------
|
|
||||||
|
|
||||||
[Home](readme.md#reference)
|
|
||||||
|
|
||||||
<p align="center"><img src="../../scripts/data/logo/icon_2.svg"></p>
|
|
|
@ -1,202 +0,0 @@
|
||||||
# Benchmarks
|
|
||||||
|
|
||||||
The benchmarks are done with [**this**](../../scripts/bench/bench.py) script using CMake. There are 3 benchmarking scenarios:
|
|
||||||
|
|
||||||
- [the cost of including the header](#cost-of-including-the-header)
|
|
||||||
- [the cost of an assertion macro](#cost-of-an-assertion-macro)
|
|
||||||
- [runtime speed of lots of asserts](#runtime-benchmarks)
|
|
||||||
|
|
||||||
Compilers used:
|
|
||||||
|
|
||||||
- WINDOWS: Microsoft Visual Studio Community 2017 - Version 15.8.1+28010.2003
|
|
||||||
- WINDOWS: gcc 8.1.0 (x86_64-posix-seh-rev0, Built by MinGW-W64 project)
|
|
||||||
- LINUX: gcc 6.3.0 20170406 (Ubuntu 6.3.0-12ubuntu2)
|
|
||||||
- LINUX: clang 4.0.0-1 (tags/RELEASE_400/rc1) Target: x86_64-pc-linux-gnu
|
|
||||||
|
|
||||||
Environment used (Intel i7 3770k, 16g RAM):
|
|
||||||
|
|
||||||
- Windows 7 - on an SSD
|
|
||||||
- Ubuntu 17.04 in a VirtualBox VM - on a HDD
|
|
||||||
|
|
||||||
**doctest** version: 2.2.0 (released on 2018.12.02)
|
|
||||||
|
|
||||||
[**Catch**](https://github.com/catchorg/Catch2) version: 2.3.0 (released on 2018.07.22)
|
|
||||||
|
|
||||||
# Compile time benchmarks
|
|
||||||
|
|
||||||
## Cost of including the header
|
|
||||||
|
|
||||||
This is a benchmark that is relevant only to single header and header only frameworks - like **doctest** and [**Catch**](https://github.com/catchorg/Catch2).
|
|
||||||
|
|
||||||
The script generates 201 source files and in 200 of them makes a function in the form of ```int f135() { return 135; }``` and in ```main.cpp``` it forward declares all the 200 such dummy functions and accumulates their result to return from the ```main()``` function. This is done to ensure that all source files are built and that the linker doesn't remove/optimize anything.
|
|
||||||
|
|
||||||
- **baseline** - how much time the source files need for a single threaded build with ```msbuild```/```make```
|
|
||||||
- **+ implement** - only in ```main.cpp``` the header is included with a ```#define``` before it so the test runner gets implemented:
|
|
||||||
|
|
||||||
```c++
|
|
||||||
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
|
|
||||||
#include "doctest.h"
|
|
||||||
```
|
|
||||||
- **+ header everywhere** - the framework header is also included in all the other source files
|
|
||||||
- **+ disabled** - remove everything testing-related from the binary
|
|
||||||
|
|
||||||
| doctest | baseline | + implement | + header everywhere | + disabled |
|
|
||||||
|---------------------|----------|-------------|---------------------|------------|
|
|
||||||
| MSVC Debug | 4.89 | 6.21 | 8.33 | 6.39 |
|
|
||||||
| MSVC Release | 4.38 | 6.39 | 8.71 | 6.02 |
|
|
||||||
| MinGW GCC Debug | 8.12 | 10.86 | 14.73 | 10.17 |
|
|
||||||
| MinGW GCC Release | 8.21 | 11.11 | 15.03 | 10.71 |
|
|
||||||
| Linux GCC Debug | 4.20 | 6.23 | 9.81 | 6.24 |
|
|
||||||
| Linux GCC Release | 4.29 | 6.93 | 11.05 | 6.76 |
|
|
||||||
| Linux Clang Debug | 8.70 | 10.02 | 14.43 | 11.13 |
|
|
||||||
| Linux Clang Release | 9.30 | 11.68 | 16.20 | 11.58 |
|
|
||||||
|
|
||||||
| Catch | baseline | + implement | + header everywhere | + disabled |
|
|
||||||
|---------------------|----------|-------------|---------------------|------------|
|
|
||||||
| MSVC Debug | 4.82 | 7.83 | 88.85 | 88.72 |
|
|
||||||
| MSVC Release | 4.38 | 9.97 | 87.17 | 88.35 |
|
|
||||||
| MinGW GCC Debug | 8.00 | 57.28 | 137.28 | 132.73 |
|
|
||||||
| MinGW GCC Release | 8.38 | 22.94 | 97.17 | 97.22 |
|
|
||||||
| Linux GCC Debug | 4.42 | 15.57 | 97.94 | 97.18 |
|
|
||||||
| Linux GCC Release | 4.50 | 19.59 | 99.48 | 100.75 |
|
|
||||||
| Linux Clang Debug | 8.76 | 15.60 | 107.99 | 110.61 |
|
|
||||||
| Linux Clang Release | 9.32 | 25.75 | 118.67 | 117.11 |
|
|
||||||
|
|
||||||
<img src="../../scripts/data/benchmarks/header.png" width="410" align="right">
|
|
||||||
<img src="../../scripts/data/benchmarks/implement.png" width="410">
|
|
||||||
|
|
||||||
### Conclusion
|
|
||||||
|
|
||||||
#### doctest
|
|
||||||
|
|
||||||
- instantiating the test runner in one source file costs ~1-3 seconds ```implement - baseline```
|
|
||||||
- the inclusion of ```doctest.h``` in one source file costs between 11ms - 23ms ```(header_everywhere - implement) / 200```
|
|
||||||
- including the library everywhere but everything disabled costs around 2 seconds ```disabled - baseline``` for 200 files
|
|
||||||
|
|
||||||
#### [Catch](https://github.com/catchorg/Catch2)
|
|
||||||
|
|
||||||
- instantiating the test runner in one source file costs ~3-50 seconds ```implement - baseline```
|
|
||||||
- the inclusion of ```catch.hpp``` in one source file costs between 380ms - 470ms ```(header_everywhere - implement) / 200```
|
|
||||||
- using the config option to disable the library (**```CATCH_CONFIG_DISABLE```**) has no effect on the header cost
|
|
||||||
|
|
||||||
----------
|
|
||||||
|
|
||||||
So if ```doctest.h``` costs 11ms and ```catch.hpp``` costs 400ms on MSVC - then the **doctest** header is >> **36** << times lighter (for MSVC)!
|
|
||||||
|
|
||||||
----------
|
|
||||||
|
|
||||||
The results are in seconds and are in **no way** intended to bash [**Catch**](https://github.com/catchorg/Catch2) - the **doctest** framework wouldn't exist without it.
|
|
||||||
|
|
||||||
The reason the **doctest** header is so light on compile times is because it forward declares everything and doesn't drag any headers in the source files (except for the source file where the test runner gets implemented). This was a key design decision.
|
|
||||||
|
|
||||||
## Cost of an assertion macro
|
|
||||||
|
|
||||||
The script generates 11 ```.cpp``` files and in 10 of them makes 50 test cases with 100 asserts in them (of the form ```CHECK(a==b)``` where ```a``` and ```b``` are always the same ```int``` variables) - **50k** asserts! The testing framework gets implemented in ```main.cpp```.
|
|
||||||
|
|
||||||
- **baseline** - how much time a single threaded build takes with the header included everywhere - no test cases or asserts!
|
|
||||||
- ```CHECK(a==b)``` - will add ```CHECK()``` asserts which decompose the expression with template machinery
|
|
||||||
|
|
||||||
**doctest** specific:
|
|
||||||
|
|
||||||
- **+fast 1** - will add [**```DOCTEST_CONFIG_SUPER_FAST_ASSERTS```**](configuration.md#doctest_config_super_fast_asserts) to speed up the compilation of the normal asserts ```CHECK(a==b)```
|
|
||||||
- ```CHECK_EQ(a,b)``` - will use ```CHECK_EQ(a,b)``` instead of the expression decomposing ones
|
|
||||||
- **+fast 2** - will add [**```DOCTEST_CONFIG_SUPER_FAST_ASSERTS```**](configuration.md#doctest_config_super_fast_asserts) to speed up the compilation of the binary asserts ```CHECK_EQ(a,b)```
|
|
||||||
- **+disabled** - all test case and assert macros will be disabled with [**```DOCTEST_CONFIG_DISABLE```**](configuration.md#doctest_config_disable)
|
|
||||||
|
|
||||||
[**Catch**](https://github.com/catchorg/Catch2) specific:
|
|
||||||
|
|
||||||
- **+fast** - will add [**```CATCH_CONFIG_FAST_COMPILE```**](https://github.com/catchorg/Catch2/blob/master/docs/configuration.md#catch_config_fast_compile) which speeds up the compilation of the normal asserts ```CHECK(a==b)```
|
|
||||||
- **+disabled** - all test case and assert macros will be disabled with **```CATCH_CONFIG_DISABLE```**
|
|
||||||
|
|
||||||
| doctest | baseline | ```CHECK(a==b)``` | +fast 1 | ```CHECK_EQ(a,b)``` | +fast 2 | +disabled |
|
|
||||||
|---------------------|----------|-------------------|---------|---------------------|---------|-----------|
|
|
||||||
| MSVC Debug | 2.69 | 27.37 | 10.37 | 17.17 | 4.82 | 1.91 |
|
|
||||||
| MSVC Release | 3.15 | 58.73 | 20.73 | 26.07 | 6.43 | 1.83 |
|
|
||||||
| MinGW GCC Debug | 3.78 | 97.29 | 43.05 | 59.86 | 11.88 | 1.67 |
|
|
||||||
| MinGW GCC Release | 4.09 | 286.70 | 95.42 | 156.73 | 18.16 | 2.03 |
|
|
||||||
| Linux GCC Debug | 2.39 | 91.36 | 41.92 | 52.26 | 10.16 | 1.32 |
|
|
||||||
| Linux GCC Release | 3.29 | 257.40 | 97.46 | 128.84 | 19.38 | 1.79 |
|
|
||||||
| Linux Clang Debug | 2.40 | 85.52 | 43.53 | 51.24 | 8.32 | 1.62 |
|
|
||||||
| Linux Clang Release | 3.40 | 160.65 | 79.34 | 81.52 | 11.90 | 1.82 |
|
|
||||||
|
|
||||||
And here is [**Catch**](https://github.com/catchorg/Catch2) which only has normal ```CHECK(a==b)``` asserts:
|
|
||||||
|
|
||||||
| Catch | baseline | ```CHECK(a==b)``` | +fast | +disabled |
|
|
||||||
|---------------------|----------|-------------------|-------|-----------|
|
|
||||||
| MSVC Debug | 8.20 | 31.22 | 25.54 | 8.22 |
|
|
||||||
| MSVC Release | 10.13 | 448.68 | 168.67 | 10.20 |
|
|
||||||
| MinGW GCC Debug | 53.54 | 152.38 | 131.85 | 49.07 |
|
|
||||||
| MinGW GCC Release | 19.26 | 590.16 | 466.69 | 18.99 |
|
|
||||||
| Linux GCC Debug | 15.05 | 117.30 | 95.33 | 14.79 |
|
|
||||||
| Linux GCC Release | 18.77 | 608.94 | 482.73 | 18.96 |
|
|
||||||
| Linux Clang Debug | 12.27 | 94.39 | 77.33 | 12.11 |
|
|
||||||
| Linux Clang Release | 20.75 | 545.84 | 506.02 | 20.15 |
|
|
||||||
|
|
||||||
<img src="../../scripts/data/benchmarks/asserts.png">
|
|
||||||
|
|
||||||
### Conclusion
|
|
||||||
|
|
||||||
**doctest**:
|
|
||||||
|
|
||||||
- is between 0 and 8 times faster than [**Catch**](https://github.com/catchorg/Catch2) when using normal expression decomposing ```CHECK(a==b)``` asserts
|
|
||||||
- asserts of the form ```CHECK_EQ(a,b)``` with no expression decomposition - around 31-63% faster than ```CHECK(a==b)```
|
|
||||||
- the [**```DOCTEST_CONFIG_SUPER_FAST_ASSERTS```**](configuration.md#doctest_config_super_fast_asserts) identifier makes the normal asserts faster by 57-68%
|
|
||||||
- the [**```DOCTEST_CONFIG_SUPER_FAST_ASSERTS```**](configuration.md#doctest_config_super_fast_asserts) identifier makes the binary asserts even faster by another 84-91%
|
|
||||||
- using the [**```DOCTEST_CONFIG_DISABLE```**](configuration.md#doctest_config_disable) identifier the asserts just disappear as if they were never written - even lower than the baseline (because most of the implementation is also gone)
|
|
||||||
|
|
||||||
[**Catch**](https://github.com/catchorg/Catch2):
|
|
||||||
|
|
||||||
- using [**```CATCH_CONFIG_FAST_COMPILE```**](https://github.com/catchorg/Catch2/blob/master/docs/configuration.md#catch_config_fast_compile) results in 10-30% faster build times for asserts (and in one case 73%).
|
|
||||||
- using the **```CATCH_CONFIG_DISABLE```** identifier provides the same great benefits for assert macros as the doctest version ([**```DOCTEST_CONFIG_DISABLE```**](configuration.md#doctest_config_disable)) - but not for the header cost
|
|
||||||
|
|
||||||
## Runtime benchmarks
|
|
||||||
|
|
||||||
The runtime benchmarks consist of a single test case with a loop of 10 million iterations performing the task - a single normal assert (using expression decomposition) or the assert + the logging of the loop iterator ```i```:
|
|
||||||
|
|
||||||
```c++
|
|
||||||
for(int i = 0; i < 10000000; ++i)
|
|
||||||
CHECK(i == i);
|
|
||||||
```
|
|
||||||
|
|
||||||
or
|
|
||||||
|
|
||||||
```c++
|
|
||||||
for(int i = 0; i < 10000000; ++i) {
|
|
||||||
INFO(i);
|
|
||||||
CHECK(i == i);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Note that the assert always passes - the goal should be to optimize for the common case - lots of passing test cases and a few that maybe fail.
|
|
||||||
|
|
||||||
| doctest | assert | + info | | Catch | assert | + info |
|
|
||||||
|---------------------|---------|---------|-|---------------------|---------|---------|
|
|
||||||
| MSVC Debug | 4.00 | 11.41 | | MSVC Debug | 5.60 | 213.91 |
|
|
||||||
| MSVC Release | 0.40 | 1.47 | | MSVC Release | 0.76 | 7.60 |
|
|
||||||
| MinGW GCC Debug | 1.05 | 2.93 | | MinGW GCC Debug | 1.17 | 9.54 |
|
|
||||||
| MinGW GCC Release | 0.34 | 1.27 | | MinGW GCC Release | 0.36 | 4.28 |
|
|
||||||
| Linux GCC Debug | 1.24 | 2.34 | | Linux GCC Debug | 1.44 | 9.69 |
|
|
||||||
| Linux GCC Release | 0.29 | 0.52 | | Linux GCC Release | 0.29 | 3.60 |
|
|
||||||
| Linux Clang Debug | 1.15 | 2.38 | | Linux Clang Debug | 1.21 | 9.91 |
|
|
||||||
| Linux Clang Release | 0.28 | 0.50 | | Linux Clang Release | 0.32 | 3.27 |
|
|
||||||
|
|
||||||
<img src="../../scripts/data/benchmarks/runtime_info.png" width="410" align="right">
|
|
||||||
<img src="../../scripts/data/benchmarks/runtime_assert.png" width="410">
|
|
||||||
|
|
||||||
### Conclusion
|
|
||||||
|
|
||||||
**doctest** is around ~20% faster than catch for asserts but a few times faster when also logging variables and context (and in the case of one particular compiler over 18 times faster).
|
|
||||||
|
|
||||||
----------
|
|
||||||
|
|
||||||
The bar charts were generated using [**this google spreadsheet**](https://docs.google.com/spreadsheets/d/1p3MAURUfPzKT7gtJOVuJU2_yVKSqkoD1nbypA1K3618) by pasting the data from the tables.
|
|
||||||
|
|
||||||
If you want a benchmark that is not synthetic - check out [**this blog post**](http://baptiste-wicht.com/posts/2016/09/blazing-fast-unit-test-compilation-with-doctest-11.html) of [**Baptiste Wicht**](https://github.com/wichtounet) who tested the compile times of the asserts in the 1.1 release with his [**Expression Templates Library**](https://github.com/wichtounet/etl)!
|
|
||||||
|
|
||||||
While reading the post - keep in mind that if a part of a process takes 50% of the time and is made 10000 times faster - the overall process would still be only roughly 50% faster.
|
|
||||||
|
|
||||||
---------------
|
|
||||||
|
|
||||||
[Home](readme.md#reference)
|
|
||||||
|
|
||||||
<p align="center"><img src="../../scripts/data/logo/icon_2.svg"></p>
|
|
|
@ -1,83 +0,0 @@
|
||||||
## Build systems
|
|
||||||
|
|
||||||
The latest released version of doctest can be obtained from here: https://raw.githubusercontent.com/onqtam/doctest/master/doctest/doctest.h
|
|
||||||
|
|
||||||
You can substitute ```master``` with ```dev``` or a tag like ```1.2.9``` for a specific version in the URL above.
|
|
||||||
|
|
||||||
### CMake
|
|
||||||
|
|
||||||
- **doctest** is easiest to use as a single file inside your own repository. Then the following minimal example will work:
|
|
||||||
|
|
||||||
```cmake
|
|
||||||
cmake_minimum_required(VERSION 3.0)
|
|
||||||
project(cmake_test VERSION 0.0.1 LANGUAGES CXX)
|
|
||||||
|
|
||||||
# Prepare doctest for other targets to use
|
|
||||||
find_package(doctest REQUIRED)
|
|
||||||
|
|
||||||
# Make test executable
|
|
||||||
add_executable(tests main.cpp)
|
|
||||||
target_compile_features(test PRIVATE cxx_std_17)
|
|
||||||
target_link_libraries(test PRIVATE doctest::doctest)
|
|
||||||
```
|
|
||||||
|
|
||||||
- You can also use the following CMake snippet to automatically fetch the entire **doctest** repository from github and configure it as an external project:
|
|
||||||
|
|
||||||
```cmake
|
|
||||||
include(ExternalProject)
|
|
||||||
find_package(Git REQUIRED)
|
|
||||||
|
|
||||||
ExternalProject_Add(
|
|
||||||
doctest
|
|
||||||
PREFIX ${CMAKE_BINARY_DIR}/doctest
|
|
||||||
GIT_REPOSITORY https://github.com/onqtam/doctest.git
|
|
||||||
TIMEOUT 10
|
|
||||||
UPDATE_COMMAND ${GIT_EXECUTABLE} pull
|
|
||||||
CONFIGURE_COMMAND ""
|
|
||||||
BUILD_COMMAND ""
|
|
||||||
INSTALL_COMMAND ""
|
|
||||||
LOG_DOWNLOAD ON
|
|
||||||
)
|
|
||||||
|
|
||||||
# Expose required variable (DOCTEST_INCLUDE_DIR) to parent scope
|
|
||||||
ExternalProject_Get_Property(doctest source_dir)
|
|
||||||
set(DOCTEST_INCLUDE_DIR ${source_dir}/doctest CACHE INTERNAL "Path to include folder for doctest")
|
|
||||||
```
|
|
||||||
|
|
||||||
And later you'll be able to use the doctest include directory like this:
|
|
||||||
|
|
||||||
```cmake
|
|
||||||
# add it globally
|
|
||||||
include_directories(${DOCTEST_INCLUDE_DIR})
|
|
||||||
|
|
||||||
# or per target
|
|
||||||
target_include_directories(my_target PUBLIC ${DOCTEST_INCLUDE_DIR})
|
|
||||||
```
|
|
||||||
|
|
||||||
- If you have the entire doctest repository available (as a submodule or just as files) you could also include it in your CMake build by using ```add_subdirectory(path/to/doctest)``` and then you could use it like this:
|
|
||||||
|
|
||||||
```cmake
|
|
||||||
add_executable(my_tests src_1.cpp src_2.cpp ...)
|
|
||||||
target_link_libraries(my_tests doctest)
|
|
||||||
```
|
|
||||||
|
|
||||||
- The ```CMakeLists.txt``` file of the doctest repository has ```install()``` commands so you could also use doctest as a package.
|
|
||||||
|
|
||||||
- To discover tests from an executable and register them in ctest you could use [```doctest_discover_tests(<target>)``` from scripts/cmake/doctest.cmake](../../scripts/cmake/doctest.cmake) - read the comments in the file on how to use it. It works just like [the same functionality in Catch](https://github.com/catchorg/Catch2/blob/master/docs/cmake-integration.md#automatic-test-registration).
|
|
||||||
|
|
||||||
### Package managers
|
|
||||||
|
|
||||||
**doctest** is available through the following package managers:
|
|
||||||
|
|
||||||
- vcpkg
|
|
||||||
- hunter
|
|
||||||
- conan
|
|
||||||
- https://bintray.com/bincrafters/public-conan/doctest:bincrafters
|
|
||||||
- https://bintray.com/mmha/conan/doctest%3Ammha
|
|
||||||
- Homebrew (`brew install doctest`)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
[Home](readme.md#reference)
|
|
||||||
|
|
||||||
<p align="center"><img src="../../scripts/data/logo/icon_2.svg"></p>
|
|
|
@ -1,133 +0,0 @@
|
||||||
## Command line
|
|
||||||
|
|
||||||
**doctest** works quite nicely without any command line options at all - but for more control a bunch are available.
|
|
||||||
|
|
||||||
**Query flags** - after the result is printed the program quits without executing any test cases (and if the framework is integrated into a client codebase which [**supplies it's own ```main()``` entry point**](main.md) - the program should check the result of ```shouldExit()``` method after calling ```run()``` on a ```doctest::Context``` object and should exit - this is left up to the user).
|
|
||||||
|
|
||||||
**Int/String options** - they require a value after the ```=``` sign - without spaces! For example: ```--order-by=rand```.
|
|
||||||
|
|
||||||
**Bool options** - they expect ```1```/```yes```/```on```/```true``` or ```0```/```no```/```off```/```false``` after the ```=``` sign - but they can also be used like flags and the ```=value``` part can be skipped - then ```true``` is assumed.
|
|
||||||
|
|
||||||
**Filters** - a comma-separated list of wildcards for matching values - where ```*``` means "match any sequence" and ```?``` means "match any one character".
|
|
||||||
To pass patterns with intervals use ```""``` like this: ```--test-case="*no sound*,vaguely named test number ?"```. Patterns that contain a comma can be escaped with ```\``` (example: ```--test-case=this\,test\,has\,commas```).
|
|
||||||
|
|
||||||
All the options can also be set with code (defaults/overrides) if the user [**supplies the ```main()``` function**](main.md).
|
|
||||||
|
|
||||||
| Query Flags | Description |
|
|
||||||
|:------------|-------------|
|
|
||||||
| ```-?``` ```--help``` ```-h``` | Prints a help message listing all these flags/options |
|
|
||||||
| ```-v``` ```--version``` | Prints the version of the **doctest** framework |
|
|
||||||
| ```-c``` ```--count``` | Prints the number of test cases matching the current filters (see below) |
|
|
||||||
| ```-ltc``` ```--list-test-cases``` | Lists all test cases by name which match the current filters (see below) |
|
|
||||||
| ```-lts``` ```--list-test-suites``` | Lists all test suites by name which have at least one test case matching the current filters (see below) |
|
|
||||||
| ```-lr``` ```--list-reporters``` | Lists all registered [**reporters**](reporters.md) |
|
|
||||||
| **Int/String Options** | <hr> |
|
|
||||||
| ```-tc``` ```--test-case=<filters>``` | Filters test cases based on their name. By default all test cases match but if a value is given to this filter like ```--test-case=*math*,*sound*``` then only test cases who match at least one of the patterns in the comma-separated list with wildcards will get executed/counted/listed |
|
|
||||||
| ```-tce``` ```--test-case-exclude=<filters>``` | Same as the ```-test-case=<filters>``` option but if any of the patterns in the comma-separated list of values matches - then the test case is skipped |
|
|
||||||
| ```-sf``` ```--source-file=<filters>``` | Same as ```--test-case=<filters>``` but filters based on the file in which test cases are written |
|
|
||||||
| ```-sfe``` ```--source-file-exclude=<filters>``` | Same as ```--test-case-exclude=<filters>``` but filters based on the file in which test cases are written |
|
|
||||||
| ```-ts``` ```--test-suite=<filters>``` | Same as ```--test-case=<filters>``` but filters based on the test suite in which test cases are in |
|
|
||||||
| ```-tse``` ```--test-suite-exclude=<filters>``` | Same as ```--test-case-exclude=<filters>``` but filters based on the test suite in which test cases are in |
|
|
||||||
| ```-sc``` ```--subcase=<filters>``` | Same as ```--test-case=<filters>``` but filters subcases based on their names. Does not filter test cases (they have to be executed for subcases to be discovered) so you might want to use this together with ```--test-case=<filters>```. |
|
|
||||||
| ```-sce``` ```--subcase-exclude=<filters>``` | Same as ```--test-case-exclude=<filters>``` but filters based on subcase names |
|
|
||||||
| ```-r``` ```--reporters=<filters>``` | List of [**reporters**](reporters.md) to use (default is ```console```) |
|
|
||||||
| ```-o``` ```--out=<string>``` | Output filename |
|
|
||||||
| ```-ob``` ```--order-by=<string>``` | Test cases will be sorted before being executed either by **the file in which they are** / **the test suite they are in** / **their name** / **random**. The possible values of ```<string>``` are ```file```/```suite```/```name```/```rand```/```none```. The default is ```file```. **NOTE: the order produced by the ```file```, ```suite``` and ```name``` options is compiler-dependent and might differ depending on the compiler used.** |
|
|
||||||
| ```-rs``` ```--rand-seed=<int>``` | The seed for random ordering |
|
|
||||||
| ```-f``` ```--first=<int>``` | The **first** test case to execute which passes the current filters - for range-based execution - see [**the example python script**](../../examples/range_based_execution.py) |
|
|
||||||
| ```-l``` ```--last=<int>``` | The **last** test case to execute which passes the current filters - for range-based execution - see [**the example python script**](../../examples/range_based_execution.py) |
|
|
||||||
| ```-aa``` ```--abort-after=<int>``` | The testing framework will stop executing test cases/assertions after this many failed assertions. The default is 0 which means don't stop at all. Note that the framework uses an exception to stop the current test case regardless of the level of the assert (```CHECK```/```REQUIRE```) - so be careful with asserts in destructors... |
|
|
||||||
| ```-scfl``` ```--subcase-filter-levels=<int>``` | Apply subcase filters only for the first ```<int>``` levels of nested subcases and just run the ones nested deeper. Default is a very high number which means *filter any subcase* |
|
|
||||||
| **Bool Options** | <hr> |
|
|
||||||
| ```-s``` ```--success=<bool>``` | To include successful assertions in the output |
|
|
||||||
| ```-cs``` ```--case-sensitive=<bool>``` | Filters being treated as case sensitive |
|
|
||||||
| ```-e``` ```--exit=<bool>``` | Exits after the tests finish - this is meaningful only when the client has [**provided the ```main()``` entry point**](main.md) - the program should check the ```shouldExit()``` method after calling ```run()``` on a ```doctest::Context``` object and should exit - this is left up to the user. The idea is to be able to execute just the tests in a client program and to not continue with it's execution |
|
|
||||||
| ```-d``` ```--duration=<bool>``` | Prints the time each test case took in seconds |
|
|
||||||
| ```-m``` ```--minimal=<bool>``` | Only prints failing tests |
|
|
||||||
| ```-q``` ```--quiet=<bool>``` | Does not print any output |
|
|
||||||
| ```-nt``` ```--no-throw=<bool>``` | Skips [**exceptions-related assertion**](assertions.md#exceptions) checks |
|
|
||||||
| ```-ne``` ```--no-exitcode=<bool>``` | Always returns a successful exit code - even if a test case has failed |
|
|
||||||
| ```-nr``` ```--no-run=<bool>``` | Skips all runtime **doctest** operations (except the test registering which happens before the program enters ```main()```). This is useful if the testing framework is integrated into a client codebase which has [**provided the ```main()``` entry point**](main.md) and the user wants to skip running the tests and just use the program |
|
|
||||||
| ```-ni``` ```--no-intro=<bool>``` | Omits the framework intro in the output |
|
|
||||||
| ```-nv``` ```--no-version=<bool>``` | Omits the framework version in the output |
|
|
||||||
| ```-nc``` ```--no-colors=<bool>``` | Disables colors in the output |
|
|
||||||
| ```-fc``` ```--force-colors=<bool>``` | Forces the use of colors even when a tty cannot be detected |
|
|
||||||
| ```-nb``` ```--no-breaks=<bool>``` | Disables breakpoints in debuggers when an assertion fails |
|
|
||||||
| ```-ns``` ```--no-skip=<bool>``` | Don't skip test cases marked as skip with a decorator |
|
|
||||||
| ```-gfl``` ```--gnu-file-line=<bool>``` | ```:n:``` vs ```(n):``` for line numbers in output (gnu mode is usually for linux tools/IDEs and is with the ```:``` separator) |
|
|
||||||
| ```-npf``` ```--no-path-filenames=<bool>``` | Paths are removed from the output when a filename is printed - useful if you want the same output from the testing framework on different environments |
|
|
||||||
| ```-nln``` ```--no-line-numbers=<bool>``` | Line numbers are replaced with ```0``` in the output when a source location is printed - useful if you want the same output from the testing framework even when test positions change within a source file |
|
|
||||||
| ```-ndo``` ```--no-debug-output=<bool>``` | Disables output in the debug console when a debugger is attached |
|
|
||||||
| | |
|
|
||||||
|
|
||||||
All the flags/options also come with a prefixed version (with ```--dt-``` at the front by default) - for example ```--version``` can be used also with ```--dt-version``` or ```--dt-v```.
|
|
||||||
|
|
||||||
The default prefix is ```--dt-```, but this can be changed by setting the [**```DOCTEST_CONFIG_OPTIONS_PREFIX```**](configuration.md#doctest_config_options_prefix) define.
|
|
||||||
|
|
||||||
All the unprefixed versions listed here can be disabled with the [**```DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS```**](configuration.md#doctest_config_no_unprefixed_options) define.
|
|
||||||
|
|
||||||
This is done for easy interoperability with client command line option handling when the testing framework is integrated within a client codebase - all **doctest** related flags/options can be prefixed so there are no clashes and so that the user can exclude everything starting with ```--dt-``` from their option parsing.
|
|
||||||
|
|
||||||
If there isn't an option to exclude those starting with ```--dt-``` then the ```dt_removed``` helper class might help to filter them out:
|
|
||||||
|
|
||||||
```c++
|
|
||||||
#define DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS
|
|
||||||
#define DOCTEST_CONFIG_IMPLEMENT
|
|
||||||
#include "doctest.h"
|
|
||||||
|
|
||||||
class dt_removed {
|
|
||||||
std::vector<const char*> vec;
|
|
||||||
public:
|
|
||||||
dt_removed(const char** argv_in) {
|
|
||||||
for(; *argv_in; ++argv_in)
|
|
||||||
if(strncmp(*argv_in, "--dt-", strlen("--dt-")) != 0)
|
|
||||||
vec.push_back(*argv_in);
|
|
||||||
vec.push_back(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
int argc() { return static_cast<int>(vec.size()) - 1; }
|
|
||||||
const char** argv() { return &vec[0]; } // Note: non-const char **:
|
|
||||||
};
|
|
||||||
|
|
||||||
int program(int argc, const char** argv);
|
|
||||||
|
|
||||||
int main(int argc, const char** argv) {
|
|
||||||
doctest::Context context(argc, argv);
|
|
||||||
int test_result = context.run(); // run queries, or run tests unless --no-run
|
|
||||||
|
|
||||||
if(context.shouldExit()) // honor query flags and --exit
|
|
||||||
return test_result;
|
|
||||||
|
|
||||||
dt_removed args(argv);
|
|
||||||
int app_result = program(args.argc(), args.argv());
|
|
||||||
|
|
||||||
return test_result + app_result; // combine the 2 results
|
|
||||||
}
|
|
||||||
|
|
||||||
int program(int argc, const char** argv) {
|
|
||||||
printf("Program: %d arguments received:\n", argc - 1);
|
|
||||||
while(*++argv)
|
|
||||||
printf("'%s'\n", *argv);
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
When ran like this:
|
|
||||||
|
|
||||||
```
|
|
||||||
program.exe --dt-test-case=math* --my-option -s --dt-no-breaks
|
|
||||||
```
|
|
||||||
|
|
||||||
Will output this:
|
|
||||||
|
|
||||||
```
|
|
||||||
Program: 2 arguments received:
|
|
||||||
'--my-option'
|
|
||||||
'-s'
|
|
||||||
```
|
|
||||||
|
|
||||||
---------------
|
|
||||||
|
|
||||||
[Home](readme.md#reference)
|
|
||||||
|
|
||||||
<p align="center"><img src="../../scripts/data/logo/icon_2.svg"></p>
|
|
|
@ -1,246 +0,0 @@
|
||||||
## Configuration
|
|
||||||
|
|
||||||
**doctest** is designed to "just work" as much as possible. It also allows configuring how it is built with a set of identifiers.
|
|
||||||
|
|
||||||
The identifiers should be defined before the inclusion of the framework header.
|
|
||||||
|
|
||||||
Defining something ```globally``` means for every source file of the binary (executable / shared object).
|
|
||||||
|
|
||||||
- [**```DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN```**](#doctest_config_implement_with_main)
|
|
||||||
- [**```DOCTEST_CONFIG_IMPLEMENT```**](#doctest_config_implement)
|
|
||||||
- [**```DOCTEST_CONFIG_DISABLE```**](#doctest_config_disable)
|
|
||||||
- [**```DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL```**](#doctest_config_implementation_in_dll)
|
|
||||||
- [**```DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES```**](#doctest_config_no_short_macro_names)
|
|
||||||
- [**```DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING```**](#doctest_config_treat_char_star_as_string)
|
|
||||||
- [**```DOCTEST_CONFIG_SUPER_FAST_ASSERTS```**](#doctest_config_super_fast_asserts)
|
|
||||||
- [**```DOCTEST_CONFIG_USE_STD_HEADERS```**](#doctest_config_use_std_headers)
|
|
||||||
- [**```DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS```**](#doctest_config_void_cast_expressions)
|
|
||||||
- [**```DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION```**](#doctest_config_no_comparison_warning_suppression)
|
|
||||||
- [**```DOCTEST_CONFIG_OPTIONS_PREFIX```**](#doctest_config_options_prefix)
|
|
||||||
- [**```DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS```**](#doctest_config_no_unprefixed_options)
|
|
||||||
- [**```DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS```**](#doctest_config_no_try_catch_in_asserts)
|
|
||||||
- [**```DOCTEST_CONFIG_NO_EXCEPTIONS```**](#doctest_config_no_exceptions)
|
|
||||||
- [**```DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS```**](#doctest_config_no_exceptions_but_with_all_asserts)
|
|
||||||
- [**```DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE```**](#doctest_config_assertion_parameters_by_value)
|
|
||||||
- [**```DOCTEST_CONFIG_COLORS_NONE```**](#doctest_config_colors_none)
|
|
||||||
- [**```DOCTEST_CONFIG_COLORS_WINDOWS```**](#doctest_config_colors_windows)
|
|
||||||
- [**```DOCTEST_CONFIG_COLORS_ANSI```**](#doctest_config_colors_ansi)
|
|
||||||
- [**```DOCTEST_CONFIG_WINDOWS_SEH```**](#doctest_config_windows_seh)
|
|
||||||
- [**```DOCTEST_CONFIG_NO_WINDOWS_SEH```**](#doctest_config_no_windows_seh)
|
|
||||||
- [**```DOCTEST_CONFIG_POSIX_SIGNALS```**](#doctest_config_posix_signals)
|
|
||||||
- [**```DOCTEST_CONFIG_NO_POSIX_SIGNALS```**](#doctest_config_no_posix_signals)
|
|
||||||
- [**```DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS```**](#doctest_config_include_type_traits)
|
|
||||||
- [**```DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS```**](#doctest_config_no_multi_lane_atomics)
|
|
||||||
|
|
||||||
For most people the only configuration needed is telling **doctest** which source file should host all the implementation code:
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN```**
|
|
||||||
|
|
||||||
```c++
|
|
||||||
#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN
|
|
||||||
#include "doctest.h"
|
|
||||||
```
|
|
||||||
|
|
||||||
This should be defined only in the source file where the library is implemented. It also creates a ```main()``` entry point.
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_IMPLEMENT```**
|
|
||||||
|
|
||||||
If the client wants to [**supply the ```main()``` function**](main.md) (either to set an option with some value from the code or to integrate the framework into their existing project codebase) this identifier should be used.
|
|
||||||
|
|
||||||
This should be defined only in the source file where the library is implemented.
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_DISABLE```**
|
|
||||||
|
|
||||||
One of the most most important configuration option - everything testing-related is removed from the binary - including most of the framework implementation and every test case written anywhere! This is one of the most unique features of **doctest**.
|
|
||||||
|
|
||||||
This should be defined globally.
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL```**
|
|
||||||
|
|
||||||
This will affect the public interface of doctest - all necessary forward declarations for writing tests will be turned into imported symbols. That way the test runner doesn't have to be implemented in the binary (executable / shared object) and can be reused from another binary where it is built and exported.
|
|
||||||
|
|
||||||
To export the test runner from a binary simply use [**```DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL```**](#doctest_config_implementation_in_dll) together with [**```DOCTEST_CONFIG_IMPLEMENT```**](#doctest_config_implement) (or [**```DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN```**](#doctest_config_implement_with_main) but then the other binaries will have to link to the executable) in whatever source file the test runner gets implemented into. Note that this identifier should not be defined in the other source files of the binary which exports the doctest test runner - or there will be linker conflicts - having the same symbols as both imported and exported within the same binary.
|
|
||||||
|
|
||||||
Checkout the [**example**](../../examples/executable_dll_and_plugin/) - it shows how to have the test runner implemented in a dll (and there are even tests in a plugin which is dynamically loaded).
|
|
||||||
|
|
||||||
This should be defined globally in binaries that import the symbols.
|
|
||||||
|
|
||||||
This should be defined only in the source file where the library is implemented for binaries that export the test runner.
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_NO_SHORT_MACRO_NAMES```**
|
|
||||||
|
|
||||||
This will remove all macros from **doctest** that don't have the **```DOCTEST_```** prefix - like **```CHECK```**, **```TEST_CASE```** and **```SUBCASE```**. Then only the full macro names will be available - **```DOCTEST_CHECK```**, **```DOCTEST_TEST_CASE```** and **```DOCTEST_SUBCASE```**. The user is free to make their own short versions of these macros - [**example**](../../examples/all_features/alternative_macros.cpp).
|
|
||||||
|
|
||||||
This can be defined both globally and in specific source files only.
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING```**
|
|
||||||
|
|
||||||
By default ```char*``` is being treated as a pointer. With this option comparing ```char*``` pointers will switch to using ```strcmp()``` for comparisons and when stringified the string will be printed instead of the pointer value.
|
|
||||||
|
|
||||||
This should be defined globally.
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_SUPER_FAST_ASSERTS```**
|
|
||||||
|
|
||||||
This config option makes the assert macros (except for those dealing with exceptions) compile [**much faster**](benchmarks.md#cost-of-an-assertion-macro)! (31-91% - depending on the type - [**normal**](assertions.md#expression-decomposing-asserts) or [**binary**](assertions.md#binary-and-unary-asserts))
|
|
||||||
|
|
||||||
Each assert is turned into a single function call - the only downside of this is: if an assert fails and a debugger is attached - when it breaks it will be in an internal function - the user will have to go 1 level up in the callstack to see the actual assert.
|
|
||||||
|
|
||||||
It also implies [**```DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS```**](#doctest_config_no_try_catch_in_asserts) (so exceptions thrown during the evaluation of an assert are not caught by the assert itself but by the testing framework - meaning that the test case is immediately aborted).
|
|
||||||
|
|
||||||
This can be defined both globally and in specific source files only.
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_USE_STD_HEADERS```**
|
|
||||||
|
|
||||||
The library by default provides a forward declaration of ```std::ostream``` in order to support the ```operator<<``` [**stringification**](stringification.md) mechanism (also ```std::tuple<>``` and ```std::nullptr_t```). This is forbidden by the standard (even though it works everywhere on all tested compilers). However if the user wishes to be 100% standards compliant - then this configuration option can be used to force the inclusion of the relevant standard headers.
|
|
||||||
|
|
||||||
Also it is possible that some STL implementation of a compiler with niche usage defines them differently - then there will be compilation errors in STL headers and using this option should fix the problem.
|
|
||||||
|
|
||||||
This should be defined globally.
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_VOID_CAST_EXPRESSIONS```**
|
|
||||||
|
|
||||||
This affects the [asserts dealing with exceptions](assertions.md#exceptions) - the expression is cast to void to avoid problems such as when functions with the ```[[nodiscard]]``` attribute are used but their result isn't checked.
|
|
||||||
|
|
||||||
This can be defined both globally and in specific source files only.
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_NO_COMPARISON_WARNING_SUPPRESSION```**
|
|
||||||
|
|
||||||
By default the library suppresses warnings about comparing signed and unsigned types, etc.
|
|
||||||
|
|
||||||
- g++/clang ```-Wsign-conversion```
|
|
||||||
- g++/clang ```-Wsign-compare```
|
|
||||||
- msvc ```C4389``` 'operator' : signed/unsigned mismatch
|
|
||||||
- msvc ```C4018``` 'expression' : signed/unsigned mismatch
|
|
||||||
|
|
||||||
You can checkout [**this**](https://github.com/onqtam/doctest/issues/16#issuecomment-246803303) issue to better understand why I suppress these warnings by default.
|
|
||||||
|
|
||||||
This can be defined both globally and in specific source files only.
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_OPTIONS_PREFIX```**
|
|
||||||
|
|
||||||
Defining this as a string will change the prefix of the [**command line**](commandline.md) options to use the given prefix instead of the default ```dt-``` prefix. This can be useful for integrating the testing framework into a client codebase, where a command option prefix like ```selftest-``` might be more clear to users.
|
|
||||||
|
|
||||||
This should be defined only in the source file where the library is implemented (it's relevant only there).
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_NO_UNPREFIXED_OPTIONS```**
|
|
||||||
|
|
||||||
This will disable the short versions of the [**command line**](commandline.md) options and only the versions with ```--dt-``` prefix will be parsed by **doctest** - this is possible for easy interoperability with client command line option handling when the testing framework is integrated within a client codebase - so there are no clashes and so that the user can exclude everything starting with ```--dt-``` from their option parsing.
|
|
||||||
|
|
||||||
This should be defined only in the source file where the library is implemented (it's relevant only there).
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS```**
|
|
||||||
|
|
||||||
This will remove all ```try``` / ```catch``` sections from:
|
|
||||||
|
|
||||||
- the [normal asserts](assertions.md#expression-decomposing-asserts)
|
|
||||||
- the [binary and unary asserts](assertions.md#binary-and-unary-asserts)
|
|
||||||
|
|
||||||
so exceptions thrown while evaluating the expression in an assert will terminate the current test case.
|
|
||||||
|
|
||||||
This can be used for some mild compile time savings but for greater impact look into [**```DOCTEST_CONFIG_SUPER_FAST_ASSERTS```**](configuration.md#doctest_config_super_fast_asserts).
|
|
||||||
|
|
||||||
This can be defined both globally and in specific source files only.
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_NO_EXCEPTIONS```**
|
|
||||||
|
|
||||||
This will remove everything that uses exceptions from the framework - it is also auto detectable if exceptions are disabled for compilers (like with ```-fno-exceptions``` for GCC/Clang).
|
|
||||||
|
|
||||||
What gets changed:
|
|
||||||
|
|
||||||
- asserts that evaluate the expression in a ```try``` / ```catch``` section no longer evaluate in such a context
|
|
||||||
- ```REQUIRE``` macros are gone (undefined)
|
|
||||||
- [exception macros](assertions.md#exceptions) are gone (undefined)
|
|
||||||
- the ```abort-after``` option won't be fully working because an exception is used to terminate test cases
|
|
||||||
|
|
||||||
The ```REQUIRE``` family of asserts uses exceptions to terminate the current test case when they fail. An exception is used instead of a simple ```return;``` because asserts can be used not only in a test case but also in functions called by a test case.
|
|
||||||
|
|
||||||
Also some of the [**logging macros**](logging.md#messages-which-can-optionally-fail-test-cases) which act like a ```REQUIRE``` assert (terminating the test case) - like ```FAIL()``` - start to work differently - like a ```FAIL_CHECK()```.
|
|
||||||
|
|
||||||
[**```DOCTEST_CONFIG_NO_EXCEPTIONS```**](#doctest_config_no_exceptions) implies [**```DOCTEST_CONFIG_NO_TRY_CATCH_IN_ASSERTS```**](#doctest_config_no_try_catch_in_asserts)
|
|
||||||
|
|
||||||
If you wish to use asserts that deal with exceptions and only sometimes build without exceptions - check the [**```DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS```**](#doctest_config_no_exceptions_but_with_all_asserts) config option.
|
|
||||||
|
|
||||||
This should be defined globally.
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS```**
|
|
||||||
|
|
||||||
When building with no exceptions (see [**```DOCTEST_CONFIG_NO_EXCEPTIONS```**](#doctest_config_no_exceptions)) ```REQUIRE``` asserts and the ones about dealing with exceptions are gone.
|
|
||||||
|
|
||||||
If however you want your code to use these assertions and only sometimes build without exceptions - then using this config will be of help. The effects of using it are the following:
|
|
||||||
|
|
||||||
- ```REQUIRE``` asserts are not gone - but they act like ```CHECK``` asserts - when one of them fails the whole test case will be marked as failed but will not be exited immediately
|
|
||||||
- the [asserts for dealing with exceptions](assertions.md#exceptions) are turned into a no-op (instead of being totally undefined)
|
|
||||||
|
|
||||||
This can be defined both globally and in specific source files only.
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE```**
|
|
||||||
|
|
||||||
This option forces all doctest asserts to copy by value the expressions they are given instead of binding them to const references. This might be useful to avoid ODR-usage of static constants (which might lead to linker errors with g++/clang):
|
|
||||||
|
|
||||||
```c++
|
|
||||||
template<typename T> struct type_traits { static const bool value = false; };
|
|
||||||
|
|
||||||
// unless DOCTEST_CONFIG_ASSERTION_PARAMETERS_BY_VALUE is defined the following assertion
|
|
||||||
// will lead to a linker error if type_traits<int>::value isn't defined in a translation unit
|
|
||||||
CHECK(type_traits<int>::value == false);
|
|
||||||
```
|
|
||||||
|
|
||||||
This can be defined both globally and in specific source files only.
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_COLORS_NONE```**
|
|
||||||
|
|
||||||
This will remove support for colors in the console output of the framework.
|
|
||||||
|
|
||||||
This should be defined only in the source file where the library is implemented (it's relevant only there).
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_COLORS_WINDOWS```**
|
|
||||||
|
|
||||||
This will force the support for colors in the console output to use the Windows APIs and headers.
|
|
||||||
|
|
||||||
This should be defined only in the source file where the library is implemented (it's relevant only there).
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_COLORS_ANSI```**
|
|
||||||
|
|
||||||
This will force the support for colors in the console output to use ANSI escape codes.
|
|
||||||
|
|
||||||
This should be defined only in the source file where the library is implemented (it's relevant only there).
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_WINDOWS_SEH```**
|
|
||||||
|
|
||||||
This will enable SEH handling on Windows. Currently enabled only when compiled with MSVC, because some versions of MinGW do not have the necessary Win32 API support. The user may choose to enable this explicitly - it is known to work with the MinGW-w64 project.
|
|
||||||
|
|
||||||
This should be defined only in the source file where the library is implemented (it's relevant only there).
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_NO_WINDOWS_SEH```**
|
|
||||||
|
|
||||||
This can be used to disable **```DOCTEST_CONFIG_WINDOWS_SEH```** when it is auto-selected by the library.
|
|
||||||
|
|
||||||
This should be defined only in the source file where the library is implemented (it's relevant only there).
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_POSIX_SIGNALS```**
|
|
||||||
|
|
||||||
This will enable the use of signals under UNIX for handling crashes. On by default.
|
|
||||||
|
|
||||||
This should be defined only in the source file where the library is implemented (it's relevant only there).
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_NO_POSIX_SIGNALS```**
|
|
||||||
|
|
||||||
This can be used to disable **```DOCTEST_CONFIG_POSIX_SIGNALS```** when it is auto-selected by the library.
|
|
||||||
|
|
||||||
This should be defined only in the source file where the library is implemented (it's relevant only there).
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_INCLUDE_TYPE_TRAITS```**
|
|
||||||
|
|
||||||
This can be used to include the ```<type_traits>``` C++11 header. That in turn will enable the ability for the ```Approx``` helper to be used with strong typedefs of ```double``` - check [this](https://github.com/onqtam/doctest/issues/62) or [this](https://github.com/onqtam/doctest/issues/85) issue for more details on that.
|
|
||||||
|
|
||||||
This can be defined both globally and in specific source files only.
|
|
||||||
|
|
||||||
### **```DOCTEST_CONFIG_NO_MULTI_LANE_ATOMICS```**
|
|
||||||
|
|
||||||
This can be used to disable multi lane atomics. Multi lane atomics can speed up highly parallel use of assert statements, but have a small overhead for single threaded applications.
|
|
||||||
|
|
||||||
---------------
|
|
||||||
|
|
||||||
[Home](readme.md#reference)
|
|
||||||
|
|
||||||
<p align="center"><img src="../../scripts/data/logo/icon_2.svg"></p>
|
|
|
@ -1,148 +0,0 @@
|
||||||
## Extensions
|
|
||||||
|
|
||||||
The doctest header doesn't include any external or stdlib headers in it's interface part in order to provide the most optimal build times but that means it is limited in what it can provide as functionality => that's when extensions come into play. They are located as header files in [`doctest/extensions`](../../doctest/extensions) and each of them is documented in a section here.
|
|
||||||
|
|
||||||
# [Utils](../../doctest/extensions/doctest_util.h)
|
|
||||||
|
|
||||||
nothing here yet...
|
|
||||||
|
|
||||||
# [Distributed tests with MPI](../../doctest/extensions/doctest_mpi.h)
|
|
||||||
|
|
||||||
[Bruno Maugars and Bérenger Berthoul, ONERA]
|
|
||||||
|
|
||||||
Testing code over distributed processes requires support from the testing framework. **Doctest** support for MPI parallel communication is provided in the ```"doctest/extensions/doctest_mpi.h"``` header.
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
See [**the complete test**](../../examples/mpi/mpi.cpp) and [**the configuration of main()**](../../examples/mpi/main.cpp)
|
|
||||||
|
|
||||||
### MPI_TEST_CASE
|
|
||||||
|
|
||||||
```c++
|
|
||||||
#include "doctest/extensions/doctest_mpi.h"
|
|
||||||
|
|
||||||
int my_function_to_test(MPI_Comm comm) {
|
|
||||||
int rank;
|
|
||||||
MPI_Comm_rank(comm,&rank);
|
|
||||||
if (rank == 0) {
|
|
||||||
return 10;
|
|
||||||
}
|
|
||||||
return 11;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
MPI_TEST_CASE("test over two processes",2) { // Parallel test on 2 processes
|
|
||||||
int x = my_function_to_test(test_comm);
|
|
||||||
|
|
||||||
MPI_CHECK( 0, x==10 ); // CHECK for rank 0, that x==10
|
|
||||||
MPI_CHECK( 1, x==11 ); // CHECK for rank 1, that x==11
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
An ```MPI_TEST_CASE``` is like a regular ```TEST_CASE```, except it takes a second argument, which is the number of processes needed to run the test. If the number of processes is less than 2, the test will fail. If the number of processes is greater than or equal to 2, it will create a sub-communicator over 2 processes, called ```test_comm```, and execute the test over these processes. Three objects are provided by ```MPI_TEST_CASE```:
|
|
||||||
* ```test_comm```, of type ```MPI_Comm```: the mpi communicator on which the test is running,
|
|
||||||
* ```test_rank``` and ```test_nb_procs```, two ```int``` giving respectively the rank of the current process and the size of the communicator for ```test_comm```. These last two are just here for convenience and could be retrieved from ```test_comm```.
|
|
||||||
|
|
||||||
We always have:
|
|
||||||
|
|
||||||
```c++
|
|
||||||
MPI_TEST_CASE("my_test",N) {
|
|
||||||
CHECK( test_nb_procs == N );
|
|
||||||
MPI_CHECK( i, test_rank==i ); // for any i<N
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Assertions
|
|
||||||
It is possible to use regular assertions in an ```MPI_TEST_CASE```. MPI-specific assertions are also provided and are all prefixed with ```MPI_``` (```MPI_CHECK```, ```MPI_ASSERT```...). The first argument is the rank for which they are checked, and the second is the usual expression to check.
|
|
||||||
|
|
||||||
## The main entry points and mpi reporters
|
|
||||||
|
|
||||||
You need to launch the unit tests with an ```mpirun``` command:
|
|
||||||
```
|
|
||||||
mpirun -np 2 unit_test_executable.exe
|
|
||||||
```
|
|
||||||
|
|
||||||
```MPI_Init``` should be called before running the unit tests. Also, using the default console reporter will result in each process writing everything in the same place, which is not what we want. Two reporters are provided and can be enabled. A complete ```main()``` would be:
|
|
||||||
|
|
||||||
|
|
||||||
```c++
|
|
||||||
#define DOCTEST_CONFIG_IMPLEMENT
|
|
||||||
|
|
||||||
#include "doctest/extensions/doctest_mpi.h"
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
|
||||||
MPI_Init(&argc, &argv);
|
|
||||||
|
|
||||||
doctest::Context ctx;
|
|
||||||
ctx.setOption("reporters", "MpiConsoleReporter");
|
|
||||||
ctx.setOption("reporters", "MpiFileReporter");
|
|
||||||
ctx.setOption("force-colors", true);
|
|
||||||
ctx.applyCommandLine(argc, argv);
|
|
||||||
|
|
||||||
int test_result = ctx.run();
|
|
||||||
|
|
||||||
MPI_Finalize();
|
|
||||||
|
|
||||||
return test_result;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### MpiConsoleReporter
|
|
||||||
|
|
||||||
The ```MpiConsoleReporter``` should be substituted to the default reporter. It does the same as the default console reporter for regular assertions, but only outputs on process 0. For MPI test cases, if there is a failure it tells the process that failed
|
|
||||||
|
|
||||||
```
|
|
||||||
[doctest] doctest version is "2.4.0"
|
|
||||||
[doctest] run with "--help" for options
|
|
||||||
===============================================================================
|
|
||||||
[doctest] test cases: 171 | 171 passed | 0 failed | 0 skipped
|
|
||||||
[doctest] assertions: 864 | 864 passed | 0 failed |
|
|
||||||
[doctest] Status: SUCCESS!
|
|
||||||
std_e_mpi_unit_tests
|
|
||||||
[doctest] doctest version is "2.4.0"
|
|
||||||
[doctest] run with "--help" for options
|
|
||||||
===============================================================================
|
|
||||||
path/to/test.cpp:30:
|
|
||||||
TEST CASE: my test case
|
|
||||||
|
|
||||||
On rank [2] : path/to/test.cpp:35: CHECK( x==-1 ) is NOT correct!
|
|
||||||
values: CHECK( 0 == -1 )
|
|
||||||
|
|
||||||
===============================================================================
|
|
||||||
[doctest] test cases: 2 | 2 passed | 0 failed | 0 skipped
|
|
||||||
[doctest] assertions: 2 | 2 passed | 0 failed |
|
|
||||||
[doctest] Status: SUCCESS!
|
|
||||||
===============================================================================
|
|
||||||
[doctest] glob assertions: 5 | 4 passed | 1 failed |
|
|
||||||
===============================================================================
|
|
||||||
[doctest] fail on rank:
|
|
||||||
-> On rank [2] with 1 test failed
|
|
||||||
[doctest] Status: FAILURE!
|
|
||||||
```
|
|
||||||
|
|
||||||
### MpiFileReporter
|
|
||||||
The ```MpiFileReporter``` will just print the result of each process in its own file, named ```doctest_[rank].log```. Only use this reporter as a debug facility if you want to know what is going on exactly when a parallel test case is failing.
|
|
||||||
|
|
||||||
### Other reporters
|
|
||||||
Other reporters (jUnit, XML) are not supported directly, which mean that you can always print the result of each process to its own file, but there is (currently) no equivalent of the ```MpiConsoleReporter``` that will aggregate the results of all processes.
|
|
||||||
|
|
||||||
|
|
||||||
## Note
|
|
||||||
|
|
||||||
This feature is provided to unit-test mpi-distributed code. It is **not** a way to parallelize many unit tests over several processes (for that, see [**the example python script**](../../examples/range_based_execution.py)).
|
|
||||||
|
|
||||||
## TODO
|
|
||||||
|
|
||||||
* Pass ```s``` member variable of ```ConsoleReporter``` as an argument to member functions so we can use them with another object (would help to factorize ```MPIConsoleReporter```)
|
|
||||||
* Only MPI_CHECK tested. MPI_REQUIRE, exception handling: nothing tested
|
|
||||||
* If the number of processes is not enough, prints the correct message, but then deadlocks (comes from ```MPI_Probe``` in ```MpiConsoleReporter```)
|
|
||||||
* [[maybe_unused]] is C++17
|
|
||||||
* More testing, automatic testing
|
|
||||||
* Packaging: create a new target ```mpi_doctest```? (probably cleaner to depend explicitly on MPI for mpi/doctest.h)
|
|
||||||
* Later, maybe: have a general mechanism to represent assertions so we can separate the report format (console, xml, junit...) from the reporting strategy (sequential vs. MPI)
|
|
||||||
|
|
||||||
---------------
|
|
||||||
|
|
||||||
[Home](readme.md#reference)
|
|
||||||
|
|
||||||
<p align="center"><img src="../../scripts/data/logo/icon_2.svg"></p>
|
|
|
@ -1,178 +0,0 @@
|
||||||
## FAQ
|
|
||||||
|
|
||||||
- [**How is doctest different from Catch?**](#how-is-doctest-different-from-catch)
|
|
||||||
- [**How is doctest different from Google Test?**](#how-is-doctest-different-from-google-test)
|
|
||||||
- [**How to get the best compile-time performance with the framework?**](#how-to-get-the-best-compile-time-performance-with-the-framework)
|
|
||||||
- [**Is doctest thread-aware?**](#is-doctest-thread-aware)
|
|
||||||
- [**Is mocking supported?**](#is-mocking-supported)
|
|
||||||
- [**Why are my tests in a static library not getting registered?**](#why-are-my-tests-in-a-static-library-not-getting-registered)
|
|
||||||
- [**Why is comparing C strings (```char*```) actually comparing pointers?**](#why-is-comparing-c-strings-char-actually-comparing-pointers)
|
|
||||||
- [**How to write tests in header-only libraries?**](#how-to-write-tests-in-header-only-libraries)
|
|
||||||
- [**Does the framework use exceptions?**](#does-the-framework-use-exceptions)
|
|
||||||
- [**Why do I get compiler errors in STL headers when including the doctest header?**](#why-do-i-get-compiler-errors-in-stl-headers-when-including-the-doctest-header)
|
|
||||||
- [**Can different versions of the framework be used within the same binary (executable/dll)?**](#can-different-versions-of-the-framework-be-used-within-the-same-binary-executabledll)
|
|
||||||
- [**Why is doctest using macros?**](#why-is-doctest-using-macros)
|
|
||||||
- [**How to use with multiple files?**](#how-to-use-with-multiple-files)
|
|
||||||
|
|
||||||
### How is **doctest** different from Catch?
|
|
||||||
|
|
||||||
Pros of **doctest**:
|
|
||||||
|
|
||||||
- **doctest** is [**thread-safe**](faq.md#is-doctest-thread-aware)
|
|
||||||
- asserts can be used [**outside of a testing context**](assertions.md#using-asserts-out-of-a-testing-context)
|
|
||||||
- including the **doctest** header is [**over 20 times lighter**](benchmarks.md#cost-of-including-the-header) on compile times than that of [**Catch**](https://github.com/catchorg/Catch2)
|
|
||||||
- the asserts in **doctest** can be [**many times lighter**](benchmarks.md#cost-of-an-assertion-macro) on compile times than those of [**Catch**](https://github.com/catchorg/Catch2)
|
|
||||||
- **doctest** executes tests [**many times faster**](benchmarks.md#runtime-benchmarks) than [**Catch**](https://github.com/catchorg/Catch2)
|
|
||||||
- everything testing-related can be removed from the binary by defining the [**```DOCTEST_CONFIG_DISABLE```**](configuration.md#doctest_config_disable) identifier
|
|
||||||
- doesn't drag any headers when included (except for in the translation unit where the library gets implemented)
|
|
||||||
- 0 warnings even on the [**most aggressive**](../../scripts/cmake/common.cmake#L84) warning levels for MSVC/GCC/Clang
|
|
||||||
- per commit tested with 180+ builds on [**much more compilers**](features.md#extremely-portable) - and through valgrind/sanitizers/analyzers
|
|
||||||
- test cases can be written in headers - the framework will still register the tests only once - no duplicates
|
|
||||||
- binaries (exe/dll) can use the test runner of another binary - so tests end up in a single registry - [**example**](../../examples/executable_dll_and_plugin/)
|
|
||||||
|
|
||||||
Aside from everything mentioned so far doctest has some [**features**](features.md#other-features) (like [**test suites**](testcases.md#test-suites) and [**decorators**](testcases.md#decorators)) which [**Catch**](https://github.com/catchorg/Catch2) doesn't.
|
|
||||||
|
|
||||||
Missing stuff:
|
|
||||||
|
|
||||||
- matchers and generators
|
|
||||||
- micro benchmarking support - nonius is used in [**Catch**](https://github.com/catchorg/Catch2)
|
|
||||||
- other small stuff such as tags - can be easily emulated/migrated from - see below
|
|
||||||
|
|
||||||
But these things (and more!) are planned in the [**roadmap**](roadmap.md)!
|
|
||||||
|
|
||||||
**doctest** can be thought of as a very polished, light, stable and clean subset (or reimplementation) of [**Catch**](https://github.com/catchorg/Catch2) but this might change in the future as more features are added.
|
|
||||||
|
|
||||||
Also checkout [this table](https://github.com/martinmoene/catch-lest-other-comparison) that compares **doctest** / [**Catch**](https://github.com/catchorg/Catch2) / [**lest**](https://github.com/martinmoene/lest).
|
|
||||||
|
|
||||||
A quick and easy way to migrate most of your Catch tests to doctest is to change the ```TEST_CASE``` (if using tags) and ```SECTION``` macros as follows:
|
|
||||||
|
|
||||||
```c++
|
|
||||||
#include "path/to/doctest.h"
|
|
||||||
|
|
||||||
#define SECTION(name) DOCTEST_SUBCASE(name)
|
|
||||||
|
|
||||||
// only if tags are used: will concatenate them to the test name string literal
|
|
||||||
#undef TEST_CASE
|
|
||||||
#define TEST_CASE(name, tags) DOCTEST_TEST_CASE(tags " " name)
|
|
||||||
|
|
||||||
// catch exposes this by default outside of its namespace
|
|
||||||
using doctest::Approx;
|
|
||||||
```
|
|
||||||
|
|
||||||
### How is **doctest** different from Google Test?
|
|
||||||
|
|
||||||
Here are a couple of differences:
|
|
||||||
|
|
||||||
- the main one is that only doctest from the C++ frameworks is usable next to your production code (speed of compilation, ability to remove the tests from the binary, ability to execute tests/code/both, ability to have tests in multiple shared objects and still a single registry for all of them)
|
|
||||||
- doctest is a single header - Google Test has to be built as a separate static library and linked against.
|
|
||||||
- doctest has the concept of [**Subcases**](https://github.com/onqtam/doctest/blob/master/doc/markdown/tutorial.md#test-cases-and-subcases) which is a much cleaner way to share setup and teardown code between tests compared to fixtures and class inheritance - Google Test is quite verbose!
|
|
||||||
- doctest compiles faster and probably runs faster (although the runtime becomes an issue only when you have millions of asserts)
|
|
||||||
- doctest asserts are thread-safe even on Windows (Google Test uses pthreads so thread-safe asserts are available only on UNIX)
|
|
||||||
- doctest overall has a simpler API
|
|
||||||
|
|
||||||
but there are also some areas in which doctest is lacking:
|
|
||||||
|
|
||||||
- value-parameterized tests
|
|
||||||
- death tests (where you check if calling a certain function doesn’t simply throw but if it crashes the process)
|
|
||||||
- doctest has some integration with mocking libraries but Google Test works perfectly with Google Mock (although doctest should in theory work with it as well)
|
|
||||||
|
|
||||||
The areas where doctest is behind are planned for improvement in the future. There are many other smaller differences - it would be impractical to cover them all.
|
|
||||||
|
|
||||||
### How to get the best compile-time performance with the framework?
|
|
||||||
|
|
||||||
The [**```DOCTEST_CONFIG_SUPER_FAST_ASSERTS```**](configuration.md#doctest_config_super_fast_asserts) config option yields the [**fastest possible**](benchmarks.md#cost-of-an-assertion-macro) compile times (up to 31-91%). Also the expression-decomposing template machinery can be skipped by using the [**binary**](assertions.md#binary-and-unary-asserts) asserts.
|
|
||||||
|
|
||||||
There are only 2 tiny drawbacks of using this config option:
|
|
||||||
|
|
||||||
- there is no ```try/catch``` block in each assert so if an expression is thrown the whole test case ends (but is still caught and reported).
|
|
||||||
- when an assert fails and a debugger is present - the framework will break inside a doctest function so the user will have to go 1 level up in the callstack to see where the actual assert is in the source code.
|
|
||||||
|
|
||||||
These 2 things can be considered negligible and totally worth it if you are dealing mainly with expressions unlikely to throw exceptions and all the tests usually pass (you don't need to navigate often to a failing assert with a debugger attached).
|
|
||||||
|
|
||||||
### Is doctest thread-aware?
|
|
||||||
|
|
||||||
Most macros/functionality is safe to use in a multithreaded context: [**assertion**](assertions.md) and [**logging**](logging.md) macros can be safely used from multiple threads spawned from a single test case. This however does not mean that multiple test cases can be ran in parallel - test cases are still ran serially. [**Subcases**](tutorial.md#test-cases-and-subcases) should also be used only from the test runner thread and all threads spawned in a subcase ought to be joined before the end of that subcase and no new subcases should be entered while other threads with doctest assertions in them are still running - not following these instructions will lead to crashes (example in [**here**](../../examples/all_features/concurrency.cpp)). Also note that logged context in one thread will not be used/printed when asserts from another thread fail - logged context is thread-local.
|
|
||||||
|
|
||||||
There is also an option to run a [**range**](commandline.md) of tests from an executable - so tests can be ran in parallel by invoking the process multiple times with different ranges - see [**the example python script**](../../examples/range_based_execution.py).
|
|
||||||
|
|
||||||
### Is mocking supported?
|
|
||||||
|
|
||||||
**doctest** doesn't support mocking but should be easy to integrate with third-party libraries such as:
|
|
||||||
|
|
||||||
- [trompeloeil](https://github.com/rollbear/trompeloeil) - integration shown [here](https://github.com/rollbear/trompeloeil/blob/master/docs/CookBook.md#adapt_doctest)
|
|
||||||
- [FakeIt](https://github.com/eranpeer/FakeIt) - integration might be similar to that of [catch](https://github.com/eranpeer/FakeIt/tree/master/config/catch) but this has not been looked into
|
|
||||||
|
|
||||||
by using the [**logging**](logging.md#messages-which-can-optionally-fail-test-cases) macros such as ```ADD_FAIL_AT(file, line, message)```
|
|
||||||
|
|
||||||
<!--
|
|
||||||
Not sure how to integrate with these:
|
|
||||||
https://github.com/dascandy/hippomocks
|
|
||||||
https://github.com/tpounds/mockitopp
|
|
||||||
-->
|
|
||||||
|
|
||||||
### Why are my tests in a static library not getting registered?
|
|
||||||
|
|
||||||
This is a [**common problem among libraries with self-registering code**](https://groups.google.com/forum/#!msg/catch-forum/FV0Qo62DvgY/jxEO6c9_q3kJ) and it affects all modern compilers on all platforms.
|
|
||||||
|
|
||||||
The problem is that when a static library is being linked to a binary (executable or dll) - only object files from the static library that define a symbol being required from the binary will get pulled in (this is a linker/dependency optimization).
|
|
||||||
|
|
||||||
A way to solve this in CMake is to use object libraries instead of static libraries - like this:
|
|
||||||
|
|
||||||
```cmake
|
|
||||||
add_library(with_tests OBJECT src_1.cpp src_2.cpp src_3.cpp ...)
|
|
||||||
|
|
||||||
add_library(dll SHARED $<TARGET_OBJECTS:with_tests> dll_src_1.cpp ...)
|
|
||||||
add_executable(exe $<TARGET_OBJECTS:with_tests> exe_src_1.cpp ...)
|
|
||||||
```
|
|
||||||
|
|
||||||
Thanks to [pthom](https://github.com/pthom) for suggesting this.
|
|
||||||
|
|
||||||
As an alternative I have created a CMake function that forces every object file from a static library to be linked into a binary target - it is called [**```doctest_force_link_static_lib_in_target()```**](../../examples/exe_with_static_libs/doctest_force_link_static_lib_in_target.cmake). It is unintrusive - no source file gets changed - everything is done with compiler flags per source files. An example project using it can be found [**here**](../../examples/exe_with_static_libs) - the commented part of the CMakeLists.txt file.
|
|
||||||
|
|
||||||
It doesn't work in 2 scenarios:
|
|
||||||
|
|
||||||
- either the target or the library uses a precompiled header - see [**this**](https://github.com/onqtam/doctest/issues/21#issuecomment-247001423) issue for details
|
|
||||||
- either the target or the library is an imported target (pre-built) and not built within the current cmake tree
|
|
||||||
|
|
||||||
You can also checkout this repository for a different solution: [**pthom/doctest_registerlibrary**](https://github.com/pthom/doctest_registerlibrary).
|
|
||||||
|
|
||||||
A compiler-specific solution for MSVC is to use the [```/OPT:NOREF```](https://msdn.microsoft.com/en-us/library/bxwfs976.aspx) linker flag (thanks to [lectem](https://github.com/Lectem) for [reporting](https://github.com/onqtam/doctest/issues/106) it!). Another option is to look at [```/wholearchive```](https://docs.microsoft.com/en-us/cpp/build/reference/wholearchive-include-all-library-object-files?view=vs-2019) for MSVC.
|
|
||||||
|
|
||||||
### Why is comparing C strings (```char*```) actually comparing pointers?
|
|
||||||
|
|
||||||
**doctest** by default treats ```char*``` as normal pointers. Using the [**```DOCTEST_CONFIG_TREAT_CHAR_STAR_AS_STRING```**](configuration.md#doctest_config_treat_char_star_as_string) changes that.
|
|
||||||
|
|
||||||
### How to write tests in header-only libraries?
|
|
||||||
|
|
||||||
There are 2 options:
|
|
||||||
|
|
||||||
- just include the doctest header in your headers and write the tests - the doctest header should be shipped with your headers and the user will have to implement the doctest runner in one of their source files.
|
|
||||||
- don't include the doctest header and guard your test cases with ```#ifdef DOCTEST_LIBRARY_INCLUDED``` and ```#endif``` - that way your tests will be compiled and registered if the user includes the doctest header before your headers (and they will also have to implement the test runner somewhere).
|
|
||||||
|
|
||||||
Also note that it would be a good idea to add a tag in your test case names (like this: ```TEST_CASE("[the_lib] testing foo")```) so the user can easily filter them out with ```--test-case-exclude=*the_lib*``` if they wish to.
|
|
||||||
|
|
||||||
### Does the framework use exceptions?
|
|
||||||
|
|
||||||
Yes - but they can be disabled - see the [**```DOCTEST_CONFIG_NO_EXCEPTIONS```**](configuration.md#doctest_config_no_exceptions) config identifier.
|
|
||||||
|
|
||||||
### Why do I get compiler errors in STL headers when including the doctest header?
|
|
||||||
|
|
||||||
Try using the [**```DOCTEST_CONFIG_USE_STD_HEADERS```**](configuration.md#doctest_config_use_std_headers) configuration identifier.
|
|
||||||
|
|
||||||
### Can different versions of the framework be used within the same binary (executable/dll)?
|
|
||||||
|
|
||||||
Currently no. Single header libraries like [**stb**](https://github.com/nothings/stb) have this as an option (everything gets declared static - making it with internal linkage) but it isn't very logical for **doctest** - the main point is to write tests in any source file of the project and have the test runner implemented in only one source file.
|
|
||||||
|
|
||||||
### Why is doctest using macros?
|
|
||||||
|
|
||||||
Aren't they evil and not *modern*? - Check out the answer Phil Nash gives to this question [**here**](http://accu.org/index.php/journals/2064) (the creator of [**Catch**](https://github.com/catchorg/Catch2)).
|
|
||||||
|
|
||||||
### How to use with multiple files?
|
|
||||||
|
|
||||||
All you need to do is define either [**```DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN```**](configuration.md#doctest_config_implement_with_main) or [**```DOCTEST_CONFIG_IMPLEMENT```**](configuration.md#doctest_config_implement) in only ONE of the source files just before including the doctest header - in all other source files you just include the header and use the framework. The difference between the two is that one of them provides a `main()` entry point - for more info on that please refer to [`The main() entry point`](main.md).
|
|
||||||
|
|
||||||
---------------
|
|
||||||
|
|
||||||
[Home](readme.md#reference)
|
|
||||||
|
|
||||||
<p align="center"><img src="../../scripts/data/logo/icon_2.svg"></p>
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue