1 /*
2  * Cppcheck - A tool for static C/C++ code analysis
3  * Copyright (C) 2007-2021 Cppcheck team.
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include "settings.h"
20 #include "testsuite.h"
21 #include "threadexecutor.h"
22 
23 #include <map>
24 #include <string>
25 #include <utility>
26 
27 class TestThreadExecutor : public TestFixture {
28 public:
TestThreadExecutor()29     TestThreadExecutor() : TestFixture("TestThreadExecutor") {}
30 
31 private:
32     Settings settings;
33 
34     /**
35      * Execute check using n jobs for y files which are have
36      * identical data, given within data.
37      */
check(unsigned int jobs,int files,int result,const std::string & data)38     void check(unsigned int jobs, int files, int result, const std::string &data) {
39         errout.str("");
40         output.str("");
41         if (!ThreadExecutor::isEnabled()) {
42             // Skip this check on systems which don't use this feature
43             return;
44         }
45 
46         std::map<std::string, std::size_t> filemap;
47         for (int i = 1; i <= files; ++i) {
48             std::ostringstream oss;
49             oss << "file_" << i << ".cpp";
50             filemap[oss.str()] = 1;
51         }
52 
53         settings.jobs = jobs;
54         ThreadExecutor executor(filemap, settings, *this);
55         for (std::map<std::string, std::size_t>::const_iterator i = filemap.begin(); i != filemap.end(); ++i)
56             executor.addFileContent(i->first, data);
57 
58         ASSERT_EQUALS(result, executor.check());
59     }
60 
run()61     void run() OVERRIDE {
62         LOAD_LIB_2(settings.library, "std.cfg");
63 
64         TEST_CASE(deadlock_with_many_errors);
65         TEST_CASE(many_threads);
66         TEST_CASE(no_errors_more_files);
67         TEST_CASE(no_errors_less_files);
68         TEST_CASE(no_errors_equal_amount_files);
69         TEST_CASE(one_error_less_files);
70         TEST_CASE(one_error_several_files);
71     }
72 
deadlock_with_many_errors()73     void deadlock_with_many_errors() {
74         std::ostringstream oss;
75         oss << "int main()\n"
76             << "{\n";
77         for (int i = 0; i < 500; i++)
78             oss << "  {char *a = malloc(10);}\n";
79 
80         oss << "  return 0;\n"
81             << "}\n";
82         check(2, 3, 3, oss.str());
83     }
84 
many_threads()85     void many_threads() {
86         check(16, 100, 100,
87               "int main()\n"
88               "{\n"
89               "  char *a = malloc(10);\n"
90               "  return 0;\n"
91               "}");
92     }
93 
no_errors_more_files()94     void no_errors_more_files() {
95         check(2, 3, 0,
96               "int main()\n"
97               "{\n"
98               "  return 0;\n"
99               "}");
100     }
101 
no_errors_less_files()102     void no_errors_less_files() {
103         check(2, 1, 0,
104               "int main()\n"
105               "{\n"
106               "  return 0;\n"
107               "}");
108     }
109 
no_errors_equal_amount_files()110     void no_errors_equal_amount_files() {
111         check(2, 2, 0,
112               "int main()\n"
113               "{\n"
114               "  return 0;\n"
115               "}");
116     }
117 
one_error_less_files()118     void one_error_less_files() {
119         check(2, 1, 1,
120               "int main()\n"
121               "{\n"
122               "  {char *a = malloc(10);}\n"
123               "  return 0;\n"
124               "}");
125     }
126 
one_error_several_files()127     void one_error_several_files() {
128         check(2, 20, 20,
129               "int main()\n"
130               "{\n"
131               "  {char *a = malloc(10);}\n"
132               "  return 0;\n"
133               "}");
134     }
135 };
136 
137 REGISTER_TEST(TestThreadExecutor)
138