Class: Henitai::EquivalenceDetector
- Inherits:
-
Object
- Object
- Henitai::EquivalenceDetector
- Defined in:
- lib/henitai/equivalence_detector.rb,
sig/henitai.rbs
Overview
Detects obvious equivalent mutants before execution.
The detector is intentionally conservative: it only marks mutations as equivalent when the AST shape and the operand literals make the equivalence obvious enough to be useful.
Instance Method Summary collapse
- #additive_equivalent?(original, mutated) ⇒ Boolean
- #additive_operator?(operator) ⇒ Boolean
- #analyze(mutant) ⇒ Mutant
- #binary_send?(node) ⇒ Boolean
- #equivalent_arithmetic_mutation?(mutant) ⇒ Boolean
-
#initialize ⇒ EquivalenceDetector
constructor
A new instance of EquivalenceDetector.
- #multiplicative_equivalent?(original, mutated) ⇒ Boolean
- #multiplicative_operator?(operator) ⇒ Boolean
- #numeric_operand?(node, value) ⇒ Boolean
- #one_operand?(node) ⇒ Boolean
- #same_node?(left, right) ⇒ Boolean
- #same_receiver?(original, mutated) ⇒ Boolean
- #zero_operand?(node) ⇒ Boolean
Constructor Details
#initialize ⇒ EquivalenceDetector
Returns a new instance of EquivalenceDetector.
571 |
# File 'sig/henitai.rbs', line 571
def initialize: () -> void
|
Instance Method Details
#additive_equivalent?(original, mutated) ⇒ Boolean
46 47 48 49 50 51 |
# File 'lib/henitai/equivalence_detector.rb', line 46 def additive_equivalent?(original, mutated) additive_operator?(original.children[1]) && additive_operator?(mutated.children[1]) && zero_operand?(original) && zero_operand?(mutated) end |
#additive_operator?(operator) ⇒ Boolean
115 116 117 |
# File 'lib/henitai/equivalence_detector.rb', line 115 def additive_operator?(operator) %i[+ -].include?(operator) end |
#analyze(mutant) ⇒ Mutant
12 13 14 15 16 17 |
# File 'lib/henitai/equivalence_detector.rb', line 12 def analyze(mutant) return mutant unless equivalent_mutation?(mutant) mutant.status = :equivalent mutant end |
#binary_send?(node) ⇒ Boolean
38 39 40 |
# File 'lib/henitai/equivalence_detector.rb', line 38 def binary_send?(node) node.is_a?(Parser::AST::Node) && node.type == :send && node.children.size >= 3 end |
#equivalent_arithmetic_mutation?(mutant) ⇒ Boolean
28 29 30 31 32 33 34 35 36 |
# File 'lib/henitai/equivalence_detector.rb', line 28 def equivalent_arithmetic_mutation?(mutant) original = mutant.original_node mutated = mutant.mutated_node return false unless binary_send?(original) && binary_send?(mutated) return false unless same_receiver?(original, mutated) additive_equivalent?(original, mutated) || multiplicative_equivalent?(original, mutated) end |
#multiplicative_equivalent?(original, mutated) ⇒ Boolean
53 54 55 56 57 58 |
# File 'lib/henitai/equivalence_detector.rb', line 53 def multiplicative_equivalent?(original, mutated) multiplicative_operator?(original.children[1]) && multiplicative_operator?(mutated.children[1]) && one_operand?(original) && one_operand?(mutated) end |
#multiplicative_operator?(operator) ⇒ Boolean
119 120 121 |
# File 'lib/henitai/equivalence_detector.rb', line 119 def multiplicative_operator?(operator) %i[* / **].include?(operator) end |
#numeric_operand?(node, value) ⇒ Boolean
131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/henitai/equivalence_detector.rb', line 131 def numeric_operand?(node, value) operand = node.children[2] return false unless operand.is_a?(Parser::AST::Node) case operand.type when :int, :float operand.children.first == value || operand.children.first == value.to_i else false end end |
#one_operand?(node) ⇒ Boolean
127 128 129 |
# File 'lib/henitai/equivalence_detector.rb', line 127 def one_operand?(node) numeric_operand?(node, 1) end |
#same_node?(left, right) ⇒ Boolean
252 253 254 |
# File 'lib/henitai/equivalence_detector.rb', line 252 def same_node?(left, right) left == right end |
#same_receiver?(original, mutated) ⇒ Boolean
42 43 44 |
# File 'lib/henitai/equivalence_detector.rb', line 42 def same_receiver?(original, mutated) same_node?(original.children[0], mutated.children[0]) end |
#zero_operand?(node) ⇒ Boolean
123 124 125 |
# File 'lib/henitai/equivalence_detector.rb', line 123 def zero_operand?(node) numeric_operand?(node, 0) end |