1 /** 2 Copyright: Copyright (c) 2018, Joakim Brännström. All rights reserved. 3 License: MPL-2 4 Author: Joakim Brännström (joakim.brannstrom@gmx.com) 5 6 This Source Code Form is subject to the terms of the Mozilla Public License, 7 v.2.0. If a copy of the MPL was not distributed with this file, You can obtain 8 one at http://mozilla.org/MPL/2.0/. 9 10 #SPC-track_ctest 11 */ 12 module dextool.plugin.mutate.backend.test_mutant.ctest_post_analyze; 13 14 import std.exception : collectException; 15 import std.range : isInputRange, isOutputRange; 16 import logger = std.experimental.logger; 17 18 import my.set; 19 20 import dextool.plugin.mutate.backend.test_mutant.test_case_analyze : GatherTestCase; 21 import dextool.plugin.mutate.backend.type : TestCase; 22 import dextool.type : AbsolutePath; 23 24 /** Parse input for ctest test cases. 25 * 26 * Params: 27 * r = range that is chunked by line 28 * report = where the results are put. 29 */ 30 struct CtestParser { 31 import std.regex : regex, matchFirst; 32 33 private { 34 // example: Start 35: gtest_repeat_test 35 enum re_start_tc = regex(`^\s*Start\s*\d*:\s*(?P<tc>.*)`); 36 // example: 2/3 Test #2: gmock-cardinalities_test ................***Failed 0.00 sec 37 enum re_fail_tc = regex(`.*?Test.*:\s*(?P<tc>.*?)\s*\.*\*\*\*.*`); 38 39 StateData data; 40 } 41 42 void process(T)(T line, ref GatherTestCase report) { 43 auto start_tc_match = matchFirst(line, re_start_tc); 44 auto fail_tc_match = matchFirst(line, re_fail_tc); 45 46 data.hasStartTc = !start_tc_match.empty; 47 data.hasFailTc = !fail_tc_match.empty; 48 49 if (data.hasStartTc) 50 report.reportFound(TestCase(start_tc_match["tc"].idup)); 51 52 if (data.hasFailTc) 53 report.reportFailed(TestCase(fail_tc_match["tc"].idup)); 54 } 55 } 56 57 private: 58 59 struct StateData { 60 bool hasStartTc; 61 bool hasFailTc; 62 } 63 64 version (unittest) { 65 import std.algorithm : each, sort; 66 import std.array : array; 67 import unit_threaded : shouldEqual, shouldBeIn; 68 } 69 70 @("shall report the failed test cases") 71 unittest { 72 GatherTestCase app; 73 CtestParser parser; 74 testData2.each!(a => parser.process(a, app)); 75 76 // dfmt off 77 shouldEqual(app.failed.toArray.sort, 78 [TestCase("gmock-cardinalities_test")] 79 ); 80 // dfmt on 81 } 82 83 @("shall report the found test cases") 84 unittest { 85 GatherTestCase app; 86 CtestParser parser; 87 testData1.each!(a => parser.process(a, app)); 88 89 // dfmt off 90 shouldEqual(app.found.toArray.sort, [ 91 TestCase("gmock-actions_test"), 92 TestCase("gmock-cardinalities_test"), 93 TestCase("gmock_ex_test") 94 ]); 95 // dfmt on 96 } 97 98 version (unittest) { 99 string[] testData1() { 100 // dfmt off 101 return [ 102 "Test project /home/joker/src/cpp/googletest/build", 103 " Start 1: gmock-actions_test", 104 " 1/3 Test #1: gmock-actions_test ...................... Passed 1.61 sec", 105 " Start 2: gmock-cardinalities_test", 106 " 2/3 Test #2: gmock-cardinalities_test ................ Passed 0.00 sec", 107 " Start 3: gmock_ex_test", 108 " 3/3 Test #3: gmock_ex_test ........................... Passed 0.01 sec", 109 "", 110 "100% tests passed, 0 tests failed out of 3", 111 "", 112 "Total Test time (real) = 7.10 sec", 113 ]; 114 // dfmt on 115 } 116 117 string[] testData2() { 118 // dfmt off 119 return [ 120 "Test project /home/joker/src/cpp/googletest/build", 121 " Start 1: gmock-actions_test", 122 " 1/3 Test #1: gmock-actions_test ...................... Passed 1.61 sec", 123 " Start 2: gmock-cardinalities_test", 124 " 2/3 Test #2: gmock-cardinalities_test ................***Failed 0.00 sec", 125 " Start 3: gmock_ex_test", 126 " 3/3 Test #3: gmock_ex_test ........................... Passed 0.01 sec", 127 "", 128 "100% tests passed, 0 tests failed out of 3", 129 "", 130 "Total Test time (real) = 7.10 sec", 131 "", 132 "The following tests FAILED:", 133 " 15 - gmock-cardinalities_test (Failed)", 134 ]; 135 // dfmt on 136 } 137 }