From 11a130ed4340f0bdb53943a18735e6f3333e01ec Mon Sep 17 00:00:00 2001 From: John Backus Date: Mon, 23 May 2016 22:16:00 -0700 Subject: [PATCH] Add character type mutations Mutations: - `/\b/` -> `/\B/` (closes #577) - `/\B/` -> `/\b/` (closes #578) - `/\d/` -> `/\D/` (closes #579) - `/\D/` -> `/\d/` (closes #580) - `/\s/` -> `/\S/` (closes #583) - `/\S/` -> `/\s/` (closes #584) - `/\w/` -> `/\W/` (closes #585) - `/\W/` -> `/\w/` (closes #586) --- config/flay.yml | 2 +- lib/mutant.rb | 1 + lib/mutant/mutator/node/generic.rb | 8 ++++++ .../mutator/node/regexp/character_type.rb | 28 +++++++++++++++++++ meta/regexp/character_types.rb | 19 +++++++++++++ 5 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 lib/mutant/mutator/node/regexp/character_type.rb create mode 100644 meta/regexp/character_types.rb diff --git a/config/flay.yml b/config/flay.yml index 092e69b3..860f2976 100644 --- a/config/flay.yml +++ b/config/flay.yml @@ -1,3 +1,3 @@ --- threshold: 16 -total_score: 1290 +total_score: 1317 diff --git a/lib/mutant.rb b/lib/mutant.rb index 50d1125d..6e698023 100644 --- a/lib/mutant.rb +++ b/lib/mutant.rb @@ -91,6 +91,7 @@ require 'mutant/mutator/util/symbol' require 'mutant/mutator/node' require 'mutant/mutator/node/generic' require 'mutant/mutator/node/regexp' +require 'mutant/mutator/node/regexp/character_type' require 'mutant/mutator/node/literal' require 'mutant/mutator/node/literal/boolean' require 'mutant/mutator/node/literal/range' diff --git a/lib/mutant/mutator/node/generic.rb b/lib/mutant/mutator/node/generic.rb index 7dbacf84..c34c1eda 100644 --- a/lib/mutant/mutator/node/generic.rb +++ b/lib/mutant/mutator/node/generic.rb @@ -39,6 +39,14 @@ module Mutant unsupported_regexp_nodes = AST::Types::REGEXP.to_a - %i[ regexp_root_expression regexp_bol_anchor + regexp_word_type + regexp_nonword_type + regexp_digit_type + regexp_nondigit_type + regexp_space_type + regexp_nonspace_type + regexp_word_boundary_anchor + regexp_nonword_boundary_anchor ] # These nodes still need a dedicated mutator, diff --git a/lib/mutant/mutator/node/regexp/character_type.rb b/lib/mutant/mutator/node/regexp/character_type.rb new file mode 100644 index 00000000..d874ab6e --- /dev/null +++ b/lib/mutant/mutator/node/regexp/character_type.rb @@ -0,0 +1,28 @@ +module Mutant + class Mutator + class Node + module Regexp + # Character type mutator + class CharacterType < Node + map = { + regexp_word_type: :regexp_nonword_type, + regexp_digit_type: :regexp_nondigit_type, + regexp_space_type: :regexp_nonspace_type, + regexp_word_boundary_anchor: :regexp_nonword_boundary_anchor + } + + MAP = IceNine.deep_freeze(map.merge(map.invert)) + + handle(*MAP.keys) + + # Mutate to invert character type + # + # @return [undefined] + def dispatch + emit(s(MAP.fetch(node.type))) + end + end # CharacterType + end # Regexp + end # Node + end # Mutator +end # Mutant diff --git a/meta/regexp/character_types.rb b/meta/regexp/character_types.rb new file mode 100644 index 00000000..6fe47547 --- /dev/null +++ b/meta/regexp/character_types.rb @@ -0,0 +1,19 @@ +mutations = { + [:regexp_word_type, '/\w/'] => [:regexp_nonword_type, '/\W/'], + [:regexp_digit_type, '/\d/'] => [:regexp_nondigit_type, '/\D/'], + [:regexp_space_type, '/\s/'] => [:regexp_nonspace_type, '/\S/'], + [:regexp_word_boundary_anchor, '/\b/'] => [:regexp_nonword_boundary_anchor, '/\B/'] +} + +mutations = mutations.merge(mutations.invert) + +mutations.each do |(source_type, source_mutation), (_, regexp_mutation)| + Mutant::Meta::Example.add source_type do + source(source_mutation) + + singleton_mutations + regexp_mutations + + mutation(regexp_mutation) + end +end