summaryrefslogtreecommitdiff
path: root/jstests/concurrency/fsm_libs/assert.js
blob: 437742ac39628f181d6e426b5f54c669385fc58c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
'use strict';

/**
 * Helpers for controlling under which situations an assert is actually executed.
 * This allows us to define workloads that will have only valid assertions,
 * regardless of how any particular workload gets run with any others.
 *
 * There are 3 different assert levels:
 *   ALWAYS   = these assertions are always executed
 *   OWN_COLL = these assertions are executed when workloads are run on separate collections
 *   OWN_DB   = these assertions are executed when workloads are run on separate databases
 */

var AssertLevel = (function() {

    function AssertLevel(level) {
        this.level = level;

        // Returns < 0 if this < other
        //         = 0 if this == other
        //         > 0 if this > other
        this.compareTo = function(other) {
            return this.level - other.level;
        };
    }

    function isAssertLevel(obj) {
        return obj instanceof AssertLevel;
    }

    return {
        ALWAYS: new AssertLevel(0),
        OWN_COLL: new AssertLevel(1),
        OWN_DB: new AssertLevel(2),
        isAssertLevel: isAssertLevel
    };

})();

if (typeof globalAssertLevel === 'undefined') {
    var globalAssertLevel = AssertLevel.OWN_DB;
}

var assertWithLevel = function(level) {
    assert(AssertLevel.isAssertLevel(level), 'expected AssertLevel as first argument');

    function quietlyDoAssert(msg, obj) {
        // eval if msg is a function
        if (typeof msg === 'function') {
            msg = msg();
        }

        var ex;
        if (obj) {
            ex = _getErrorWithCode(obj, msg);
        } else {
            ex = new Error(msg);
        }

        throw ex;
    }

    function wrapAssertFn(fn, args) {
        var doassertSaved = doassert;
        try {
            doassert = quietlyDoAssert;
            fn.apply(assert, args);  // functions typically get called on 'assert'
        } finally {
            doassert = doassertSaved;
        }
    }

    var assertWithLevel = function() {
        // Only execute assertion if level for which it was defined is
        // a subset of the global assertion level
        if (level.compareTo(globalAssertLevel) > 0) {
            return;
        }

        if (arguments.length === 1 && typeof arguments[0] === 'function') {
            // Assert against the value returned by the function
            arguments[0] = arguments[0]();

            // If a function does not explictly return a value,
            // then have it implicitly return true
            if (typeof arguments[0] === 'undefined') {
                arguments[0] = true;
            }
        }

        wrapAssertFn(assert, arguments);
    };

    Object.keys(assert).forEach(function(fn) {
        if (typeof assert[fn] !== 'function') {
            return;
        }

        assertWithLevel[fn] = function() {
            // Only execute assertion if level for which it was defined is
            // a subset of the global assertion level
            if (level.compareTo(globalAssertLevel) > 0) {
                return;
            }

            wrapAssertFn(assert[fn], arguments);
        };
    });

    return assertWithLevel;
};

var assertAlways = assertWithLevel(AssertLevel.ALWAYS);
var assertWhenOwnColl = assertWithLevel(AssertLevel.OWN_COLL);
var assertWhenOwnDB = assertWithLevel(AssertLevel.OWN_DB);