├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── include └── check │ ├── check.h │ ├── dcheck.h │ └── notreached.h ├── package.json └── test ├── check.sh ├── common.sh ├── dcheck.sh └── notreached.sh /.gitignore: -------------------------------------------------------------------------------- 1 | test/check 2 | test/dcheck 3 | test/notreached 4 | deps/ 5 | 6 | # Object files 7 | *.o 8 | *.ko 9 | *.obj 10 | *.elf 11 | 12 | # Precompiled Headers 13 | *.gch 14 | *.pch 15 | 16 | # Libraries 17 | *.lib 18 | *.a 19 | *.la 20 | *.lo 21 | 22 | # Shared objects (inc. Windows DLLs) 23 | *.dll 24 | *.so 25 | *.so.* 26 | *.dylib 27 | 28 | # Executables 29 | *.exe 30 | *.out 31 | *.app 32 | *.i*86 33 | *.x86_64 34 | *.hex 35 | 36 | # Debug files 37 | *.dSYM/ 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 clibs 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PROJECT_NAME ?= check 2 | 3 | ## Install headers 4 | .PHONY: install 5 | install: 6 | $(CP) -rf include/$(PROJECT_NAME) $(PREFIX)/include/$(PROJECT_NAME) 7 | 8 | ## Uninstall headers 9 | .PHONY: uninstall 10 | uninstall: 11 | $(RM) -f $(PREFIX)/include/$(PROJECT_NAME) 12 | 13 | ## Tests 14 | .PHONY: test 15 | test: test/check 16 | test: test/dcheck 17 | test: test/notreached 18 | test/check test/dcheck test/notreached: 19 | @exec $@.sh 20 | @echo "exec: $@" 21 | @echo " ok: $@" 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # check 2 | 3 | Super basic `CHECK()`, `DCHECK()`, and `NOTREACHED()` macro implementations. 4 | 5 | ## install 6 | 7 | ```sh 8 | $ clib install check 9 | ``` 10 | 11 | ## usage 12 | 13 | [As described by the Chromium 14 | authors](https://www.chromium.org/developers/coding-style#TOC-CHECK-DCHECK-and-NOTREACHED-): 15 | 16 | > The `CHECK()` macro will cause an immediate crash if its condition is 17 | > not met. `DCHECK()` is like `CHECK()` but is only compiled in when 18 | > `DCHECK_IS_ON` is true (debug builds and some bot configurations, but 19 | > not end-user builds). `NOTREACHED()` is equivalent to `DCHECK(0)`. 20 | > Here are some rules for using these: 21 | 22 | > Use `DCHECK()` or `NOTREACHED()` as assertions, e.g. to document pre- and 23 | > post-conditions. A `DCHECK()` means *"this condition must always be true"*, 24 | > not **"this condition is normally true, but perhaps not in exceptional 25 | > cases."** Things like disk corruption or strange network errors are 26 | > examples of exceptional circumstances that nevertheless should not 27 | > result in `DCHECK()` failure. 28 | 29 | > A consequence of this is that you should not handle `DCHECK()` failures, 30 | > even if failure would result in a crash. Attempting to handle a `DCHECK()` 31 | > failure is a statement that the `DCHECK()` can fail, which contradicts the 32 | > point of writing the `DCHECK()`. In particular, do not write code like the 33 | > following: 34 | 35 | ```c 36 | DCHECK(foo); 37 | if (!foo) ... // Can't succeed! 38 | 39 | // Replace this whole conditional with "DCHECK(bar);" and 40 | // keep going instead. 41 | if (!bar) { 42 | NOTREACHED(); 43 | return; 44 | } 45 | ... 46 | ``` 47 | 48 | > Use `CHECK()` if the consequence of a failed assertion would be a security 49 | > vulnerability, where crashing the browser is preferable. Because this 50 | > takes down the whole browser, sometimes there are better options than 51 | > `CHECK()`. For example, if a renderer sends the browser process a 52 | > malformed IPC, an attacker may control the renderer, but we can simply 53 | > kill the offending renderer instead of crashing the whole browser. 54 | > You can temporarily use `CHECK()` instead of `DCHECK()` when trying to force 55 | > crashes in release builds to sniff out which of your assertions is 56 | > failing. Don't leave these in the codebase forever; remove them or 57 | > change them back once you've solved the problem. 58 | > Don't use these macros in tests, as they crash the test binary and leave 59 | > bots in a bad state. Use the `ASSERT_xx()` and `EXPECT_xx()` family of 60 | > macros, which report failures gracefully and can continue running other 61 | > tests. 62 | 63 | ### CHECK() 64 | 65 | ```c 66 | CHECK(user->data); 67 | ``` 68 | 69 | ### DCHECK() 70 | 71 | ```c 72 | CHECK(user->data); 73 | // do something with user dat 74 | DCHECK(user->network_connection); 75 | ``` 76 | 77 | ### NOTREACHED() 78 | 79 | ```c 80 | #ifdef BROKEN_CODE 81 | NOTREACHED(); 82 | #endif 83 | ``` 84 | 85 | ## license 86 | 87 | MIT 88 | -------------------------------------------------------------------------------- /include/check/check.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * You can read more about these macros on chromium.org. 4 | * Go to the direct link - https://www.chromium.org/developers/coding-style#TOC-CHECK-DCHECK-and-NOTREACHED- 5 | * 6 | * ... other source files should be here in this repo or folder or w/e 7 | * 8 | */ 9 | 10 | #ifndef CLIB_CHECK_H 11 | #define CLIB_CHECK_H 12 | 13 | // thank you brother tj & stephen (https://github.com/clibs/unlikely) 14 | #if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__) 15 | # define likely(expr) (__builtin_expect(!!(expr), 1)) 16 | # define unlikely(expr) (__builtin_expect(!!(expr), 0)) 17 | #else 18 | # define likely(expr) (1 == !!(expr)) 19 | # define unlikely(expr) (0 == !!(expr)) 20 | #endif 21 | 22 | // overload if you want your own abort fn - w/e 23 | #ifndef CHECK_ABORT_FUNCTION 24 | // need that prototype def 25 | # include 26 | # define CHECK_ABORT_FUNCTION abort 27 | #endif 28 | 29 | // check and bail if nope 30 | #ifndef CHECK 31 | # define CHECK(expr) if (!likely(expr)) { CHECK_ABORT_FUNCTION(); } 32 | #endif 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /include/check/dcheck.h: -------------------------------------------------------------------------------- 1 | #ifndef CLIB_DCHECK_H 2 | #define CLIB_DCHECK_H 3 | 4 | #include "check.h" 5 | 6 | // check and bail if nope. however, this only works if `-D DCHECK_IS_ON` 7 | // or equivalent is defined 8 | #ifdef DCHECK_IS_ON 9 | # define DCHECK(...) CHECK(__VA_ARGS__); 10 | #else 11 | # define DCHECK(expr) ((void) expr); 12 | #endif 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /include/check/notreached.h: -------------------------------------------------------------------------------- 1 | #ifndef CLIB_NOTREACHED_H 2 | #define CLIB_NOTREACHED_H 3 | 4 | #include "check.h" 5 | 6 | // equivalent to CEHCK(false) 7 | #ifndef NOTREACHED 8 | #define NOTREACHED() CHECK(0) 9 | #endif 10 | 11 | // alias `NOTREACHED()` because YOLO 12 | #ifndef NOTREACHABLE 13 | #define NOTREACHABLE NOTREACHED 14 | #endif 15 | 16 | #endif 17 | 18 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "check", 3 | "version": "0.0.2", 4 | "repo": "clibs/check", 5 | "description": "Super basic CHECK(), DCHECK(), and NOTREACHED() macro implementations.", 6 | "keywords": [ 7 | "check", 8 | "macro" 9 | ], 10 | "src": [ 11 | "include/check/check.h", 12 | "include/check/dcheck.h", 13 | "include/check/notreached.h" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /test/check.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## dependencies 4 | source test/common.sh 5 | 6 | ## target 7 | TARGET=test/check 8 | 9 | ## test suite 10 | suite () { 11 | ## unit test 12 | run-test $TARGET "`cat <<-SRC 13 | 14 | #include 15 | #include 16 | int main (void) { 17 | CHECK(0); 18 | return 0; 19 | } 20 | 21 | SRC`" 22 | return $? 23 | } 24 | 25 | suite 26 | expect "$? > 0" 27 | -------------------------------------------------------------------------------- /test/common.sh: -------------------------------------------------------------------------------- 1 | CFLAGS+="-I include " 2 | CC=gcc 3 | 4 | run-test () { 5 | local target="$1" 6 | local src="$2" 7 | rm -f $TARGET 8 | if echo "$src" | $CC -o $target $CFLAGS -xc -; then 9 | if test -f $target; then 10 | eval "./$target 2>/dev/null" 2>/dev/null 11 | let local rc=$? 12 | rm -f ./$target 13 | return $rc 14 | fi 15 | fi 16 | return 0 17 | } 18 | 19 | assert () { 20 | let local condition=$1 21 | local message="$2" 22 | 23 | if ! (( $condition )); then 24 | { echo $message; } >&2 25 | exit 1 26 | fi 27 | 28 | return 0 29 | } 30 | 31 | expect () { 32 | local expr=$@ 33 | local op=`expr "'$expr'"` 34 | if ! (( $expr )); then 35 | assert 0 "AssertionError: true != \`$expr\`" 36 | return 1 37 | fi 38 | return 0 39 | } 40 | -------------------------------------------------------------------------------- /test/dcheck.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## dependencies 4 | source test/common.sh 5 | 6 | ## target 7 | TARGET=test/dcheck 8 | 9 | ## test suite 10 | suite () { 11 | ## unit test 12 | run-test $TARGET "`cat <<-SRC 13 | 14 | #include 15 | #include 16 | int main (void) { 17 | DCHECK(0); 18 | return 0; 19 | } 20 | 21 | SRC`" 22 | return $? 23 | } 24 | 25 | ## DCHECK is off 26 | suite 27 | expect "$? == 0" 28 | 29 | ## DCHECK is on 30 | CFLAGS+="-D DCHECK_IS_ON" 31 | suite 32 | expect "$? > 0" 33 | -------------------------------------------------------------------------------- /test/notreached.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ## dependencies 4 | source test/common.sh 5 | 6 | ## target 7 | TARGET=test/notreached 8 | 9 | ## test suite 10 | suite () { 11 | ## unit test 12 | run-test $TARGET "`cat <<-SRC 13 | 14 | #include 15 | #include 16 | int main (void) { 17 | NOTREACHED(); 18 | printf("foo\n"); 19 | return 0; 20 | } 21 | 22 | SRC`" 23 | return $? 24 | } 25 | 26 | suite 27 | expect "$? > 0" 28 | --------------------------------------------------------------------------------