xref: /src/contrib/kyua/model/test_program.cpp (revision b0d29bc47dba79f6f38e67eabadfb4b32ffd9390)
108334c51SBrooks Davis // Copyright 2010 The Kyua Authors.
208334c51SBrooks Davis // All rights reserved.
308334c51SBrooks Davis //
408334c51SBrooks Davis // Redistribution and use in source and binary forms, with or without
508334c51SBrooks Davis // modification, are permitted provided that the following conditions are
608334c51SBrooks Davis // met:
708334c51SBrooks Davis //
808334c51SBrooks Davis // * Redistributions of source code must retain the above copyright
908334c51SBrooks Davis //   notice, this list of conditions and the following disclaimer.
1008334c51SBrooks Davis // * Redistributions in binary form must reproduce the above copyright
1108334c51SBrooks Davis //   notice, this list of conditions and the following disclaimer in the
1208334c51SBrooks Davis //   documentation and/or other materials provided with the distribution.
1308334c51SBrooks Davis // * Neither the name of Google Inc. nor the names of its contributors
1408334c51SBrooks Davis //   may be used to endorse or promote products derived from this software
1508334c51SBrooks Davis //   without specific prior written permission.
1608334c51SBrooks Davis //
1708334c51SBrooks Davis // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1808334c51SBrooks Davis // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1908334c51SBrooks Davis // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2008334c51SBrooks Davis // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2108334c51SBrooks Davis // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2208334c51SBrooks Davis // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2308334c51SBrooks Davis // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2408334c51SBrooks Davis // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2508334c51SBrooks Davis // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2608334c51SBrooks Davis // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2708334c51SBrooks Davis // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2808334c51SBrooks Davis 
2908334c51SBrooks Davis #include "model/test_program.hpp"
3008334c51SBrooks Davis 
3108334c51SBrooks Davis #include <map>
3208334c51SBrooks Davis #include <sstream>
3308334c51SBrooks Davis 
3408334c51SBrooks Davis #include "model/exceptions.hpp"
3508334c51SBrooks Davis #include "model/metadata.hpp"
3608334c51SBrooks Davis #include "model/test_case.hpp"
3708334c51SBrooks Davis #include "model/test_result.hpp"
3808334c51SBrooks Davis #include "utils/format/containers.ipp"
3908334c51SBrooks Davis #include "utils/format/macros.hpp"
4008334c51SBrooks Davis #include "utils/fs/path.hpp"
4108334c51SBrooks Davis #include "utils/noncopyable.hpp"
4208334c51SBrooks Davis #include "utils/sanity.hpp"
4308334c51SBrooks Davis #include "utils/text/operations.ipp"
4408334c51SBrooks Davis 
4508334c51SBrooks Davis namespace fs = utils::fs;
4608334c51SBrooks Davis namespace text = utils::text;
4708334c51SBrooks Davis 
4808334c51SBrooks Davis using utils::none;
4908334c51SBrooks Davis 
5008334c51SBrooks Davis 
5108334c51SBrooks Davis /// Internal implementation of a test_program.
5208334c51SBrooks Davis struct model::test_program::impl : utils::noncopyable {
5308334c51SBrooks Davis     /// Name of the test program interface.
5408334c51SBrooks Davis     std::string interface_name;
5508334c51SBrooks Davis 
5608334c51SBrooks Davis     /// Name of the test program binary relative to root.
5708334c51SBrooks Davis     fs::path binary;
5808334c51SBrooks Davis 
5908334c51SBrooks Davis     /// Root of the test suite containing the test program.
6008334c51SBrooks Davis     fs::path root;
6108334c51SBrooks Davis 
6208334c51SBrooks Davis     /// Name of the test suite this program belongs to.
6308334c51SBrooks Davis     std::string test_suite_name;
6408334c51SBrooks Davis 
6508334c51SBrooks Davis     /// Metadata of the test program.
6608334c51SBrooks Davis     model::metadata md;
6708334c51SBrooks Davis 
6808334c51SBrooks Davis     /// List of test cases in the test program.
6908334c51SBrooks Davis     ///
7008334c51SBrooks Davis     /// Must be queried via the test_program::test_cases() method.
7108334c51SBrooks Davis     model::test_cases_map test_cases;
7208334c51SBrooks Davis 
7308334c51SBrooks Davis     /// Constructor.
7408334c51SBrooks Davis     ///
7508334c51SBrooks Davis     /// \param interface_name_ Name of the test program interface.
7608334c51SBrooks Davis     /// \param binary_ The name of the test program binary relative to root_.
7708334c51SBrooks Davis     /// \param root_ The root of the test suite containing the test program.
7808334c51SBrooks Davis     /// \param test_suite_name_ The name of the test suite this program
7908334c51SBrooks Davis     ///     belongs to.
8008334c51SBrooks Davis     /// \param md_ Metadata of the test program.
8108334c51SBrooks Davis     /// \param test_cases_ The collection of test cases in the test program.
implmodel::test_program::impl8208334c51SBrooks Davis     impl(const std::string& interface_name_, const fs::path& binary_,
8308334c51SBrooks Davis          const fs::path& root_, const std::string& test_suite_name_,
8408334c51SBrooks Davis          const model::metadata& md_, const model::test_cases_map& test_cases_) :
8508334c51SBrooks Davis         interface_name(interface_name_),
8608334c51SBrooks Davis         binary(binary_),
8708334c51SBrooks Davis         root(root_),
8808334c51SBrooks Davis         test_suite_name(test_suite_name_),
8908334c51SBrooks Davis         md(md_)
9008334c51SBrooks Davis     {
9108334c51SBrooks Davis         PRE_MSG(!binary.is_absolute(),
9208334c51SBrooks Davis                 F("The program '%s' must be relative to the root of the test "
9308334c51SBrooks Davis                   "suite '%s'") % binary % root);
9408334c51SBrooks Davis 
9508334c51SBrooks Davis         set_test_cases(test_cases_);
9608334c51SBrooks Davis     }
9708334c51SBrooks Davis 
9808334c51SBrooks Davis     /// Sets the list of test cases of the test program.
9908334c51SBrooks Davis     ///
10008334c51SBrooks Davis     /// \param test_cases_ The new list of test cases.
10108334c51SBrooks Davis     void
set_test_casesmodel::test_program::impl10208334c51SBrooks Davis     set_test_cases(const model::test_cases_map& test_cases_)
10308334c51SBrooks Davis     {
10408334c51SBrooks Davis         for (model::test_cases_map::const_iterator iter = test_cases_.begin();
10508334c51SBrooks Davis              iter != test_cases_.end(); ++iter) {
10608334c51SBrooks Davis             const std::string& name = (*iter).first;
10708334c51SBrooks Davis             const model::test_case& test_case = (*iter).second;
10808334c51SBrooks Davis 
10908334c51SBrooks Davis             PRE_MSG(name == test_case.name(),
11008334c51SBrooks Davis                     F("The test case '%s' has been registered with the "
11108334c51SBrooks Davis                       "non-matching name '%s'") % name % test_case.name());
11208334c51SBrooks Davis 
11308334c51SBrooks Davis             test_cases.insert(model::test_cases_map::value_type(
11408334c51SBrooks Davis                 name, test_case.apply_metadata_defaults(&md)));
11508334c51SBrooks Davis         }
11608334c51SBrooks Davis         INV(test_cases.size() == test_cases_.size());
11708334c51SBrooks Davis     }
11808334c51SBrooks Davis };
11908334c51SBrooks Davis 
12008334c51SBrooks Davis 
12108334c51SBrooks Davis /// Constructs a new test program.
12208334c51SBrooks Davis ///
12308334c51SBrooks Davis /// \param interface_name_ Name of the test program interface.
12408334c51SBrooks Davis /// \param binary_ The name of the test program binary relative to root_.
12508334c51SBrooks Davis /// \param root_ The root of the test suite containing the test program.
12608334c51SBrooks Davis /// \param test_suite_name_ The name of the test suite this program belongs to.
12708334c51SBrooks Davis /// \param md_ Metadata of the test program.
12808334c51SBrooks Davis /// \param test_cases_ The collection of test cases in the test program.
test_program(const std::string & interface_name_,const fs::path & binary_,const fs::path & root_,const std::string & test_suite_name_,const model::metadata & md_,const model::test_cases_map & test_cases_)12908334c51SBrooks Davis model::test_program::test_program(const std::string& interface_name_,
13008334c51SBrooks Davis                                   const fs::path& binary_,
13108334c51SBrooks Davis                                   const fs::path& root_,
13208334c51SBrooks Davis                                   const std::string& test_suite_name_,
13308334c51SBrooks Davis                                   const model::metadata& md_,
13408334c51SBrooks Davis                                   const model::test_cases_map& test_cases_) :
13508334c51SBrooks Davis     _pimpl(new impl(interface_name_, binary_, root_, test_suite_name_, md_,
13608334c51SBrooks Davis                     test_cases_))
13708334c51SBrooks Davis {
13808334c51SBrooks Davis }
13908334c51SBrooks Davis 
14008334c51SBrooks Davis 
14108334c51SBrooks Davis /// Destroys a test program.
~test_program(void)14208334c51SBrooks Davis model::test_program::~test_program(void)
14308334c51SBrooks Davis {
14408334c51SBrooks Davis }
14508334c51SBrooks Davis 
14608334c51SBrooks Davis 
14708334c51SBrooks Davis /// Gets the name of the test program interface.
14808334c51SBrooks Davis ///
14908334c51SBrooks Davis /// \return An interface name.
15008334c51SBrooks Davis const std::string&
interface_name(void) const15108334c51SBrooks Davis model::test_program::interface_name(void) const
15208334c51SBrooks Davis {
15308334c51SBrooks Davis     return _pimpl->interface_name;
15408334c51SBrooks Davis }
15508334c51SBrooks Davis 
15608334c51SBrooks Davis 
15708334c51SBrooks Davis /// Gets the path to the test program relative to the root of the test suite.
15808334c51SBrooks Davis ///
15908334c51SBrooks Davis /// \return The relative path to the test program binary.
16008334c51SBrooks Davis const fs::path&
relative_path(void) const16108334c51SBrooks Davis model::test_program::relative_path(void) const
16208334c51SBrooks Davis {
16308334c51SBrooks Davis     return _pimpl->binary;
16408334c51SBrooks Davis }
16508334c51SBrooks Davis 
16608334c51SBrooks Davis 
16708334c51SBrooks Davis /// Gets the absolute path to the test program.
16808334c51SBrooks Davis ///
16908334c51SBrooks Davis /// \return The absolute path to the test program binary.
17008334c51SBrooks Davis const fs::path
absolute_path(void) const17108334c51SBrooks Davis model::test_program::absolute_path(void) const
17208334c51SBrooks Davis {
17308334c51SBrooks Davis     const fs::path full_path = _pimpl->root / _pimpl->binary;
17408334c51SBrooks Davis     return full_path.is_absolute() ? full_path : full_path.to_absolute();
17508334c51SBrooks Davis }
17608334c51SBrooks Davis 
17708334c51SBrooks Davis 
17808334c51SBrooks Davis /// Gets the root of the test suite containing this test program.
17908334c51SBrooks Davis ///
18008334c51SBrooks Davis /// \return The path to the root of the test suite.
18108334c51SBrooks Davis const fs::path&
root(void) const18208334c51SBrooks Davis model::test_program::root(void) const
18308334c51SBrooks Davis {
18408334c51SBrooks Davis     return _pimpl->root;
18508334c51SBrooks Davis }
18608334c51SBrooks Davis 
18708334c51SBrooks Davis 
18808334c51SBrooks Davis /// Gets the name of the test suite containing this test program.
18908334c51SBrooks Davis ///
19008334c51SBrooks Davis /// \return The name of the test suite.
19108334c51SBrooks Davis const std::string&
test_suite_name(void) const19208334c51SBrooks Davis model::test_program::test_suite_name(void) const
19308334c51SBrooks Davis {
19408334c51SBrooks Davis     return _pimpl->test_suite_name;
19508334c51SBrooks Davis }
19608334c51SBrooks Davis 
19708334c51SBrooks Davis 
19808334c51SBrooks Davis /// Gets the metadata of the test program.
19908334c51SBrooks Davis ///
20008334c51SBrooks Davis /// \return The metadata.
20108334c51SBrooks Davis const model::metadata&
get_metadata(void) const20208334c51SBrooks Davis model::test_program::get_metadata(void) const
20308334c51SBrooks Davis {
20408334c51SBrooks Davis     return _pimpl->md;
20508334c51SBrooks Davis }
20608334c51SBrooks Davis 
20708334c51SBrooks Davis 
20808334c51SBrooks Davis /// Gets a test case by its name.
20908334c51SBrooks Davis ///
21008334c51SBrooks Davis /// \param name The name of the test case to locate.
21108334c51SBrooks Davis ///
21208334c51SBrooks Davis /// \return The requested test case.
21308334c51SBrooks Davis ///
21408334c51SBrooks Davis /// \throw not_found_error If the specified test case is not in the test
21508334c51SBrooks Davis ///     program.
21608334c51SBrooks Davis const model::test_case&
find(const std::string & name) const21708334c51SBrooks Davis model::test_program::find(const std::string& name) const
21808334c51SBrooks Davis {
21908334c51SBrooks Davis     const test_cases_map& tcs = test_cases();
22008334c51SBrooks Davis 
22108334c51SBrooks Davis     const test_cases_map::const_iterator iter = tcs.find(name);
22208334c51SBrooks Davis     if (iter == tcs.end())
22308334c51SBrooks Davis         throw not_found_error(F("Unknown test case %s in test program %s") %
22408334c51SBrooks Davis                               name % relative_path());
22508334c51SBrooks Davis     return (*iter).second;
22608334c51SBrooks Davis }
22708334c51SBrooks Davis 
22808334c51SBrooks Davis 
22908334c51SBrooks Davis /// Gets the list of test cases from the test program.
23008334c51SBrooks Davis ///
23108334c51SBrooks Davis /// \return The list of test cases provided by the test program.
23208334c51SBrooks Davis const model::test_cases_map&
test_cases(void) const23308334c51SBrooks Davis model::test_program::test_cases(void) const
23408334c51SBrooks Davis {
23508334c51SBrooks Davis     return _pimpl->test_cases;
23608334c51SBrooks Davis }
23708334c51SBrooks Davis 
23808334c51SBrooks Davis 
23908334c51SBrooks Davis /// Sets the list of test cases of the test program.
24008334c51SBrooks Davis ///
24108334c51SBrooks Davis /// This can only be called once and it may only be called from within
24208334c51SBrooks Davis /// overridden test_cases() before that method ever returns a value for the
24308334c51SBrooks Davis /// first time.  Any other invocations will result in inconsistent program
24408334c51SBrooks Davis /// state.
24508334c51SBrooks Davis ///
24608334c51SBrooks Davis /// \param test_cases_ The new list of test cases.
24708334c51SBrooks Davis void
set_test_cases(const model::test_cases_map & test_cases_)24808334c51SBrooks Davis model::test_program::set_test_cases(const model::test_cases_map& test_cases_)
24908334c51SBrooks Davis {
25008334c51SBrooks Davis     PRE(_pimpl->test_cases.empty());
25108334c51SBrooks Davis     _pimpl->set_test_cases(test_cases_);
25208334c51SBrooks Davis }
25308334c51SBrooks Davis 
25408334c51SBrooks Davis 
25508334c51SBrooks Davis /// Equality comparator.
25608334c51SBrooks Davis ///
25708334c51SBrooks Davis /// \param other The other object to compare this one to.
25808334c51SBrooks Davis ///
25908334c51SBrooks Davis /// \return True if this object and other are equal; false otherwise.
26008334c51SBrooks Davis bool
operator ==(const test_program & other) const26108334c51SBrooks Davis model::test_program::operator==(const test_program& other) const
26208334c51SBrooks Davis {
26308334c51SBrooks Davis     return _pimpl == other._pimpl || (
26408334c51SBrooks Davis         _pimpl->interface_name == other._pimpl->interface_name &&
26508334c51SBrooks Davis         _pimpl->binary == other._pimpl->binary &&
26608334c51SBrooks Davis         _pimpl->root == other._pimpl->root &&
26708334c51SBrooks Davis         _pimpl->test_suite_name == other._pimpl->test_suite_name &&
26808334c51SBrooks Davis         _pimpl->md == other._pimpl->md &&
26908334c51SBrooks Davis         test_cases() == other.test_cases());
27008334c51SBrooks Davis }
27108334c51SBrooks Davis 
27208334c51SBrooks Davis 
27308334c51SBrooks Davis /// Inequality comparator.
27408334c51SBrooks Davis ///
27508334c51SBrooks Davis /// \param other The other object to compare this one to.
27608334c51SBrooks Davis ///
27708334c51SBrooks Davis /// \return True if this object and other are different; false otherwise.
27808334c51SBrooks Davis bool
operator !=(const test_program & other) const27908334c51SBrooks Davis model::test_program::operator!=(const test_program& other) const
28008334c51SBrooks Davis {
28108334c51SBrooks Davis     return !(*this == other);
28208334c51SBrooks Davis }
28308334c51SBrooks Davis 
28408334c51SBrooks Davis 
28508334c51SBrooks Davis /// Less-than comparator.
28608334c51SBrooks Davis ///
28708334c51SBrooks Davis /// A test program is considered to be less than another if and only if the
28808334c51SBrooks Davis /// former's absolute path is less than the absolute path of the latter.  In
28908334c51SBrooks Davis /// other words, the absolute path is used here as the test program's
29008334c51SBrooks Davis /// identifier.
29108334c51SBrooks Davis ///
29208334c51SBrooks Davis /// This simplistic less-than operator overload is provided so that test
29308334c51SBrooks Davis /// programs can be held in sets and other containers.
29408334c51SBrooks Davis ///
29508334c51SBrooks Davis /// \param other The other object to compare this one to.
29608334c51SBrooks Davis ///
29708334c51SBrooks Davis /// \return True if this object sorts before the other object; false otherwise.
29808334c51SBrooks Davis bool
operator <(const test_program & other) const29908334c51SBrooks Davis model::test_program::operator<(const test_program& other) const
30008334c51SBrooks Davis {
30108334c51SBrooks Davis     return absolute_path() < other.absolute_path();
30208334c51SBrooks Davis }
30308334c51SBrooks Davis 
30408334c51SBrooks Davis 
30508334c51SBrooks Davis /// Injects the object into a stream.
30608334c51SBrooks Davis ///
30708334c51SBrooks Davis /// \param output The stream into which to inject the object.
30808334c51SBrooks Davis /// \param object The object to format.
30908334c51SBrooks Davis ///
31008334c51SBrooks Davis /// \return The output stream.
31108334c51SBrooks Davis std::ostream&
operator <<(std::ostream & output,const test_program & object)31208334c51SBrooks Davis model::operator<<(std::ostream& output, const test_program& object)
31308334c51SBrooks Davis {
31408334c51SBrooks Davis     output << F("test_program{interface=%s, binary=%s, root=%s, test_suite=%s, "
31508334c51SBrooks Davis                 "metadata=%s, test_cases=%s}")
31608334c51SBrooks Davis         % text::quote(object.interface_name(), '\'')
31708334c51SBrooks Davis         % text::quote(object.relative_path().str(), '\'')
31808334c51SBrooks Davis         % text::quote(object.root().str(), '\'')
31908334c51SBrooks Davis         % text::quote(object.test_suite_name(), '\'')
32008334c51SBrooks Davis         % object.get_metadata()
32108334c51SBrooks Davis         % object.test_cases();
32208334c51SBrooks Davis     return output;
32308334c51SBrooks Davis }
32408334c51SBrooks Davis 
32508334c51SBrooks Davis 
32608334c51SBrooks Davis /// Internal implementation of the test_program_builder class.
32708334c51SBrooks Davis struct model::test_program_builder::impl : utils::noncopyable {
32808334c51SBrooks Davis     /// Partially-constructed program with only the required properties.
32908334c51SBrooks Davis     model::test_program prototype;
33008334c51SBrooks Davis 
33108334c51SBrooks Davis     /// Optional metadata for the test program.
33208334c51SBrooks Davis     model::metadata metadata;
33308334c51SBrooks Davis 
33408334c51SBrooks Davis     /// Collection of test cases.
33508334c51SBrooks Davis     model::test_cases_map test_cases;
33608334c51SBrooks Davis 
33708334c51SBrooks Davis     /// Whether we have created a test_program object or not.
33808334c51SBrooks Davis     bool built;
33908334c51SBrooks Davis 
34008334c51SBrooks Davis     /// Constructor.
34108334c51SBrooks Davis     ///
34208334c51SBrooks Davis     /// \param prototype_ The partially constructed program with only the
34308334c51SBrooks Davis     ///     required properties.
implmodel::test_program_builder::impl34408334c51SBrooks Davis     impl(const model::test_program& prototype_) :
34508334c51SBrooks Davis         prototype(prototype_),
34608334c51SBrooks Davis         metadata(model::metadata_builder().build()),
34708334c51SBrooks Davis         built(false)
34808334c51SBrooks Davis     {
34908334c51SBrooks Davis     }
35008334c51SBrooks Davis };
35108334c51SBrooks Davis 
35208334c51SBrooks Davis 
35308334c51SBrooks Davis /// Constructs a new builder with non-optional values.
35408334c51SBrooks Davis ///
35508334c51SBrooks Davis /// \param interface_name_ Name of the test program interface.
35608334c51SBrooks Davis /// \param binary_ The name of the test program binary relative to root_.
35708334c51SBrooks Davis /// \param root_ The root of the test suite containing the test program.
35808334c51SBrooks Davis /// \param test_suite_name_ The name of the test suite this program belongs to.
test_program_builder(const std::string & interface_name_,const fs::path & binary_,const fs::path & root_,const std::string & test_suite_name_)35908334c51SBrooks Davis model::test_program_builder::test_program_builder(
36008334c51SBrooks Davis     const std::string& interface_name_, const fs::path& binary_,
36108334c51SBrooks Davis     const fs::path& root_, const std::string& test_suite_name_) :
36208334c51SBrooks Davis     _pimpl(new impl(model::test_program(interface_name_, binary_, root_,
36308334c51SBrooks Davis                                         test_suite_name_,
36408334c51SBrooks Davis                                         model::metadata_builder().build(),
36508334c51SBrooks Davis                                         model::test_cases_map())))
36608334c51SBrooks Davis {
36708334c51SBrooks Davis }
36808334c51SBrooks Davis 
36908334c51SBrooks Davis 
37008334c51SBrooks Davis /// Destructor.
~test_program_builder(void)37108334c51SBrooks Davis model::test_program_builder::~test_program_builder(void)
37208334c51SBrooks Davis {
37308334c51SBrooks Davis }
37408334c51SBrooks Davis 
37508334c51SBrooks Davis 
37608334c51SBrooks Davis /// Accumulates an additional test case with default metadata.
37708334c51SBrooks Davis ///
37808334c51SBrooks Davis /// \param test_case_name The name of the test case.
37908334c51SBrooks Davis ///
38008334c51SBrooks Davis /// \return A reference to this builder.
38108334c51SBrooks Davis model::test_program_builder&
add_test_case(const std::string & test_case_name)38208334c51SBrooks Davis model::test_program_builder::add_test_case(const std::string& test_case_name)
38308334c51SBrooks Davis {
38408334c51SBrooks Davis     return add_test_case(test_case_name, model::metadata_builder().build());
38508334c51SBrooks Davis }
38608334c51SBrooks Davis 
38708334c51SBrooks Davis 
38808334c51SBrooks Davis /// Accumulates an additional test case.
38908334c51SBrooks Davis ///
39008334c51SBrooks Davis /// \param test_case_name The name of the test case.
39108334c51SBrooks Davis /// \param metadata The test case metadata.
39208334c51SBrooks Davis ///
39308334c51SBrooks Davis /// \return A reference to this builder.
39408334c51SBrooks Davis model::test_program_builder&
add_test_case(const std::string & test_case_name,const model::metadata & metadata)39508334c51SBrooks Davis model::test_program_builder::add_test_case(const std::string& test_case_name,
39608334c51SBrooks Davis                                            const model::metadata& metadata)
39708334c51SBrooks Davis {
39808334c51SBrooks Davis     const model::test_case test_case(test_case_name, metadata);
39908334c51SBrooks Davis     PRE_MSG(_pimpl->test_cases.find(test_case_name) == _pimpl->test_cases.end(),
40008334c51SBrooks Davis             F("Attempted to re-register test case '%s'") % test_case_name);
40108334c51SBrooks Davis     _pimpl->test_cases.insert(model::test_cases_map::value_type(
40208334c51SBrooks Davis         test_case_name, test_case));
40308334c51SBrooks Davis     return *this;
40408334c51SBrooks Davis }
40508334c51SBrooks Davis 
40608334c51SBrooks Davis 
40708334c51SBrooks Davis /// Sets the test program metadata.
40808334c51SBrooks Davis ///
40908334c51SBrooks Davis /// \return metadata The metadata for the test program.
41008334c51SBrooks Davis ///
41108334c51SBrooks Davis /// \return A reference to this builder.
41208334c51SBrooks Davis model::test_program_builder&
set_metadata(const model::metadata & metadata)41308334c51SBrooks Davis model::test_program_builder::set_metadata(const model::metadata& metadata)
41408334c51SBrooks Davis {
41508334c51SBrooks Davis     _pimpl->metadata = metadata;
41608334c51SBrooks Davis     return *this;
41708334c51SBrooks Davis }
41808334c51SBrooks Davis 
41908334c51SBrooks Davis 
42008334c51SBrooks Davis /// Creates a new test_program object.
42108334c51SBrooks Davis ///
42208334c51SBrooks Davis /// \pre This has not yet been called.  We only support calling this function
42308334c51SBrooks Davis /// once.
42408334c51SBrooks Davis ///
42508334c51SBrooks Davis /// \return The constructed test_program object.
42608334c51SBrooks Davis model::test_program
build(void) const42708334c51SBrooks Davis model::test_program_builder::build(void) const
42808334c51SBrooks Davis {
42908334c51SBrooks Davis     PRE(!_pimpl->built);
43008334c51SBrooks Davis     _pimpl->built = true;
43108334c51SBrooks Davis 
43208334c51SBrooks Davis     return test_program(_pimpl->prototype.interface_name(),
43308334c51SBrooks Davis                         _pimpl->prototype.relative_path(),
43408334c51SBrooks Davis                         _pimpl->prototype.root(),
43508334c51SBrooks Davis                         _pimpl->prototype.test_suite_name(),
43608334c51SBrooks Davis                         _pimpl->metadata,
43708334c51SBrooks Davis                         _pimpl->test_cases);
43808334c51SBrooks Davis }
43908334c51SBrooks Davis 
44008334c51SBrooks Davis 
44108334c51SBrooks Davis /// Creates a new dynamically-allocated test_program object.
44208334c51SBrooks Davis ///
44308334c51SBrooks Davis /// \pre This has not yet been called.  We only support calling this function
44408334c51SBrooks Davis /// once.
44508334c51SBrooks Davis ///
44608334c51SBrooks Davis /// \return The constructed test_program object.
44708334c51SBrooks Davis model::test_program_ptr
build_ptr(void) const44808334c51SBrooks Davis model::test_program_builder::build_ptr(void) const
44908334c51SBrooks Davis {
45008334c51SBrooks Davis     const test_program result = build();
45108334c51SBrooks Davis     return test_program_ptr(new test_program(result));
45208334c51SBrooks Davis }
453