diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2017-11-16 11:51:01 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-11-16 11:51:01 -0600 |
commit | 50f11e3584c9c0255098bdd438b11a84c093b197 (patch) | |
tree | a3265535f53a6354a72bc260a27c871fc4e240f2 /python/servo/mutation/test.py | |
parent | 5c7e79e91c12d19830fdb4c6c17be2a551f88aa2 (diff) | |
parent | b8c6d144f3445bc969a3bc46a6117226d1097cc1 (diff) | |
download | servo-50f11e3584c9c0255098bdd438b11a84c093b197.tar.gz servo-50f11e3584c9c0255098bdd438b11a84c093b197.zip |
Auto merge of #18984 - dsandeephegde:master, r=jdm
Initial steps of Mutation testing
<!-- Please describe your changes on the following line: -->
- Added one strategy of mutation which is replacing occurrences && to ||.
- Added test mapping framework for running mutation tests corresponding to a mutant.
- Added one test_mapping.json to map source file in a folder to WPT test.
- Added README mentioning about Mutation testing.
- Added CI script to invoke mutation test.
---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [x] These changes #18529 (github issue number if applicable).
- [x] These changes do not require tests because it is a python script to run mutation test and does not change any behavior.
<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/18984)
<!-- Reviewable:end -->
Diffstat (limited to 'python/servo/mutation/test.py')
-rw-r--r-- | python/servo/mutation/test.py | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/python/servo/mutation/test.py b/python/servo/mutation/test.py new file mode 100644 index 00000000000..2248f81ccd3 --- /dev/null +++ b/python/servo/mutation/test.py @@ -0,0 +1,78 @@ +# Copyright 2013 The Servo Project Developers. See the COPYRIGHT +# file at the top-level directory of this distribution. +# +# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +import fileinput +import re +import subprocess +import sys +import os +import random +from enum import Enum +DEVNULL = open(os.devnull, 'wb') + + +class Status(Enum): + KILLED = 0 + SURVIVED = 1 + SKIPPED = 2 + UNEXPECTED = 3 + + +def mutate_random_line(file_name, strategy): + line_numbers = [] + for line in fileinput.input(file_name): + if re.search(strategy['regex'], line): + line_numbers.append(fileinput.lineno()) + if len(line_numbers) == 0: + return -1 + else: + mutation_line_number = line_numbers[random.randint(0, len(line_numbers) - 1)] + for line in fileinput.input(file_name, inplace=True): + if fileinput.lineno() == mutation_line_number: + line = re.sub(strategy['regex'], strategy['replaceString'], line) + print line.rstrip() + return mutation_line_number + + +def mutation_test(file_name, tests): + status = Status.UNEXPECTED + local_changes_present = subprocess.call('git diff --quiet {0}'.format(file_name), shell=True) + if local_changes_present == 1: + status = Status.SKIPPED + print "{0} has local changes, please commit/remove changes before running the test".format(file_name) + else: + strategy = {'regex': r'\s&&\s', 'replaceString': ' || '} + mutated_line = mutate_random_line(file_name, strategy) + if mutated_line != -1: + print "Mutating {0} at line {1}".format(file_name, mutated_line) + print "compiling mutant {0}:{1}".format(file_name, mutated_line) + sys.stdout.flush() + subprocess.call('python mach build --release', shell=True, stdout=DEVNULL) + for test in tests: + test_command = "python mach test-wpt {0} --release".format(test.encode('utf-8')) + print "running `{0}` test for mutant {1}:{2}".format(test, file_name, mutated_line) + sys.stdout.flush() + test_status = subprocess.call(test_command, shell=True, stdout=DEVNULL) + if test_status != 0: + print("Failed: while running `{0}`".format(test_command)) + print "mutated file {0} diff".format(file_name) + sys.stdout.flush() + subprocess.call('git --no-pager diff {0}'.format(file_name), shell=True) + status = Status.SURVIVED + else: + print("Success: Mutation killed by {0}".format(test.encode('utf-8'))) + status = Status.KILLED + break + print "reverting mutant {0}:{1}".format(file_name, mutated_line) + sys.stdout.flush() + subprocess.call('git checkout {0}'.format(file_name), shell=True) + else: + print "Cannot mutate {0}".format(file_name) + print "-" * 80 + "\n" + return status |