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
45namespace 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 */
63template <class Value>
64struct 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 */
108template <class Value>
109using Tests = std::vector<Test<Value>>;
110
111/** Defer Parameter Framework creation.
112 * A custom configuration can be provided.
113 */
114class LazyPF
115{
116public:
117    using PF = ParameterFramework;
118
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. */
124struct WarningPF : public ParameterFramework
125{
126    WarningPF() : ParameterFramework{{&Config::domains, "<InvalidDomain/>"}}
127    {
128        setFailureOnFailedSettingsLoad(false);
129    }
130};
131}
132