1 // Copyright 2015 The Kyua Authors.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 // * Neither the name of Google Inc. nor the names of its contributors
14 // may be used to endorse or promote products derived from this software
15 // without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29 #include "engine/atf_list.hpp"
30
31 #include <sstream>
32 #include <string>
33
34 #include <atf-c++.hpp>
35
36 #include "engine/exceptions.hpp"
37 #include "model/metadata.hpp"
38 #include "model/test_case.hpp"
39 #include "model/types.hpp"
40 #include "utils/datetime.hpp"
41 #include "utils/format/containers.ipp"
42 #include "utils/fs/path.hpp"
43 #include "utils/units.hpp"
44
45 namespace datetime = utils::datetime;
46 namespace fs = utils::fs;
47 namespace units = utils::units;
48
49
50 ATF_TEST_CASE_WITHOUT_HEAD(parse_atf_metadata__defaults)
ATF_TEST_CASE_BODY(parse_atf_metadata__defaults)51 ATF_TEST_CASE_BODY(parse_atf_metadata__defaults)
52 {
53 const model::properties_map properties;
54 const model::metadata md = engine::parse_atf_metadata(properties);
55
56 const model::metadata exp_md = model::metadata_builder().build();
57 ATF_REQUIRE_EQ(exp_md, md);
58 }
59
60
61 ATF_TEST_CASE_WITHOUT_HEAD(parse_atf_metadata__override_all)
ATF_TEST_CASE_BODY(parse_atf_metadata__override_all)62 ATF_TEST_CASE_BODY(parse_atf_metadata__override_all)
63 {
64 model::properties_map properties;
65 properties["descr"] = "Some text";
66 properties["has.cleanup"] = "true";
67 properties["require.arch"] = "i386 x86_64";
68 properties["require.config"] = "var1 var2 var3";
69 properties["require.files"] = "/file1 /dir/file2";
70 properties["require.machine"] = "amd64";
71 properties["require.memory"] = "1m";
72 properties["require.progs"] = "/bin/ls svn";
73 properties["require.user"] = "root";
74 properties["timeout"] = "123";
75 properties["X-foo"] = "value1";
76 properties["X-bar"] = "value2";
77 properties["X-baz-www"] = "value3";
78 const model::metadata md = engine::parse_atf_metadata(properties);
79
80 const model::metadata exp_md = model::metadata_builder()
81 .add_allowed_architecture("i386")
82 .add_allowed_architecture("x86_64")
83 .add_allowed_platform("amd64")
84 .add_custom("foo", "value1")
85 .add_custom("bar", "value2")
86 .add_custom("baz-www", "value3")
87 .add_required_config("var1")
88 .add_required_config("var2")
89 .add_required_config("var3")
90 .add_required_file(fs::path("/file1"))
91 .add_required_file(fs::path("/dir/file2"))
92 .add_required_program(fs::path("/bin/ls"))
93 .add_required_program(fs::path("svn"))
94 .set_description("Some text")
95 .set_has_cleanup(true)
96 .set_required_memory(units::bytes::parse("1m"))
97 .set_required_user("root")
98 .set_timeout(datetime::delta(123, 0))
99 .build();
100 ATF_REQUIRE_EQ(exp_md, md);
101 }
102
103
104 ATF_TEST_CASE_WITHOUT_HEAD(parse_atf_metadata__unknown)
ATF_TEST_CASE_BODY(parse_atf_metadata__unknown)105 ATF_TEST_CASE_BODY(parse_atf_metadata__unknown)
106 {
107 model::properties_map properties;
108 properties["foobar"] = "Some text";
109
110 ATF_REQUIRE_THROW_RE(engine::format_error, "Unknown.*property.*'foobar'",
111 engine::parse_atf_metadata(properties));
112 }
113
114
115 ATF_TEST_CASE_WITHOUT_HEAD(parse_atf_list__empty);
ATF_TEST_CASE_BODY(parse_atf_list__empty)116 ATF_TEST_CASE_BODY(parse_atf_list__empty)
117 {
118 const std::string text = "";
119 std::istringstream input(text);
120 ATF_REQUIRE_THROW_RE(engine::format_error, "expecting Content-Type",
121 engine::parse_atf_list(input));
122 }
123
124
125 ATF_TEST_CASE_WITHOUT_HEAD(parse_atf_list__invalid_header);
ATF_TEST_CASE_BODY(parse_atf_list__invalid_header)126 ATF_TEST_CASE_BODY(parse_atf_list__invalid_header)
127 {
128 {
129 const std::string text =
130 "Content-Type: application/X-atf-tp; version=\"1\"\n";
131 std::istringstream input(text);
132 ATF_REQUIRE_THROW_RE(engine::format_error, "expecting.*blank line",
133 engine::parse_atf_list(input));
134 }
135
136 {
137 const std::string text =
138 "Content-Type: application/X-atf-tp; version=\"1\"\nfoo\n";
139 std::istringstream input(text);
140 ATF_REQUIRE_THROW_RE(engine::format_error, "expecting.*blank line",
141 engine::parse_atf_list(input));
142 }
143
144 {
145 const std::string text =
146 "Content-Type: application/X-atf-tp; version=\"2\"\n\n";
147 std::istringstream input(text);
148 ATF_REQUIRE_THROW_RE(engine::format_error, "expecting Content-Type",
149 engine::parse_atf_list(input));
150 }
151 }
152
153
154 ATF_TEST_CASE_WITHOUT_HEAD(parse_atf_list__no_test_cases);
ATF_TEST_CASE_BODY(parse_atf_list__no_test_cases)155 ATF_TEST_CASE_BODY(parse_atf_list__no_test_cases)
156 {
157 const std::string text =
158 "Content-Type: application/X-atf-tp; version=\"1\"\n\n";
159 std::istringstream input(text);
160 ATF_REQUIRE_THROW_RE(engine::format_error, "No test cases",
161 engine::parse_atf_list(input));
162 }
163
164
165 ATF_TEST_CASE_WITHOUT_HEAD(parse_atf_list__one_test_case_simple);
ATF_TEST_CASE_BODY(parse_atf_list__one_test_case_simple)166 ATF_TEST_CASE_BODY(parse_atf_list__one_test_case_simple)
167 {
168 const std::string text =
169 "Content-Type: application/X-atf-tp; version=\"1\"\n"
170 "\n"
171 "ident: test-case\n";
172 std::istringstream input(text);
173 const model::test_cases_map tests = engine::parse_atf_list(input);
174
175 const model::test_cases_map exp_tests = model::test_cases_map_builder()
176 .add("test-case").build();
177 ATF_REQUIRE_EQ(exp_tests, tests);
178 }
179
180
181 ATF_TEST_CASE_WITHOUT_HEAD(parse_atf_list__one_test_case_complex);
ATF_TEST_CASE_BODY(parse_atf_list__one_test_case_complex)182 ATF_TEST_CASE_BODY(parse_atf_list__one_test_case_complex)
183 {
184 const std::string text =
185 "Content-Type: application/X-atf-tp; version=\"1\"\n"
186 "\n"
187 "ident: first\n"
188 "descr: This is the description\n"
189 "timeout: 500\n";
190 std::istringstream input(text);
191 const model::test_cases_map tests = engine::parse_atf_list(input);
192
193 const model::test_cases_map exp_tests = model::test_cases_map_builder()
194 .add("first", model::metadata_builder()
195 .set_description("This is the description")
196 .set_timeout(datetime::delta(500, 0))
197 .build())
198 .build();
199 ATF_REQUIRE_EQ(exp_tests, tests);
200 }
201
202
203 ATF_TEST_CASE_WITHOUT_HEAD(parse_atf_list__one_test_case_invalid_syntax);
ATF_TEST_CASE_BODY(parse_atf_list__one_test_case_invalid_syntax)204 ATF_TEST_CASE_BODY(parse_atf_list__one_test_case_invalid_syntax)
205 {
206 const std::string text =
207 "Content-Type: application/X-atf-tp; version=\"1\"\n\n"
208 "descr: This is the description\n"
209 "ident: first\n";
210 std::istringstream input(text);
211 ATF_REQUIRE_THROW_RE(engine::format_error, "preceeded.*identifier",
212 engine::parse_atf_list(input));
213 }
214
215
216 ATF_TEST_CASE_WITHOUT_HEAD(parse_atf_list__one_test_case_invalid_properties);
ATF_TEST_CASE_BODY(parse_atf_list__one_test_case_invalid_properties)217 ATF_TEST_CASE_BODY(parse_atf_list__one_test_case_invalid_properties)
218 {
219 // Inject a single invalid property that makes test_case::from_properties()
220 // raise a particular error message so that we can validate that such
221 // function was called. We do intensive testing separately, so it is not
222 // necessary to redo it here.
223 const std::string text =
224 "Content-Type: application/X-atf-tp; version=\"1\"\n\n"
225 "ident: first\n"
226 "require.progs: bin/ls\n";
227 std::istringstream input(text);
228 ATF_REQUIRE_THROW_RE(engine::format_error, "Relative path 'bin/ls'",
229 engine::parse_atf_list(input));
230 }
231
232
233 ATF_TEST_CASE_WITHOUT_HEAD(parse_atf_list__many_test_cases);
ATF_TEST_CASE_BODY(parse_atf_list__many_test_cases)234 ATF_TEST_CASE_BODY(parse_atf_list__many_test_cases)
235 {
236 const std::string text =
237 "Content-Type: application/X-atf-tp; version=\"1\"\n"
238 "\n"
239 "ident: first\n"
240 "descr: This is the description\n"
241 "\n"
242 "ident: second\n"
243 "timeout: 500\n"
244 "descr: Some text\n"
245 "\n"
246 "ident: third\n";
247 std::istringstream input(text);
248 const model::test_cases_map tests = engine::parse_atf_list(input);
249
250 const model::test_cases_map exp_tests = model::test_cases_map_builder()
251 .add("first", model::metadata_builder()
252 .set_description("This is the description")
253 .build())
254 .add("second", model::metadata_builder()
255 .set_description("Some text")
256 .set_timeout(datetime::delta(500, 0))
257 .build())
258 .add("third")
259 .build();
260 ATF_REQUIRE_EQ(exp_tests, tests);
261 }
262
263
ATF_INIT_TEST_CASES(tcs)264 ATF_INIT_TEST_CASES(tcs)
265 {
266 ATF_ADD_TEST_CASE(tcs, parse_atf_metadata__defaults);
267 ATF_ADD_TEST_CASE(tcs, parse_atf_metadata__override_all);
268 ATF_ADD_TEST_CASE(tcs, parse_atf_metadata__unknown);
269
270 ATF_ADD_TEST_CASE(tcs, parse_atf_list__empty);
271 ATF_ADD_TEST_CASE(tcs, parse_atf_list__invalid_header);
272 ATF_ADD_TEST_CASE(tcs, parse_atf_list__no_test_cases);
273 ATF_ADD_TEST_CASE(tcs, parse_atf_list__one_test_case_simple);
274 ATF_ADD_TEST_CASE(tcs, parse_atf_list__one_test_case_complex);
275 ATF_ADD_TEST_CASE(tcs, parse_atf_list__one_test_case_invalid_syntax);
276 ATF_ADD_TEST_CASE(tcs, parse_atf_list__one_test_case_invalid_properties);
277 ATF_ADD_TEST_CASE(tcs, parse_atf_list__many_test_cases);
278 }
279