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 dextool.plugin.mutate.backend.test_mutant.interface_ : TestCaseReport,
19     GatherTestCase;
20 import dextool.plugin.mutate.backend.type : TestCase;
21 import dextool.type : AbsolutePath;
22 
23 /** Parse input for ctest test cases.
24  *
25  * Params:
26  *  r = range that is chunked by line
27  *  report = where the results are put.
28  */
29 struct CtestParser {
30     import std.regex : ctRegex, matchFirst;
31 
32     private {
33         // example: Start 35: gtest_repeat_test
34         enum re_start_tc = ctRegex!(`^\s*Start\s*\d*:\s*(?P<tc>.*)`);
35         // example:  2/3  Test  #2: gmock-cardinalities_test ................***Failed    0.00 sec
36         enum re_fail_tc = ctRegex!(`.*?Test.*:\s*(?P<tc>.*?)\s*\.*\*\*\*.*`);
37 
38         StateData data;
39     }
40 
41     void process(T)(T line, TestCaseReport report) {
42         auto start_tc_match = matchFirst(line, re_start_tc);
43         auto fail_tc_match = matchFirst(line, re_fail_tc);
44 
45         data.hasStartTc = !start_tc_match.empty;
46         data.hasFailTc = !fail_tc_match.empty;
47 
48         if (data.hasStartTc)
49             report.reportFound(TestCase(start_tc_match["tc"].idup));
50 
51         if (data.hasFailTc)
52             report.reportFailed(TestCase(fail_tc_match["tc"].idup));
53     }
54 }
55 
56 private:
57 
58 struct StateData {
59     bool hasStartTc;
60     bool hasFailTc;
61 }
62 
63 version (unittest) {
64     import std.algorithm : each, sort;
65     import std.array : array;
66     import dextool.type : FileName;
67     import unit_threaded : shouldEqual, shouldBeIn;
68 }
69 
70 @("shall report the failed test cases")
71 unittest {
72     auto app = new GatherTestCase;
73     CtestParser parser;
74     testData2.each!(a => parser.process(a, app));
75 
76     // dfmt off
77     shouldEqual(app.failedAsArray.sort,
78                 [TestCase("gmock-cardinalities_test")]
79                 );
80     // dfmt on
81 }
82 
83 @("shall report the found test cases")
84 unittest {
85     auto app = new GatherTestCase;
86     CtestParser parser;
87     testData1.each!(a => parser.process(a, app));
88 
89     // dfmt off
90     shouldEqual(app.foundAsArray.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 }