1//
2// Automated Testing Framework (atf)
3//
4// Copyright (c) 2010 The NetBSD Foundation, Inc.
5// All rights reserved.
6//
7// Redistribution and use in source and binary forms, with or without
8// modification, are permitted provided that the following conditions
9// are met:
10// 1. Redistributions of source code must retain the above copyright
11//    notice, this list of conditions and the following disclaimer.
12// 2. Redistributions in binary form must reproduce the above copyright
13//    notice, this list of conditions and the following disclaimer in the
14//    documentation and/or other materials provided with the distribution.
15//
16// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
17// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
18// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
21// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28//
29
30#include "atf-c++/detail/test_helpers.hpp"
31#include "atf-c++/macros.hpp"
32
33#include "config.hpp"
34
35namespace impl = atf::atf_run;
36namespace detail = atf::atf_run::detail;
37
38using atf::tests::vars_map;
39
40// -------------------------------------------------------------------------
41// Tests for the "config" parser.
42// -------------------------------------------------------------------------
43
44class config_reader : protected detail::atf_config_reader {
45    void
46    got_var(const std::string& name, const std::string& val)
47    {
48        m_calls.push_back("got_var(" + name + ", " + val + ")");
49    }
50
51    void
52    got_eof(void)
53    {
54        m_calls.push_back("got_eof()");
55    }
56
57public:
58    config_reader(std::istream& is) :
59        detail::atf_config_reader(is)
60    {
61    }
62
63    void
64    read(void)
65    {
66        atf_config_reader::read();
67    }
68
69    std::vector< std::string > m_calls;
70};
71
72ATF_TEST_CASE_WITHOUT_HEAD(config_1);
73ATF_TEST_CASE_BODY(config_1)
74{
75    const char* input =
76        "Content-Type: application/X-atf-config; version=\"1\"\n"
77        "\n"
78    ;
79
80    const char* exp_calls[] = {
81        "got_eof()",
82        NULL
83    };
84
85    const char* exp_errors[] = {
86        NULL
87    };
88
89    do_parser_test< config_reader >(input, exp_calls, exp_errors);
90}
91
92ATF_TEST_CASE_WITHOUT_HEAD(config_2);
93ATF_TEST_CASE_BODY(config_2)
94{
95    const char* input =
96        "Content-Type: application/X-atf-config; version=\"1\"\n"
97        "\n"
98        "# This is a comment on a line of its own.\n"
99        "# And this is another one.\n"
100        "\n"
101        "	    # Another after some whitespace.\n"
102        "\n"
103        "# The last one after an empty line.\n"
104    ;
105
106    const char* exp_calls[] = {
107        "got_eof()",
108        NULL
109    };
110
111    const char* exp_errors[] = {
112        NULL
113    };
114
115    do_parser_test< config_reader >(input, exp_calls, exp_errors);
116}
117
118ATF_TEST_CASE_WITHOUT_HEAD(config_3);
119ATF_TEST_CASE_BODY(config_3)
120{
121    const char* input =
122        "Content-Type: application/X-atf-config; version=\"1\"\n"
123        "\n"
124        "var1=value1\n"
125        "var2 = value2\n"
126        "var3	=	value3\n"
127        "var4	    =	    value4\n"
128        "\n"
129        "var5=value5\n"
130        "    var6=value6\n"
131        "\n"
132        "var7 = \"This is a long value.\"\n"
133        "var8 = \"Single-word\"\n"
134        "var9 = \"    Single-word	\"\n"
135        "var10 = Single-word\n"
136    ;
137
138    const char* exp_calls[] = {
139        "got_var(var1, value1)",
140        "got_var(var2, value2)",
141        "got_var(var3, value3)",
142        "got_var(var4, value4)",
143        "got_var(var5, value5)",
144        "got_var(var6, value6)",
145        "got_var(var7, This is a long value.)",
146        "got_var(var8, Single-word)",
147        "got_var(var9,     Single-word	)",
148        "got_var(var10, Single-word)",
149        "got_eof()",
150        NULL
151    };
152
153    const char* exp_errors[] = {
154        NULL
155    };
156
157    do_parser_test< config_reader >(input, exp_calls, exp_errors);
158}
159
160ATF_TEST_CASE_WITHOUT_HEAD(config_4);
161ATF_TEST_CASE_BODY(config_4)
162{
163    const char* input =
164        "Content-Type: application/X-atf-config; version=\"1\"\n"
165        "\n"
166        "foo = bar # A comment.\n"
167    ;
168
169    const char* exp_calls[] = {
170        "got_var(foo, bar)",
171        "got_eof()",
172        NULL
173    };
174
175    const char* exp_errors[] = {
176        NULL
177    };
178
179    do_parser_test< config_reader >(input, exp_calls, exp_errors);
180}
181
182ATF_TEST_CASE_WITHOUT_HEAD(config_50);
183ATF_TEST_CASE_BODY(config_50)
184{
185    const char* input =
186        "Content-Type: application/X-atf-config; version=\"1\"\n"
187        "\n"
188        "foo\n"
189    ;
190
191    const char* exp_calls[] = {
192        NULL
193    };
194
195    const char* exp_errors[] = {
196        "3: Unexpected token `<<NEWLINE>>'; expected equal sign",
197        NULL
198    };
199
200    do_parser_test< config_reader >(input, exp_calls, exp_errors);
201}
202
203ATF_TEST_CASE_WITHOUT_HEAD(config_51);
204ATF_TEST_CASE_BODY(config_51)
205{
206    const char* input =
207        "Content-Type: application/X-atf-config; version=\"1\"\n"
208        "\n"
209        "foo bar\n"
210        "baz\n"
211    ;
212
213    const char* exp_calls[] = {
214        NULL
215    };
216
217    const char* exp_errors[] = {
218        "3: Unexpected token `bar'; expected equal sign",
219        "4: Unexpected token `<<NEWLINE>>'; expected equal sign",
220        NULL
221    };
222
223    do_parser_test< config_reader >(input, exp_calls, exp_errors);
224}
225
226ATF_TEST_CASE_WITHOUT_HEAD(config_52);
227ATF_TEST_CASE_BODY(config_52)
228{
229    const char* input =
230        "Content-Type: application/X-atf-config; version=\"1\"\n"
231        "\n"
232        "foo =\n"
233        "bar = # A comment.\n"
234    ;
235
236    const char* exp_calls[] = {
237        NULL
238    };
239
240    const char* exp_errors[] = {
241        "3: Unexpected token `<<NEWLINE>>'; expected word or quoted string",
242        "4: Unexpected token `#'; expected word or quoted string",
243        NULL
244    };
245
246    do_parser_test< config_reader >(input, exp_calls, exp_errors);
247}
248
249ATF_TEST_CASE_WITHOUT_HEAD(config_53);
250ATF_TEST_CASE_BODY(config_53)
251{
252    const char* input =
253        "Content-Type: application/X-atf-config; version=\"1\"\n"
254        "\n"
255        "foo = \"Correct value\" # With comment.\n"
256        "\n"
257        "bar = # A comment.\n"
258        "\n"
259        "baz = \"Last variable\"\n"
260        "\n"
261        "# End of file.\n"
262    ;
263
264    const char* exp_calls[] = {
265        "got_var(foo, Correct value)",
266        NULL
267    };
268
269    const char* exp_errors[] = {
270        "5: Unexpected token `#'; expected word or quoted string",
271        NULL
272    };
273
274    do_parser_test< config_reader >(input, exp_calls, exp_errors);
275}
276
277ATF_TEST_CASE_WITHOUT_HEAD(config_54);
278ATF_TEST_CASE_BODY(config_54)
279{
280    const char* input =
281        "Content-Type: application/X-atf-config; version=\"1\"\n"
282        "\n"
283        "foo = \"\n"
284        "bar = \"text\n"
285        "baz = \"te\\\"xt\n"
286        "last = \"\\\"\n"
287    ;
288
289    const char* exp_calls[] = {
290        NULL
291    };
292
293    const char* exp_errors[] = {
294        "3: Missing double quotes before end of line",
295        "4: Missing double quotes before end of line",
296        "5: Missing double quotes before end of line",
297        "6: Missing double quotes before end of line",
298        NULL
299    };
300
301    do_parser_test< config_reader >(input, exp_calls, exp_errors);
302}
303
304// -------------------------------------------------------------------------
305// Tests for the free functions.
306// -------------------------------------------------------------------------
307
308ATF_TEST_CASE(merge_configs_both_empty);
309ATF_TEST_CASE_HEAD(merge_configs_both_empty) {}
310ATF_TEST_CASE_BODY(merge_configs_both_empty) {
311    vars_map lower, upper;
312
313    ATF_REQUIRE(impl::merge_configs(lower, upper).empty());
314}
315
316ATF_TEST_CASE(merge_configs_lower_empty);
317ATF_TEST_CASE_HEAD(merge_configs_lower_empty) {}
318ATF_TEST_CASE_BODY(merge_configs_lower_empty) {
319    vars_map lower, upper;
320    upper["var"] = "value";
321
322    vars_map merged = impl::merge_configs(lower, upper);
323    ATF_REQUIRE_EQ("value", merged["var"]);
324}
325
326ATF_TEST_CASE(merge_configs_upper_empty);
327ATF_TEST_CASE_HEAD(merge_configs_upper_empty) {}
328ATF_TEST_CASE_BODY(merge_configs_upper_empty) {
329    vars_map lower, upper;
330    lower["var"] = "value";
331
332    vars_map merged = impl::merge_configs(lower, upper);
333    ATF_REQUIRE_EQ("value", merged["var"]);
334}
335
336ATF_TEST_CASE(merge_configs_mixed);
337ATF_TEST_CASE_HEAD(merge_configs_mixed) {}
338ATF_TEST_CASE_BODY(merge_configs_mixed) {
339    vars_map lower, upper;
340    lower["var1"] = "value1";
341    lower["var2"] = "value2-l";
342    upper["var2"] = "value2-u";
343    upper["var3"] = "value3";
344
345    vars_map merged = impl::merge_configs(lower, upper);
346    ATF_REQUIRE_EQ("value1", merged["var1"]);
347    ATF_REQUIRE_EQ("value2-u", merged["var2"]);
348    ATF_REQUIRE_EQ("value3", merged["var3"]);
349}
350
351ATF_TEST_CASE(read_config_files_none);
352ATF_TEST_CASE_HEAD(read_config_files_none) {}
353ATF_TEST_CASE_BODY(read_config_files_none) {
354    ATF_REQUIRE(vars_map() == impl::read_config_files("test-suite"));
355}
356
357// -------------------------------------------------------------------------
358// Main.
359// -------------------------------------------------------------------------
360
361ATF_INIT_TEST_CASES(tcs)
362{
363    ATF_ADD_TEST_CASE(tcs, config_1);
364    ATF_ADD_TEST_CASE(tcs, config_2);
365    ATF_ADD_TEST_CASE(tcs, config_3);
366    ATF_ADD_TEST_CASE(tcs, config_4);
367    ATF_ADD_TEST_CASE(tcs, config_50);
368    ATF_ADD_TEST_CASE(tcs, config_51);
369    ATF_ADD_TEST_CASE(tcs, config_52);
370    ATF_ADD_TEST_CASE(tcs, config_53);
371    ATF_ADD_TEST_CASE(tcs, config_54);
372
373    ATF_ADD_TEST_CASE(tcs, merge_configs_both_empty);
374    ATF_ADD_TEST_CASE(tcs, merge_configs_lower_empty);
375    ATF_ADD_TEST_CASE(tcs, merge_configs_upper_empty);
376    ATF_ADD_TEST_CASE(tcs, merge_configs_mixed);
377
378    ATF_ADD_TEST_CASE(tcs, read_config_files_none);
379}
380