mutant_kraken/mutation_tool/
mutation.rs

1use std::fmt::Display;
2
3use cli_table::Table;
4use uuid::Uuid;
5
6use crate::mutation_tool::MutationOperators;
7
8#[derive(Debug, Clone, serde::Serialize, PartialEq, Eq)]
9pub enum MutationResult {
10    InProgress,
11    Survived,
12    Killed,
13    BuildFailed,
14    Timeout,
15    Failed,
16}
17
18impl Display for MutationResult {
19    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
20        match self {
21            MutationResult::InProgress => write!(f, "In Progress"),
22            MutationResult::Survived => write!(f, "Mutant Survived"),
23            MutationResult::Killed => write!(f, "Mutant Killed"),
24            MutationResult::BuildFailed => write!(f, "Build Failed"),
25            MutationResult::Timeout => write!(f, "Timeout"),
26            MutationResult::Failed => write!(f, "Failed"),
27        }
28    }
29}
30
31impl Default for MutationResult {
32    fn default() -> Self {
33        Self::InProgress
34    }
35}
36
37#[derive(Debug, Clone, Table, serde::Serialize)]
38/// Represents a mutation applied to a code file.
39pub struct Mutation {
40    /// The unique identifier for the mutation.
41    #[table(title = "Id")]
42    #[serde(skip)]
43    pub id: Uuid,
44    /// The starting byte of the old operator.
45    #[table(skip)]
46    #[serde(skip)]
47    pub start_byte: usize,
48    /// The ending byte of the old operator.
49    #[table(skip)]
50    #[serde(skip)]
51    pub end_byte: usize,
52    /// The name of the file that was mutated.
53    #[table(title = "File Name")]
54    pub file_name: String,
55    /// The line number where the mutation was applied.
56    #[table(title = "Line Number")]
57    pub line_number: usize,
58    /// The new operator that was applied.
59    #[table(title = "New Operator")]
60    pub new_op: String,
61    /// The old operator that was replaced.
62    #[table(title = "Old Operator")]
63    pub old_op: String,
64    /// The type of mutation that was applied.
65    #[table(title = "Mutation Type")]
66    pub mutation_type: MutationOperators,
67    /// The result of the mutation.
68    #[table(title = "Result")]
69    pub result: MutationResult,
70}
71
72impl Mutation {
73    pub fn new(
74        start_byte: usize,
75        end_byte: usize,
76        new_op: String,
77        old_op: String,
78        line_number: usize,
79        mutation_type: MutationOperators,
80        file_name: String,
81    ) -> Self {
82        Self {
83            start_byte,
84            end_byte,
85            line_number,
86            new_op,
87            old_op,
88            mutation_type,
89            id: Uuid::new_v4(),
90            result: MutationResult::default(),
91            file_name,
92        }
93    }
94}
95
96impl Display for Mutation {
97    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
98        write!(
99            f,
100            "
101            /**
102            AUTO GENERATED COMMENT
103            Mutation Operator: {}
104            Line number: {}
105            Id: {},
106            Old Operator: {},
107            New Operator: {}
108            */",
109            self.mutation_type,
110            (self.line_number + 9),
111            self.id,
112            self.old_op,
113            self.new_op
114        )
115    }
116}
117
118#[derive(Debug, Clone, serde::Serialize)]
119pub struct FileMutations {
120    pub mutations: Vec<Mutation>,
121}
122#[cfg(test)]
123mod tests {
124    use super::*;
125
126    #[test]
127    fn test_default_mutation_result() {
128        let default_result = MutationResult::default();
129        assert_eq!(default_result, MutationResult::InProgress);
130    }
131
132    #[test]
133    fn test_display_mutation_result() {
134        let result = MutationResult::Timeout;
135        let formatted_result = format!("{}", result);
136        assert_eq!(formatted_result, "Timeout");
137    }
138
139    #[test]
140    fn test_create_mutation() {
141        let mutation = Mutation::new(
142            10, // start_byte
143            20, // end_byte
144            "new_op".to_string(),
145            "old_op".to_string(),
146            42, // line_number
147            MutationOperators::ArithmeticReplacementOperator,
148            "example.rs".to_string(),
149        );
150
151        assert_eq!(mutation.start_byte, 10);
152        assert_eq!(mutation.end_byte, 20);
153        assert_eq!(mutation.new_op, "new_op");
154        assert_eq!(mutation.old_op, "old_op");
155        assert_eq!(mutation.line_number, 42);
156        assert_eq!(
157            mutation.mutation_type,
158            MutationOperators::ArithmeticReplacementOperator
159        );
160        assert_eq!(mutation.file_name, "example.rs");
161        assert_ne!(mutation.id, Uuid::nil()); // Ensure that UUID is not nil
162        assert_eq!(mutation.result, MutationResult::InProgress);
163    }
164
165    #[test]
166    fn test_display_mutation() {
167        let mutation = Mutation::new(
168            10, // start_byte
169            20, // end_byte
170            "new_op".to_string(),
171            "old_op".to_string(),
172            42, // line_number
173            MutationOperators::ArithmeticReplacementOperator,
174            "example.rs".to_string(),
175        );
176
177        let expected_output = format!(
178            "
179            /**
180            AUTO GENERATED COMMENT
181            Mutation Operator: ArithmeticReplacementOperator
182            Line number: {}
183            Id: {},
184            Old Operator: old_op,
185            New Operator: new_op
186            */",
187            (42 + 9),
188            mutation.id
189        );
190
191        assert_eq!(format!("{}", mutation), expected_output);
192    }
193
194    #[test]
195    fn test_create_file_mutations() {
196        let mutations = vec![
197            Mutation::new(
198                10, // start_byte
199                20, // end_byte
200                "new_op1".to_string(),
201                "old_op1".to_string(),
202                42, // line_number
203                MutationOperators::ArithmeticReplacementOperator,
204                "example.rs".to_string(),
205            ),
206            Mutation::new(
207                30, // start_byte
208                40, // end_byte
209                "new_op2".to_string(),
210                "old_op2".to_string(),
211                56, // line_number
212                MutationOperators::UnaryRemovalOperator,
213                "example.rs".to_string(),
214            ),
215        ];
216
217        let file_mutations = FileMutations { mutations };
218
219        assert_eq!(file_mutations.mutations.len(), 2);
220        // Add more assertions based on your specific requirements
221    }
222}