1
1
/* jshint globalstrict:false, strict:false, maxlen: 200 */
2
2
/* global fail, assertTrue, assertFalse, assertEqual,
3
3
assertNotEqual, arango, print */
4
+
5
+ // //////////////////////////////////////////////////////////////////////////////
6
+ // / DISCLAIMER
7
+ // /
8
+ // / Copyright 2014-2021 ArangoDB GmbH, Cologne, Germany
9
+ // / Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
10
+ // /
11
+ // / Licensed under the Apache License, Version 2.0 (the "License")
12
+ // / you may not use this file except in compliance with the License.
13
+ // / You may obtain a copy of the License at
14
+ // /
15
+ // / http://www.apache.org/licenses/LICENSE-2.0
16
+ // /
17
+ // / Unless required by applicable law or agreed to in writing, software
18
+ // / distributed under the License is distributed on an "AS IS" BASIS,
19
+ // / WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
+ // / See the License for the specific language governing permissions and
21
+ // / limitations under the License.
22
+ // /
23
+ // / Copyright holder is ArangoDB GmbH, Cologne, Germany
24
+ // /
25
+ // / @author Manuel Pöter
26
+ // //////////////////////////////////////////////////////////////////////////////
4
27
5
- // //////////////////////////////////////////////////////////////////////////////
6
- // / DISCLAIMER
7
- // /
8
- // / Copyright 2018 ArangoDB GmbH, Cologne, Germany
9
- // /
10
- // / Licensed under the Apache License, Version 2.0 (the "License")
11
- // / you may not use this file except in compliance with the License.
12
- // / You may obtain a copy of the License at
13
- // /
14
- // / http://www.apache.org/licenses/LICENSE-2.0
15
- // /
16
- // / Unless required by applicable law or agreed to in writing, software
17
- // / distributed under the License is distributed on an "AS IS" BASIS,
18
- // / WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
- // / See the License for the specific language governing permissions and
20
- // / limitations under the License.
21
- // /
22
- // / Copyright holder is triAGENS GmbH, Cologne, Germany
23
- // /
24
- // / @author Manuel Pöter
25
- // //////////////////////////////////////////////////////////////////////////////
26
28
'use strict' ;
27
29
const _ = require('lodash' );
28
30
const jsunity = require('jsunity' );
@@ -122,16 +124,15 @@ const clearAllFailurePoints = () => {
122
124
function BaseChaosSuite(testOpts) {
123
125
// generate a random collection name
124
126
const cn = "UnitTests" + require("@arangodb/crypto" ).md5(internal.genRandomAlphaNumbers(32));
125
- const communication_cn = cn + "_comm" ;
126
-
127
+ const coordination_cn = cn + "_coord" ;
127
128
128
129
return {
129
130
setUp: function () {
130
131
db._drop(cn);
131
- db . _drop ( communication_cn ) ;
132
+ db._drop(coordination_cn );
132
133
let rf = Math.max(2, getDBServers().length);
133
134
db._create(cn, { numberOfShards: rf * 2, replicationFactor: rf });
134
- db . _create ( communication_cn ) ;
135
+ db._create(coordination_cn );
135
136
136
137
if (testOpts.withFailurePoints) {
137
138
let servers = getDBServers();
@@ -160,12 +161,12 @@ function BaseChaosSuite(testOpts) {
160
161
clearAllFailurePoints();
161
162
db._drop(cn);
162
163
163
- const shells = db [ communication_cn ] . all ( ) ;
164
+ const shells = db[coordination_cn ].all();
164
165
if (shells.length > 0) {
165
- print ( "Found remaining docs in communication collection:" ) ;
166
+ print("Found remaining docs in coordination collection:" );
166
167
print(shells);
167
168
}
168
- db . _drop ( communication_cn ) ;
169
+ db._drop(coordination_cn );
169
170
},
170
171
171
172
testWorkInParallel: function () {
@@ -176,8 +177,12 @@ function BaseChaosSuite(testOpts) {
176
177
const key = () => "testmann" + Math.floor(Math.random() * 100000000);
177
178
const docs = () => {
178
179
let result = [];
179
- // TODO - optionally use only single-document operations
180
- const r = Math . floor ( Math . random ( ) * 2000 ) + 1 ;
180
+ const max = 2000;
181
+ const r = Math.floor(Math.random() * max) + 1;
182
+ if (r > (max * 0.8)) {
183
+ // we want ~20% of all requests to be single document operations
184
+ r = 1;
185
+ }
181
186
for (let i = 0; i < r; ++i) {
182
187
result.push({ _key: key() });
183
188
}
@@ -208,26 +213,24 @@ function BaseChaosSuite(testOpts) {
208
213
209
214
let query = (...args) => db._query(...args);
210
215
let trx = null;
211
- let isTransaction = false ;
212
216
if (testOpts.withStreamingTransactions && Math.random() < 0.5) {
213
217
trx = db._createTransaction({ collections: { write: [c.name()] } });
214
218
c = trx.collection(testOpts.collection);
215
219
query = (...args) => trx.query(...args);
216
- isTransaction = true ;
217
220
}
218
221
219
- const logAllOps = false ;
222
+ const logAllOps = false ; // can be set to true for debugging purposes
220
223
const log = (msg) => {
221
224
if (logAllOps) {
222
225
console.info(msg);
223
226
}
224
227
};
225
- const ops = isTransaction ? Math . floor ( Math . random ( ) * 5 ) + 1 : 1 ;
228
+ const ops = trx === null ? 1 : Math.floor(Math.random() * 5) + 1;
226
229
for (let op = 0; op < ops; ++op) {
227
230
try {
228
231
const d = Math.random();
229
232
if (d >= 0.98 && testOpts.withTruncate) {
230
- console . warn ( "RUNNING TRUNCATE" ) ;
233
+ log ("RUNNING TRUNCATE" );
231
234
c.truncate();
232
235
} else if (d >= 0.9) {
233
236
let o = opts();
@@ -248,10 +251,12 @@ function BaseChaosSuite(testOpts) {
248
251
let o = opts();
249
252
let d = docs();
250
253
log(`RUNNING INSERT WITH ${d.length} DOCS. OPTIONS: ${JSON.stringify(o)}`);
254
+ d = d.length == 1 ? d[0] : d;
251
255
c.insert(d, o);
252
256
} else {
253
257
let d = docs();
254
258
log(`RUNNING REMOVE WITH ${d.length} DOCS`);
259
+ d = d.length == 1 ? d[0] : d;
255
260
c.remove(d);
256
261
}
257
262
} catch (err) {}
@@ -275,7 +280,7 @@ function BaseChaosSuite(testOpts) {
275
280
}
276
281
277
282
// run the suite for 5 minutes
278
- runParallelArangoshTests ( tests , 5 * 60 , communication_cn ) ;
283
+ runParallelArangoshTests(tests, 5 * 60, coordination_cn );
279
284
280
285
print("Finished load test - waiting for cluster to get in sync before checking consistency." );
281
286
clearAllFailurePoints();
@@ -285,44 +290,40 @@ function BaseChaosSuite(testOpts) {
285
290
};
286
291
}
287
292
288
- function BuildChaosSuite ( opts , suffix ) {
289
- let suite = { } ;
290
- deriveTestSuite ( BaseChaosSuite ( opts ) , suite , suffix ) ;
291
- return suite ;
292
- }
293
-
294
- const params = [ "IntermediateCommits" , "FailurePoints" , "Truncate" , "VaryingOverwriteMode" , "StreamingTransactions" ] ;
293
+ // truncate is disabled because it does not work reliably ATM
294
+ const params = ["IntermediateCommits" , "FailurePoints" , /* "Truncate",*/ "VaryingOverwriteMode" , "StreamingTransactions" ];
295
295
296
- function addSuite ( paramValues ) {
296
+ const makeConfig = (paramValues) => {
297
297
let suffix = "" ;
298
298
let opts = {};
299
299
for (let j = 0; j < params.length; ++j) {
300
300
suffix += paramValues[j] ? "_with_" : "_no_" ;
301
301
suffix += params[j];
302
302
opts["with" + params[j]] = paramValues[j];
303
- }
304
- let func = function ( ) { return BuildChaosSuite ( opts , suffix ) ; } ;
303
+ }
304
+ return { suffix: suffix, options: opts };
305
+ }
306
+
307
+ const run = () => {
308
+ if (!global.currentTestConfig) {
309
+ throw "Chaos test requires global currentTestConfig to be defined!" ;
310
+ }
311
+ const { options, suffix } = global.currentTestConfig;
312
+ print("Running chaos test with config " , options);
313
+
314
+ let func = function () {
315
+ let suite = {};
316
+ deriveTestSuite(BaseChaosSuite(options), suite, suffix);
317
+ return suite;
318
+ };
305
319
// define the function name as it shows up as suiteName
306
320
Object.defineProperty(func, 'name' , {value: "ChaosSuite" + suffix, writable: false });
307
321
308
322
jsunity.run(func);
309
- }
310
323
311
- /*
312
- This code dynamically creates test suites for all parameter combinations.
313
- ATM we don't use it since we don't want to include ALL suites in the PR tests, but
314
- we do want to have them in the nightlies, but that will be done in a separate PR.
315
- for (let i = 0; i < (1 << params.length); ++i) {
316
- let paramValues = [];
317
- for (let j = params.length - 1; j >= 0; --j) {
318
- paramValues.push(Boolean(i & (1 << j)));
319
- }
320
- addSuite(paramValues);
324
+ return jsunity.done();
321
325
}
322
- */
323
-
324
- // ATM we only create a single suite with all options except Truncate, because there are still known issues.
325
- // Later we probably want to have all possible combinations, at least for the nightly builds.
326
- addSuite ( [ true , true , false , true , true ] ) ;
327
326
328
- return jsunity . done ( ) ;
327
+ module.exports.parameters = params;
328
+ module.exports.makeConfig = makeConfig;
329
+ module.exports.run = run;
0 commit comments