summaryrefslogtreecommitdiff
path: root/jstests/concurrency/fsm_libs/parse_config.js
blob: 1b53f42841c736195c7fb2ce272c5491b6ccd436 (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
'use strict';

// Validate the config object and return a normalized copy of it.
// Normalized means all optional parameters are set to their default values,
// and any parameters that need to be coerced have been coerced.
function parseConfig(config) {
    config = Object.extend({}, config, true); // defensive deep copy

    var allowedKeys = [
        'data',
        'iterations',
        'passConnectionCache',
        'setup',
        'startState',
        'states',
        'teardown',
        'threadCount',
        'transitions'
    ];

    Object.keys(config).forEach(function(key) {
        assert.contains(key, allowedKeys,
                       'invalid config parameter: ' + key +
                       '; valid parameters are: ' + tojson(allowedKeys));
    });

    assert(Number.isInteger(config.threadCount),
           'expected number of threads to be an integer');
    assert.gt(config.threadCount, 0,
              'expected number of threads to be positive');

    assert(Number.isInteger(config.iterations),
           'expected number of iterations to be an integer');
    assert.gt(config.iterations, 0,
              'expected number of iterations to be positive');

    config.startState = config.startState || 'init';
    assert.eq('string', typeof config.startState);

    assert.eq('object', typeof config.states);
    assert.gt(Object.keys(config.states).length, 0);
    Object.keys(config.states).forEach(function(k) {
        assert.eq('function', typeof config.states[k],
                   'config.states.' + k + ' is not a function');
        if (config.passConnectionCache) {
             assert.eq(3, config.states[k].length,
                      'if passConnectionCache is true, state functions should ' +
                      'accept 3 parameters: db, collName, and connCache');
        } else {
            assert.eq(2, config.states[k].length,
                      'if passConnectionCache is false, state functions should ' +
                      'accept 2 parameters: db and collName');
        }
    });

    // assert all states mentioned in config.transitions are present in config.states
    assert.eq('object', typeof config.transitions);
    assert.gt(Object.keys(config.transitions).length, 0);
    Object.keys(config.transitions).forEach(function(fromState) {
        assert(config.states.hasOwnProperty(fromState),
               'config.transitions contains a state not in config.states: ' + fromState);

        assert.gt(Object.keys(config.transitions[fromState]).length, 0);
        Object.keys(config.transitions[fromState]).forEach(function(toState) {
            assert(config.states.hasOwnProperty(toState),
                   'config.transitions.' + fromState +
                   ' contains a state not in config.states: ' + toState);
            assert.eq('number', typeof config.transitions[fromState][toState],
                      'transitions.' + fromState + '.' + toState + ' should be a number');
            assert(!isNaN(config.transitions[fromState][toState]),
                   'transitions.' + fromState + '.' + toState + ' cannot be NaN');
        });
    });

    config.setup = config.setup || function(){};
    assert.eq('function', typeof config.setup);

    config.teardown = config.teardown || function(){};
    assert.eq('function', typeof config.teardown);

    config.data = config.data || {};
    assert.eq('object', typeof config.data);
    assert.eq(false, config.data.hasOwnProperty('tid'),
              'data object cannot redefine "tid"');
    assert.eq(false, config.data.hasOwnProperty('iterations'),
              'data object cannot redefine "iterations"');
    assert.eq(false, config.data.hasOwnProperty('threadCount'),
              'data object cannot redefine "threadCount"');

    config.passConnectionCache = config.passConnectionCache || false;
    assert.eq('boolean', typeof config.passConnectionCache);

    return config;
}