1// Copyright 2010 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 "model/test_case.hpp"
30
31#include <sstream>
32
33#include <atf-c++.hpp>
34
35#include "model/metadata.hpp"
36#include "model/test_result.hpp"
37#include "utils/datetime.hpp"
38#include "utils/format/containers.ipp"
39#include "utils/fs/path.hpp"
40#include "utils/optional.ipp"
41
42namespace datetime = utils::datetime;
43namespace fs = utils::fs;
44
45
46ATF_TEST_CASE_WITHOUT_HEAD(test_case__ctor_and_getters)
47ATF_TEST_CASE_BODY(test_case__ctor_and_getters)
48{
49    const model::metadata md = model::metadata_builder()
50        .add_custom("first", "value")
51        .build();
52    const model::test_case test_case("foo", md);
53    ATF_REQUIRE_EQ("foo", test_case.name());
54    ATF_REQUIRE_EQ(md, test_case.get_metadata());
55    ATF_REQUIRE_EQ(md, test_case.get_raw_metadata());
56}
57
58
59ATF_TEST_CASE_WITHOUT_HEAD(test_case__fake_result)
60ATF_TEST_CASE_BODY(test_case__fake_result)
61{
62    const model::test_result result(model::test_result_skipped,
63                                    "Some reason");
64    const model::test_case test_case("__foo__", "Some description", result);
65    ATF_REQUIRE_EQ("__foo__", test_case.name());
66    ATF_REQUIRE_EQ(result, test_case.fake_result().get());
67
68    const model::metadata exp_metadata = model::metadata_builder()
69        .set_description("Some description")
70        .build();
71    ATF_REQUIRE_EQ(exp_metadata, test_case.get_metadata());
72    ATF_REQUIRE_EQ(exp_metadata, test_case.get_raw_metadata());
73}
74
75
76ATF_TEST_CASE_WITHOUT_HEAD(test_case__apply_metadata_overrides__real_test_case)
77ATF_TEST_CASE_BODY(test_case__apply_metadata_overrides__real_test_case)
78{
79    const model::metadata overrides = model::metadata_builder()
80        .add_required_config("the-variable")
81        .set_description("The test case")
82        .build();
83    const model::test_case base_test_case("foo", overrides);
84
85    const model::metadata defaults = model::metadata_builder()
86        .set_description("Default description")
87        .set_timeout(datetime::delta(10, 0))
88        .build();
89
90    const model::test_case test_case = base_test_case.apply_metadata_defaults(
91        &defaults);
92
93    const model::metadata expected = model::metadata_builder()
94        .add_required_config("the-variable")
95        .set_description("The test case")
96        .set_timeout(datetime::delta(10, 0))
97        .build();
98    ATF_REQUIRE_EQ(expected, test_case.get_metadata());
99    ATF_REQUIRE_EQ(overrides, test_case.get_raw_metadata());
100
101    // Ensure the original (although immutable) test case was not touched.
102    ATF_REQUIRE_EQ(overrides, base_test_case.get_metadata());
103}
104
105
106ATF_TEST_CASE_WITHOUT_HEAD(test_case__apply_metadata_overrides__fake_test_case)
107ATF_TEST_CASE_BODY(test_case__apply_metadata_overrides__fake_test_case)
108{
109    const model::test_result result(model::test_result_skipped, "Irrelevant");
110    const model::test_case base_test_case("__foo__", "Fake test", result);
111
112    const model::metadata overrides = model::metadata_builder()
113        .set_description("Fake test")
114        .build();
115
116    const model::metadata defaults = model::metadata_builder()
117        .add_allowed_platform("some-value")
118        .set_description("Default description")
119        .build();
120
121    const model::test_case test_case = base_test_case.apply_metadata_defaults(
122        &defaults);
123
124    const model::metadata expected = model::metadata_builder()
125        .add_allowed_platform("some-value")
126        .set_description("Fake test")
127        .build();
128    ATF_REQUIRE_EQ(expected, test_case.get_metadata());
129    ATF_REQUIRE_EQ(overrides, test_case.get_raw_metadata());
130}
131
132
133ATF_TEST_CASE_WITHOUT_HEAD(test_case__operators_eq_and_ne__copy);
134ATF_TEST_CASE_BODY(test_case__operators_eq_and_ne__copy)
135{
136    const model::test_case tc1("name", model::metadata_builder().build());
137    const model::test_case tc2 = tc1;
138    ATF_REQUIRE(  tc1 == tc2);
139    ATF_REQUIRE(!(tc1 != tc2));
140}
141
142
143ATF_TEST_CASE_WITHOUT_HEAD(test_case__operators_eq_and_ne__not_copy);
144ATF_TEST_CASE_BODY(test_case__operators_eq_and_ne__not_copy)
145{
146    const std::string base_name("name");
147    const model::metadata base_metadata = model::metadata_builder()
148        .add_custom("foo", "bar")
149        .build();
150
151    const model::test_case base_tc(base_name, base_metadata);
152
153    // Construct with all same values.
154    {
155        const model::test_case other_tc(base_name, base_metadata);
156
157        ATF_REQUIRE(  base_tc == other_tc);
158        ATF_REQUIRE(!(base_tc != other_tc));
159    }
160
161    // Construct with all same values but different metadata objects.
162    {
163        const model::metadata other_metadata = model::metadata_builder()
164            .add_custom("foo", "bar")
165            .set_timeout(base_metadata.timeout())
166            .build();
167        const model::test_case other_tc(base_name, other_metadata);
168
169        ATF_REQUIRE(  base_tc == other_tc);
170        ATF_REQUIRE(!(base_tc != other_tc));
171    }
172
173    // Different name.
174    {
175        const model::test_case other_tc("other", base_metadata);
176
177        ATF_REQUIRE(!(base_tc == other_tc));
178        ATF_REQUIRE(  base_tc != other_tc);
179    }
180
181    // Different metadata.
182    {
183        const model::test_case other_tc(base_name,
184                                        model::metadata_builder().build());
185
186        ATF_REQUIRE(!(base_tc == other_tc));
187        ATF_REQUIRE(  base_tc != other_tc);
188    }
189}
190
191
192ATF_TEST_CASE_WITHOUT_HEAD(test_case__output);
193ATF_TEST_CASE_BODY(test_case__output)
194{
195    const model::test_case tc1(
196        "the-name", model::metadata_builder()
197        .add_allowed_platform("foo").add_custom("bar", "baz").build());
198    std::ostringstream str;
199    str << tc1;
200    ATF_REQUIRE_EQ(
201        "test_case{name='the-name', "
202        "metadata=metadata{allowed_architectures='', allowed_platforms='foo', "
203        "custom.bar='baz', description='', has_cleanup='false', "
204        "is_exclusive='false', "
205        "required_configs='', required_disk_space='0', required_files='', "
206        "required_memory='0', "
207        "required_programs='', required_user='', timeout='300'}}",
208        str.str());
209}
210
211
212ATF_TEST_CASE_WITHOUT_HEAD(test_cases_map__builder);
213ATF_TEST_CASE_BODY(test_cases_map__builder)
214{
215    model::test_cases_map_builder builder;
216    model::test_cases_map exp_test_cases;
217
218    ATF_REQUIRE_EQ(exp_test_cases, builder.build());
219
220    builder.add("default-metadata");
221    {
222        const model::test_case tc1("default-metadata",
223                                   model::metadata_builder().build());
224        exp_test_cases.insert(
225            model::test_cases_map::value_type(tc1.name(), tc1));
226    }
227    ATF_REQUIRE_EQ(exp_test_cases, builder.build());
228
229    builder.add("with-metadata",
230                model::metadata_builder().set_description("text").build());
231    {
232        const model::test_case tc1("with-metadata",
233                                   model::metadata_builder()
234                                   .set_description("text").build());
235        exp_test_cases.insert(
236            model::test_cases_map::value_type(tc1.name(), tc1));
237    }
238    ATF_REQUIRE_EQ(exp_test_cases, builder.build());
239
240    const model::test_case tc1("fully_built",
241                               model::metadata_builder()
242                               .set_description("something else").build());
243    builder.add(tc1);
244    exp_test_cases.insert(model::test_cases_map::value_type(tc1.name(), tc1));
245    ATF_REQUIRE_EQ(exp_test_cases, builder.build());
246}
247
248
249ATF_INIT_TEST_CASES(tcs)
250{
251    ATF_ADD_TEST_CASE(tcs, test_case__ctor_and_getters);
252    ATF_ADD_TEST_CASE(tcs, test_case__fake_result);
253
254    ATF_ADD_TEST_CASE(tcs, test_case__apply_metadata_overrides__real_test_case);
255    ATF_ADD_TEST_CASE(tcs, test_case__apply_metadata_overrides__fake_test_case);
256
257    ATF_ADD_TEST_CASE(tcs, test_case__operators_eq_and_ne__copy);
258    ATF_ADD_TEST_CASE(tcs, test_case__operators_eq_and_ne__not_copy);
259
260    ATF_ADD_TEST_CASE(tcs, test_case__output);
261
262    ATF_ADD_TEST_CASE(tcs, test_cases_map__builder);
263}
264