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, GatherTestCase;
19 import dextool.plugin.mutate.backend.type : TestCase;
20 import dextool.type : AbsolutePath;
21 
22 /** Parse input for ctest test cases.
23  *
24  * Params:
25  *  r = range that is chunked by line
26  *  report = where the results are put.
27  */
28 struct CtestParser {
29     import std.regex : ctRegex, matchFirst;
30 
31     private {
32         // example: Start 35: gtest_repeat_test
33         enum re_start_tc = ctRegex!(`^\s*Start\s*\d*:\s*(?P<tc>.*)`);
34         // example:  2/3  Test  #2: gmock-cardinalities_test ................***Failed    0.00 sec
35         enum re_fail_tc = ctRegex!(`.*?Test.*:\s*(?P<tc>.*?)\s*\.*\*\*\*.*`);
36 
37         StateData data;
38     }
39 
40     void process(T)(T line, TestCaseReport report) {
41         auto start_tc_match = matchFirst(line, re_start_tc);
42         auto fail_tc_match = matchFirst(line, re_fail_tc);
43 
44         data.hasStartTc = !start_tc_match.empty;
45         data.hasFailTc = !fail_tc_match.empty;
46 
47         if (data.hasStartTc)
48             report.reportFound(TestCase(start_tc_match["tc"].idup));
49 
50         if (data.hasFailTc)
51             report.reportFailed(TestCase(fail_tc_match["tc"].idup));
52     }
53 }
54 
55 private:
56 
57 struct StateData {
58     bool hasStartTc;
59     bool hasFailTc;
60 }
61 
62 version (unittest) {
63     import std.algorithm : each, sort;
64     import std.array : array;
65     import dextool.type : FileName;
66     import unit_threaded : shouldEqual, shouldBeIn;
67 }
68 
69 @("shall report the failed test cases")
70 unittest {
71     auto app = new GatherTestCase;
72     CtestParser parser;
73     testData2.each!(a => parser.process(a, app));
74 
75     // dfmt off
76     shouldEqual(app.failedAsArray.sort,
77                 [TestCase("gmock-cardinalities_test")]
78                 );
79     // dfmt on
80 }
81 
82 @("shall report the found test cases")
83 unittest {
84     auto app = new GatherTestCase;
85     CtestParser parser;
86     testData1.each!(a => parser.process(a, app));
87 
88     // dfmt off
89     shouldEqual(app.foundAsArray.sort, [
90                 TestCase("gmock-actions_test"),
91                 TestCase("gmock-cardinalities_test"),
92                 TestCase("gmock_ex_test")
93                 ]);
94     // dfmt on
95 }
96 
97 version (unittest) {
98     string[] testData1() {
99         // dfmt off
100         return [
101 "Test project /home/joker/src/cpp/googletest/build",
102 "      Start  1: gmock-actions_test",
103 " 1/3  Test  #1: gmock-actions_test ......................   Passed    1.61 sec",
104 "      Start  2: gmock-cardinalities_test",
105 " 2/3  Test  #2: gmock-cardinalities_test ................   Passed    0.00 sec",
106 "      Start  3: gmock_ex_test",
107 " 3/3  Test  #3: gmock_ex_test ...........................   Passed    0.01 sec",
108 "",
109 "100% tests passed, 0 tests failed out of 3",
110 "",
111 "Total Test time (real) =   7.10 sec",
112         ];
113         // dfmt on
114     }
115 
116     string[] testData2() {
117         // dfmt off
118         return [
119 "Test project /home/joker/src/cpp/googletest/build",
120 "      Start  1: gmock-actions_test",
121 " 1/3  Test  #1: gmock-actions_test ......................   Passed    1.61 sec",
122 "      Start  2: gmock-cardinalities_test",
123 " 2/3  Test  #2: gmock-cardinalities_test ................***Failed    0.00 sec",
124 "      Start  3: gmock_ex_test",
125 " 3/3  Test  #3: gmock_ex_test ...........................   Passed    0.01 sec",
126 "",
127 "100% tests passed, 0 tests failed out of 3",
128 "",
129 "Total Test time (real) =   7.10 sec",
130 "",
131 "The following tests FAILED:",
132 "         15 - gmock-cardinalities_test (Failed)",
133         ];
134         // dfmt on
135     }
136 }