Skip to main content

verificar/mutator/
operators.rs

1//! Mutation operator definitions
2//!
3//! From Jia & Harman (2011) "An Analysis and Survey of the Development of Mutation Testing"
4
5/// Mutation operators from the standard catalog
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
7pub enum MutationOperator {
8    /// Arithmetic Operator Replacement
9    /// `a + b` → `a - b`, `a * b`, `a / b`, `a % b`
10    Aor,
11
12    /// Relational Operator Replacement
13    /// `a < b` → `a <= b`, `a > b`, `a >= b`, `a == b`, `a != b`
14    Ror,
15
16    /// Logical Operator Replacement
17    /// `a and b` → `a or b`
18    Lor,
19
20    /// Unary Operator Insertion
21    /// `x` → `-x`, `not x`
22    Uoi,
23
24    /// Absolute Value Insertion
25    /// `x` → `abs(x)`
26    Abs,
27
28    /// Statement Deletion
29    /// Delete a statement from the program
30    Sdl,
31
32    /// Scalar Variable Replacement
33    /// `x` → `y` (where y has the same type)
34    Svr,
35
36    /// Boundary Substitution Replacement
37    /// `0` → `-1`, `""` → `" "`, `[]` → `[None]`
38    Bsr,
39}
40
41impl MutationOperator {
42    /// Get all mutation operators
43    #[must_use]
44    pub fn all() -> Vec<Self> {
45        vec![
46            Self::Aor,
47            Self::Ror,
48            Self::Lor,
49            Self::Uoi,
50            Self::Abs,
51            Self::Sdl,
52            Self::Svr,
53            Self::Bsr,
54        ]
55    }
56
57    /// Get operators recommended for ASTTransform bugs (P0 priority)
58    ///
59    /// From spec: ASTTransform bugs are 40-62% of defects
60    #[must_use]
61    pub fn ast_transform_operators() -> Vec<Self> {
62        vec![Self::Aor, Self::Ror, Self::Lor]
63    }
64
65    /// Get operators recommended for OwnershipBorrow bugs (P1 priority)
66    ///
67    /// From spec: OwnershipBorrow bugs are 15-20% of defects
68    #[must_use]
69    pub fn ownership_operators() -> Vec<Self> {
70        vec![Self::Bsr, Self::Svr]
71    }
72
73    /// Get description of the operator
74    #[must_use]
75    pub fn description(&self) -> &'static str {
76        match self {
77            Self::Aor => "Arithmetic Operator Replacement",
78            Self::Ror => "Relational Operator Replacement",
79            Self::Lor => "Logical Operator Replacement",
80            Self::Uoi => "Unary Operator Insertion",
81            Self::Abs => "Absolute Value Insertion",
82            Self::Sdl => "Statement Deletion",
83            Self::Svr => "Scalar Variable Replacement",
84            Self::Bsr => "Boundary Substitution Replacement",
85        }
86    }
87}
88
89impl std::fmt::Display for MutationOperator {
90    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
91        match self {
92            Self::Aor => write!(f, "AOR"),
93            Self::Ror => write!(f, "ROR"),
94            Self::Lor => write!(f, "LOR"),
95            Self::Uoi => write!(f, "UOI"),
96            Self::Abs => write!(f, "ABS"),
97            Self::Sdl => write!(f, "SDL"),
98            Self::Svr => write!(f, "SVR"),
99            Self::Bsr => write!(f, "BSR"),
100        }
101    }
102}
103
104#[cfg(test)]
105mod tests {
106    use super::*;
107
108    #[test]
109    fn test_all_operators() {
110        let ops = MutationOperator::all();
111        assert_eq!(ops.len(), 8);
112    }
113
114    #[test]
115    fn test_ast_transform_operators() {
116        let ops = MutationOperator::ast_transform_operators();
117        assert_eq!(ops.len(), 3);
118        assert!(ops.contains(&MutationOperator::Aor));
119        assert!(ops.contains(&MutationOperator::Ror));
120        assert!(ops.contains(&MutationOperator::Lor));
121    }
122
123    #[test]
124    fn test_ownership_operators() {
125        let ops = MutationOperator::ownership_operators();
126        assert_eq!(ops.len(), 2);
127        assert!(ops.contains(&MutationOperator::Bsr));
128        assert!(ops.contains(&MutationOperator::Svr));
129    }
130
131    #[test]
132    fn test_operator_display_all() {
133        assert_eq!(format!("{}", MutationOperator::Aor), "AOR");
134        assert_eq!(format!("{}", MutationOperator::Ror), "ROR");
135        assert_eq!(format!("{}", MutationOperator::Lor), "LOR");
136        assert_eq!(format!("{}", MutationOperator::Uoi), "UOI");
137        assert_eq!(format!("{}", MutationOperator::Abs), "ABS");
138        assert_eq!(format!("{}", MutationOperator::Sdl), "SDL");
139        assert_eq!(format!("{}", MutationOperator::Svr), "SVR");
140        assert_eq!(format!("{}", MutationOperator::Bsr), "BSR");
141    }
142
143    #[test]
144    fn test_operator_description_all() {
145        assert_eq!(
146            MutationOperator::Aor.description(),
147            "Arithmetic Operator Replacement"
148        );
149        assert_eq!(
150            MutationOperator::Ror.description(),
151            "Relational Operator Replacement"
152        );
153        assert_eq!(
154            MutationOperator::Lor.description(),
155            "Logical Operator Replacement"
156        );
157        assert_eq!(
158            MutationOperator::Uoi.description(),
159            "Unary Operator Insertion"
160        );
161        assert_eq!(
162            MutationOperator::Abs.description(),
163            "Absolute Value Insertion"
164        );
165        assert_eq!(MutationOperator::Sdl.description(), "Statement Deletion");
166        assert_eq!(
167            MutationOperator::Svr.description(),
168            "Scalar Variable Replacement"
169        );
170        assert_eq!(
171            MutationOperator::Bsr.description(),
172            "Boundary Substitution Replacement"
173        );
174    }
175
176    #[test]
177    fn test_operator_clone_copy() {
178        let op = MutationOperator::Aor;
179        let cloned = op.clone();
180        let copied = op;
181        assert_eq!(op, cloned);
182        assert_eq!(op, copied);
183    }
184
185    #[test]
186    fn test_operator_eq() {
187        assert_eq!(MutationOperator::Aor, MutationOperator::Aor);
188        assert_ne!(MutationOperator::Aor, MutationOperator::Ror);
189    }
190
191    #[test]
192    fn test_operator_hash() {
193        use std::collections::HashSet;
194        let mut set = HashSet::new();
195        set.insert(MutationOperator::Aor);
196        set.insert(MutationOperator::Ror);
197        set.insert(MutationOperator::Aor); // duplicate
198        assert_eq!(set.len(), 2);
199    }
200
201    #[test]
202    fn test_operator_debug() {
203        let debug_str = format!("{:?}", MutationOperator::Aor);
204        assert!(debug_str.contains("Aor"));
205    }
206}