• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

dedicate-project / beast / 8dc5bfe9-9d35-4561-9ca2-fb0308b78ba7

pending completion
8dc5bfe9-9d35-4561-9ca2-fb0308b78ba7

push

circleci

GitHub
Added program factory skeleton implementation (#3)

343 of 343 new or added lines in 4 files covered. (100.0%)

2166 of 2222 relevant lines covered (97.48%)

17707.24 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.41
/src/random_program_factory.cpp
1
#include <beast/random_program_factory.hpp>
2

3
// Standard
4
#include <random>
5

6
namespace beast {
7

8
Program RandomProgramFactory::generate(
1,003✔
9
    uint32_t size, uint32_t memory_size, uint32_t string_table_size,
10
    uint32_t string_table_item_length) {
11
  Program prg(size);
1,003✔
12

13
  std::random_device random_device;
2,006✔
14
  std::mt19937 mersenne_engine{random_device()};
1,003✔
15
  std::uniform_int_distribution<> code_distribution(
16
      0, static_cast<int32_t>(OpCode::Size) - 1);
1,003✔
17
  std::uniform_int_distribution<> var_distribution(0, static_cast<int32_t>(memory_size) - 1);
1,003✔
18
  std::uniform_int_distribution<> bool_distribution(0, 1);
1,003✔
19
  std::uniform_int_distribution<> int32_distribution(
20
      std::numeric_limits<int32_t>::min(), std::numeric_limits<int32_t>::max());
1,003✔
21
  std::uniform_int_distribution<> int8_distribution(
22
      std::numeric_limits<int8_t>::min(), std::numeric_limits<int8_t>::max());
1,003✔
23
  std::uniform_int_distribution<> rel_addr_distribution(
24
      -static_cast<int32_t>(static_cast<double>(size) * 0.5),
1,003✔
25
      static_cast<int32_t>(static_cast<double>(size) * 0.5));
1,003✔
26
  std::uniform_int_distribution<> abs_addr_distribution(0, static_cast<int32_t>(size));
1,003✔
27
  std::uniform_int_distribution<> string_table_index_distribution(
28
      0, static_cast<int32_t>(string_table_size));
1,003✔
29

30
  // A random string that fits into the string table, with characters ranging from ASCII 33-126.
31
  const auto string_item_generator = [&mersenne_engine, &string_table_item_length]() {
320,683✔
32
      std::string random_string;
6,105✔
33
      std::uniform_int_distribution<> length_distribution(
34
          0, static_cast<int32_t>(string_table_item_length));
6,105✔
35
      std::uniform_int_distribution<> char_distribution(33, 126);
6,105✔
36
      const int32_t length = length_distribution(mersenne_engine);
6,105✔
37
      for (int32_t idx = 0; idx < length; idx++) {
308,473✔
38
        random_string += static_cast<char>(char_distribution(mersenne_engine));
302,368✔
39
      }
40
      return random_string;
12,210✔
41
  };
1,003✔
42

43
  // Random true/false switch.
44
  const auto bool_generator =
45
      [&bool_distribution, &mersenne_engine]() {
336,171✔
46
        return bool_distribution(mersenne_engine) == 1;
336,171✔
47
      };
1,003✔
48
  // Select variable indices only from the range that actually fits into variable memory.
49
  const auto var_generator =
50
      [&var_distribution, &mersenne_engine]() {
336,199✔
51
        return var_distribution(mersenne_engine);
336,199✔
52
      };
1,003✔
53
  // A random value from the signed int32 range.
54
  const auto int32_generator =
55
      [&int32_distribution, &mersenne_engine]() {
30,256✔
56
        return int32_distribution(mersenne_engine);
30,256✔
57
      };
1,003✔
58
  // A random value from the signed int8 range.
59
  const auto int8_generator =
60
      [&int8_distribution, &mersenne_engine]() {
17,750✔
61
        return static_cast<int8_t>(int8_distribution(mersenne_engine));
17,750✔
62
      };
1,003✔
63
  // A random relative address in the range [-size/2, size/2).
64
  const auto rel_addr_generator =
65
      [&rel_addr_distribution, &mersenne_engine]() {
20,934✔
66
        return rel_addr_distribution(mersenne_engine);
20,934✔
67
      };
1,003✔
68
  // A random valid absolute address in the range [0, size];
69
  const auto abs_addr_generator =
70
      [&abs_addr_distribution, &mersenne_engine]() {
3,066✔
71
        return abs_addr_distribution(mersenne_engine);
3,066✔
72
      };
1,003✔
73
  // A random valid string table index.
74
  const auto string_table_index_generator =
75
      [&string_table_index_distribution, &mersenne_engine]() {
11,814✔
76
        return string_table_index_distribution(mersenne_engine);
11,814✔
77
      };
1,003✔
78

79
  while (true) {
80
    Program fragment;
231,024✔
81

82
    switch (static_cast<OpCode>(code_distribution(mersenne_engine))) {
231,024✔
83
    case OpCode::NoOp: {
2,887✔
84
      fragment.noop();
2,887✔
85
    } break;
2,887✔
86

87
    case OpCode::LoadMemorySizeIntoVariable: {
2,985✔
88
      fragment.loadMemorySizeIntoVariable(var_generator(), bool_generator());
2,985✔
89
    } break;
2,985✔
90

91
    case OpCode::LoadCurrentAddressIntoVariable: {
2,953✔
92
      fragment.loadCurrentAddressIntoVariable(var_generator(), bool_generator());
2,953✔
93
    } break;
2,953✔
94

95
    case OpCode::Terminate: {
3,019✔
96
      std::uniform_int_distribution<> return_code_distribution{-127, 128};
3,019✔
97
      fragment.terminate(static_cast<int8_t>(return_code_distribution(mersenne_engine)));
3,019✔
98
    } break;
3,019✔
99

100
    case OpCode::TerminateWithVariableReturnCode: {
3,014✔
101
      fragment.terminateWithVariableReturnCode(var_generator(), bool_generator());
3,014✔
102
    } break;
3,014✔
103

104
    case OpCode::PerformSystemCall: {
2,935✔
105
      fragment.performSystemCall(
11,740✔
106
          int8_generator(), int8_generator(), var_generator(), bool_generator());
2,935✔
107
    } break;
2,935✔
108

109
    case OpCode::LoadRandomValueIntoVariable: {
2,922✔
110
      fragment.loadRandomValueIntoVariable(var_generator(), bool_generator());
2,922✔
111
    } break;
2,922✔
112

113
    case OpCode::DeclareVariable: {
3,061✔
114
      fragment.declareVariable(
3,061✔
115
          var_generator(),
116
          bool_generator() ? Program::VariableType::Int32 : Program::VariableType::Link);
3,061✔
117
    } break;
3,061✔
118

119
    case OpCode::SetVariable: {
3,078✔
120
      fragment.setVariable(var_generator(), int32_generator(), bool_generator());
3,078✔
121
    } break;
3,078✔
122

123
    case OpCode::UndeclareVariable: {
3,035✔
124
      fragment.undeclareVariable(var_generator());
3,035✔
125
    } break;
3,035✔
126

127
    case OpCode::CopyVariable: {
2,989✔
128
      fragment.copyVariable(var_generator(), bool_generator(), var_generator(), bool_generator());
2,989✔
129
    } break;
2,989✔
130

131
    case OpCode::SwapVariables: {
2,858✔
132
      fragment.swapVariables(var_generator(), bool_generator(), var_generator(), bool_generator());
2,858✔
133
    } break;
2,858✔
134

135
    case OpCode::AddConstantToVariable: {
3,067✔
136
      fragment.addConstantToVariable(var_generator(), int32_generator(), bool_generator());
3,067✔
137
    } break;
3,067✔
138

139
    case OpCode::AddVariableToVariable: {
2,953✔
140
      fragment.addVariableToVariable(
2,953✔
141
          var_generator(), bool_generator(), var_generator(), bool_generator());
2,953✔
142
    } break;
2,953✔
143

144
    case OpCode::SubtractConstantFromVariable: {
2,950✔
145
      fragment.subtractConstantFromVariable(var_generator(), int32_generator(), bool_generator());
2,950✔
146
    } break;
2,950✔
147

148
    case OpCode::SubtractVariableFromVariable: {
2,968✔
149
      fragment.subtractVariableFromVariable(
2,968✔
150
          var_generator(), bool_generator(), var_generator(), bool_generator());
2,968✔
151
    } break;
2,968✔
152

153
    case OpCode::CompareIfVariableGtConstant: {
2,897✔
154
      fragment.compareIfVariableGtConstant(
5,794✔
155
          var_generator(), bool_generator(), int32_generator(), var_generator(), bool_generator());
5,794✔
156
    } break;
2,897✔
157

158
    case OpCode::CompareIfVariableLtConstant: {
3,048✔
159
      fragment.compareIfVariableLtConstant(
6,096✔
160
          var_generator(), bool_generator(), int32_generator(), var_generator(), bool_generator());
6,096✔
161
    } break;
3,048✔
162

163
    case OpCode::CompareIfVariableEqConstant: {
3,018✔
164
      fragment.compareIfVariableEqConstant(
6,036✔
165
          var_generator(), bool_generator(), int32_generator(), var_generator(), bool_generator());
6,036✔
166
    } break;
3,018✔
167

168
    case OpCode::CompareIfVariableGtVariable: {
3,037✔
169
      fragment.compareIfVariableGtVariable(
3,037✔
170
          var_generator(), bool_generator(), var_generator(), bool_generator(),
3,037✔
171
          var_generator(), bool_generator());
3,037✔
172
    } break;
3,037✔
173

174
    case OpCode::CompareIfVariableLtVariable: {
3,001✔
175
      fragment.compareIfVariableLtVariable(
3,001✔
176
          var_generator(), bool_generator(), var_generator(), bool_generator(),
3,001✔
177
          var_generator(), bool_generator());
3,001✔
178
    } break;
3,001✔
179

180
    case OpCode::CompareIfVariableEqVariable: {
2,919✔
181
      fragment.compareIfVariableEqVariable(
2,919✔
182
          var_generator(), bool_generator(), var_generator(), bool_generator(),
2,919✔
183
          var_generator(), bool_generator());
2,919✔
184
    } break;
2,919✔
185

186
    case OpCode::GetMaxOfVariableAndConstant: {
3,071✔
187
      fragment.getMaxOfVariableAndConstant(
6,142✔
188
          var_generator(), bool_generator(), int32_generator(),
3,071✔
189
          var_generator(), bool_generator());
3,071✔
190
    } break;
3,071✔
191

192
    case OpCode::GetMinOfVariableAndConstant: {
3,077✔
193
      fragment.getMinOfVariableAndConstant(
6,154✔
194
          var_generator(), bool_generator(), int32_generator(),
3,077✔
195
          var_generator(), bool_generator());
3,077✔
196
    } break;
3,077✔
197

198
    case OpCode::GetMaxOfVariableAndVariable: {
2,951✔
199
      fragment.getMaxOfVariableAndVariable(
2,951✔
200
          var_generator(), bool_generator(), var_generator(), bool_generator(),
2,951✔
201
          var_generator(), bool_generator());
2,951✔
202
    } break;
2,951✔
203

204
    case OpCode::GetMinOfVariableAndVariable: {
3,047✔
205
      fragment.getMinOfVariableAndVariable(
3,047✔
206
          var_generator(), bool_generator(), var_generator(), bool_generator(),
3,047✔
207
          var_generator(), bool_generator());
3,047✔
208
    } break;
3,047✔
209

210
    case OpCode::ModuloVariableByConstant: {
3,030✔
211
      fragment.moduloVariableByConstant(
6,060✔
212
          var_generator(), bool_generator(), int32_generator());
3,030✔
213
    } break;
3,030✔
214

215
    case OpCode::ModuloVariableByVariable: {
3,035✔
216
      fragment.moduloVariableByVariable(
3,035✔
217
          var_generator(), bool_generator(), var_generator(), bool_generator());
3,035✔
218
    } break;
3,035✔
219

220
    case OpCode::BitShiftVariableLeft: {
2,984✔
221
      fragment.bitShiftVariableLeft(
2,984✔
222
          var_generator(), bool_generator(), int8_generator());
2,984✔
223
    } break;
2,984✔
224

225
    case OpCode::BitShiftVariableRight: {
3,018✔
226
      fragment.bitShiftVariableRight(
3,018✔
227
          var_generator(), bool_generator(), int8_generator());
3,018✔
228
    } break;
3,018✔
229

230
    case OpCode::BitWiseInvertVariable: {
2,927✔
231
      fragment.bitWiseInvertVariable(var_generator(), bool_generator());
2,927✔
232
    } break;
2,927✔
233

234
    case OpCode::BitWiseAndTwoVariables: {
2,981✔
235
      fragment.bitWiseAndTwoVariables(
2,981✔
236
          var_generator(), bool_generator(), var_generator(), bool_generator());
2,981✔
237
    } break;
2,981✔
238

239
    case OpCode::BitWiseOrTwoVariables: {
2,960✔
240
      fragment.bitWiseOrTwoVariables(
2,960✔
241
          var_generator(), bool_generator(), var_generator(), bool_generator());
2,960✔
242
    } break;
2,960✔
243

244
    case OpCode::BitWiseXorTwoVariables: {
2,959✔
245
      fragment.bitWiseXorTwoVariables(
2,959✔
246
          var_generator(), bool_generator(), var_generator(), bool_generator());
2,959✔
247
    } break;
2,959✔
248

249
    case OpCode::RotateVariableLeft: {
2,835✔
250
      fragment.rotateVariableLeft(var_generator(), bool_generator(), int8_generator());
2,835✔
251
    } break;
2,835✔
252

253
    case OpCode::RotateVariableRight: {
3,043✔
254
      fragment.rotateVariableRight(var_generator(), bool_generator(), int8_generator());
3,043✔
255
    } break;
3,043✔
256

257
    case OpCode::VariableBitShiftVariableLeft: {
2,956✔
258
      fragment.variableBitShiftVariableLeft(
2,956✔
259
          var_generator(), bool_generator(), var_generator(), bool_generator());
2,956✔
260
    } break;
2,956✔
261

262
    case OpCode::VariableBitShiftVariableRight: {
2,982✔
263
      fragment.variableBitShiftVariableRight(
2,982✔
264
          var_generator(), bool_generator(), var_generator(), bool_generator());
2,982✔
265
    } break;
2,982✔
266

267
    case OpCode::VariableRotateVariableLeft: {
2,949✔
268
      fragment.variableRotateVariableLeft(
2,949✔
269
          var_generator(), bool_generator(), var_generator(), bool_generator());
2,949✔
270
    } break;
2,949✔
271

272
    case OpCode::VariableRotateVariableRight: {
2,971✔
273
      fragment.variableRotateVariableRight(
2,971✔
274
          var_generator(), bool_generator(), var_generator(), bool_generator());
2,971✔
275
    } break;
2,971✔
276

277
    case OpCode::RelativeJumpToVariableAddressIfVariableGt0: {
3,088✔
278
      fragment.relativeJumpToVariableAddressIfVariableGreaterThanZero(
3,088✔
279
          var_generator(), bool_generator(), var_generator(), bool_generator());
3,088✔
280
    } break;
3,088✔
281

282
    case OpCode::RelativeJumpToVariableAddressIfVariableLt0: {
3,033✔
283
      fragment.relativeJumpToVariableAddressIfVariableLessThanZero(
3,033✔
284
          var_generator(), bool_generator(), var_generator(), bool_generator());
3,033✔
285
    } break;
3,033✔
286

287
    case OpCode::RelativeJumpToVariableAddressIfVariableEq0: {
3,016✔
288
      fragment.relativeJumpToVariableAddressIfVariableEqualsZero(
3,016✔
289
          var_generator(), bool_generator(), var_generator(), bool_generator());
3,016✔
290
    } break;
3,016✔
291

292
    case OpCode::AbsoluteJumpToVariableAddressIfVariableGt0: {
3,036✔
293
      fragment.absoluteJumpToVariableAddressIfVariableGreaterThanZero(
3,036✔
294
          var_generator(), bool_generator(), var_generator(), bool_generator());
3,036✔
295
    } break;
3,036✔
296

297
    case OpCode::AbsoluteJumpToVariableAddressIfVariableLt0: {
3,002✔
298
      fragment.absoluteJumpToVariableAddressIfVariableLessThanZero(
3,002✔
299
          var_generator(), bool_generator(), var_generator(), bool_generator());
3,002✔
300
    } break;
3,002✔
301

302
    case OpCode::AbsoluteJumpToVariableAddressIfVariableEq0: {
3,009✔
303
      fragment.absoluteJumpToVariableAddressIfVariableEqualsZero(
3,009✔
304
          var_generator(), bool_generator(), var_generator(), bool_generator());
3,009✔
305
    } break;
3,009✔
306

307
    case OpCode::RelativeJumpIfVariableGt0: {
3,037✔
308
      fragment.relativeJumpToAddressIfVariableGreaterThanZero(
6,074✔
309
          var_generator(), bool_generator(), rel_addr_generator());
3,037✔
310
    } break;
3,037✔
311

312
    case OpCode::RelativeJumpIfVariableLt0: {
3,039✔
313
      fragment.relativeJumpToAddressIfVariableLessThanZero(
6,078✔
314
          var_generator(), bool_generator(), rel_addr_generator());
3,039✔
315
    } break;
3,039✔
316

317
    case OpCode::RelativeJumpIfVariableEq0: {
3,024✔
318
      fragment.relativeJumpToAddressIfVariableEqualsZero(
6,048✔
319
          var_generator(), bool_generator(), rel_addr_generator());
3,024✔
320
    } break;
3,024✔
321

322
    case OpCode::AbsoluteJumpIfVariableGt0: {
2,976✔
323
      fragment.absoluteJumpToAddressIfVariableGreaterThanZero(
5,952✔
324
          var_generator(), bool_generator(), rel_addr_generator());
2,976✔
325
    } break;
2,976✔
326

327
    case OpCode::AbsoluteJumpIfVariableLt0: {
2,927✔
328
      fragment.absoluteJumpToAddressIfVariableLessThanZero(
5,854✔
329
          var_generator(), bool_generator(), rel_addr_generator());
2,927✔
330
    } break;
2,927✔
331

332
    case OpCode::AbsoluteJumpIfVariableEq0: {
2,991✔
333
      fragment.absoluteJumpToAddressIfVariableEqualsZero(
5,982✔
334
          var_generator(), bool_generator(), rel_addr_generator());
2,991✔
335
    } break;
2,991✔
336

337
    case OpCode::UnconditionalJumpToAbsoluteAddress: {
3,066✔
338
      fragment.unconditionalJumpToAbsoluteAddress(abs_addr_generator());
3,066✔
339
    } break;
3,066✔
340

341
    case OpCode::UnconditionalJumpToAbsoluteVariableAddress: {
3,027✔
342
      fragment.unconditionalJumpToAbsoluteVariableAddress(var_generator(), bool_generator());
3,027✔
343
    } break;
3,027✔
344

345
    case OpCode::UnconditionalJumpToRelativeAddress: {
2,940✔
346
      fragment.unconditionalJumpToRelativeAddress(rel_addr_generator());
2,940✔
347
    } break;
2,940✔
348

349
    case OpCode::UnconditionalJumpToRelativeVariableAddress: {
3,011✔
350
      fragment.unconditionalJumpToRelativeVariableAddress(var_generator(), bool_generator());
3,011✔
351
    } break;
3,011✔
352

353
    case OpCode::CheckIfVariableIsInput: {
2,988✔
354
      fragment.checkIfVariableIsInput(
2,988✔
355
          var_generator(), bool_generator(), var_generator(), bool_generator());
2,988✔
356
    } break;
2,988✔
357

358
    case OpCode::CheckIfVariableIsOutput: {
3,014✔
359
      fragment.checkIfVariableIsOutput(
3,014✔
360
          var_generator(), bool_generator(), var_generator(), bool_generator());
3,014✔
361
    } break;
3,014✔
362

363
    case OpCode::LoadInputCountIntoVariable: {
3,038✔
364
      fragment.loadInputCountIntoVariable(var_generator(), bool_generator());
3,038✔
365
    } break;
3,038✔
366

367
    case OpCode::LoadOutputCountIntoVariable: {
3,026✔
368
      fragment.loadOutputCountIntoVariable(var_generator(), bool_generator());
3,026✔
369
    } break;
3,026✔
370

371
    case OpCode::CheckIfInputWasSet: {
3,073✔
372
      fragment.checkIfInputWasSet(
3,073✔
373
          var_generator(), bool_generator(), var_generator(), bool_generator());
3,073✔
374
    } break;
3,073✔
375

376
    case OpCode::PrintVariable: {
3,007✔
377
      fragment.printVariable(var_generator(), bool_generator(), bool_generator());
3,007✔
378
    } break;
3,007✔
379

380
    case OpCode::SetStringTableEntry: {
3,014✔
381
      fragment.setStringTableEntry(string_table_index_generator(), string_item_generator());
3,014✔
382
    } break;
3,014✔
383

384
    case OpCode::PrintStringFromStringTable: {
2,935✔
385
      fragment.printStringFromStringTable(string_table_index_generator());
2,935✔
386
    } break;
2,935✔
387

388
    case OpCode::LoadStringTableLimitIntoVariable: {
3,020✔
389
      fragment.loadStringTableLimitIntoVariable(var_generator(), bool_generator());
3,020✔
390
    } break;
3,020✔
391

392
    case OpCode::LoadStringTableItemLengthLimitIntoVariable: {
3,045✔
393
      fragment.loadStringTableItemLengthLimitIntoVariable(var_generator(), bool_generator());
3,045✔
394
    } break;
3,045✔
395

396
    case OpCode::SetVariableStringTableEntry: {
3,091✔
397
      fragment.setVariableStringTableEntry(
3,091✔
398
          var_generator(), bool_generator(), string_item_generator());
6,182✔
399
    } break;
3,091✔
400

401
    case OpCode::PrintVariableStringFromStringTable: {
3,097✔
402
      fragment.printVariableStringFromStringTable(var_generator(), bool_generator());
3,097✔
403
    } break;
3,097✔
404

405
    case OpCode::LoadVariableStringItemLengthIntoVariable: {
3,048✔
406
      fragment.loadVariableStringItemLengthIntoVariable(
3,048✔
407
          var_generator(), bool_generator(), var_generator(), bool_generator());
3,048✔
408
    } break;
3,048✔
409

410
    case OpCode::LoadVariableStringItemIntoVariables: {
3,031✔
411
      fragment.loadVariableStringItemIntoVariables(
3,031✔
412
          var_generator(), bool_generator(), var_generator(), bool_generator());
3,031✔
413
    } break;
3,031✔
414

415
    case OpCode::LoadStringItemLengthIntoVariable: {
2,984✔
416
      fragment.loadStringItemLengthIntoVariable(
2,984✔
417
          string_table_index_generator(), var_generator(), bool_generator());
2,984✔
418
    } break;
2,984✔
419

420
    case OpCode::LoadStringItemIntoVariables: {
2,881✔
421
      fragment.loadStringItemIntoVariables(
2,881✔
422
          string_table_index_generator(), var_generator(), bool_generator());
2,881✔
423
    } break;
2,881✔
424

425
    case OpCode::PushVariableOnStack: {
2,985✔
426
      fragment.pushVariableOnStack(
2,985✔
427
          var_generator(), bool_generator(), var_generator(), bool_generator());
2,985✔
428
    } break;
2,985✔
429

430
    case OpCode::PushConstantOnStack: {
3,020✔
431
      fragment.pushConstantOnStack(var_generator(), bool_generator(), int32_generator());
3,020✔
432
    } break;
3,020✔
433

434
    case OpCode::PopVariableFromStack: {
3,089✔
435
      fragment.popVariableFromStack(
3,089✔
436
          var_generator(), bool_generator(), var_generator(), bool_generator());
3,089✔
437
    } break;
3,089✔
438

439
    case OpCode::PopTopItemFromStack: {
3,004✔
440
      fragment.popTopItemFromStack(var_generator(), bool_generator());
3,004✔
441
    } break;
3,004✔
442

443
    case OpCode::CheckIfStackIsEmpty: {
3,042✔
444
      fragment.checkIfStackIsEmpty(
3,042✔
445
          var_generator(), bool_generator(), var_generator(), bool_generator());
3,042✔
446
    } break;
3,042✔
447

448
    case OpCode::Size:
×
449
      // Do nothing
450
      break;
×
451
    }
452

453
    if (fragment.getSize() + prg.getPointer() > prg.getSize()) {
231,024✔
454
      // The instruction doesn't fit into the program anymore. Generation is done.
455
      break;
1,003✔
456
    }
457
    prg.insertProgram(fragment);
230,021✔
458
  }
230,021✔
459

460
  return prg;
2,006✔
461
}
462

463
}  // namespace beast
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc