1 /** 2 Copyright: Copyright (c) 2017, Joakim Brännström. All rights reserved. 3 License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 4 Author: Joakim Brännström (joakim.brannstrom@gmx.com) 5 6 #TST-plugin_mutate_mutation_ror 7 */ 8 module dextool_test.mutate_ror; 9 10 import dextool_test.utility; 11 12 import unit_threaded; 13 14 // dfmt off 15 16 @("shall produce all ROR mutations") 17 @Values("ror_primitive.cpp", "ror_overload.cpp") 18 unittest { 19 mixin(envSetup(globalTestdir, No.setupEnv)); 20 testEnv.outputSuffix(getValue!string); 21 testEnv.setupEnv; 22 23 makeDextoolAnalyze(testEnv) 24 .addInputArg(testData ~ getValue!string) 25 .run; 26 auto r = makeDextool(testEnv) 27 .addArg(["test"]) 28 .addArg(["--mutant", "ror"]) 29 .run; 30 verifyRor(r.stdout); 31 } 32 33 void verifyRor(string[] txt) { 34 import std.algorithm; 35 36 static struct Ex { 37 string[2] ops; 38 string expr; 39 } 40 Ex[string] tbl = [ 41 "<": Ex(["<=", "!="], "false"), 42 ">": Ex([">=", "!="], "false"), 43 "<=": Ex(["<", "=="], "true"), 44 ">=": Ex([">", "=="], "true"), 45 "==": Ex(["<=", ">="], "false"), 46 "!=": Ex(["<", ">"], "true"), 47 ]; 48 49 foreach (mut; tbl.byKeyValue) { 50 foreach (op; mut.value.ops) { 51 auto expected = format("from '%s' to '%s'", mut.key, op); 52 dextoolYap("Testing: " ~ expected); 53 txt.sliceContains(expected).shouldBeTrue; 54 } 55 56 auto expected = format("from 'a %s b' to '%s'", mut.key, mut.value.expr); 57 dextoolYap("Testing: " ~ expected); 58 txt.sliceContains(expected).shouldBeTrue; 59 } 60 } 61 62 @("shall produce all ROR mutations according to the alternative schema when both types are floating point types") 63 unittest { 64 mixin(envSetup(globalTestdir)); 65 66 makeDextoolAnalyze(testEnv) 67 .addInputArg(testData ~ "ror_float_primitive.cpp") 68 .run; 69 auto r = makeDextool(testEnv) 70 .addArg(["test"]) 71 .addArg(["--mutant", "ror"]) 72 .run; 73 verifyFloatRor(r.stdout); 74 } 75 76 void verifyFloatRor(string[] txt) { 77 import std.algorithm; 78 79 static struct Ex { 80 string[] ops; 81 string expr; 82 } 83 Ex[string] tbl = [ 84 "<": Ex([">"], "false"), 85 ">": Ex(["<"], "false"), 86 "<=": Ex([">"], "true"), 87 ">=": Ex(["<"], "true"), 88 "==": Ex(["<=", ">="], "false"), 89 "!=": Ex(["<", ">"], "true"), 90 ]; 91 92 foreach (mut; tbl.byKeyValue) { 93 foreach (op; mut.value.ops) { 94 auto expected = format("from '%s' to '%s'", mut.key, op); 95 dextoolYap("Testing: " ~ expected); 96 txt.sliceContains(expected).shouldBeTrue; 97 } 98 99 auto expected = format("from 'a %s b' to '%s'", mut.key, mut.value.expr); 100 dextoolYap("Testing: " ~ expected); 101 txt.sliceContains(expected).shouldBeTrue; 102 } 103 } 104 105 @("shall produce all ROR mutations according to the enum schema when both types are enum type and one is an enum const declaration") 106 unittest { 107 mixin(envSetup(globalTestdir)); 108 109 makeDextoolAnalyze(testEnv) 110 .addInputArg(testData ~ "ror_enum_primitive.cpp") 111 .run; 112 auto r = makeDextool(testEnv) 113 .addArg(["test"]) 114 .addArg(["--mutant", "ror"]) 115 .run; 116 117 testConsecutiveSparseOrder!SubStr([ 118 "from '<' to '<='", 119 "from '<' to '!='", 120 "from 'a < MyE::C' to 'false'", 121 122 "from '<' to '<='", 123 "from '<' to '!='", 124 "from 'MyE::C < b' to 'false'", 125 126 "from '>' to '>='", 127 "from '>' to '!='", 128 "from 'a > MyE::C' to 'false'", 129 130 "from '>' to '>='", 131 "from '>' to '!='", 132 "from 'MyE::C > b' to 'false'", 133 134 "from '<=' to '<'", 135 "from '<=' to '=='", 136 // this will always be true. Generating it for now because code like this should not exist 137 "from 'a <= MyE::C' to 'true'", 138 139 // No test case can catch this. Generating it for now because code like this should not exist 140 "from '<=' to '<'", 141 "from '<=' to '=='", 142 "from 'MyE::C <= b' to 'true'", 143 144 "from '>=' to '>'", 145 "from '>=' to '=='", 146 "from 'a >= MyE::C' to 'true'", 147 148 "from '>=' to '>'", 149 "from '>=' to '=='", 150 "from 'MyE::C >= b' to 'true'", 151 ]).shouldBeIn(r.stdout); 152 } 153 154 @("shall produce all ROR mutations according to the enum schema for equal when both types are enum type and one is an enum const declaration") 155 unittest { 156 mixin(envSetup(globalTestdir)); 157 158 makeDextoolAnalyze(testEnv) 159 .addInputArg(testData ~ "ror_enum_primitive_equal.cpp") 160 .run; 161 auto r = makeDextool(testEnv) 162 .addArg(["test"]) 163 .addArg(["--mutant", "ror"]) 164 .run; 165 166 testConsecutiveSparseOrder!SubStr([ 167 "from '==' to '<='", 168 "from '==' to '>='", 169 "from 'a == b' to 'false'", 170 171 "from '==' to '<='", 172 "from 'MyE::A == b' to 'false'", 173 174 "from '==' to '<='", 175 "from '==' to '>='", 176 "from 'MyE::B == b' to 'false'", 177 178 "from '==' to '>='", 179 "from 'MyE::C == b' to 'false'", 180 181 "from '==' to '>='", 182 "from 'a == MyE::A' to 'false'", 183 184 "from '==' to '<='", 185 "from '==' to '>='", 186 "from 'a == MyE::B' to 'false'", 187 188 "from '==' to '<='", 189 "from 'a == MyE::C' to 'false'", 190 ]).shouldBeIn(r.stdout); 191 192 testConsecutiveSparseOrder!SubStr([ 193 "from 'a == MyE::C' to 'false'", 194 // test that g4 do NOT generate a <= because the left side is already min 195 "from '==' to '<='", 196 "from '==' to '>='", 197 "from 'a == MyE::A' to 'false'", 198 ]).shouldNotBeIn(r.stdout); 199 } 200 201 @("shall produce all ROR mutations according to the enum schema for not-equal when both types are enum type and one is an enum const declaration") 202 unittest { 203 mixin(envSetup(globalTestdir)); 204 205 makeDextoolAnalyze(testEnv) 206 .addInputArg(testData ~ "ror_enum_primitive_not_equal.cpp") 207 .run; 208 auto r = makeDextool(testEnv) 209 .addArg(["test"]) 210 .addArg(["--mutant", "ror"]) 211 .run; 212 213 testConsecutiveSparseOrder!SubStr([ 214 "from '!=' to '<'", 215 "from '!=' to '>'", 216 "from 'a != b' to 'true'", 217 218 "from '!=' to '<'", 219 "from 'MyE::A != b' to 'true'", 220 221 "from '!=' to '<'", 222 "from '!=' to '>'", 223 "from 'MyE::B != b' to 'true'", 224 225 "from '!=' to '>'", 226 "from 'a != MyE::A' to 'true'", 227 228 "from '!=' to '<'", 229 "from '!=' to '>'", 230 "from 'a != MyE::B' to 'true'", 231 232 "from '!=' to '<'", 233 "from 'a != MyE::C' to 'true'", 234 ]).shouldBeIn(r.stdout); 235 } 236 237 @("shall produce all ROR mutations according to floating point schema when either type are pointers") 238 unittest { 239 mixin(envSetup(globalTestdir)); 240 241 makeDextoolAnalyze(testEnv) 242 .addInputArg(testData ~ "ror_pointer_primitive.cpp") 243 .run; 244 auto r = makeDextool(testEnv) 245 .addArg(["test"]) 246 .addArg(["--mutant", "rorp"]) 247 .run; 248 249 testConsecutiveSparseOrder!SubStr([ 250 "from '==' to '!='", 251 "from 'a0 == a1' to 'false'", 252 253 "from '!=' to '=='", 254 "from 'b0 != b1' to 'true'", 255 256 "from '==' to '!='", 257 "from 'c0 == 0' to 'false'", 258 259 "from '!=' to '=='", 260 "from 'd0 != 0' to 'true'", 261 262 "from '==' to '<='", 263 "from '==' to '>='", 264 "from 'e0 == e1' to 'false'", 265 266 "from '!=' to '<'", 267 "from '!=' to '>'", 268 "from 'f0 != f1' to 'true'", 269 ]).shouldBeIn(r.stdout); 270 } 271 272 @("shall produce all ROR mutations according to floating point schema when either type are pointers") 273 unittest { 274 mixin(envSetup(globalTestdir)); 275 276 makeDextoolAnalyze(testEnv) 277 .addInputArg(testData ~ "ror_pointer_return_value.cpp") 278 .run; 279 auto r = makeDextool(testEnv) 280 .addArg(["test"]) 281 .addArg(["--mutant", "rorp"]) 282 .run; 283 284 testConsecutiveSparseOrder!SubStr([ 285 "from '!=' to '=='", 286 "from 'clone_ != &Foo::initRef' to 'true'", 287 288 "from '==' to '!='", 289 "from 'a0() == a1()' to 'false'", 290 291 "from '!=' to '=='", 292 "from 'b0() != b1()' to 'true'", 293 294 "from '==' to '!='", 295 "from 'c0() == 0' to 'false'", 296 297 "from '!=' to '=='", 298 "from 'd0() != 0' to 'true'", 299 ]).shouldBeIn(r.stdout); 300 } 301 302 @("shall produce all ROR mutations according to the bool schema when both types are bools") 303 unittest { 304 mixin(envSetup(globalTestdir)); 305 306 makeDextoolAnalyze(testEnv) 307 .addInputArg(testData ~ "ror_bool_primitive.cpp") 308 .run; 309 auto r = makeDextool(testEnv) 310 .addArg(["test"]) 311 .addArg(["--mutant", "ror"]) 312 .run; 313 314 testConsecutiveSparseOrder!SubStr([ 315 "from '==' to '!='", 316 "from 'a0 == a1' to 'false'", 317 318 "from '!=' to '=='", 319 "from 'b0 != b1' to 'true'", 320 ]).shouldBeIn(r.stdout); 321 } 322 323 @("shall produce all ROR mutations according to the bool schema when both functions return type is bool") 324 unittest { 325 mixin(envSetup(globalTestdir)); 326 327 makeDextoolAnalyze(testEnv) 328 .addInputArg(testData ~ "ror_bool_return_value.cpp") 329 .run; 330 auto r = makeDextool(testEnv) 331 .addArg(["test"]) 332 .addArg(["--mutant", "ror"]) 333 .run; 334 335 testConsecutiveSparseOrder!SubStr([ 336 "from '==' to '!='", 337 "from 'a0() == a1()' to 'false'", 338 339 "from '!=' to '=='", 340 "from 'b0() != b1()' to 'true'", 341 ]).shouldBeIn(r.stdout); 342 }