xref: /freebsd/contrib/kyua/engine/atf_list_test.cpp (revision dd21556857e8d40f66bf5ad54754d9d52669ebf7)
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)
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)
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["is.exclusive"] = "true";
68     properties["require.arch"] = "i386 x86_64";
69     properties["require.config"] = "var1 var2 var3";
70     properties["require.files"] = "/file1 /dir/file2";
71     properties["require.machine"] = "amd64";
72     properties["require.memory"] = "1m";
73     properties["require.progs"] = "/bin/ls svn";
74     properties["require.user"] = "root";
75     properties["timeout"] = "123";
76     properties["X-foo"] = "value1";
77     properties["X-bar"] = "value2";
78     properties["X-baz-www"] = "value3";
79     const model::metadata md = engine::parse_atf_metadata(properties);
80 
81     const model::metadata exp_md = model::metadata_builder()
82         .add_allowed_architecture("i386")
83         .add_allowed_architecture("x86_64")
84         .add_allowed_platform("amd64")
85         .add_custom("foo", "value1")
86         .add_custom("bar", "value2")
87         .add_custom("baz-www", "value3")
88         .add_required_config("var1")
89         .add_required_config("var2")
90         .add_required_config("var3")
91         .add_required_file(fs::path("/file1"))
92         .add_required_file(fs::path("/dir/file2"))
93         .add_required_program(fs::path("/bin/ls"))
94         .add_required_program(fs::path("svn"))
95         .set_description("Some text")
96         .set_has_cleanup(true)
97         .set_is_exclusive(true)
98         .set_required_memory(units::bytes::parse("1m"))
99         .set_required_user("root")
100         .set_timeout(datetime::delta(123, 0))
101         .build();
102     ATF_REQUIRE_EQ(exp_md, md);
103 }
104 
105 
106 ATF_TEST_CASE_WITHOUT_HEAD(parse_atf_metadata__unknown)
107 ATF_TEST_CASE_BODY(parse_atf_metadata__unknown)
108 {
109     model::properties_map properties;
110     properties["foobar"] = "Some text";
111 
112     ATF_REQUIRE_THROW_RE(engine::format_error, "Unknown.*property.*'foobar'",
113                          engine::parse_atf_metadata(properties));
114 }
115 
116 
117 ATF_TEST_CASE_WITHOUT_HEAD(parse_atf_list__empty);
118 ATF_TEST_CASE_BODY(parse_atf_list__empty)
119 {
120     const std::string text = "";
121     std::istringstream input(text);
122     ATF_REQUIRE_THROW_RE(engine::format_error, "expecting Content-Type",
123         engine::parse_atf_list(input));
124 }
125 
126 
127 ATF_TEST_CASE_WITHOUT_HEAD(parse_atf_list__invalid_header);
128 ATF_TEST_CASE_BODY(parse_atf_list__invalid_header)
129 {
130     {
131         const std::string text =
132             "Content-Type: application/X-atf-tp; version=\"1\"\n";
133         std::istringstream input(text);
134         ATF_REQUIRE_THROW_RE(engine::format_error, "expecting.*blank line",
135             engine::parse_atf_list(input));
136     }
137 
138     {
139         const std::string text =
140             "Content-Type: application/X-atf-tp; version=\"1\"\nfoo\n";
141         std::istringstream input(text);
142         ATF_REQUIRE_THROW_RE(engine::format_error, "expecting.*blank line",
143             engine::parse_atf_list(input));
144     }
145 
146     {
147         const std::string text =
148             "Content-Type: application/X-atf-tp; version=\"2\"\n\n";
149         std::istringstream input(text);
150         ATF_REQUIRE_THROW_RE(engine::format_error, "expecting Content-Type",
151             engine::parse_atf_list(input));
152     }
153 }
154 
155 
156 ATF_TEST_CASE_WITHOUT_HEAD(parse_atf_list__no_test_cases);
157 ATF_TEST_CASE_BODY(parse_atf_list__no_test_cases)
158 {
159     const std::string text =
160         "Content-Type: application/X-atf-tp; version=\"1\"\n\n";
161     std::istringstream input(text);
162     ATF_REQUIRE_THROW_RE(engine::format_error, "No test cases",
163         engine::parse_atf_list(input));
164 }
165 
166 
167 ATF_TEST_CASE_WITHOUT_HEAD(parse_atf_list__one_test_case_simple);
168 ATF_TEST_CASE_BODY(parse_atf_list__one_test_case_simple)
169 {
170     const std::string text =
171         "Content-Type: application/X-atf-tp; version=\"1\"\n"
172         "\n"
173         "ident: test-case\n";
174     std::istringstream input(text);
175     const model::test_cases_map tests = engine::parse_atf_list(input);
176 
177     const model::test_cases_map exp_tests = model::test_cases_map_builder()
178         .add("test-case").build();
179     ATF_REQUIRE_EQ(exp_tests, tests);
180 }
181 
182 
183 ATF_TEST_CASE_WITHOUT_HEAD(parse_atf_list__one_test_case_complex);
184 ATF_TEST_CASE_BODY(parse_atf_list__one_test_case_complex)
185 {
186     const std::string text =
187         "Content-Type: application/X-atf-tp; version=\"1\"\n"
188         "\n"
189         "ident: first\n"
190         "descr: This is the description\n"
191         "timeout: 500\n";
192     std::istringstream input(text);
193     const model::test_cases_map tests = engine::parse_atf_list(input);
194 
195     const model::test_cases_map exp_tests = model::test_cases_map_builder()
196         .add("first", model::metadata_builder()
197              .set_description("This is the description")
198              .set_timeout(datetime::delta(500, 0))
199              .build())
200         .build();
201     ATF_REQUIRE_EQ(exp_tests, tests);
202 }
203 
204 
205 ATF_TEST_CASE_WITHOUT_HEAD(parse_atf_list__one_test_case_invalid_syntax);
206 ATF_TEST_CASE_BODY(parse_atf_list__one_test_case_invalid_syntax)
207 {
208     const std::string text =
209         "Content-Type: application/X-atf-tp; version=\"1\"\n\n"
210         "descr: This is the description\n"
211         "ident: first\n";
212     std::istringstream input(text);
213     ATF_REQUIRE_THROW_RE(engine::format_error, "preceeded.*identifier",
214         engine::parse_atf_list(input));
215 }
216 
217 
218 ATF_TEST_CASE_WITHOUT_HEAD(parse_atf_list__one_test_case_invalid_properties);
219 ATF_TEST_CASE_BODY(parse_atf_list__one_test_case_invalid_properties)
220 {
221     // Inject a single invalid property that makes test_case::from_properties()
222     // raise a particular error message so that we can validate that such
223     // function was called.  We do intensive testing separately, so it is not
224     // necessary to redo it here.
225     const std::string text =
226         "Content-Type: application/X-atf-tp; version=\"1\"\n\n"
227         "ident: first\n"
228         "require.progs: bin/ls\n";
229     std::istringstream input(text);
230     ATF_REQUIRE_THROW_RE(engine::format_error, "Relative path 'bin/ls'",
231         engine::parse_atf_list(input));
232 }
233 
234 
235 ATF_TEST_CASE_WITHOUT_HEAD(parse_atf_list__many_test_cases);
236 ATF_TEST_CASE_BODY(parse_atf_list__many_test_cases)
237 {
238     const std::string text =
239         "Content-Type: application/X-atf-tp; version=\"1\"\n"
240         "\n"
241         "ident: first\n"
242         "descr: This is the description\n"
243         "\n"
244         "ident: second\n"
245         "timeout: 500\n"
246         "descr: Some text\n"
247         "\n"
248         "ident: third\n";
249     std::istringstream input(text);
250     const model::test_cases_map tests = engine::parse_atf_list(input);
251 
252     const model::test_cases_map exp_tests = model::test_cases_map_builder()
253         .add("first", model::metadata_builder()
254              .set_description("This is the description")
255              .build())
256         .add("second", model::metadata_builder()
257              .set_description("Some text")
258              .set_timeout(datetime::delta(500, 0))
259              .build())
260         .add("third")
261         .build();
262     ATF_REQUIRE_EQ(exp_tests, tests);
263 }
264 
265 
266 ATF_TEST_CASE_WITHOUT_HEAD(parse_atf_list__is_exclusive_support);
267 ATF_TEST_CASE_BODY(parse_atf_list__is_exclusive_support)
268 {
269     const std::string text =
270         "Content-Type: application/X-atf-tp; version=\"1\"\n"
271         "\n"
272         "ident: first\n"
273         "is.exclusive: false\n"
274         "descr: This is the descr\n"
275         "\n"
276         "ident: second\n"
277         "is.exclusive: true\n"
278         "\n"
279         "ident: third\n";
280     std::istringstream input(text);
281     const model::test_cases_map tests = engine::parse_atf_list(input);
282 
283     const model::test_cases_map exp_tests = model::test_cases_map_builder()
284         .add("first", model::metadata_builder()
285              .set_description("This is the descr")
286              .build())
287         .add("second", model::metadata_builder()
288              .set_is_exclusive(true)
289              .build())
290         .add("third")
291         .build();
292     ATF_REQUIRE_EQ(exp_tests, tests);
293 }
294 
295 
296 ATF_INIT_TEST_CASES(tcs)
297 {
298     ATF_ADD_TEST_CASE(tcs, parse_atf_metadata__defaults);
299     ATF_ADD_TEST_CASE(tcs, parse_atf_metadata__override_all);
300     ATF_ADD_TEST_CASE(tcs, parse_atf_metadata__unknown);
301 
302     ATF_ADD_TEST_CASE(tcs, parse_atf_list__empty);
303     ATF_ADD_TEST_CASE(tcs, parse_atf_list__invalid_header);
304     ATF_ADD_TEST_CASE(tcs, parse_atf_list__no_test_cases);
305     ATF_ADD_TEST_CASE(tcs, parse_atf_list__one_test_case_simple);
306     ATF_ADD_TEST_CASE(tcs, parse_atf_list__one_test_case_complex);
307     ATF_ADD_TEST_CASE(tcs, parse_atf_list__one_test_case_invalid_syntax);
308     ATF_ADD_TEST_CASE(tcs, parse_atf_list__one_test_case_invalid_properties);
309     ATF_ADD_TEST_CASE(tcs, parse_atf_list__many_test_cases);
310     ATF_ADD_TEST_CASE(tcs, parse_atf_list__is_exclusive_support);
311 }
312