1159571Sgallatin// Copyright 2012 The Kyua Authors. 2155852Sgallatin// All rights reserved. 3247160Sgallatin// 4155852Sgallatin// Redistribution and use in source and binary forms, with or without 5155852Sgallatin// modification, are permitted provided that the following conditions are 6155852Sgallatin// met: 7155852Sgallatin// 8155852Sgallatin// * Redistributions of source code must retain the above copyright 9155852Sgallatin// notice, this list of conditions and the following disclaimer. 10155852Sgallatin// * Redistributions in binary form must reproduce the above copyright 11155852Sgallatin// notice, this list of conditions and the following disclaimer in the 12171405Sgallatin// documentation and/or other materials provided with the distribution. 13155852Sgallatin// * Neither the name of Google Inc. nor the names of its contributors 14155852Sgallatin// may be used to endorse or promote products derived from this software 15155852Sgallatin// without specific prior written permission. 16155852Sgallatin// 17155852Sgallatin// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18155852Sgallatin// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19155852Sgallatin// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20155852Sgallatin// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21155852Sgallatin// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22155852Sgallatin// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23155852Sgallatin// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24155852Sgallatin// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25155852Sgallatin// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26155852Sgallatin// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27155852Sgallatin// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28155852Sgallatin 29155852Sgallatin#include "model/metadata.hpp" 30155852Sgallatin 31155852Sgallatin#include <memory> 32155852Sgallatin 33155852Sgallatin#include "model/exceptions.hpp" 34155852Sgallatin#include "model/types.hpp" 35155852Sgallatin#include "utils/config/exceptions.hpp" 36155852Sgallatin#include "utils/config/nodes.ipp" 37155852Sgallatin#include "utils/config/tree.ipp" 38155852Sgallatin#include "utils/datetime.hpp" 39155852Sgallatin#include "utils/defs.hpp" 40155852Sgallatin#include "utils/format/macros.hpp" 41155852Sgallatin#include "utils/fs/exceptions.hpp" 42155852Sgallatin#include "utils/fs/path.hpp" 43168191Sjhb#include "utils/noncopyable.hpp" 44155852Sgallatin#include "utils/optional.ipp" 45155852Sgallatin#include "utils/sanity.hpp" 46155852Sgallatin#include "utils/text/exceptions.hpp" 47155852Sgallatin#include "utils/text/operations.hpp" 48198250Sgallatin#include "utils/units.hpp" 49155852Sgallatin 50155852Sgallatinnamespace config = utils::config; 51155852Sgallatinnamespace datetime = utils::datetime; 52155852Sgallatinnamespace fs = utils::fs; 53155852Sgallatinnamespace text = utils::text; 54155852Sgallatinnamespace units = utils::units; 55155852Sgallatin 56155852Sgallatinusing utils::optional; 57155852Sgallatin 58155852Sgallatin 59155852Sgallatinnamespace { 60155852Sgallatin 61155852Sgallatin 62155852Sgallatin/// Global instance of defaults. 63155852Sgallatin/// 64155852Sgallatin/// This exists so that the getters in metadata can return references instead 65247011Sgallatin/// of object copies. Use get_defaults() to query. 66162322Sgallatinstatic optional< config::tree > defaults; 67247133Sgallatin 68247011Sgallatin 69155852Sgallatin/// A leaf node that holds a bytes quantity. 70155852Sgallatinclass bytes_node : public config::native_leaf_node< units::bytes > { 71169840Sgallatinpublic: 72155852Sgallatin /// Copies the node. 73155852Sgallatin /// 74155852Sgallatin /// \return A dynamically-allocated node. 75175365Sgallatin virtual base_node* 76155852Sgallatin deep_copy(void) const 77155852Sgallatin { 78155852Sgallatin std::auto_ptr< bytes_node > new_node(new bytes_node()); 79180567Sgallatin new_node->_value = _value; 80155852Sgallatin return new_node.release(); 81155852Sgallatin } 82155852Sgallatin 83155852Sgallatin /// Pushes the node's value onto the Lua stack. 84170330Sgallatin void 85170330Sgallatin push_lua(lutok::state& /* state */) const 86170330Sgallatin { 87170330Sgallatin UNREACHABLE; 88159571Sgallatin } 89159571Sgallatin 90175365Sgallatin /// Sets the value of the node from an entry in the Lua stack. 91159571Sgallatin void 92193311Sgallatin set_lua(lutok::state& /* state */, const int /* index */) 93193311Sgallatin { 94193311Sgallatin UNREACHABLE; 95155852Sgallatin } 96194743Sgallatin}; 97247011Sgallatin 98194743Sgallatin 99155852Sgallatin/// A leaf node that holds a time delta. 100159571Sgallatinclass delta_node : public config::typed_leaf_node< datetime::delta > { 101164513Sgallatinpublic: 102159571Sgallatin /// Copies the node. 103159612Sgallatin /// 104159571Sgallatin /// \return A dynamically-allocated node. 105159612Sgallatin virtual base_node* 106166373Sgallatin deep_copy(void) const 107175365Sgallatin { 108202121Sgallatin std::auto_ptr< delta_node > new_node(new delta_node()); 109175365Sgallatin new_node->_value = _value; 110194836Sgallatin return new_node.release(); 111197391Sgallatin } 112159571Sgallatin 113159571Sgallatin /// Sets the value of the node from a raw string representation. 114175365Sgallatin /// 115175365Sgallatin /// \param raw_value The value to set the node to. 116155852Sgallatin /// 117159571Sgallatin /// \throw value_error If the value is invalid. 118159571Sgallatin void 119159571Sgallatin set_string(const std::string& raw_value) 120159571Sgallatin { 121159571Sgallatin unsigned int seconds; 122155852Sgallatin try { 123159571Sgallatin seconds = text::to_type< unsigned int >(raw_value); 124155852Sgallatin } catch (const text::error& e) { 125155852Sgallatin throw config::value_error(F("Invalid time delta %s") % raw_value); 126159571Sgallatin } 127159571Sgallatin set(datetime::delta(seconds, 0)); 128159571Sgallatin } 129159571Sgallatin 130246128Ssbz /// Converts the contents of the node to a string. 131246128Ssbz /// 132155852Sgallatin /// \pre The node must have a value. 133155852Sgallatin /// 134159571Sgallatin /// \return A string representation of the value held by the node. 135155852Sgallatin std::string 136159571Sgallatin to_string(void) const 137159571Sgallatin { 138159571Sgallatin return F("%s") % value().seconds; 139155852Sgallatin } 140155852Sgallatin 141159571Sgallatin /// Pushes the node's value onto the Lua stack. 142155852Sgallatin void 143155852Sgallatin push_lua(lutok::state& /* state */) const 144159571Sgallatin { 145159571Sgallatin UNREACHABLE; 146171500Sgallatin } 147155852Sgallatin 148175365Sgallatin /// Sets the value of the node from an entry in the Lua stack. 149169376Sgallatin void 150197395Sgallatin set_lua(lutok::state& /* state */, const int /* index */) 151170559Sgallatin { 152170559Sgallatin UNREACHABLE; 153169376Sgallatin } 154155852Sgallatin}; 155159571Sgallatin 156155852Sgallatin 157188736Sgallatin/// A leaf node that holds a "required user" property. 158188736Sgallatin/// 159188736Sgallatin/// This node is just a string, but it provides validation of the only allowed 160188736Sgallatin/// values. 161188736Sgallatinclass user_node : public config::string_node { 162188736Sgallatin /// Copies the node. 163188736Sgallatin /// 164188736Sgallatin /// \return A dynamically-allocated node. 165188736Sgallatin virtual base_node* 166188736Sgallatin deep_copy(void) const 167188736Sgallatin { 168188736Sgallatin std::auto_ptr< user_node > new_node(new user_node()); 169188736Sgallatin new_node->_value = _value; 170188736Sgallatin return new_node.release(); 171188736Sgallatin } 172188736Sgallatin 173188736Sgallatin /// Checks a given user textual representation for validity. 174188736Sgallatin /// 175188736Sgallatin /// \param user The value to validate. 176188736Sgallatin /// 177188736Sgallatin /// \throw config::value_error If the value is not valid. 178188736Sgallatin void 179188736Sgallatin validate(const value_type& user) const 180155852Sgallatin { 181155852Sgallatin if (!user.empty() && user != "root" && user != "unprivileged") 182155852Sgallatin throw config::value_error("Invalid required user value"); 183159571Sgallatin } 184155852Sgallatin}; 185171500Sgallatin 186155852Sgallatin 187177104Sgallatin/// A leaf node that holds a set of paths. 188155852Sgallatin/// 189170853Sgallatin/// This node type is used to represent the value of the required files and 190170330Sgallatin/// required programs, for example, and these do not allow relative paths. We 191170330Sgallatin/// check this here. 192170330Sgallatinclass paths_set_node : public config::base_set_node< fs::path > { 193177104Sgallatin /// Copies the node. 194170330Sgallatin /// 195170330Sgallatin /// \return A dynamically-allocated node. 196170853Sgallatin virtual base_node* 197155852Sgallatin deep_copy(void) const 198171500Sgallatin { 199155852Sgallatin std::auto_ptr< paths_set_node > new_node(new paths_set_node()); 200155852Sgallatin new_node->_value = _value; 201155852Sgallatin return new_node.release(); 202155852Sgallatin } 203155852Sgallatin 204159571Sgallatin /// Converts a single path to the native type. 205155852Sgallatin /// 206155852Sgallatin /// \param raw_value The value to parse. 207155852Sgallatin /// 208155852Sgallatin /// \return The parsed value. 209155852Sgallatin /// 210155852Sgallatin /// \throw config::value_error If the value is invalid. 211155852Sgallatin fs::path 212155852Sgallatin parse_one(const std::string& raw_value) const 213159571Sgallatin { 214155852Sgallatin try { 215155852Sgallatin return fs::path(raw_value); 216155852Sgallatin } catch (const fs::error& e) { 217155852Sgallatin throw config::value_error(e.what()); 218175365Sgallatin } 219155852Sgallatin } 220175365Sgallatin 221175365Sgallatin /// Checks a collection of paths for validity. 222175365Sgallatin /// 223175365Sgallatin /// \param paths The value to validate. 224175365Sgallatin /// 225175365Sgallatin /// \throw config::value_error If the value is not valid. 226175365Sgallatin void 227175365Sgallatin validate(const value_type& paths) const 228155852Sgallatin { 229155852Sgallatin for (value_type::const_iterator iter = paths.begin(); 230155852Sgallatin iter != paths.end(); ++iter) { 231175365Sgallatin const fs::path& path = *iter; 232155852Sgallatin if (!path.is_absolute() && path.ncomponents() > 1) 233155852Sgallatin throw config::value_error(F("Relative path '%s' not allowed") % 234155852Sgallatin *iter); 235155852Sgallatin } 236155852Sgallatin } 237175365Sgallatin}; 238155852Sgallatin 239155852Sgallatin 240155852Sgallatin/// Initializes a tree to hold test case requirements. 241155852Sgallatin/// 242155852Sgallatin/// \param [in,out] tree The tree to initialize. 243155852Sgallatinstatic void 244155852Sgallatininit_tree(config::tree& tree) 245155852Sgallatin{ 246155852Sgallatin tree.define< config::strings_set_node >("allowed_architectures"); 247155852Sgallatin tree.define< config::strings_set_node >("allowed_platforms"); 248155852Sgallatin tree.define_dynamic("custom"); 249155852Sgallatin tree.define< config::string_node >("description"); 250155852Sgallatin tree.define< config::bool_node >("has_cleanup"); 251155852Sgallatin tree.define< config::bool_node >("is_exclusive"); 252155852Sgallatin tree.define< config::strings_set_node >("required_configs"); 253155852Sgallatin tree.define< bytes_node >("required_disk_space"); 254155852Sgallatin tree.define< paths_set_node >("required_files"); 255155852Sgallatin tree.define< bytes_node >("required_memory"); 256155852Sgallatin tree.define< paths_set_node >("required_programs"); 257159571Sgallatin tree.define< user_node >("required_user"); 258155852Sgallatin tree.define< delta_node >("timeout"); 259155852Sgallatin} 260155852Sgallatin 261155852Sgallatin 262155852Sgallatin/// Sets default values on a tree object. 263155852Sgallatin/// 264155852Sgallatin/// \param [in,out] tree The tree to configure. 265155852Sgallatinstatic void 266155852Sgallatinset_defaults(config::tree& tree) 267155852Sgallatin{ 268155852Sgallatin tree.set< config::strings_set_node >("allowed_architectures", 269155852Sgallatin model::strings_set()); 270155852Sgallatin tree.set< config::strings_set_node >("allowed_platforms", 271155852Sgallatin model::strings_set()); 272155852Sgallatin tree.set< config::string_node >("description", ""); 273155852Sgallatin tree.set< config::bool_node >("has_cleanup", false); 274159571Sgallatin tree.set< config::bool_node >("is_exclusive", false); 275155852Sgallatin tree.set< config::strings_set_node >("required_configs", 276155852Sgallatin model::strings_set()); 277155852Sgallatin tree.set< bytes_node >("required_disk_space", units::bytes(0)); 278155852Sgallatin tree.set< paths_set_node >("required_files", model::paths_set()); 279155852Sgallatin tree.set< bytes_node >("required_memory", units::bytes(0)); 280155852Sgallatin tree.set< paths_set_node >("required_programs", model::paths_set()); 281155852Sgallatin tree.set< user_node >("required_user", ""); 282155852Sgallatin // TODO(jmmv): We shouldn't be setting a default timeout like this. See 283155852Sgallatin // Issue 5 for details. 284155852Sgallatin tree.set< delta_node >("timeout", datetime::delta(300, 0)); 285155852Sgallatin} 286155852Sgallatin 287155852Sgallatin 288155852Sgallatin/// Queries the global defaults tree object with lazy initialization. 289159571Sgallatin/// 290155852Sgallatin/// \return A metadata tree. This object is statically allocated so it is 291247268Sgallatin/// acceptable to obtain references to it and its members. 292247159Sgallatinconst config::tree& 293247268Sgallatinget_defaults(void) 294155852Sgallatin{ 295155852Sgallatin if (!defaults) { 296155852Sgallatin config::tree props; 297247159Sgallatin init_tree(props); 298247268Sgallatin set_defaults(props); 299247268Sgallatin defaults = props; 300247268Sgallatin } 301247268Sgallatin return defaults.get(); 302247268Sgallatin} 303247268Sgallatin 304155852Sgallatin 305247268Sgallatin/// Looks up a value in a tree with error rewriting. 306247268Sgallatin/// 307247268Sgallatin/// \tparam NodeType The type of the node. 308247268Sgallatin/// \param tree The tree in which to insert the value. 309247268Sgallatin/// \param key The key to set. 310155852Sgallatin/// 311247268Sgallatin/// \return A read-write reference to the value in the node. 312247268Sgallatin/// 313159612Sgallatin/// \throw model::error If the key is not known or if the value is not valid. 314247268Sgallatintemplate< class NodeType > 315247268Sgallatintypename NodeType::value_type& 316247268Sgallatinlookup_rw(config::tree& tree, const std::string& key) 317159612Sgallatin{ 318247268Sgallatin try { 319247268Sgallatin return tree.lookup_rw< NodeType >(key); 320247268Sgallatin } catch (const config::unknown_key_error& e) { 321247159Sgallatin throw model::error(F("Unknown metadata property %s") % key); 322247159Sgallatin } catch (const config::value_error& e) { 323247159Sgallatin throw model::error(F("Invalid value for metadata property %s: %s") % 324247268Sgallatin key % e.what()); 325247268Sgallatin } 326155852Sgallatin} 327247268Sgallatin 328155852Sgallatin 329155852Sgallatin/// Sets a value in a tree with error rewriting. 330155852Sgallatin/// 331155852Sgallatin/// \tparam NodeType The type of the node. 332155852Sgallatin/// \param tree The tree in which to insert the value. 333155852Sgallatin/// \param key The key to set. 334155852Sgallatin/// \param value The value to set the node to. 335155852Sgallatin/// 336155852Sgallatin/// \throw model::error If the key is not known or if the value is not valid. 337155852Sgallatintemplate< class NodeType > 338155852Sgallatinvoid 339188531Srdivackyset(config::tree& tree, const std::string& key, 340169376Sgallatin const typename NodeType::value_type& value) 341169376Sgallatin{ 342155852Sgallatin try { 343155852Sgallatin tree.set< NodeType >(key, value); 344169376Sgallatin } catch (const config::unknown_key_error& e) { 345155852Sgallatin throw model::error(F("Unknown metadata property %s") % key); 346169376Sgallatin } catch (const config::value_error& e) { 347169376Sgallatin throw model::error(F("Invalid value for metadata property %s: %s") % 348155852Sgallatin key % e.what()); 349155852Sgallatin } 350155852Sgallatin} 351169376Sgallatin 352169376Sgallatin 353169376Sgallatin} // anonymous namespace 354169376Sgallatin 355169376Sgallatin 356169376Sgallatin/// Internal implementation of the metadata class. 357169376Sgallatinstruct model::metadata::impl : utils::noncopyable { 358169376Sgallatin /// Metadata properties. 359169376Sgallatin config::tree props; 360169376Sgallatin 361169376Sgallatin /// Constructor. 362169376Sgallatin /// 363169376Sgallatin /// \param props_ Metadata properties of the test. 364169376Sgallatin impl(const utils::config::tree& props_) : 365169376Sgallatin props(props_) 366169376Sgallatin { 367169376Sgallatin } 368169376Sgallatin 369169376Sgallatin /// Equality comparator. 370169376Sgallatin /// 371169376Sgallatin /// \param other The other object to compare this one to. 372169376Sgallatin /// 373169376Sgallatin /// \return True if this object and other are equal; false otherwise. 374169376Sgallatin bool 375169376Sgallatin operator==(const impl& other) const 376169376Sgallatin { 377169376Sgallatin return (get_defaults().combine(props) == 378169376Sgallatin get_defaults().combine(other.props)); 379169376Sgallatin } 380169376Sgallatin}; 381169376Sgallatin 382169376Sgallatin 383169376Sgallatin/// Constructor. 384155852Sgallatin/// 385155852Sgallatin/// \param props Metadata properties of the test. 386155852Sgallatinmodel::metadata::metadata(const utils::config::tree& props) : 387155852Sgallatin _pimpl(new impl(props)) 388155852Sgallatin{ 389155852Sgallatin} 390155852Sgallatin 391155852Sgallatin 392155852Sgallatin/// Destructor. 393155852Sgallatinmodel::metadata::~metadata(void) 394155852Sgallatin{ 395155852Sgallatin} 396155852Sgallatin 397155852Sgallatin 398169376Sgallatin/// Applies a set of overrides to this metadata object. 399155852Sgallatin/// 400155852Sgallatin/// \param overrides The overrides to apply. Any values explicitly set in this 401155852Sgallatin/// other object will override any possible values set in this object. 402155852Sgallatin/// 403155852Sgallatin/// \return A new metadata object with the combination. 404155852Sgallatinmodel::metadata 405155852Sgallatinmodel::metadata::apply_overrides(const metadata& overrides) const 406155852Sgallatin{ 407155852Sgallatin return metadata(_pimpl->props.combine(overrides._pimpl->props)); 408155852Sgallatin} 409155852Sgallatin 410155852Sgallatin 411155852Sgallatin/// Returns the architectures allowed by the test. 412155852Sgallatin/// 413155852Sgallatin/// \return Set of architectures, or empty if this does not apply. 414155852Sgallatinconst model::strings_set& 415155852Sgallatinmodel::metadata::allowed_architectures(void) const 416155852Sgallatin{ 417155852Sgallatin if (_pimpl->props.is_set("allowed_architectures")) { 418155852Sgallatin return _pimpl->props.lookup< config::strings_set_node >( 419155852Sgallatin "allowed_architectures"); 420169376Sgallatin } else { 421155852Sgallatin return get_defaults().lookup< config::strings_set_node >( 422155852Sgallatin "allowed_architectures"); 423155852Sgallatin } 424155852Sgallatin} 425155852Sgallatin 426155852Sgallatin 427155852Sgallatin/// Returns the platforms allowed by the test. 428155852Sgallatin/// 429155852Sgallatin/// \return Set of platforms, or empty if this does not apply. 430155852Sgallatinconst model::strings_set& 431169376Sgallatinmodel::metadata::allowed_platforms(void) const 432155852Sgallatin{ 433155852Sgallatin if (_pimpl->props.is_set("allowed_platforms")) { 434155852Sgallatin return _pimpl->props.lookup< config::strings_set_node >( 435155852Sgallatin "allowed_platforms"); 436155852Sgallatin } else { 437155852Sgallatin return get_defaults().lookup< config::strings_set_node >( 438155852Sgallatin "allowed_platforms"); 439155852Sgallatin } 440155852Sgallatin} 441155852Sgallatin 442155852Sgallatin 443169376Sgallatin/// Returns all the user-defined metadata properties. 444155852Sgallatin/// 445155852Sgallatin/// \return A key/value map of properties. 446155852Sgallatinmodel::properties_map 447155852Sgallatinmodel::metadata::custom(void) const 448155852Sgallatin{ 449155852Sgallatin return _pimpl->props.all_properties("custom", true); 450155852Sgallatin} 451155852Sgallatin 452169376Sgallatin 453155852Sgallatin/// Returns the description of the test. 454155852Sgallatin/// 455155852Sgallatin/// \return Textual description; may be empty. 456159612Sgallatinconst std::string& 457159612Sgallatinmodel::metadata::description(void) const 458159612Sgallatin{ 459159612Sgallatin if (_pimpl->props.is_set("description")) { 460159612Sgallatin return _pimpl->props.lookup< config::string_node >("description"); 461169376Sgallatin } else { 462155852Sgallatin return get_defaults().lookup< config::string_node >("description"); 463155852Sgallatin } 464169376Sgallatin} 465171500Sgallatin 466155852Sgallatin 467155852Sgallatin/// Returns whether the test has a cleanup part or not. 468155852Sgallatin/// 469169376Sgallatin/// \return True if there is a cleanup part; false otherwise. 470155852Sgallatinbool 471155852Sgallatinmodel::metadata::has_cleanup(void) const 472169376Sgallatin{ 473169376Sgallatin if (_pimpl->props.is_set("has_cleanup")) { 474169376Sgallatin return _pimpl->props.lookup< config::bool_node >("has_cleanup"); 475169376Sgallatin } else { 476169376Sgallatin return get_defaults().lookup< config::bool_node >("has_cleanup"); 477169376Sgallatin } 478169376Sgallatin} 479169376Sgallatin 480169376Sgallatin 481169376Sgallatin/// Returns whether the test is exclusive or not. 482169376Sgallatin/// 483169376Sgallatin/// \return True if the test has to be run on its own, not concurrently with any 484169376Sgallatin/// other tests; false otherwise. 485169376Sgallatinbool 486169376Sgallatinmodel::metadata::is_exclusive(void) const 487169376Sgallatin{ 488169376Sgallatin if (_pimpl->props.is_set("is_exclusive")) { 489169376Sgallatin return _pimpl->props.lookup< config::bool_node >("is_exclusive"); 490169376Sgallatin } else { 491169376Sgallatin return get_defaults().lookup< config::bool_node >("is_exclusive"); 492169376Sgallatin } 493175365Sgallatin} 494169376Sgallatin 495169376Sgallatin 496169376Sgallatin/// Returns the list of configuration variables needed by the test. 497169376Sgallatin/// 498169376Sgallatin/// \return Set of configuration variables. 499169376Sgallatinconst model::strings_set& 500169376Sgallatinmodel::metadata::required_configs(void) const 501169376Sgallatin{ 502169376Sgallatin if (_pimpl->props.is_set("required_configs")) { 503169376Sgallatin return _pimpl->props.lookup< config::strings_set_node >( 504169376Sgallatin "required_configs"); 505169376Sgallatin } else { 506169376Sgallatin return get_defaults().lookup< config::strings_set_node >( 507169376Sgallatin "required_configs"); 508169376Sgallatin } 509169376Sgallatin} 510169376Sgallatin 511169376Sgallatin 512169376Sgallatin/// Returns the amount of free disk space required by the test. 513169376Sgallatin/// 514169376Sgallatin/// \return Number of bytes, or 0 if this does not apply. 515169376Sgallatinconst units::bytes& 516169376Sgallatinmodel::metadata::required_disk_space(void) const 517169376Sgallatin{ 518169376Sgallatin if (_pimpl->props.is_set("required_disk_space")) { 519169376Sgallatin return _pimpl->props.lookup< bytes_node >("required_disk_space"); 520169376Sgallatin } else { 521169376Sgallatin return get_defaults().lookup< bytes_node >("required_disk_space"); 522169376Sgallatin } 523169376Sgallatin} 524169376Sgallatin 525169376Sgallatin 526169376Sgallatin/// Returns the list of files needed by the test. 527169376Sgallatin/// 528169376Sgallatin/// \return Set of paths. 529169376Sgallatinconst model::paths_set& 530169376Sgallatinmodel::metadata::required_files(void) const 531169376Sgallatin{ 532169376Sgallatin if (_pimpl->props.is_set("required_files")) { 533169376Sgallatin return _pimpl->props.lookup< paths_set_node >("required_files"); 534169376Sgallatin } else { 535155852Sgallatin return get_defaults().lookup< paths_set_node >("required_files"); 536155852Sgallatin } 537155852Sgallatin} 538155852Sgallatin 539155852Sgallatin 540155852Sgallatin/// Returns the amount of memory required by the test. 541155852Sgallatin/// 542155852Sgallatin/// \return Number of bytes, or 0 if this does not apply. 543155852Sgallatinconst units::bytes& 544155852Sgallatinmodel::metadata::required_memory(void) const 545155852Sgallatin{ 546155852Sgallatin if (_pimpl->props.is_set("required_memory")) { 547155852Sgallatin return _pimpl->props.lookup< bytes_node >("required_memory"); 548155852Sgallatin } else { 549175365Sgallatin return get_defaults().lookup< bytes_node >("required_memory"); 550155852Sgallatin } 551175365Sgallatin} 552155852Sgallatin 553155852Sgallatin 554169376Sgallatin/// Returns the list of programs needed by the test. 555169376Sgallatin/// 556169376Sgallatin/// \return Set of paths. 557169376Sgallatinconst model::paths_set& 558169376Sgallatinmodel::metadata::required_programs(void) const 559169376Sgallatin{ 560169376Sgallatin if (_pimpl->props.is_set("required_programs")) { 561175365Sgallatin return _pimpl->props.lookup< paths_set_node >("required_programs"); 562169376Sgallatin } else { 563169376Sgallatin return get_defaults().lookup< paths_set_node >("required_programs"); 564169376Sgallatin } 565169376Sgallatin} 566219902Sjhb 567169376Sgallatin 568169376Sgallatin/// Returns the user required by the test. 569169376Sgallatin/// 570169376Sgallatin/// \return One of unprivileged, root or empty. 571175365Sgallatinconst std::string& 572169376Sgallatinmodel::metadata::required_user(void) const 573169376Sgallatin{ 574169376Sgallatin if (_pimpl->props.is_set("required_user")) { 575169376Sgallatin return _pimpl->props.lookup< user_node >("required_user"); 576169376Sgallatin } else { 577169376Sgallatin return get_defaults().lookup< user_node >("required_user"); 578169376Sgallatin } 579169376Sgallatin} 580175365Sgallatin 581169376Sgallatin 582169376Sgallatin/// Returns the timeout of the test. 583169376Sgallatin/// 584169376Sgallatin/// \return A time delta; should be compared to default_timeout to see if it has 585169376Sgallatin/// been overriden. 586169376Sgallatinconst datetime::delta& 587169376Sgallatinmodel::metadata::timeout(void) const 588169376Sgallatin{ 589169376Sgallatin if (_pimpl->props.is_set("timeout")) { 590169376Sgallatin return _pimpl->props.lookup< delta_node >("timeout"); 591169376Sgallatin } else { 592247159Sgallatin return get_defaults().lookup< delta_node >("timeout"); 593169376Sgallatin } 594247159Sgallatin} 595247159Sgallatin 596169376Sgallatin 597169376Sgallatin/// Externalizes the metadata to a set of key/value textual pairs. 598169376Sgallatin/// 599169376Sgallatin/// \return A key/value representation of the metadata. 600169376Sgallatinmodel::properties_map 601169376Sgallatinmodel::metadata::to_properties(void) const 602169376Sgallatin{ 603169376Sgallatin const config::tree fully_specified = get_defaults().combine(_pimpl->props); 604169376Sgallatin return fully_specified.all_properties(); 605169376Sgallatin} 606169376Sgallatin 607169376Sgallatin 608169376Sgallatin/// Equality comparator. 609159571Sgallatin/// 610155852Sgallatin/// \param other The other object to compare this one to. 611169376Sgallatin/// 612197391Sgallatin/// \return True if this object and other are equal; false otherwise. 613155852Sgallatinbool 614197391Sgallatinmodel::metadata::operator==(const metadata& other) const 615197391Sgallatin{ 616164513Sgallatin return _pimpl == other._pimpl || *_pimpl == *other._pimpl; 617197391Sgallatin} 618197391Sgallatin 619164513Sgallatin 620164513Sgallatin/// Inequality comparator. 621164513Sgallatin/// 622164513Sgallatin/// \param other The other object to compare this one to. 623164513Sgallatin/// 624164513Sgallatin/// \return True if this object and other are different; false otherwise. 625164513Sgallatinbool 626164513Sgallatinmodel::metadata::operator!=(const metadata& other) const 627164513Sgallatin{ 628164513Sgallatin return !(*this == other); 629164513Sgallatin} 630164513Sgallatin 631164513Sgallatin 632164513Sgallatin/// Injects the object into a stream. 633164513Sgallatin/// 634164513Sgallatin/// \param output The stream into which to inject the object. 635164513Sgallatin/// \param object The object to format. 636164513Sgallatin/// 637164513Sgallatin/// \return The output stream. 638164513Sgallatinstd::ostream& 639169376Sgallatinmodel::operator<<(std::ostream& output, const metadata& object) 640169376Sgallatin{ 641155852Sgallatin output << "metadata{"; 642155852Sgallatin 643155852Sgallatin bool first = true; 644159571Sgallatin const model::properties_map props = object.to_properties(); 645175365Sgallatin for (model::properties_map::const_iterator iter = props.begin(); 646155852Sgallatin iter != props.end(); ++iter) { 647159571Sgallatin if (!first) 648175365Sgallatin output << ", "; 649155852Sgallatin output << F("%s=%s") % (*iter).first % 650175365Sgallatin text::quote((*iter).second, '\''); 651155852Sgallatin first = false; 652155852Sgallatin } 653160456Sgallatin 654160456Sgallatin output << "}"; 655160456Sgallatin return output; 656155852Sgallatin} 657166875Sgallatin 658160456Sgallatin 659160456Sgallatin/// Internal implementation of the metadata_builder class. 660160456Sgallatinstruct model::metadata_builder::impl : utils::noncopyable { 661160456Sgallatin /// Collection of requirements. 662160456Sgallatin config::tree props; 663160456Sgallatin 664160456Sgallatin /// Whether we have created a metadata object or not. 665247268Sgallatin bool built; 666160456Sgallatin 667160456Sgallatin /// Constructor. 668160456Sgallatin impl(void) : 669166875Sgallatin built(false) 670166875Sgallatin { 671160456Sgallatin init_tree(props); 672166875Sgallatin } 673166875Sgallatin 674160456Sgallatin /// Constructor. 675160456Sgallatin /// 676160456Sgallatin /// \param base The base model to construct a copy from. 677160456Sgallatin impl(const model::metadata& base) : 678160456Sgallatin props(base._pimpl->props.deep_copy()), 679160456Sgallatin built(false) 680160456Sgallatin { 681160456Sgallatin } 682160456Sgallatin}; 683160456Sgallatin 684171500Sgallatin 685171500Sgallatin/// Constructor. 686171500Sgallatinmodel::metadata_builder::metadata_builder(void) : 687171500Sgallatin _pimpl(new impl()) 688171500Sgallatin{ 689171500Sgallatin} 690171500Sgallatin 691171500Sgallatin 692171500Sgallatin/// Constructor. 693171500Sgallatinmodel::metadata_builder::metadata_builder(const model::metadata& base) : 694171500Sgallatin _pimpl(new impl(base)) 695171500Sgallatin{ 696171500Sgallatin} 697171500Sgallatin 698171500Sgallatin 699171500Sgallatin/// Destructor. 700155852Sgallatinmodel::metadata_builder::~metadata_builder(void) 701159571Sgallatin{ 702155852Sgallatin} 703171500Sgallatin 704171500Sgallatin 705166756Sluigi/// Accumulates an additional allowed architecture. 706155852Sgallatin/// 707155852Sgallatin/// \param arch The architecture. 708155852Sgallatin/// 709160456Sgallatin/// \return A reference to this builder. 710160456Sgallatin/// 711171500Sgallatin/// \throw model::error If the value is invalid. 712155852Sgallatinmodel::metadata_builder& 713155852Sgallatinmodel::metadata_builder::add_allowed_architecture(const std::string& arch) 714155852Sgallatin{ 715155852Sgallatin if (!_pimpl->props.is_set("allowed_architectures")) { 716155852Sgallatin _pimpl->props.set< config::strings_set_node >( 717155852Sgallatin "allowed_architectures", 718155852Sgallatin get_defaults().lookup< config::strings_set_node >( 719171500Sgallatin "allowed_architectures")); 720171500Sgallatin } 721171500Sgallatin lookup_rw< config::strings_set_node >( 722171500Sgallatin _pimpl->props, "allowed_architectures").insert(arch); 723171500Sgallatin return *this; 724171500Sgallatin} 725171500Sgallatin 726171500Sgallatin 727171500Sgallatin/// Accumulates an additional allowed platform. 728171500Sgallatin/// 729155852Sgallatin/// \param platform The platform. 730155852Sgallatin/// 731155852Sgallatin/// \return A reference to this builder. 732171500Sgallatin/// 733171500Sgallatin/// \throw model::error If the value is invalid. 734171500Sgallatinmodel::metadata_builder& 735171500Sgallatinmodel::metadata_builder::add_allowed_platform(const std::string& platform) 736171500Sgallatin{ 737171500Sgallatin if (!_pimpl->props.is_set("allowed_platforms")) { 738171500Sgallatin _pimpl->props.set< config::strings_set_node >( 739171500Sgallatin "allowed_platforms", 740171500Sgallatin get_defaults().lookup< config::strings_set_node >( 741171500Sgallatin "allowed_platforms")); 742171500Sgallatin } 743171500Sgallatin lookup_rw< config::strings_set_node >( 744171500Sgallatin _pimpl->props, "allowed_platforms").insert(platform); 745171500Sgallatin return *this; 746171500Sgallatin} 747171500Sgallatin 748171500Sgallatin 749155852Sgallatin/// Accumulates a single user-defined property. 750155852Sgallatin/// 751171500Sgallatin/// \param key Name of the property to define. 752171500Sgallatin/// \param value Value of the property. 753155852Sgallatin/// 754155852Sgallatin/// \return A reference to this builder. 755171500Sgallatin/// 756155852Sgallatin/// \throw model::error If the value is invalid. 757171500Sgallatinmodel::metadata_builder& 758160456Sgallatinmodel::metadata_builder::add_custom(const std::string& key, 759160456Sgallatin const std::string& value) 760160456Sgallatin{ 761171500Sgallatin _pimpl->props.set_string(F("custom.%s") % key, value); 762155852Sgallatin return *this; 763155852Sgallatin} 764171500Sgallatin 765160456Sgallatin 766171500Sgallatin/// Accumulates an additional required configuration variable. 767171500Sgallatin/// 768185255Sgallatin/// \param var The name of the configuration variable. 769160456Sgallatin/// 770185255Sgallatin/// \return A reference to this builder. 771160456Sgallatin/// 772155852Sgallatin/// \throw model::error If the value is invalid. 773171500Sgallatinmodel::metadata_builder& 774155852Sgallatinmodel::metadata_builder::add_required_config(const std::string& var) 775171500Sgallatin{ 776171500Sgallatin if (!_pimpl->props.is_set("required_configs")) { 777171500Sgallatin _pimpl->props.set< config::strings_set_node >( 778171500Sgallatin "required_configs", 779155852Sgallatin get_defaults().lookup< config::strings_set_node >( 780155852Sgallatin "required_configs")); 781155852Sgallatin } 782155852Sgallatin lookup_rw< config::strings_set_node >( 783155852Sgallatin _pimpl->props, "required_configs").insert(var); 784155852Sgallatin return *this; 785155852Sgallatin} 786155852Sgallatin 787155852Sgallatin 788155852Sgallatin/// Accumulates an additional required file. 789155852Sgallatin/// 790159571Sgallatin/// \param path The path to the file. 791155852Sgallatin/// 792155852Sgallatin/// \return A reference to this builder. 793155852Sgallatin/// 794155852Sgallatin/// \throw model::error If the value is invalid. 795155852Sgallatinmodel::metadata_builder& 796155852Sgallatinmodel::metadata_builder::add_required_file(const fs::path& path) 797155852Sgallatin{ 798155852Sgallatin if (!_pimpl->props.is_set("required_files")) { 799155852Sgallatin _pimpl->props.set< paths_set_node >( 800155852Sgallatin "required_files", 801155852Sgallatin get_defaults().lookup< paths_set_node >("required_files")); 802155852Sgallatin } 803185255Sgallatin lookup_rw< paths_set_node >(_pimpl->props, "required_files").insert(path); 804155852Sgallatin return *this; 805155852Sgallatin} 806155852Sgallatin 807155852Sgallatin 808155852Sgallatin/// Accumulates an additional required program. 809155852Sgallatin/// 810159571Sgallatin/// \param path The path to the program. 811159571Sgallatin/// 812155852Sgallatin/// \return A reference to this builder. 813155852Sgallatin/// 814155852Sgallatin/// \throw model::error If the value is invalid. 815159571Sgallatinmodel::metadata_builder& 816159571Sgallatinmodel::metadata_builder::add_required_program(const fs::path& path) 817155852Sgallatin{ 818155852Sgallatin if (!_pimpl->props.is_set("required_programs")) { 819155852Sgallatin _pimpl->props.set< paths_set_node >( 820155852Sgallatin "required_programs", 821155852Sgallatin get_defaults().lookup< paths_set_node >("required_programs")); 822162328Sgallatin } 823155852Sgallatin lookup_rw< paths_set_node >(_pimpl->props, 824159571Sgallatin "required_programs").insert(path); 825185255Sgallatin return *this; 826155852Sgallatin} 827185255Sgallatin 828155852Sgallatin 829155852Sgallatin/// Sets the architectures allowed by the test. 830155852Sgallatin/// 831155852Sgallatin/// \param as Set of architectures. 832155852Sgallatin/// 833155852Sgallatin/// \return A reference to this builder. 834155852Sgallatin/// 835155852Sgallatin/// \throw model::error If the value is invalid. 836155852Sgallatinmodel::metadata_builder& 837155852Sgallatinmodel::metadata_builder::set_allowed_architectures( 838155852Sgallatin const model::strings_set& as) 839155852Sgallatin{ 840155852Sgallatin set< config::strings_set_node >(_pimpl->props, "allowed_architectures", as); 841155852Sgallatin return *this; 842159571Sgallatin} 843155852Sgallatin 844155852Sgallatin 845155852Sgallatin/// Sets the platforms allowed by the test. 846155852Sgallatin/// 847162328Sgallatin/// \return ps Set of platforms. 848155852Sgallatin/// 849169384Sgallatin/// \return A reference to this builder. 850155852Sgallatin/// 851155852Sgallatin/// \throw model::error If the value is invalid. 852155852Sgallatinmodel::metadata_builder& 853155852Sgallatinmodel::metadata_builder::set_allowed_platforms(const model::strings_set& ps) 854155852Sgallatin{ 855155852Sgallatin set< config::strings_set_node >(_pimpl->props, "allowed_platforms", ps); 856155852Sgallatin return *this; 857155852Sgallatin} 858159571Sgallatin 859159571Sgallatin 860155852Sgallatin/// Sets the user-defined properties. 861155852Sgallatin/// 862155852Sgallatin/// \param props The custom properties to set. 863166370Sgallatin/// 864155852Sgallatin/// \return A reference to this builder. 865185255Sgallatin/// 866159571Sgallatin/// \throw model::error If the value is invalid. 867155852Sgallatinmodel::metadata_builder& 868159612Sgallatinmodel::metadata_builder::set_custom(const model::properties_map& props) 869169384Sgallatin{ 870159612Sgallatin for (model::properties_map::const_iterator iter = props.begin(); 871155852Sgallatin iter != props.end(); ++iter) 872155852Sgallatin _pimpl->props.set_string(F("custom.%s") % (*iter).first, 873185255Sgallatin (*iter).second); 874169384Sgallatin return *this; 875169384Sgallatin} 876169384Sgallatin 877169384Sgallatin 878169384Sgallatin/// Sets the description of the test. 879169384Sgallatin/// 880169384Sgallatin/// \param description Textual description of the test. 881169384Sgallatin/// 882169384Sgallatin/// \return A reference to this builder. 883169384Sgallatin/// 884169384Sgallatin/// \throw model::error If the value is invalid. 885169384Sgallatinmodel::metadata_builder& 886169384Sgallatinmodel::metadata_builder::set_description(const std::string& description) 887169384Sgallatin{ 888171917Sgallatin set< config::string_node >(_pimpl->props, "description", description); 889171917Sgallatin return *this; 890171917Sgallatin} 891206662Sgallatin 892206662Sgallatin 893206662Sgallatin/// Sets whether the test has a cleanup part or not. 894169384Sgallatin/// 895169384Sgallatin/// \param cleanup True if the test has a cleanup part; false otherwise. 896169384Sgallatin/// 897169384Sgallatin/// \return A reference to this builder. 898169384Sgallatin/// 899169384Sgallatin/// \throw model::error If the value is invalid. 900169384Sgallatinmodel::metadata_builder& 901155852Sgallatinmodel::metadata_builder::set_has_cleanup(const bool cleanup) 902169384Sgallatin{ 903169384Sgallatin set< config::bool_node >(_pimpl->props, "has_cleanup", cleanup); 904155852Sgallatin return *this; 905169384Sgallatin} 906169384Sgallatin 907169384Sgallatin 908169384Sgallatin/// Sets whether the test is exclusive or not. 909166370Sgallatin/// 910169384Sgallatin/// \param exclusive True if the test is exclusive; false otherwise. 911155852Sgallatin/// 912155852Sgallatin/// \return A reference to this builder. 913160456Sgallatin/// 914160456Sgallatin/// \throw model::error If the value is invalid. 915160456Sgallatinmodel::metadata_builder& 916160456Sgallatinmodel::metadata_builder::set_is_exclusive(const bool exclusive) 917160456Sgallatin{ 918160456Sgallatin set< config::bool_node >(_pimpl->props, "is_exclusive", exclusive); 919160456Sgallatin return *this; 920155852Sgallatin} 921160456Sgallatin 922160456Sgallatin 923160456Sgallatin/// Sets the list of configuration variables needed by the test. 924160456Sgallatin/// 925160456Sgallatin/// \param vars Set of configuration variables. 926160456Sgallatin/// 927160456Sgallatin/// \return A reference to this builder. 928160456Sgallatin/// 929160456Sgallatin/// \throw model::error If the value is invalid. 930160456Sgallatinmodel::metadata_builder& 931160456Sgallatinmodel::metadata_builder::set_required_configs(const model::strings_set& vars) 932160456Sgallatin{ 933160456Sgallatin set< config::strings_set_node >(_pimpl->props, "required_configs", vars); 934160456Sgallatin return *this; 935160456Sgallatin} 936160456Sgallatin 937160456Sgallatin 938160456Sgallatin/// Sets the amount of free disk space required by the test. 939160456Sgallatin/// 940160456Sgallatin/// \param bytes Number of bytes. 941160456Sgallatin/// 942160456Sgallatin/// \return A reference to this builder. 943160456Sgallatin/// 944166875Sgallatin/// \throw model::error If the value is invalid. 945166875Sgallatinmodel::metadata_builder& 946166875Sgallatinmodel::metadata_builder::set_required_disk_space(const units::bytes& bytes) 947166875Sgallatin{ 948166875Sgallatin set< bytes_node >(_pimpl->props, "required_disk_space", bytes); 949166875Sgallatin return *this; 950166875Sgallatin} 951166875Sgallatin 952166875Sgallatin 953166875Sgallatin/// Sets the list of files needed by the test. 954166875Sgallatin/// 955166875Sgallatin/// \param files Set of paths. 956166875Sgallatin/// 957166875Sgallatin/// \return A reference to this builder. 958166875Sgallatin/// 959160456Sgallatin/// \throw model::error If the value is invalid. 960160456Sgallatinmodel::metadata_builder& 961160456Sgallatinmodel::metadata_builder::set_required_files(const model::paths_set& files) 962160456Sgallatin{ 963155852Sgallatin set< paths_set_node >(_pimpl->props, "required_files", files); 964175365Sgallatin return *this; 965155852Sgallatin} 966155852Sgallatin 967155852Sgallatin 968155852Sgallatin/// Sets the amount of memory required by the test. 969155852Sgallatin/// 970155852Sgallatin/// \param bytes Number of bytes. 971155852Sgallatin/// 972155852Sgallatin/// \return A reference to this builder. 973155852Sgallatin/// 974155852Sgallatin/// \throw model::error If the value is invalid. 975159571Sgallatinmodel::metadata_builder& 976155852Sgallatinmodel::metadata_builder::set_required_memory(const units::bytes& bytes) 977175365Sgallatin{ 978175365Sgallatin set< bytes_node >(_pimpl->props, "required_memory", bytes); 979160456Sgallatin return *this; 980160456Sgallatin} 981160456Sgallatin 982160456Sgallatin 983160456Sgallatin/// Sets the list of programs needed by the test. 984160456Sgallatin/// 985160456Sgallatin/// \param progs Set of paths. 986160456Sgallatin/// 987160456Sgallatin/// \return A reference to this builder. 988160456Sgallatin/// 989175365Sgallatin/// \throw model::error If the value is invalid. 990160456Sgallatinmodel::metadata_builder& 991160456Sgallatinmodel::metadata_builder::set_required_programs(const model::paths_set& progs) 992160456Sgallatin{ 993160456Sgallatin set< paths_set_node >(_pimpl->props, "required_programs", progs); 994160456Sgallatin return *this; 995160456Sgallatin} 996160456Sgallatin 997164513Sgallatin 998175365Sgallatin/// Sets the user required by the test. 999164513Sgallatin/// 1000155852Sgallatin/// \param user One of unprivileged, root or empty. 1001155852Sgallatin/// 1002155852Sgallatin/// \return A reference to this builder. 1003155852Sgallatin/// 1004185255Sgallatin/// \throw model::error If the value is invalid. 1005155852Sgallatinmodel::metadata_builder& 1006155852Sgallatinmodel::metadata_builder::set_required_user(const std::string& user) 1007155852Sgallatin{ 1008155852Sgallatin set< user_node >(_pimpl->props, "required_user", user); 1009155852Sgallatin return *this; 1010159571Sgallatin} 1011159571Sgallatin 1012155852Sgallatin 1013155852Sgallatin/// Sets a metadata property by name from its textual representation. 1014155852Sgallatin/// 1015155852Sgallatin/// \param key The property to set. 1016155852Sgallatin/// \param value The value to set the property to. 1017155852Sgallatin/// 1018155852Sgallatin/// \return A reference to this builder. 1019155852Sgallatin/// 1020155852Sgallatin/// \throw model::error If the value is invalid or the key does not exist. 1021155852Sgallatinmodel::metadata_builder& 1022159571Sgallatinmodel::metadata_builder::set_string(const std::string& key, 1023155852Sgallatin const std::string& value) 1024155852Sgallatin{ 1025155852Sgallatin try { 1026155852Sgallatin _pimpl->props.set_string(key, value); 1027162328Sgallatin } catch (const config::unknown_key_error& e) { 1028159571Sgallatin throw model::format_error(F("Unknown metadata property %s") % key); 1029185255Sgallatin } catch (const config::value_error& e) { 1030155852Sgallatin throw model::format_error( 1031185255Sgallatin F("Invalid value for metadata property %s: %s") % key % e.what()); 1032155852Sgallatin } 1033155852Sgallatin return *this; 1034155852Sgallatin} 1035155852Sgallatin 1036155852Sgallatin 1037155852Sgallatin/// Sets the timeout of the test. 1038155852Sgallatin/// 1039155852Sgallatin/// \param timeout The timeout to set. 1040155852Sgallatin/// 1041155852Sgallatin/// \return A reference to this builder. 1042155852Sgallatin/// 1043155852Sgallatin/// \throw model::error If the value is invalid. 1044155852Sgallatinmodel::metadata_builder& 1045155852Sgallatinmodel::metadata_builder::set_timeout(const datetime::delta& timeout) 1046155852Sgallatin{ 1047155852Sgallatin set< delta_node >(_pimpl->props, "timeout", timeout); 1048155852Sgallatin return *this; 1049159571Sgallatin} 1050155852Sgallatin 1051159571Sgallatin 1052155852Sgallatin/// Creates a new metadata object. 1053155852Sgallatin/// 1054155852Sgallatin/// \pre This has not yet been called. We only support calling this function 1055155852Sgallatin/// once due to the way the internal tree works: we pass around references, not 1056155852Sgallatin/// deep copies, so if we allowed a second build, we'd encourage reusing the 1057155852Sgallatin/// same builder to construct different metadata objects, and this could have 1058155852Sgallatin/// unintended consequences. 1059155852Sgallatin/// 1060155852Sgallatin/// \return The constructed metadata object. 1061159612Sgallatinmodel::metadata 1062155852Sgallatinmodel::metadata_builder::build(void) const 1063155852Sgallatin{ 1064155852Sgallatin PRE(!_pimpl->built); 1065155852Sgallatin _pimpl->built = true; 1066159571Sgallatin 1067155852Sgallatin return metadata(_pimpl->props); 1068159571Sgallatin} 1069155852Sgallatin