1 /*
2  * Copyright (c) 2015, Intel Corporation
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this
9  * list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation and/or
13  * other materials provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors
16  * may be used to endorse or promote products derived from this software without
17  * specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #pragma once
32 
33 #include "Config.hpp"
34 #include "ParameterFramework.hpp"
35 
36 #include <catch.hpp>
37 
38 #include <string>
39 
40 #ifndef SCENARIO_METHOD
41 /** SCENARIO_METHOD is not available in catch on ubuntu 12.04 */
42 #define SCENARIO_METHOD(className, ...) TEST_CASE_METHOD(className, "Scenario: " __VA_ARGS__)
43 #endif
44 
45 namespace parameterFramework
46 {
47 
48 /** Value to test with a title.
49  *
50  * When testing code it is often useful to have an list of possible
51  * values and run the test for each of them.
52  * This class represents one element of this list. For the complete list
53  * see Tests.
54  *
55  * Catch has no build-in support for such need
56  * (in fact it has but it is still experimental, look for "generators")
57  * but it can be emulated with a loop over Tests.
58  *
59  * Each Test MUST specify a unique title, Ie all titles of a Tests MUST
60  * be different. This is dued to the way that catch detects that a SECTION
61  * has already been run. For more explanation see Tests.
62  */
63 template <class Value>
64 struct Test
65 {
66     std::string title;
67     Value payload;
68 };
69 
70 /** Use a vector to represent a collection of test input.
71  *
72  * This type is designed to be used to parametrize tests.
73  * Use it as follow:
74  *     for (auto &test : Tests<std::string>{
75  *     //                      ^~~~~~~~~~~ Test parameter type
76  *             {"an invalid tag", "<invalid tag\"/> "},
77  *           //^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Test parameters
78  *             {"an unknown tag", "<unknown_tag/>"},
79  *           // ^~~~~~~~~~~~~~~~ Unique title across the tests
80  *             {"an unclosed tag", "<unclosed>"} }) {
81  *           //                    ^~~~~~~~~~~ Value to test
82  *         SECTION("Testing: " + test.title) {
83  *         //                     ^~~~~~~~~~ Section title MUST unique
84  *            test.payload //< value to test
85  *            REQUIRE(getTag() != test.payload); // Example
86  *            ...
87  *         }
88  *     }
89  *
90  *
91  * Beware that if Value is not copyable, only movable this will
92  * fail to compile as initializer_list does not support move semantic
93  * (lets hope it will be fix in C++17).
94  *
95  * If a new test vector needs to support move, define:
96  *     template <class Value>
97  *     using MovableTests = Test<value>[];
98  * This could be the default but VS2013 does not support it.
99  * VS requires that an array size be defined. Thus define
100  *     template <class Value, size_t size>
101  *     using MovableTests = Test<value>[size];
102  * will fix the VS compilation. Nevertheless this means that
103  * all move only test vector will need to specify their size
104  * which is redondant.
105  * This is why it is not the default.
106  * Hopefully it will be when VS will support deducing the size.
107  */
108 template <class Value>
109 using Tests = std::vector<Test<Value>>;
110 
111 /** Defer Parameter Framework creation.
112  * A custom configuration can be provided.
113  */
114 class LazyPF
115 {
116 public:
117     using PF = ParameterFramework;
118 
create(Config && configFile)119     void create(Config &&configFile) { mPf.reset(new PF{std::move(configFile)}); }
120     std::unique_ptr<PF> mPf;
121 };
122 
123 /** PF that will log a warning at start. */
124 struct WarningPF : public ParameterFramework
125 {
WarningPFparameterFramework::WarningPF126     WarningPF() : ParameterFramework{{&Config::domains, "<InvalidDomain/>"}}
127     {
128         setFailureOnFailedSettingsLoad(false);
129     }
130 };
131 } // namespace parameterFramework
132