includer_test.cc
Go to the documentation of this file.
1 // ======================================================================
2 //
3 // includer_test
4 //
5 // ======================================================================
6 
7 #define BOOST_TEST_MODULE (includer test)
8 #include "boost/test/unit_test.hpp"
9 
10 #include "cetlib/filepath_maker.h"
11 #include "cetlib/includer.h"
12 #include "cetlib_except/exception.h"
13 
14 #include <fstream>
15 #include <iostream>
16 #include <regex>
17 #include <sstream>
18 #include <string>
19 #include <system_error>
20 #include <unistd.h>
21 
22 namespace {
23 
24  std::string const file_a = "./a.txt";
25  std::string const file_b = "./b.txt";
26  std::string const file_c = "./c.txt";
27  std::string const file_i = "./i.txt";
28  std::string const file_j = "./j.txt";
29  std::string const file_k = "./k.txt";
30  std::string const file_r = "./r.txt";
31  std::string const file_r2 = "./r2.txt";
32  std::string const file_r3 = "./r3.txt";
33  std::string const file_r4 = "./r4.txt";
34  std::string const file_x1 = "./x1.txt";
35  std::string const file_x2 = "./x2.txt";
36  std::string const file_x3 = "./x3.txt";
37 
38  std::string const contents_a = "abcde\n"
39  "vwxyz\n";
40 
41  std::string const contents_b = "12345\n"
42  "67890\n";
43 
44  std::string const contents_c = "a1b2c3\r"
45  "d4e5f6\r";
46 
47  std::string const contents_i = "begin\n"
48  "#include \"./a.txt\" \t \n"
49  "end\n";
50 
51  std::string const contents_j = "begin\n"
52  "#include \"./a.txt\"\n"
53  "#include \"./b.txt\"\t\r\n"
54  "#include \"./c.txt\"\r"
55  "end\n";
56 
57  std::string const contents_k = "begin\n"
58  "#include \"./j.txt\"\n"
59  "#include \"./i.txt\"\n"
60  "end\n";
61 
62  std::string const contents_r = "begin\n"
63  "#include \"./r.txt\"\n"
64  "end\n";
65 
66  std::string const contents_r2 = "begin\n"
67  "#include \"./r3.txt\"\n"
68  "end\n";
69 
70  std::string const contents_r3 = "begin\n"
71  "#include \"./j.txt\"\n"
72  "#include \"./r4.txt\"\n"
73  "end\n";
74 
75  std::string const contents_r4 = "begin\n"
76  "#include \"./linked/r2.txt\"\n"
77  "end\n";
78 
79  std::string const contents_x1 = "#include\"./a.txt\"\n";
80  std::string const contents_x2 = "#include ./a.txt\"\n";
81  std::string const contents_x3 = "#include \"./a.txt\n";
82 
83  inline std::string
84  expected_string(std::string const& str)
85  {
86  return std::regex_replace(str, std::regex("\r"), "\n");
87  }
88 
89  void
90  write_files()
91  {
92  std::ofstream a(file_a);
93  a << contents_a;
94  std::ofstream b(file_b);
95  b << contents_b;
96  std::ofstream c(file_c);
97  c << contents_c;
98  std::ofstream i(file_i);
99  i << contents_i;
100  std::ofstream j(file_j);
101  j << contents_j;
102  std::ofstream k(file_k);
103  k << contents_k;
104  std::ofstream r(file_r);
105  r << contents_r;
106  std::ofstream r2(file_r2);
107  r2 << contents_r2;
108  std::ofstream r3(file_r3);
109  r3 << contents_r3;
110  std::ofstream r4(file_r4);
111  r4 << contents_r4;
112  std::ofstream x1(file_x1);
113  x1 << contents_x1;
114  std::ofstream x2(file_x2);
115  x2 << contents_x2;
116  std::ofstream x3(file_x3);
117  x3 << contents_x3;
118  if (symlink(".", "linked") == -1) {
119  throw std::system_error(std::error_code(errno, std::system_category()));
120  }
121  }
122 
123  cet::filepath_lookup policy{".:./test"};
124 }
125 
126 BOOST_AUTO_TEST_SUITE(includer_test)
127 
128 BOOST_AUTO_TEST_CASE(no_inclusion_test)
129 {
130  write_files();
131 
132  cet::includer const a{file_a, policy};
133  std::string const result1{a.begin(), a.end()};
134  BOOST_TEST(result1 == expected_string(contents_a));
135 
136  cet::includer const b{file_b, policy};
137  std::string const result2{b.begin(), b.end()};
138  BOOST_TEST(result2 == expected_string(contents_b));
139 
140  cet::includer const c{file_c, policy};
141  std::string const result3{c.begin(), c.end()};
142  BOOST_TEST(result3 == expected_string(contents_c));
143 }
144 
145 BOOST_AUTO_TEST_CASE(single_inclusion_test)
146 {
147  cet::includer const i{file_i, policy};
148  std::string const result{i.begin(), i.end()};
149  BOOST_TEST(result == expected_string("begin\n") +
150  expected_string(contents_a) +
151  expected_string("end\n"));
152 }
153 
154 BOOST_AUTO_TEST_CASE(double_inclusion_test)
155 {
156  cet::includer j(file_j, policy);
157  std::string result(j.begin(), j.end());
158  BOOST_TEST(result ==
159  expected_string("begin\n") + expected_string(contents_a) +
160  expected_string(contents_b) + expected_string(contents_c) +
161  expected_string("end\n"));
162 }
163 
164 BOOST_AUTO_TEST_CASE(repeated_inclusion_test)
165 {
166  cet::includer k(file_k, policy);
167  std::string result(k.begin(), k.end());
168  BOOST_TEST(result ==
169  expected_string("begin\n") + expected_string("begin\n") +
170  expected_string(contents_a) + expected_string(contents_b) +
171  expected_string(contents_c) + expected_string("end\n") +
172  expected_string("begin\n") + expected_string(contents_a) +
173  expected_string("end\n") + expected_string("end\n"));
174 }
175 
176 BOOST_AUTO_TEST_CASE(malformed_inclusion_test)
177 {
178  BOOST_CHECK_THROW(cet::includer(file_x1, policy), cet::exception);
179  BOOST_CHECK_THROW(cet::includer(file_x2, policy), cet::exception);
180  BOOST_CHECK_THROW(cet::includer(file_x3, policy), cet::exception);
181 }
182 
183 BOOST_AUTO_TEST_CASE(simple_recursive_inclusion_test)
184 {
185  BOOST_CHECK_EXCEPTION(
186  cet::includer(file_r, policy), cet::exception, [](cet::exception const& e) {
187  return e.category() == "Recursive #include directive:";
188  });
189 }
190 
191 BOOST_AUTO_TEST_CASE(complex_recursive_inclusion_test)
192 {
193  BOOST_CHECK_EXCEPTION(cet::includer(file_r2, policy),
195  [](cet::exception const& e) {
196  return e.category() ==
197  "Recursive #include directive:";
198  });
199 }
200 
201 BOOST_AUTO_TEST_CASE(string_inclusion_test)
202 {
203  std::string a = contents_a;
204  std::istringstream is_a(a);
205  cet::includer inc_a(is_a, policy);
206  std::string result_a(inc_a.begin(), inc_a.end());
207  BOOST_TEST(result_a == a);
208 
209  std::string i = contents_i;
210  std::istringstream is_i(i);
211  cet::includer inc_i(is_i, policy);
212  std::string result_i(inc_i.begin(), inc_i.end());
213  BOOST_TEST(result_i == expected_string("begin\n") +
214  expected_string(contents_a) +
215  expected_string("end\n"));
216 }
217 
218 BOOST_AUTO_TEST_CASE(backtrace_test)
219 {
220  cet::includer j(file_j, policy);
221  auto it = j.begin();
222  std::advance(it, 5);
223  BOOST_TEST_REQUIRE(*it == '\n');
224  std::cerr << j.whereis(it) << "\n";
225  std::cerr << "\n";
226  std::string cmp("line 1, character 6, of file \"././j.txt\"");
227  BOOST_TEST_REQUIRE(j.whereis(it) == cmp);
228  std::advance(it, 10);
229  BOOST_TEST_REQUIRE(*it == 'y');
230  std::cerr << j.whereis(it) << "\n";
231  std::cerr << "\n";
232  cmp = "line 2, character 4, of file \"././a.txt\"\n"
233  "included from line 2 of file \"././j.txt\"";
234  BOOST_TEST_REQUIRE(j.whereis(it) == cmp);
235  std::advance(it, 10);
236  BOOST_TEST_REQUIRE(*it == '7');
237  std::cerr << j.whereis(it) << "\n";
238  cmp = "line 2, character 2, of file \"././b.txt\"\n"
239  "included from line 3 of file \"././j.txt\"";
240  BOOST_TEST_REQUIRE(j.whereis(it) == cmp);
241 }
242 
243 BOOST_AUTO_TEST_CASE(highlighted_backtrace_test)
244 {
245  cet::includer j(file_j, policy);
246  auto it = j.begin();
247  std::advance(it, 5);
248  BOOST_TEST_REQUIRE(*it == '\n');
249  std::cerr << j.highlighted_whereis(it) << "\n";
250  std::cerr << "\n";
251  std::string cmp("line 1, character 6, of file \"././j.txt\"");
252  cmp += "\n\nbegin\n ^";
254  std::advance(it, 10);
255  BOOST_TEST_REQUIRE(*it == 'y');
256  std::cerr << j.highlighted_whereis(it) << "\n";
257  std::cerr << "\n";
258  cmp = "line 2, character 4, of file \"././a.txt\"\n"
259  "included from line 2 of file \"././j.txt\"";
260  cmp += "\n\nvwxyz\n ^";
262  std::advance(it, 10);
263  BOOST_TEST_REQUIRE(*it == '7');
264  std::cerr << j.highlighted_whereis(it) << "\n";
265  cmp = "line 2, character 2, of file \"././b.txt\"\n"
266  "included from line 3 of file \"././j.txt\"";
267  cmp += "\n\n67890\n ^";
269 }
270 
271 BOOST_AUTO_TEST_SUITE_END()
const_iterator end() const
Definition: includer.h:40
static QCString result
std::string string
Definition: nybbler.cc:12
const_iterator begin() const
Definition: includer.h:35
std::string highlighted_whereis(const_iterator const &it) const
Definition: includer.cc:155
int errno
Contains the last error code.
Definition: structcmd.h:53
BOOST_TEST_REQUIRE(static_cast< bool >(inFile))
BOOST_AUTO_TEST_CASE(no_inclusion_test)
def symlink(src, dest)
const double e
const double a
std::string whereis(const_iterator const &it) const
Definition: includer.cc:143
static bool * b
Definition: config.cpp:1043
static QCString str
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33