@@ -104,6 +104,10 @@ jobs:
104
104
os : ubuntu-latest
105
105
python-version : 3.9
106
106
tox-env : codechecks
107
+ - name : mutation testing
108
+ os : ubuntu-latest
109
+ python-version : ' 3.11'
110
+ mutation : ' true'
107
111
steps :
108
112
- uses : actions/checkout@v2
109
113
if : ${{ !matrix.container }}
@@ -149,6 +153,11 @@ jobs:
149
153
run : |
150
154
apt-get update
151
155
apt-get install -y git make python-is-python3 python3 curl wget python3-distutils python3-pip
156
+
157
+ - name : Dependencies for mutation testing
158
+ if : ${{ matrix.mutation == 'true' }}
159
+ run : |
160
+ sudo apt-get install -y sqlite3
152
161
- name : workaround git failures with py3.10
153
162
run : |
154
163
git config --global --add safe.directory /__w/python-ecdsa/python-ecdsa
@@ -256,11 +265,15 @@ jobs:
256
265
else
257
266
pip install -r build-requirements.txt;
258
267
fi
268
+ - name : Install mutation testing dependencies
269
+ if : ${{ matrix.mutation == 'true' }}
270
+ run : |
271
+ pip install cosmic-ray
259
272
- name : Display installed python package versions
260
273
run : pip list
261
274
- name : Test native speed
262
275
# tox uses pip to install dependenceis, so it breaks on py2.6
263
- if : ${{ !contains(matrix.tox-env, 'gmpy') && matrix.python-version != '2.6'}}
276
+ if : ${{ !contains(matrix.tox-env, 'gmpy') && matrix.python-version != '2.6' && ! matrix.mutation && !contains(matrix.tox-env, 'codechecks') }}
264
277
run : tox -e speed
265
278
- name : Test speed with gmpy
266
279
if : ${{ contains(matrix.tox-env, 'gmpyp') }}
@@ -277,6 +290,25 @@ jobs:
277
290
- name : Run unit tests
278
291
if : ${{ matrix.tox-env }}
279
292
run : tox -e ${{ matrix.tox-env }}
293
+ - name : Init for mutation testing in PR
294
+ if : ${{ matrix.mutation == 'true' && github.event.pull_request }}
295
+ run : |
296
+ cosmic-ray init cosmic-ray.toml session-vs-master.sqlite
297
+ git branch master origin/master
298
+ cr-filter-git --config cosmic-ray.toml session-vs-master.sqlite
299
+ cr-report session-vs-master.sqlite | tail -n 5
300
+ - name : Exec mutation testing for PR
301
+ if : ${{ matrix.mutation == 'true' && github.event.pull_request }}
302
+ run : |
303
+ cosmic-ray exec cosmic-ray.toml session-vs-master.sqlite
304
+ - name : Check test coverage for PR
305
+ if : ${{ matrix.mutation == 'true' && github.event.pull_request }}
306
+ run : |
307
+ # remove not-executed results
308
+ sqlite3 session-vs-master.sqlite "DELETE from work_results WHERE work_results.worker_outcome = 'SKIPPED'"
309
+ cr-report session-vs-master.sqlite | tail -n 5
310
+ # check if executed have at most 5% survival rate
311
+ cr-rate --fail-over 5 session-vs-master.sqlite
280
312
- name : instrumental test coverage on PR
281
313
if : ${{ contains(matrix.opt-deps, 'instrumental') && github.event.pull_request }}
282
314
env :
@@ -337,3 +369,272 @@ jobs:
337
369
COVERALLS_SERVICE_NAME : github
338
370
run : |
339
371
coveralls --finish
372
+
373
+ mutation-prepare :
374
+ name : Prepare job files for the mutation runners
375
+ runs-on : ubuntu-latest
376
+ steps :
377
+ - uses : actions/checkout@v2
378
+ if : ${{ !matrix.container }}
379
+ with :
380
+ fetch-depth : 50
381
+ - name : save session objects
382
+ uses : actions/cache@v3
383
+ with :
384
+ path : |
385
+ sessions/
386
+ key : sessions-${{ github.sha }}
387
+ - name : Install cosmic-ray
388
+ run : |
389
+ pip3 install cosmic-ray
390
+ - name : Install dependencies
391
+ run : |
392
+ sudo apt-get install -y sqlite3
393
+ - name : Display Python version
394
+ run : python -c "import sys; print(sys.version)"
395
+ - name : Create list of mutations
396
+ run : |
397
+ cosmic-ray init cosmic-ray.toml session.sqlite
398
+ - name : Log number of jobs created
399
+ run : |
400
+ cr-report session.sqlite | tail -n 3
401
+ - name : Split up mutations to workers
402
+ run : |
403
+ cp session.sqlite session-to_del.sqlite
404
+ sqlite3 session-to_del.sqlite "$(cat sql/create_to_del.sql)"
405
+ mkdir sessions
406
+ for i in $(seq 0 19); do
407
+ sed "s/%SHARD%/$i/" < sql/shard-db.sql > shard.sql
408
+ cp session-to_del.sqlite session-$i.sqlite
409
+ sqlite3 session-$i.sqlite "$(cat shard.sql)"
410
+ mv session-$i.sqlite sessions/
411
+ done
412
+ mutation-execute :
413
+ name : Execute mutation testing
414
+ needs : mutation-prepare
415
+ runs-on : ubuntu-latest
416
+ strategy :
417
+ fail-fast : false
418
+ matrix :
419
+ include :
420
+ - name : 0
421
+ - name : 1
422
+ - name : 2
423
+ - name : 3
424
+ - name : 4
425
+ - name : 5
426
+ - name : 6
427
+ - name : 7
428
+ - name : 8
429
+ - name : 9
430
+ - name : 10
431
+ - name : 11
432
+ - name : 12
433
+ - name : 13
434
+ - name : 14
435
+ - name : 15
436
+ - name : 16
437
+ - name : 17
438
+ - name : 18
439
+ - name : 19
440
+ steps :
441
+ - uses : actions/checkout@v2
442
+ if : ${{ !matrix.container }}
443
+ with :
444
+ fetch-depth : 1
445
+ - name : Session objects
446
+ uses : actions/cache@v3
447
+ with :
448
+ path : |
449
+ sessions/
450
+ key : sessions-${{ github.sha }}
451
+ - name : Session done objects
452
+ uses : actions/cache@v3
453
+ with :
454
+ path : |
455
+ sessions-done/session-${{ matrix.name }}-done.sqlite
456
+ key : sessions-${{ github.sha }}-${{ matrix.name }}-done
457
+ - name : Install gmpy2 dependencies
458
+ run : sudo apt-get install -y libmpfr-dev libmpc-dev
459
+ - name : Install gmpy2
460
+ run : pip install gmpy2
461
+ - name : Install build dependencies
462
+ run : |
463
+ pip install -r build-requirements.txt
464
+ pip install cosmic-ray
465
+ - name : Run mutation testing
466
+ run : |
467
+ cp sessions/session-${{ matrix.name }}.sqlite session.sqlite
468
+ systemd-run --user --scope -p MemoryMax=2G -p MemoryHigh=2G cosmic-ray exec cosmic-ray.toml session.sqlite &
469
+ cosmic_pid=$!
470
+ for i in $(seq 1 10); do
471
+ echo $i
472
+ sleep 60
473
+ done
474
+ kill $cosmic_pid
475
+ mkdir sessions-done/
476
+ cp session.sqlite sessions-done/session-${{ matrix.name }}-done.sqlite
477
+ - name : Report executed
478
+ run : |
479
+ cr-report session.sqlite | tail -n 3
480
+ mutation-combine :
481
+ name : Combine mutation testing results
482
+ needs : mutation-execute
483
+ runs-on : ubuntu-latest
484
+ steps :
485
+ - uses : actions/checkout@v2
486
+ if : ${{ !matrix.container }}
487
+ with :
488
+ fetch-depth : 1
489
+ - name : Session done 0 objects
490
+ uses : actions/cache@v3
491
+ with :
492
+ path : |
493
+ sessions-done/session-0-done.sqlite
494
+ key : sessions-${{ github.sha }}-0-done
495
+ - name : Session done 1 objects
496
+ uses : actions/cache@v3
497
+ with :
498
+ path : |
499
+ sessions-done/session-1-done.sqlite
500
+ key : sessions-${{ github.sha }}-1-done
501
+ - name : Session done 2 objects
502
+ uses : actions/cache@v3
503
+ with :
504
+ path : |
505
+ sessions-done/session-2-done.sqlite
506
+ key : sessions-${{ github.sha }}-2-done
507
+ - name : Session done 3 objects
508
+ uses : actions/cache@v3
509
+ with :
510
+ path : |
511
+ sessions-done/session-3-done.sqlite
512
+ key : sessions-${{ github.sha }}-3-done
513
+ - name : Session done 4 objects
514
+ uses : actions/cache@v3
515
+ with :
516
+ path : |
517
+ sessions-done/session-4-done.sqlite
518
+ key : sessions-${{ github.sha }}-4-done
519
+ - name : Session done 5 objects
520
+ uses : actions/cache@v3
521
+ with :
522
+ path : |
523
+ sessions-done/session-5-done.sqlite
524
+ key : sessions-${{ github.sha }}-5-done
525
+ - name : Session done 6 objects
526
+ uses : actions/cache@v3
527
+ with :
528
+ path : |
529
+ sessions-done/session-6-done.sqlite
530
+ key : sessions-${{ github.sha }}-6-done
531
+ - name : Session done 7 objects
532
+ uses : actions/cache@v3
533
+ with :
534
+ path : |
535
+ sessions-done/session-7-done.sqlite
536
+ key : sessions-${{ github.sha }}-7-done
537
+ - name : Session done 8 objects
538
+ uses : actions/cache@v3
539
+ with :
540
+ path : |
541
+ sessions-done/session-8-done.sqlite
542
+ key : sessions-${{ github.sha }}-8-done
543
+ - name : Session done 9 objects
544
+ uses : actions/cache@v3
545
+ with :
546
+ path : |
547
+ sessions-done/session-9-done.sqlite
548
+ key : sessions-${{ github.sha }}-9-done
549
+ - name : Session done 10 objects
550
+ uses : actions/cache@v3
551
+ with :
552
+ path : |
553
+ sessions-done/session-10-done.sqlite
554
+ key : sessions-${{ github.sha }}-10-done
555
+ - name : Session done 11 objects
556
+ uses : actions/cache@v3
557
+ with :
558
+ path : |
559
+ sessions-done/session-11-done.sqlite
560
+ key : sessions-${{ github.sha }}-11-done
561
+ - name : Session done 12 objects
562
+ uses : actions/cache@v3
563
+ with :
564
+ path : |
565
+ sessions-done/session-12-done.sqlite
566
+ key : sessions-${{ github.sha }}-12-done
567
+ - name : Session done 13 objects
568
+ uses : actions/cache@v3
569
+ with :
570
+ path : |
571
+ sessions-done/session-13-done.sqlite
572
+ key : sessions-${{ github.sha }}-13-done
573
+ - name : Session done 14 objects
574
+ uses : actions/cache@v3
575
+ with :
576
+ path : |
577
+ sessions-done/session-14-done.sqlite
578
+ key : sessions-${{ github.sha }}-14-done
579
+ - name : Session done 15 objects
580
+ uses : actions/cache@v3
581
+ with :
582
+ path : |
583
+ sessions-done/session-15-done.sqlite
584
+ key : sessions-${{ github.sha }}-15-done
585
+ - name : Session done 16 objects
586
+ uses : actions/cache@v3
587
+ with :
588
+ path : |
589
+ sessions-done/session-16-done.sqlite
590
+ key : sessions-${{ github.sha }}-16-done
591
+ - name : Session done 17 objects
592
+ uses : actions/cache@v3
593
+ with :
594
+ path : |
595
+ sessions-done/session-17-done.sqlite
596
+ key : sessions-${{ github.sha }}-17-done
597
+ - name : Session done 18 objects
598
+ uses : actions/cache@v3
599
+ with :
600
+ path : |
601
+ sessions-done/session-18-done.sqlite
602
+ key : sessions-${{ github.sha }}-18-done
603
+ - name : Session done 19 objects
604
+ uses : actions/cache@v3
605
+ with :
606
+ path : |
607
+ sessions-done/session-19-done.sqlite
608
+ key : sessions-${{ github.sha }}-19-done
609
+ - name : Install cosmic-ray
610
+ run : |
611
+ pip3 install cosmic-ray
612
+ - name : Install dependencies
613
+ run : |
614
+ sudo apt-get install -y sqlite3
615
+ - name : Combine worker results
616
+ run : |
617
+ cp sessions-done/session-0-done.sqlite session.sqlite
618
+ for i in $(seq 1 19); do
619
+ cp sessions-done/session-$i-done.sqlite session-to_merge.sqlite && sqlite3 session.sqlite "$(cat sql/combine.sql)" || true
620
+ done
621
+ - name : Report executed
622
+ run : |
623
+ cr-report session.sqlite | tail -n 3
624
+ - name : Log survival estimate
625
+ run : cr-rate --estimate --fail-over 32 --confidence 99.9 session.sqlite || true
626
+ - name : Get mutation score
627
+ run : |
628
+ echo "print(100-$(cr-rate session.sqlite))" > print-score.py
629
+ echo "MUT_SCORE=$(python print-score.py)" >> $GITHUB_ENV
630
+ - name : Create mutation score badge
631
+ uses :
schneegans/[email protected]
632
+ with :
633
+ auth : ${{ secrets.GIST_SECRET }}
634
+ gistID : 9b6ca1f3410207fbeca785a178781651
635
+ filename : python-ecdsa-mutation-score.json
636
+ label : mutation score
637
+ message : ${{ env.MUT_SCORE }}%
638
+ valColorRange : ${{ env.MUT_SCORE }}
639
+ maxColorRange : 100
640
+ minColorRange : 0
0 commit comments