1b0d29bc4SBrooks Davis // Copyright 2012 The Kyua Authors.
2b0d29bc4SBrooks Davis // All rights reserved.
3b0d29bc4SBrooks Davis //
4b0d29bc4SBrooks Davis // Redistribution and use in source and binary forms, with or without
5b0d29bc4SBrooks Davis // modification, are permitted provided that the following conditions are
6b0d29bc4SBrooks Davis // met:
7b0d29bc4SBrooks Davis //
8b0d29bc4SBrooks Davis // * Redistributions of source code must retain the above copyright
9b0d29bc4SBrooks Davis // notice, this list of conditions and the following disclaimer.
10b0d29bc4SBrooks Davis // * Redistributions in binary form must reproduce the above copyright
11b0d29bc4SBrooks Davis // notice, this list of conditions and the following disclaimer in the
12b0d29bc4SBrooks Davis // documentation and/or other materials provided with the distribution.
13b0d29bc4SBrooks Davis // * Neither the name of Google Inc. nor the names of its contributors
14b0d29bc4SBrooks Davis // may be used to endorse or promote products derived from this software
15b0d29bc4SBrooks Davis // without specific prior written permission.
16b0d29bc4SBrooks Davis //
17b0d29bc4SBrooks Davis // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18b0d29bc4SBrooks Davis // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19b0d29bc4SBrooks Davis // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20b0d29bc4SBrooks Davis // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21b0d29bc4SBrooks Davis // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22b0d29bc4SBrooks Davis // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23b0d29bc4SBrooks Davis // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24b0d29bc4SBrooks Davis // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25b0d29bc4SBrooks Davis // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26b0d29bc4SBrooks Davis // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27b0d29bc4SBrooks Davis // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28b0d29bc4SBrooks Davis
29b0d29bc4SBrooks Davis #include "model/metadata.hpp"
30b0d29bc4SBrooks Davis
31b0d29bc4SBrooks Davis #include <memory>
32b0d29bc4SBrooks Davis
33*257e70f1SIgor Ostapenko #include "engine/execenv/execenv.hpp"
34b0d29bc4SBrooks Davis #include "model/exceptions.hpp"
35b0d29bc4SBrooks Davis #include "model/types.hpp"
36b0d29bc4SBrooks Davis #include "utils/config/exceptions.hpp"
37b0d29bc4SBrooks Davis #include "utils/config/nodes.ipp"
38b0d29bc4SBrooks Davis #include "utils/config/tree.ipp"
39b0d29bc4SBrooks Davis #include "utils/datetime.hpp"
40b0d29bc4SBrooks Davis #include "utils/defs.hpp"
41b0d29bc4SBrooks Davis #include "utils/format/macros.hpp"
42b0d29bc4SBrooks Davis #include "utils/fs/exceptions.hpp"
43b0d29bc4SBrooks Davis #include "utils/fs/path.hpp"
44b0d29bc4SBrooks Davis #include "utils/noncopyable.hpp"
45b0d29bc4SBrooks Davis #include "utils/optional.ipp"
46b0d29bc4SBrooks Davis #include "utils/sanity.hpp"
47b0d29bc4SBrooks Davis #include "utils/text/exceptions.hpp"
48b0d29bc4SBrooks Davis #include "utils/text/operations.hpp"
49b0d29bc4SBrooks Davis #include "utils/units.hpp"
50b0d29bc4SBrooks Davis
51b0d29bc4SBrooks Davis namespace config = utils::config;
52b0d29bc4SBrooks Davis namespace datetime = utils::datetime;
53b0d29bc4SBrooks Davis namespace fs = utils::fs;
54b0d29bc4SBrooks Davis namespace text = utils::text;
55b0d29bc4SBrooks Davis namespace units = utils::units;
56b0d29bc4SBrooks Davis
57b0d29bc4SBrooks Davis using utils::optional;
58b0d29bc4SBrooks Davis
59b0d29bc4SBrooks Davis
60b0d29bc4SBrooks Davis namespace {
61b0d29bc4SBrooks Davis
62b0d29bc4SBrooks Davis
63b0d29bc4SBrooks Davis /// Global instance of defaults.
64b0d29bc4SBrooks Davis ///
65b0d29bc4SBrooks Davis /// This exists so that the getters in metadata can return references instead
66b0d29bc4SBrooks Davis /// of object copies. Use get_defaults() to query.
67b0d29bc4SBrooks Davis static optional< config::tree > defaults;
68b0d29bc4SBrooks Davis
69b0d29bc4SBrooks Davis
70b0d29bc4SBrooks Davis /// A leaf node that holds a bytes quantity.
71b0d29bc4SBrooks Davis class bytes_node : public config::native_leaf_node< units::bytes > {
72b0d29bc4SBrooks Davis public:
73b0d29bc4SBrooks Davis /// Copies the node.
74b0d29bc4SBrooks Davis ///
75b0d29bc4SBrooks Davis /// \return A dynamically-allocated node.
76b0d29bc4SBrooks Davis virtual base_node*
deep_copy(void) const77b0d29bc4SBrooks Davis deep_copy(void) const
78b0d29bc4SBrooks Davis {
79b0d29bc4SBrooks Davis std::auto_ptr< bytes_node > new_node(new bytes_node());
80b0d29bc4SBrooks Davis new_node->_value = _value;
81b0d29bc4SBrooks Davis return new_node.release();
82b0d29bc4SBrooks Davis }
83b0d29bc4SBrooks Davis
84b0d29bc4SBrooks Davis /// Pushes the node's value onto the Lua stack.
85b0d29bc4SBrooks Davis void
push_lua(lutok::state &) const86b0d29bc4SBrooks Davis push_lua(lutok::state& /* state */) const
87b0d29bc4SBrooks Davis {
88b0d29bc4SBrooks Davis UNREACHABLE;
89b0d29bc4SBrooks Davis }
90b0d29bc4SBrooks Davis
91b0d29bc4SBrooks Davis /// Sets the value of the node from an entry in the Lua stack.
92b0d29bc4SBrooks Davis void
set_lua(lutok::state &,const int)93b0d29bc4SBrooks Davis set_lua(lutok::state& /* state */, const int /* index */)
94b0d29bc4SBrooks Davis {
95b0d29bc4SBrooks Davis UNREACHABLE;
96b0d29bc4SBrooks Davis }
97b0d29bc4SBrooks Davis };
98b0d29bc4SBrooks Davis
99b0d29bc4SBrooks Davis
100b0d29bc4SBrooks Davis /// A leaf node that holds a time delta.
101b0d29bc4SBrooks Davis class delta_node : public config::typed_leaf_node< datetime::delta > {
102b0d29bc4SBrooks Davis public:
103b0d29bc4SBrooks Davis /// Copies the node.
104b0d29bc4SBrooks Davis ///
105b0d29bc4SBrooks Davis /// \return A dynamically-allocated node.
106b0d29bc4SBrooks Davis virtual base_node*
deep_copy(void) const107b0d29bc4SBrooks Davis deep_copy(void) const
108b0d29bc4SBrooks Davis {
109b0d29bc4SBrooks Davis std::auto_ptr< delta_node > new_node(new delta_node());
110b0d29bc4SBrooks Davis new_node->_value = _value;
111b0d29bc4SBrooks Davis return new_node.release();
112b0d29bc4SBrooks Davis }
113b0d29bc4SBrooks Davis
114b0d29bc4SBrooks Davis /// Sets the value of the node from a raw string representation.
115b0d29bc4SBrooks Davis ///
116b0d29bc4SBrooks Davis /// \param raw_value The value to set the node to.
117b0d29bc4SBrooks Davis ///
118b0d29bc4SBrooks Davis /// \throw value_error If the value is invalid.
119b0d29bc4SBrooks Davis void
set_string(const std::string & raw_value)120b0d29bc4SBrooks Davis set_string(const std::string& raw_value)
121b0d29bc4SBrooks Davis {
122b0d29bc4SBrooks Davis unsigned int seconds;
123b0d29bc4SBrooks Davis try {
124b0d29bc4SBrooks Davis seconds = text::to_type< unsigned int >(raw_value);
125b0d29bc4SBrooks Davis } catch (const text::error& e) {
126b0d29bc4SBrooks Davis throw config::value_error(F("Invalid time delta %s") % raw_value);
127b0d29bc4SBrooks Davis }
128b0d29bc4SBrooks Davis set(datetime::delta(seconds, 0));
129b0d29bc4SBrooks Davis }
130b0d29bc4SBrooks Davis
131b0d29bc4SBrooks Davis /// Converts the contents of the node to a string.
132b0d29bc4SBrooks Davis ///
133b0d29bc4SBrooks Davis /// \pre The node must have a value.
134b0d29bc4SBrooks Davis ///
135b0d29bc4SBrooks Davis /// \return A string representation of the value held by the node.
136b0d29bc4SBrooks Davis std::string
to_string(void) const137b0d29bc4SBrooks Davis to_string(void) const
138b0d29bc4SBrooks Davis {
139b0d29bc4SBrooks Davis return F("%s") % value().seconds;
140b0d29bc4SBrooks Davis }
141b0d29bc4SBrooks Davis
142b0d29bc4SBrooks Davis /// Pushes the node's value onto the Lua stack.
143b0d29bc4SBrooks Davis void
push_lua(lutok::state &) const144b0d29bc4SBrooks Davis push_lua(lutok::state& /* state */) const
145b0d29bc4SBrooks Davis {
146b0d29bc4SBrooks Davis UNREACHABLE;
147b0d29bc4SBrooks Davis }
148b0d29bc4SBrooks Davis
149b0d29bc4SBrooks Davis /// Sets the value of the node from an entry in the Lua stack.
150b0d29bc4SBrooks Davis void
set_lua(lutok::state &,const int)151b0d29bc4SBrooks Davis set_lua(lutok::state& /* state */, const int /* index */)
152b0d29bc4SBrooks Davis {
153b0d29bc4SBrooks Davis UNREACHABLE;
154b0d29bc4SBrooks Davis }
155b0d29bc4SBrooks Davis };
156b0d29bc4SBrooks Davis
157b0d29bc4SBrooks Davis
158b0d29bc4SBrooks Davis /// A leaf node that holds a "required user" property.
159b0d29bc4SBrooks Davis ///
160b0d29bc4SBrooks Davis /// This node is just a string, but it provides validation of the only allowed
161b0d29bc4SBrooks Davis /// values.
162b0d29bc4SBrooks Davis class user_node : public config::string_node {
163b0d29bc4SBrooks Davis /// Copies the node.
164b0d29bc4SBrooks Davis ///
165b0d29bc4SBrooks Davis /// \return A dynamically-allocated node.
166b0d29bc4SBrooks Davis virtual base_node*
deep_copy(void) const167b0d29bc4SBrooks Davis deep_copy(void) const
168b0d29bc4SBrooks Davis {
169b0d29bc4SBrooks Davis std::auto_ptr< user_node > new_node(new user_node());
170b0d29bc4SBrooks Davis new_node->_value = _value;
171b0d29bc4SBrooks Davis return new_node.release();
172b0d29bc4SBrooks Davis }
173b0d29bc4SBrooks Davis
174b0d29bc4SBrooks Davis /// Checks a given user textual representation for validity.
175b0d29bc4SBrooks Davis ///
176b0d29bc4SBrooks Davis /// \param user The value to validate.
177b0d29bc4SBrooks Davis ///
178b0d29bc4SBrooks Davis /// \throw config::value_error If the value is not valid.
179b0d29bc4SBrooks Davis void
validate(const value_type & user) const180b0d29bc4SBrooks Davis validate(const value_type& user) const
181b0d29bc4SBrooks Davis {
182b0d29bc4SBrooks Davis if (!user.empty() && user != "root" && user != "unprivileged")
183b0d29bc4SBrooks Davis throw config::value_error("Invalid required user value");
184b0d29bc4SBrooks Davis }
185b0d29bc4SBrooks Davis };
186b0d29bc4SBrooks Davis
187b0d29bc4SBrooks Davis
188b0d29bc4SBrooks Davis /// A leaf node that holds a set of paths.
189b0d29bc4SBrooks Davis ///
190b0d29bc4SBrooks Davis /// This node type is used to represent the value of the required files and
191b0d29bc4SBrooks Davis /// required programs, for example, and these do not allow relative paths. We
192b0d29bc4SBrooks Davis /// check this here.
193b0d29bc4SBrooks Davis class paths_set_node : public config::base_set_node< fs::path > {
194b0d29bc4SBrooks Davis /// Copies the node.
195b0d29bc4SBrooks Davis ///
196b0d29bc4SBrooks Davis /// \return A dynamically-allocated node.
197b0d29bc4SBrooks Davis virtual base_node*
deep_copy(void) const198b0d29bc4SBrooks Davis deep_copy(void) const
199b0d29bc4SBrooks Davis {
200b0d29bc4SBrooks Davis std::auto_ptr< paths_set_node > new_node(new paths_set_node());
201b0d29bc4SBrooks Davis new_node->_value = _value;
202b0d29bc4SBrooks Davis return new_node.release();
203b0d29bc4SBrooks Davis }
204b0d29bc4SBrooks Davis
205b0d29bc4SBrooks Davis /// Converts a single path to the native type.
206b0d29bc4SBrooks Davis ///
207b0d29bc4SBrooks Davis /// \param raw_value The value to parse.
208b0d29bc4SBrooks Davis ///
209b0d29bc4SBrooks Davis /// \return The parsed value.
210b0d29bc4SBrooks Davis ///
211b0d29bc4SBrooks Davis /// \throw config::value_error If the value is invalid.
212b0d29bc4SBrooks Davis fs::path
parse_one(const std::string & raw_value) const213b0d29bc4SBrooks Davis parse_one(const std::string& raw_value) const
214b0d29bc4SBrooks Davis {
215b0d29bc4SBrooks Davis try {
216b0d29bc4SBrooks Davis return fs::path(raw_value);
217b0d29bc4SBrooks Davis } catch (const fs::error& e) {
218b0d29bc4SBrooks Davis throw config::value_error(e.what());
219b0d29bc4SBrooks Davis }
220b0d29bc4SBrooks Davis }
221b0d29bc4SBrooks Davis
222b0d29bc4SBrooks Davis /// Checks a collection of paths for validity.
223b0d29bc4SBrooks Davis ///
224b0d29bc4SBrooks Davis /// \param paths The value to validate.
225b0d29bc4SBrooks Davis ///
226b0d29bc4SBrooks Davis /// \throw config::value_error If the value is not valid.
227b0d29bc4SBrooks Davis void
validate(const value_type & paths) const228b0d29bc4SBrooks Davis validate(const value_type& paths) const
229b0d29bc4SBrooks Davis {
230b0d29bc4SBrooks Davis for (value_type::const_iterator iter = paths.begin();
231b0d29bc4SBrooks Davis iter != paths.end(); ++iter) {
232b0d29bc4SBrooks Davis const fs::path& path = *iter;
233b0d29bc4SBrooks Davis if (!path.is_absolute() && path.ncomponents() > 1)
234b0d29bc4SBrooks Davis throw config::value_error(F("Relative path '%s' not allowed") %
235b0d29bc4SBrooks Davis *iter);
236b0d29bc4SBrooks Davis }
237b0d29bc4SBrooks Davis }
238b0d29bc4SBrooks Davis };
239b0d29bc4SBrooks Davis
240b0d29bc4SBrooks Davis
241b0d29bc4SBrooks Davis /// Initializes a tree to hold test case requirements.
242b0d29bc4SBrooks Davis ///
243b0d29bc4SBrooks Davis /// \param [in,out] tree The tree to initialize.
244b0d29bc4SBrooks Davis static void
init_tree(config::tree & tree)245b0d29bc4SBrooks Davis init_tree(config::tree& tree)
246b0d29bc4SBrooks Davis {
247b0d29bc4SBrooks Davis tree.define< config::strings_set_node >("allowed_architectures");
248b0d29bc4SBrooks Davis tree.define< config::strings_set_node >("allowed_platforms");
249b0d29bc4SBrooks Davis tree.define_dynamic("custom");
250b0d29bc4SBrooks Davis tree.define< config::string_node >("description");
251*257e70f1SIgor Ostapenko tree.define< config::string_node >("execenv");
252*257e70f1SIgor Ostapenko tree.define< config::string_node >("execenv_jail_params");
253b0d29bc4SBrooks Davis tree.define< config::bool_node >("has_cleanup");
254b0d29bc4SBrooks Davis tree.define< config::bool_node >("is_exclusive");
255b0d29bc4SBrooks Davis tree.define< config::strings_set_node >("required_configs");
256b0d29bc4SBrooks Davis tree.define< bytes_node >("required_disk_space");
257b0d29bc4SBrooks Davis tree.define< paths_set_node >("required_files");
258b0d29bc4SBrooks Davis tree.define< bytes_node >("required_memory");
259b0d29bc4SBrooks Davis tree.define< paths_set_node >("required_programs");
260b0d29bc4SBrooks Davis tree.define< user_node >("required_user");
261b0d29bc4SBrooks Davis tree.define< delta_node >("timeout");
262b0d29bc4SBrooks Davis }
263b0d29bc4SBrooks Davis
264b0d29bc4SBrooks Davis
265b0d29bc4SBrooks Davis /// Sets default values on a tree object.
266b0d29bc4SBrooks Davis ///
267b0d29bc4SBrooks Davis /// \param [in,out] tree The tree to configure.
268b0d29bc4SBrooks Davis static void
set_defaults(config::tree & tree)269b0d29bc4SBrooks Davis set_defaults(config::tree& tree)
270b0d29bc4SBrooks Davis {
271b0d29bc4SBrooks Davis tree.set< config::strings_set_node >("allowed_architectures",
272b0d29bc4SBrooks Davis model::strings_set());
273b0d29bc4SBrooks Davis tree.set< config::strings_set_node >("allowed_platforms",
274b0d29bc4SBrooks Davis model::strings_set());
275b0d29bc4SBrooks Davis tree.set< config::string_node >("description", "");
276*257e70f1SIgor Ostapenko tree.set< config::string_node >("execenv", "");
277*257e70f1SIgor Ostapenko tree.set< config::string_node >("execenv_jail_params", "");
278b0d29bc4SBrooks Davis tree.set< config::bool_node >("has_cleanup", false);
279b0d29bc4SBrooks Davis tree.set< config::bool_node >("is_exclusive", false);
280b0d29bc4SBrooks Davis tree.set< config::strings_set_node >("required_configs",
281b0d29bc4SBrooks Davis model::strings_set());
282b0d29bc4SBrooks Davis tree.set< bytes_node >("required_disk_space", units::bytes(0));
283b0d29bc4SBrooks Davis tree.set< paths_set_node >("required_files", model::paths_set());
284b0d29bc4SBrooks Davis tree.set< bytes_node >("required_memory", units::bytes(0));
285b0d29bc4SBrooks Davis tree.set< paths_set_node >("required_programs", model::paths_set());
286b0d29bc4SBrooks Davis tree.set< user_node >("required_user", "");
287b0d29bc4SBrooks Davis // TODO(jmmv): We shouldn't be setting a default timeout like this. See
288b0d29bc4SBrooks Davis // Issue 5 for details.
289b0d29bc4SBrooks Davis tree.set< delta_node >("timeout", datetime::delta(300, 0));
290b0d29bc4SBrooks Davis }
291b0d29bc4SBrooks Davis
292b0d29bc4SBrooks Davis
293b0d29bc4SBrooks Davis /// Queries the global defaults tree object with lazy initialization.
294b0d29bc4SBrooks Davis ///
295b0d29bc4SBrooks Davis /// \return A metadata tree. This object is statically allocated so it is
296b0d29bc4SBrooks Davis /// acceptable to obtain references to it and its members.
297b0d29bc4SBrooks Davis const config::tree&
get_defaults(void)298b0d29bc4SBrooks Davis get_defaults(void)
299b0d29bc4SBrooks Davis {
300b0d29bc4SBrooks Davis if (!defaults) {
301b0d29bc4SBrooks Davis config::tree props;
302b0d29bc4SBrooks Davis init_tree(props);
303b0d29bc4SBrooks Davis set_defaults(props);
304b0d29bc4SBrooks Davis defaults = props;
305b0d29bc4SBrooks Davis }
306b0d29bc4SBrooks Davis return defaults.get();
307b0d29bc4SBrooks Davis }
308b0d29bc4SBrooks Davis
309b0d29bc4SBrooks Davis
310b0d29bc4SBrooks Davis /// Looks up a value in a tree with error rewriting.
311b0d29bc4SBrooks Davis ///
312b0d29bc4SBrooks Davis /// \tparam NodeType The type of the node.
313b0d29bc4SBrooks Davis /// \param tree The tree in which to insert the value.
314b0d29bc4SBrooks Davis /// \param key The key to set.
315b0d29bc4SBrooks Davis ///
316b0d29bc4SBrooks Davis /// \return A read-write reference to the value in the node.
317b0d29bc4SBrooks Davis ///
318b0d29bc4SBrooks Davis /// \throw model::error If the key is not known or if the value is not valid.
319b0d29bc4SBrooks Davis template< class NodeType >
320b0d29bc4SBrooks Davis typename NodeType::value_type&
lookup_rw(config::tree & tree,const std::string & key)321b0d29bc4SBrooks Davis lookup_rw(config::tree& tree, const std::string& key)
322b0d29bc4SBrooks Davis {
323b0d29bc4SBrooks Davis try {
324b0d29bc4SBrooks Davis return tree.lookup_rw< NodeType >(key);
325b0d29bc4SBrooks Davis } catch (const config::unknown_key_error& e) {
326b0d29bc4SBrooks Davis throw model::error(F("Unknown metadata property %s") % key);
327b0d29bc4SBrooks Davis } catch (const config::value_error& e) {
328b0d29bc4SBrooks Davis throw model::error(F("Invalid value for metadata property %s: %s") %
329b0d29bc4SBrooks Davis key % e.what());
330b0d29bc4SBrooks Davis }
331b0d29bc4SBrooks Davis }
332b0d29bc4SBrooks Davis
333b0d29bc4SBrooks Davis
334b0d29bc4SBrooks Davis /// Sets a value in a tree with error rewriting.
335b0d29bc4SBrooks Davis ///
336b0d29bc4SBrooks Davis /// \tparam NodeType The type of the node.
337b0d29bc4SBrooks Davis /// \param tree The tree in which to insert the value.
338b0d29bc4SBrooks Davis /// \param key The key to set.
339b0d29bc4SBrooks Davis /// \param value The value to set the node to.
340b0d29bc4SBrooks Davis ///
341b0d29bc4SBrooks Davis /// \throw model::error If the key is not known or if the value is not valid.
342b0d29bc4SBrooks Davis template< class NodeType >
343b0d29bc4SBrooks Davis void
set(config::tree & tree,const std::string & key,const typename NodeType::value_type & value)344b0d29bc4SBrooks Davis set(config::tree& tree, const std::string& key,
345b0d29bc4SBrooks Davis const typename NodeType::value_type& value)
346b0d29bc4SBrooks Davis {
347b0d29bc4SBrooks Davis try {
348b0d29bc4SBrooks Davis tree.set< NodeType >(key, value);
349b0d29bc4SBrooks Davis } catch (const config::unknown_key_error& e) {
350b0d29bc4SBrooks Davis throw model::error(F("Unknown metadata property %s") % key);
351b0d29bc4SBrooks Davis } catch (const config::value_error& e) {
352b0d29bc4SBrooks Davis throw model::error(F("Invalid value for metadata property %s: %s") %
353b0d29bc4SBrooks Davis key % e.what());
354b0d29bc4SBrooks Davis }
355b0d29bc4SBrooks Davis }
356b0d29bc4SBrooks Davis
357b0d29bc4SBrooks Davis
358b0d29bc4SBrooks Davis } // anonymous namespace
359b0d29bc4SBrooks Davis
360b0d29bc4SBrooks Davis
361b0d29bc4SBrooks Davis /// Internal implementation of the metadata class.
362b0d29bc4SBrooks Davis struct model::metadata::impl : utils::noncopyable {
363b0d29bc4SBrooks Davis /// Metadata properties.
364b0d29bc4SBrooks Davis config::tree props;
365b0d29bc4SBrooks Davis
366b0d29bc4SBrooks Davis /// Constructor.
367b0d29bc4SBrooks Davis ///
368b0d29bc4SBrooks Davis /// \param props_ Metadata properties of the test.
implmodel::metadata::impl369b0d29bc4SBrooks Davis impl(const utils::config::tree& props_) :
370b0d29bc4SBrooks Davis props(props_)
371b0d29bc4SBrooks Davis {
372b0d29bc4SBrooks Davis }
373b0d29bc4SBrooks Davis
374b0d29bc4SBrooks Davis /// Equality comparator.
375b0d29bc4SBrooks Davis ///
376b0d29bc4SBrooks Davis /// \param other The other object to compare this one to.
377b0d29bc4SBrooks Davis ///
378b0d29bc4SBrooks Davis /// \return True if this object and other are equal; false otherwise.
379b0d29bc4SBrooks Davis bool
operator ==model::metadata::impl380b0d29bc4SBrooks Davis operator==(const impl& other) const
381b0d29bc4SBrooks Davis {
382b0d29bc4SBrooks Davis return (get_defaults().combine(props) ==
383b0d29bc4SBrooks Davis get_defaults().combine(other.props));
384b0d29bc4SBrooks Davis }
385b0d29bc4SBrooks Davis };
386b0d29bc4SBrooks Davis
387b0d29bc4SBrooks Davis
388b0d29bc4SBrooks Davis /// Constructor.
389b0d29bc4SBrooks Davis ///
390b0d29bc4SBrooks Davis /// \param props Metadata properties of the test.
metadata(const utils::config::tree & props)391b0d29bc4SBrooks Davis model::metadata::metadata(const utils::config::tree& props) :
392b0d29bc4SBrooks Davis _pimpl(new impl(props))
393b0d29bc4SBrooks Davis {
394b0d29bc4SBrooks Davis }
395b0d29bc4SBrooks Davis
396b0d29bc4SBrooks Davis
397b0d29bc4SBrooks Davis /// Destructor.
~metadata(void)398b0d29bc4SBrooks Davis model::metadata::~metadata(void)
399b0d29bc4SBrooks Davis {
400b0d29bc4SBrooks Davis }
401b0d29bc4SBrooks Davis
402b0d29bc4SBrooks Davis
403b0d29bc4SBrooks Davis /// Applies a set of overrides to this metadata object.
404b0d29bc4SBrooks Davis ///
405b0d29bc4SBrooks Davis /// \param overrides The overrides to apply. Any values explicitly set in this
406b0d29bc4SBrooks Davis /// other object will override any possible values set in this object.
407b0d29bc4SBrooks Davis ///
408b0d29bc4SBrooks Davis /// \return A new metadata object with the combination.
409b0d29bc4SBrooks Davis model::metadata
apply_overrides(const metadata & overrides) const410b0d29bc4SBrooks Davis model::metadata::apply_overrides(const metadata& overrides) const
411b0d29bc4SBrooks Davis {
412b0d29bc4SBrooks Davis return metadata(_pimpl->props.combine(overrides._pimpl->props));
413b0d29bc4SBrooks Davis }
414b0d29bc4SBrooks Davis
415b0d29bc4SBrooks Davis
416b0d29bc4SBrooks Davis /// Returns the architectures allowed by the test.
417b0d29bc4SBrooks Davis ///
418b0d29bc4SBrooks Davis /// \return Set of architectures, or empty if this does not apply.
419b0d29bc4SBrooks Davis const model::strings_set&
allowed_architectures(void) const420b0d29bc4SBrooks Davis model::metadata::allowed_architectures(void) const
421b0d29bc4SBrooks Davis {
422b0d29bc4SBrooks Davis if (_pimpl->props.is_set("allowed_architectures")) {
423b0d29bc4SBrooks Davis return _pimpl->props.lookup< config::strings_set_node >(
424b0d29bc4SBrooks Davis "allowed_architectures");
425b0d29bc4SBrooks Davis } else {
426b0d29bc4SBrooks Davis return get_defaults().lookup< config::strings_set_node >(
427b0d29bc4SBrooks Davis "allowed_architectures");
428b0d29bc4SBrooks Davis }
429b0d29bc4SBrooks Davis }
430b0d29bc4SBrooks Davis
431b0d29bc4SBrooks Davis
432b0d29bc4SBrooks Davis /// Returns the platforms allowed by the test.
433b0d29bc4SBrooks Davis ///
434b0d29bc4SBrooks Davis /// \return Set of platforms, or empty if this does not apply.
435b0d29bc4SBrooks Davis const model::strings_set&
allowed_platforms(void) const436b0d29bc4SBrooks Davis model::metadata::allowed_platforms(void) const
437b0d29bc4SBrooks Davis {
438b0d29bc4SBrooks Davis if (_pimpl->props.is_set("allowed_platforms")) {
439b0d29bc4SBrooks Davis return _pimpl->props.lookup< config::strings_set_node >(
440b0d29bc4SBrooks Davis "allowed_platforms");
441b0d29bc4SBrooks Davis } else {
442b0d29bc4SBrooks Davis return get_defaults().lookup< config::strings_set_node >(
443b0d29bc4SBrooks Davis "allowed_platforms");
444b0d29bc4SBrooks Davis }
445b0d29bc4SBrooks Davis }
446b0d29bc4SBrooks Davis
447b0d29bc4SBrooks Davis
448b0d29bc4SBrooks Davis /// Returns all the user-defined metadata properties.
449b0d29bc4SBrooks Davis ///
450b0d29bc4SBrooks Davis /// \return A key/value map of properties.
451b0d29bc4SBrooks Davis model::properties_map
custom(void) const452b0d29bc4SBrooks Davis model::metadata::custom(void) const
453b0d29bc4SBrooks Davis {
454b0d29bc4SBrooks Davis return _pimpl->props.all_properties("custom", true);
455b0d29bc4SBrooks Davis }
456b0d29bc4SBrooks Davis
457b0d29bc4SBrooks Davis
458b0d29bc4SBrooks Davis /// Returns the description of the test.
459b0d29bc4SBrooks Davis ///
460b0d29bc4SBrooks Davis /// \return Textual description; may be empty.
461b0d29bc4SBrooks Davis const std::string&
description(void) const462b0d29bc4SBrooks Davis model::metadata::description(void) const
463b0d29bc4SBrooks Davis {
464b0d29bc4SBrooks Davis if (_pimpl->props.is_set("description")) {
465b0d29bc4SBrooks Davis return _pimpl->props.lookup< config::string_node >("description");
466b0d29bc4SBrooks Davis } else {
467b0d29bc4SBrooks Davis return get_defaults().lookup< config::string_node >("description");
468b0d29bc4SBrooks Davis }
469b0d29bc4SBrooks Davis }
470b0d29bc4SBrooks Davis
471b0d29bc4SBrooks Davis
472*257e70f1SIgor Ostapenko /// Returns execution environment name.
473*257e70f1SIgor Ostapenko ///
474*257e70f1SIgor Ostapenko /// \return Name of configured execution environment.
475*257e70f1SIgor Ostapenko const std::string&
execenv(void) const476*257e70f1SIgor Ostapenko model::metadata::execenv(void) const
477*257e70f1SIgor Ostapenko {
478*257e70f1SIgor Ostapenko if (_pimpl->props.is_set("execenv")) {
479*257e70f1SIgor Ostapenko return _pimpl->props.lookup< config::string_node >("execenv");
480*257e70f1SIgor Ostapenko } else {
481*257e70f1SIgor Ostapenko return get_defaults().lookup< config::string_node >("execenv");
482*257e70f1SIgor Ostapenko }
483*257e70f1SIgor Ostapenko }
484*257e70f1SIgor Ostapenko
485*257e70f1SIgor Ostapenko
486*257e70f1SIgor Ostapenko /// Returns execenv jail(8) parameters string to run a test with.
487*257e70f1SIgor Ostapenko ///
488*257e70f1SIgor Ostapenko /// \return String of jail parameters.
489*257e70f1SIgor Ostapenko const std::string&
execenv_jail_params(void) const490*257e70f1SIgor Ostapenko model::metadata::execenv_jail_params(void) const
491*257e70f1SIgor Ostapenko {
492*257e70f1SIgor Ostapenko if (_pimpl->props.is_set("execenv_jail_params")) {
493*257e70f1SIgor Ostapenko return _pimpl->props.lookup< config::string_node >(
494*257e70f1SIgor Ostapenko "execenv_jail_params");
495*257e70f1SIgor Ostapenko } else {
496*257e70f1SIgor Ostapenko return get_defaults().lookup< config::string_node >(
497*257e70f1SIgor Ostapenko "execenv_jail_params");
498*257e70f1SIgor Ostapenko }
499*257e70f1SIgor Ostapenko }
500*257e70f1SIgor Ostapenko
501*257e70f1SIgor Ostapenko
502b0d29bc4SBrooks Davis /// Returns whether the test has a cleanup part or not.
503b0d29bc4SBrooks Davis ///
504b0d29bc4SBrooks Davis /// \return True if there is a cleanup part; false otherwise.
505b0d29bc4SBrooks Davis bool
has_cleanup(void) const506b0d29bc4SBrooks Davis model::metadata::has_cleanup(void) const
507b0d29bc4SBrooks Davis {
508b0d29bc4SBrooks Davis if (_pimpl->props.is_set("has_cleanup")) {
509b0d29bc4SBrooks Davis return _pimpl->props.lookup< config::bool_node >("has_cleanup");
510b0d29bc4SBrooks Davis } else {
511b0d29bc4SBrooks Davis return get_defaults().lookup< config::bool_node >("has_cleanup");
512b0d29bc4SBrooks Davis }
513b0d29bc4SBrooks Davis }
514b0d29bc4SBrooks Davis
515b0d29bc4SBrooks Davis
516*257e70f1SIgor Ostapenko /// Returns whether the test has a specific execenv apart from default one.
517*257e70f1SIgor Ostapenko ///
518*257e70f1SIgor Ostapenko /// \return True if there is a non-host execenv configured; false otherwise.
519*257e70f1SIgor Ostapenko bool
has_execenv(void) const520*257e70f1SIgor Ostapenko model::metadata::has_execenv(void) const
521*257e70f1SIgor Ostapenko {
522*257e70f1SIgor Ostapenko const std::string& name = execenv();
523*257e70f1SIgor Ostapenko return !name.empty() && name != engine::execenv::default_execenv_name;
524*257e70f1SIgor Ostapenko }
525*257e70f1SIgor Ostapenko
526*257e70f1SIgor Ostapenko
527b0d29bc4SBrooks Davis /// Returns whether the test is exclusive or not.
528b0d29bc4SBrooks Davis ///
529b0d29bc4SBrooks Davis /// \return True if the test has to be run on its own, not concurrently with any
530b0d29bc4SBrooks Davis /// other tests; false otherwise.
531b0d29bc4SBrooks Davis bool
is_exclusive(void) const532b0d29bc4SBrooks Davis model::metadata::is_exclusive(void) const
533b0d29bc4SBrooks Davis {
534b0d29bc4SBrooks Davis if (_pimpl->props.is_set("is_exclusive")) {
535b0d29bc4SBrooks Davis return _pimpl->props.lookup< config::bool_node >("is_exclusive");
536b0d29bc4SBrooks Davis } else {
537b0d29bc4SBrooks Davis return get_defaults().lookup< config::bool_node >("is_exclusive");
538b0d29bc4SBrooks Davis }
539b0d29bc4SBrooks Davis }
540b0d29bc4SBrooks Davis
541b0d29bc4SBrooks Davis
542b0d29bc4SBrooks Davis /// Returns the list of configuration variables needed by the test.
543b0d29bc4SBrooks Davis ///
544b0d29bc4SBrooks Davis /// \return Set of configuration variables.
545b0d29bc4SBrooks Davis const model::strings_set&
required_configs(void) const546b0d29bc4SBrooks Davis model::metadata::required_configs(void) const
547b0d29bc4SBrooks Davis {
548b0d29bc4SBrooks Davis if (_pimpl->props.is_set("required_configs")) {
549b0d29bc4SBrooks Davis return _pimpl->props.lookup< config::strings_set_node >(
550b0d29bc4SBrooks Davis "required_configs");
551b0d29bc4SBrooks Davis } else {
552b0d29bc4SBrooks Davis return get_defaults().lookup< config::strings_set_node >(
553b0d29bc4SBrooks Davis "required_configs");
554b0d29bc4SBrooks Davis }
555b0d29bc4SBrooks Davis }
556b0d29bc4SBrooks Davis
557b0d29bc4SBrooks Davis
558b0d29bc4SBrooks Davis /// Returns the amount of free disk space required by the test.
559b0d29bc4SBrooks Davis ///
560b0d29bc4SBrooks Davis /// \return Number of bytes, or 0 if this does not apply.
561b0d29bc4SBrooks Davis const units::bytes&
required_disk_space(void) const562b0d29bc4SBrooks Davis model::metadata::required_disk_space(void) const
563b0d29bc4SBrooks Davis {
564b0d29bc4SBrooks Davis if (_pimpl->props.is_set("required_disk_space")) {
565b0d29bc4SBrooks Davis return _pimpl->props.lookup< bytes_node >("required_disk_space");
566b0d29bc4SBrooks Davis } else {
567b0d29bc4SBrooks Davis return get_defaults().lookup< bytes_node >("required_disk_space");
568b0d29bc4SBrooks Davis }
569b0d29bc4SBrooks Davis }
570b0d29bc4SBrooks Davis
571b0d29bc4SBrooks Davis
572b0d29bc4SBrooks Davis /// Returns the list of files needed by the test.
573b0d29bc4SBrooks Davis ///
574b0d29bc4SBrooks Davis /// \return Set of paths.
575b0d29bc4SBrooks Davis const model::paths_set&
required_files(void) const576b0d29bc4SBrooks Davis model::metadata::required_files(void) const
577b0d29bc4SBrooks Davis {
578b0d29bc4SBrooks Davis if (_pimpl->props.is_set("required_files")) {
579b0d29bc4SBrooks Davis return _pimpl->props.lookup< paths_set_node >("required_files");
580b0d29bc4SBrooks Davis } else {
581b0d29bc4SBrooks Davis return get_defaults().lookup< paths_set_node >("required_files");
582b0d29bc4SBrooks Davis }
583b0d29bc4SBrooks Davis }
584b0d29bc4SBrooks Davis
585b0d29bc4SBrooks Davis
586b0d29bc4SBrooks Davis /// Returns the amount of memory required by the test.
587b0d29bc4SBrooks Davis ///
588b0d29bc4SBrooks Davis /// \return Number of bytes, or 0 if this does not apply.
589b0d29bc4SBrooks Davis const units::bytes&
required_memory(void) const590b0d29bc4SBrooks Davis model::metadata::required_memory(void) const
591b0d29bc4SBrooks Davis {
592b0d29bc4SBrooks Davis if (_pimpl->props.is_set("required_memory")) {
593b0d29bc4SBrooks Davis return _pimpl->props.lookup< bytes_node >("required_memory");
594b0d29bc4SBrooks Davis } else {
595b0d29bc4SBrooks Davis return get_defaults().lookup< bytes_node >("required_memory");
596b0d29bc4SBrooks Davis }
597b0d29bc4SBrooks Davis }
598b0d29bc4SBrooks Davis
599b0d29bc4SBrooks Davis
600b0d29bc4SBrooks Davis /// Returns the list of programs needed by the test.
601b0d29bc4SBrooks Davis ///
602b0d29bc4SBrooks Davis /// \return Set of paths.
603b0d29bc4SBrooks Davis const model::paths_set&
required_programs(void) const604b0d29bc4SBrooks Davis model::metadata::required_programs(void) const
605b0d29bc4SBrooks Davis {
606b0d29bc4SBrooks Davis if (_pimpl->props.is_set("required_programs")) {
607b0d29bc4SBrooks Davis return _pimpl->props.lookup< paths_set_node >("required_programs");
608b0d29bc4SBrooks Davis } else {
609b0d29bc4SBrooks Davis return get_defaults().lookup< paths_set_node >("required_programs");
610b0d29bc4SBrooks Davis }
611b0d29bc4SBrooks Davis }
612b0d29bc4SBrooks Davis
613b0d29bc4SBrooks Davis
614b0d29bc4SBrooks Davis /// Returns the user required by the test.
615b0d29bc4SBrooks Davis ///
616b0d29bc4SBrooks Davis /// \return One of unprivileged, root or empty.
617b0d29bc4SBrooks Davis const std::string&
required_user(void) const618b0d29bc4SBrooks Davis model::metadata::required_user(void) const
619b0d29bc4SBrooks Davis {
620b0d29bc4SBrooks Davis if (_pimpl->props.is_set("required_user")) {
621b0d29bc4SBrooks Davis return _pimpl->props.lookup< user_node >("required_user");
622b0d29bc4SBrooks Davis } else {
623b0d29bc4SBrooks Davis return get_defaults().lookup< user_node >("required_user");
624b0d29bc4SBrooks Davis }
625b0d29bc4SBrooks Davis }
626b0d29bc4SBrooks Davis
627b0d29bc4SBrooks Davis
628b0d29bc4SBrooks Davis /// Returns the timeout of the test.
629b0d29bc4SBrooks Davis ///
630b0d29bc4SBrooks Davis /// \return A time delta; should be compared to default_timeout to see if it has
631b0d29bc4SBrooks Davis /// been overriden.
632b0d29bc4SBrooks Davis const datetime::delta&
timeout(void) const633b0d29bc4SBrooks Davis model::metadata::timeout(void) const
634b0d29bc4SBrooks Davis {
635b0d29bc4SBrooks Davis if (_pimpl->props.is_set("timeout")) {
636b0d29bc4SBrooks Davis return _pimpl->props.lookup< delta_node >("timeout");
637b0d29bc4SBrooks Davis } else {
638b0d29bc4SBrooks Davis return get_defaults().lookup< delta_node >("timeout");
639b0d29bc4SBrooks Davis }
640b0d29bc4SBrooks Davis }
641b0d29bc4SBrooks Davis
642b0d29bc4SBrooks Davis
643b0d29bc4SBrooks Davis /// Externalizes the metadata to a set of key/value textual pairs.
644b0d29bc4SBrooks Davis ///
645b0d29bc4SBrooks Davis /// \return A key/value representation of the metadata.
646b0d29bc4SBrooks Davis model::properties_map
to_properties(void) const647b0d29bc4SBrooks Davis model::metadata::to_properties(void) const
648b0d29bc4SBrooks Davis {
649b0d29bc4SBrooks Davis const config::tree fully_specified = get_defaults().combine(_pimpl->props);
650b0d29bc4SBrooks Davis return fully_specified.all_properties();
651b0d29bc4SBrooks Davis }
652b0d29bc4SBrooks Davis
653b0d29bc4SBrooks Davis
654b0d29bc4SBrooks Davis /// Equality comparator.
655b0d29bc4SBrooks Davis ///
656b0d29bc4SBrooks Davis /// \param other The other object to compare this one to.
657b0d29bc4SBrooks Davis ///
658b0d29bc4SBrooks Davis /// \return True if this object and other are equal; false otherwise.
659b0d29bc4SBrooks Davis bool
operator ==(const metadata & other) const660b0d29bc4SBrooks Davis model::metadata::operator==(const metadata& other) const
661b0d29bc4SBrooks Davis {
662b0d29bc4SBrooks Davis return _pimpl == other._pimpl || *_pimpl == *other._pimpl;
663b0d29bc4SBrooks Davis }
664b0d29bc4SBrooks Davis
665b0d29bc4SBrooks Davis
666b0d29bc4SBrooks Davis /// Inequality comparator.
667b0d29bc4SBrooks Davis ///
668b0d29bc4SBrooks Davis /// \param other The other object to compare this one to.
669b0d29bc4SBrooks Davis ///
670b0d29bc4SBrooks Davis /// \return True if this object and other are different; false otherwise.
671b0d29bc4SBrooks Davis bool
operator !=(const metadata & other) const672b0d29bc4SBrooks Davis model::metadata::operator!=(const metadata& other) const
673b0d29bc4SBrooks Davis {
674b0d29bc4SBrooks Davis return !(*this == other);
675b0d29bc4SBrooks Davis }
676b0d29bc4SBrooks Davis
677b0d29bc4SBrooks Davis
678b0d29bc4SBrooks Davis /// Injects the object into a stream.
679b0d29bc4SBrooks Davis ///
680b0d29bc4SBrooks Davis /// \param output The stream into which to inject the object.
681b0d29bc4SBrooks Davis /// \param object The object to format.
682b0d29bc4SBrooks Davis ///
683b0d29bc4SBrooks Davis /// \return The output stream.
684b0d29bc4SBrooks Davis std::ostream&
operator <<(std::ostream & output,const metadata & object)685b0d29bc4SBrooks Davis model::operator<<(std::ostream& output, const metadata& object)
686b0d29bc4SBrooks Davis {
687b0d29bc4SBrooks Davis output << "metadata{";
688b0d29bc4SBrooks Davis
689b0d29bc4SBrooks Davis bool first = true;
690b0d29bc4SBrooks Davis const model::properties_map props = object.to_properties();
691b0d29bc4SBrooks Davis for (model::properties_map::const_iterator iter = props.begin();
692b0d29bc4SBrooks Davis iter != props.end(); ++iter) {
693b0d29bc4SBrooks Davis if (!first)
694b0d29bc4SBrooks Davis output << ", ";
695b0d29bc4SBrooks Davis output << F("%s=%s") % (*iter).first %
696b0d29bc4SBrooks Davis text::quote((*iter).second, '\'');
697b0d29bc4SBrooks Davis first = false;
698b0d29bc4SBrooks Davis }
699b0d29bc4SBrooks Davis
700b0d29bc4SBrooks Davis output << "}";
701b0d29bc4SBrooks Davis return output;
702b0d29bc4SBrooks Davis }
703b0d29bc4SBrooks Davis
704b0d29bc4SBrooks Davis
705b0d29bc4SBrooks Davis /// Internal implementation of the metadata_builder class.
706b0d29bc4SBrooks Davis struct model::metadata_builder::impl : utils::noncopyable {
707b0d29bc4SBrooks Davis /// Collection of requirements.
708b0d29bc4SBrooks Davis config::tree props;
709b0d29bc4SBrooks Davis
710b0d29bc4SBrooks Davis /// Whether we have created a metadata object or not.
711b0d29bc4SBrooks Davis bool built;
712b0d29bc4SBrooks Davis
713b0d29bc4SBrooks Davis /// Constructor.
implmodel::metadata_builder::impl714b0d29bc4SBrooks Davis impl(void) :
715b0d29bc4SBrooks Davis built(false)
716b0d29bc4SBrooks Davis {
717b0d29bc4SBrooks Davis init_tree(props);
718b0d29bc4SBrooks Davis }
719b0d29bc4SBrooks Davis
720b0d29bc4SBrooks Davis /// Constructor.
721b0d29bc4SBrooks Davis ///
722b0d29bc4SBrooks Davis /// \param base The base model to construct a copy from.
implmodel::metadata_builder::impl723b0d29bc4SBrooks Davis impl(const model::metadata& base) :
724b0d29bc4SBrooks Davis props(base._pimpl->props.deep_copy()),
725b0d29bc4SBrooks Davis built(false)
726b0d29bc4SBrooks Davis {
727b0d29bc4SBrooks Davis }
728b0d29bc4SBrooks Davis };
729b0d29bc4SBrooks Davis
730b0d29bc4SBrooks Davis
731b0d29bc4SBrooks Davis /// Constructor.
metadata_builder(void)732b0d29bc4SBrooks Davis model::metadata_builder::metadata_builder(void) :
733b0d29bc4SBrooks Davis _pimpl(new impl())
734b0d29bc4SBrooks Davis {
735b0d29bc4SBrooks Davis }
736b0d29bc4SBrooks Davis
737b0d29bc4SBrooks Davis
738b0d29bc4SBrooks Davis /// Constructor.
metadata_builder(const model::metadata & base)739b0d29bc4SBrooks Davis model::metadata_builder::metadata_builder(const model::metadata& base) :
740b0d29bc4SBrooks Davis _pimpl(new impl(base))
741b0d29bc4SBrooks Davis {
742b0d29bc4SBrooks Davis }
743b0d29bc4SBrooks Davis
744b0d29bc4SBrooks Davis
745b0d29bc4SBrooks Davis /// Destructor.
~metadata_builder(void)746b0d29bc4SBrooks Davis model::metadata_builder::~metadata_builder(void)
747b0d29bc4SBrooks Davis {
748b0d29bc4SBrooks Davis }
749b0d29bc4SBrooks Davis
750b0d29bc4SBrooks Davis
751b0d29bc4SBrooks Davis /// Accumulates an additional allowed architecture.
752b0d29bc4SBrooks Davis ///
753b0d29bc4SBrooks Davis /// \param arch The architecture.
754b0d29bc4SBrooks Davis ///
755b0d29bc4SBrooks Davis /// \return A reference to this builder.
756b0d29bc4SBrooks Davis ///
757b0d29bc4SBrooks Davis /// \throw model::error If the value is invalid.
758b0d29bc4SBrooks Davis model::metadata_builder&
add_allowed_architecture(const std::string & arch)759b0d29bc4SBrooks Davis model::metadata_builder::add_allowed_architecture(const std::string& arch)
760b0d29bc4SBrooks Davis {
761b0d29bc4SBrooks Davis if (!_pimpl->props.is_set("allowed_architectures")) {
762b0d29bc4SBrooks Davis _pimpl->props.set< config::strings_set_node >(
763b0d29bc4SBrooks Davis "allowed_architectures",
764b0d29bc4SBrooks Davis get_defaults().lookup< config::strings_set_node >(
765b0d29bc4SBrooks Davis "allowed_architectures"));
766b0d29bc4SBrooks Davis }
767b0d29bc4SBrooks Davis lookup_rw< config::strings_set_node >(
768b0d29bc4SBrooks Davis _pimpl->props, "allowed_architectures").insert(arch);
769b0d29bc4SBrooks Davis return *this;
770b0d29bc4SBrooks Davis }
771b0d29bc4SBrooks Davis
772b0d29bc4SBrooks Davis
773b0d29bc4SBrooks Davis /// Accumulates an additional allowed platform.
774b0d29bc4SBrooks Davis ///
775b0d29bc4SBrooks Davis /// \param platform The platform.
776b0d29bc4SBrooks Davis ///
777b0d29bc4SBrooks Davis /// \return A reference to this builder.
778b0d29bc4SBrooks Davis ///
779b0d29bc4SBrooks Davis /// \throw model::error If the value is invalid.
780b0d29bc4SBrooks Davis model::metadata_builder&
add_allowed_platform(const std::string & platform)781b0d29bc4SBrooks Davis model::metadata_builder::add_allowed_platform(const std::string& platform)
782b0d29bc4SBrooks Davis {
783b0d29bc4SBrooks Davis if (!_pimpl->props.is_set("allowed_platforms")) {
784b0d29bc4SBrooks Davis _pimpl->props.set< config::strings_set_node >(
785b0d29bc4SBrooks Davis "allowed_platforms",
786b0d29bc4SBrooks Davis get_defaults().lookup< config::strings_set_node >(
787b0d29bc4SBrooks Davis "allowed_platforms"));
788b0d29bc4SBrooks Davis }
789b0d29bc4SBrooks Davis lookup_rw< config::strings_set_node >(
790b0d29bc4SBrooks Davis _pimpl->props, "allowed_platforms").insert(platform);
791b0d29bc4SBrooks Davis return *this;
792b0d29bc4SBrooks Davis }
793b0d29bc4SBrooks Davis
794b0d29bc4SBrooks Davis
795b0d29bc4SBrooks Davis /// Accumulates a single user-defined property.
796b0d29bc4SBrooks Davis ///
797b0d29bc4SBrooks Davis /// \param key Name of the property to define.
798b0d29bc4SBrooks Davis /// \param value Value of the property.
799b0d29bc4SBrooks Davis ///
800b0d29bc4SBrooks Davis /// \return A reference to this builder.
801b0d29bc4SBrooks Davis ///
802b0d29bc4SBrooks Davis /// \throw model::error If the value is invalid.
803b0d29bc4SBrooks Davis model::metadata_builder&
add_custom(const std::string & key,const std::string & value)804b0d29bc4SBrooks Davis model::metadata_builder::add_custom(const std::string& key,
805b0d29bc4SBrooks Davis const std::string& value)
806b0d29bc4SBrooks Davis {
807b0d29bc4SBrooks Davis _pimpl->props.set_string(F("custom.%s") % key, value);
808b0d29bc4SBrooks Davis return *this;
809b0d29bc4SBrooks Davis }
810b0d29bc4SBrooks Davis
811b0d29bc4SBrooks Davis
812b0d29bc4SBrooks Davis /// Accumulates an additional required configuration variable.
813b0d29bc4SBrooks Davis ///
814b0d29bc4SBrooks Davis /// \param var The name of the configuration variable.
815b0d29bc4SBrooks Davis ///
816b0d29bc4SBrooks Davis /// \return A reference to this builder.
817b0d29bc4SBrooks Davis ///
818b0d29bc4SBrooks Davis /// \throw model::error If the value is invalid.
819b0d29bc4SBrooks Davis model::metadata_builder&
add_required_config(const std::string & var)820b0d29bc4SBrooks Davis model::metadata_builder::add_required_config(const std::string& var)
821b0d29bc4SBrooks Davis {
822b0d29bc4SBrooks Davis if (!_pimpl->props.is_set("required_configs")) {
823b0d29bc4SBrooks Davis _pimpl->props.set< config::strings_set_node >(
824b0d29bc4SBrooks Davis "required_configs",
825b0d29bc4SBrooks Davis get_defaults().lookup< config::strings_set_node >(
826b0d29bc4SBrooks Davis "required_configs"));
827b0d29bc4SBrooks Davis }
828b0d29bc4SBrooks Davis lookup_rw< config::strings_set_node >(
829b0d29bc4SBrooks Davis _pimpl->props, "required_configs").insert(var);
830b0d29bc4SBrooks Davis return *this;
831b0d29bc4SBrooks Davis }
832b0d29bc4SBrooks Davis
833b0d29bc4SBrooks Davis
834b0d29bc4SBrooks Davis /// Accumulates an additional required file.
835b0d29bc4SBrooks Davis ///
836b0d29bc4SBrooks Davis /// \param path The path to the file.
837b0d29bc4SBrooks Davis ///
838b0d29bc4SBrooks Davis /// \return A reference to this builder.
839b0d29bc4SBrooks Davis ///
840b0d29bc4SBrooks Davis /// \throw model::error If the value is invalid.
841b0d29bc4SBrooks Davis model::metadata_builder&
add_required_file(const fs::path & path)842b0d29bc4SBrooks Davis model::metadata_builder::add_required_file(const fs::path& path)
843b0d29bc4SBrooks Davis {
844b0d29bc4SBrooks Davis if (!_pimpl->props.is_set("required_files")) {
845b0d29bc4SBrooks Davis _pimpl->props.set< paths_set_node >(
846b0d29bc4SBrooks Davis "required_files",
847b0d29bc4SBrooks Davis get_defaults().lookup< paths_set_node >("required_files"));
848b0d29bc4SBrooks Davis }
849b0d29bc4SBrooks Davis lookup_rw< paths_set_node >(_pimpl->props, "required_files").insert(path);
850b0d29bc4SBrooks Davis return *this;
851b0d29bc4SBrooks Davis }
852b0d29bc4SBrooks Davis
853b0d29bc4SBrooks Davis
854b0d29bc4SBrooks Davis /// Accumulates an additional required program.
855b0d29bc4SBrooks Davis ///
856b0d29bc4SBrooks Davis /// \param path The path to the program.
857b0d29bc4SBrooks Davis ///
858b0d29bc4SBrooks Davis /// \return A reference to this builder.
859b0d29bc4SBrooks Davis ///
860b0d29bc4SBrooks Davis /// \throw model::error If the value is invalid.
861b0d29bc4SBrooks Davis model::metadata_builder&
add_required_program(const fs::path & path)862b0d29bc4SBrooks Davis model::metadata_builder::add_required_program(const fs::path& path)
863b0d29bc4SBrooks Davis {
864b0d29bc4SBrooks Davis if (!_pimpl->props.is_set("required_programs")) {
865b0d29bc4SBrooks Davis _pimpl->props.set< paths_set_node >(
866b0d29bc4SBrooks Davis "required_programs",
867b0d29bc4SBrooks Davis get_defaults().lookup< paths_set_node >("required_programs"));
868b0d29bc4SBrooks Davis }
869b0d29bc4SBrooks Davis lookup_rw< paths_set_node >(_pimpl->props,
870b0d29bc4SBrooks Davis "required_programs").insert(path);
871b0d29bc4SBrooks Davis return *this;
872b0d29bc4SBrooks Davis }
873b0d29bc4SBrooks Davis
874b0d29bc4SBrooks Davis
875b0d29bc4SBrooks Davis /// Sets the architectures allowed by the test.
876b0d29bc4SBrooks Davis ///
877b0d29bc4SBrooks Davis /// \param as Set of architectures.
878b0d29bc4SBrooks Davis ///
879b0d29bc4SBrooks Davis /// \return A reference to this builder.
880b0d29bc4SBrooks Davis ///
881b0d29bc4SBrooks Davis /// \throw model::error If the value is invalid.
882b0d29bc4SBrooks Davis model::metadata_builder&
set_allowed_architectures(const model::strings_set & as)883b0d29bc4SBrooks Davis model::metadata_builder::set_allowed_architectures(
884b0d29bc4SBrooks Davis const model::strings_set& as)
885b0d29bc4SBrooks Davis {
886b0d29bc4SBrooks Davis set< config::strings_set_node >(_pimpl->props, "allowed_architectures", as);
887b0d29bc4SBrooks Davis return *this;
888b0d29bc4SBrooks Davis }
889b0d29bc4SBrooks Davis
890b0d29bc4SBrooks Davis
891b0d29bc4SBrooks Davis /// Sets the platforms allowed by the test.
892b0d29bc4SBrooks Davis ///
893b0d29bc4SBrooks Davis /// \return ps Set of platforms.
894b0d29bc4SBrooks Davis ///
895b0d29bc4SBrooks Davis /// \return A reference to this builder.
896b0d29bc4SBrooks Davis ///
897b0d29bc4SBrooks Davis /// \throw model::error If the value is invalid.
898b0d29bc4SBrooks Davis model::metadata_builder&
set_allowed_platforms(const model::strings_set & ps)899b0d29bc4SBrooks Davis model::metadata_builder::set_allowed_platforms(const model::strings_set& ps)
900b0d29bc4SBrooks Davis {
901b0d29bc4SBrooks Davis set< config::strings_set_node >(_pimpl->props, "allowed_platforms", ps);
902b0d29bc4SBrooks Davis return *this;
903b0d29bc4SBrooks Davis }
904b0d29bc4SBrooks Davis
905b0d29bc4SBrooks Davis
906b0d29bc4SBrooks Davis /// Sets the user-defined properties.
907b0d29bc4SBrooks Davis ///
908b0d29bc4SBrooks Davis /// \param props The custom properties to set.
909b0d29bc4SBrooks Davis ///
910b0d29bc4SBrooks Davis /// \return A reference to this builder.
911b0d29bc4SBrooks Davis ///
912b0d29bc4SBrooks Davis /// \throw model::error If the value is invalid.
913b0d29bc4SBrooks Davis model::metadata_builder&
set_custom(const model::properties_map & props)914b0d29bc4SBrooks Davis model::metadata_builder::set_custom(const model::properties_map& props)
915b0d29bc4SBrooks Davis {
916b0d29bc4SBrooks Davis for (model::properties_map::const_iterator iter = props.begin();
917b0d29bc4SBrooks Davis iter != props.end(); ++iter)
918b0d29bc4SBrooks Davis _pimpl->props.set_string(F("custom.%s") % (*iter).first,
919b0d29bc4SBrooks Davis (*iter).second);
920b0d29bc4SBrooks Davis return *this;
921b0d29bc4SBrooks Davis }
922b0d29bc4SBrooks Davis
923b0d29bc4SBrooks Davis
924b0d29bc4SBrooks Davis /// Sets the description of the test.
925b0d29bc4SBrooks Davis ///
926b0d29bc4SBrooks Davis /// \param description Textual description of the test.
927b0d29bc4SBrooks Davis ///
928b0d29bc4SBrooks Davis /// \return A reference to this builder.
929b0d29bc4SBrooks Davis ///
930b0d29bc4SBrooks Davis /// \throw model::error If the value is invalid.
931b0d29bc4SBrooks Davis model::metadata_builder&
set_description(const std::string & description)932b0d29bc4SBrooks Davis model::metadata_builder::set_description(const std::string& description)
933b0d29bc4SBrooks Davis {
934b0d29bc4SBrooks Davis set< config::string_node >(_pimpl->props, "description", description);
935b0d29bc4SBrooks Davis return *this;
936b0d29bc4SBrooks Davis }
937b0d29bc4SBrooks Davis
938b0d29bc4SBrooks Davis
939*257e70f1SIgor Ostapenko /// Sets execution environment name.
940*257e70f1SIgor Ostapenko ///
941*257e70f1SIgor Ostapenko /// \param name Execution environment name.
942*257e70f1SIgor Ostapenko ///
943*257e70f1SIgor Ostapenko /// \return A reference to this builder.
944*257e70f1SIgor Ostapenko ///
945*257e70f1SIgor Ostapenko /// \throw model::error If the value is invalid.
946*257e70f1SIgor Ostapenko model::metadata_builder&
set_execenv(const std::string & name)947*257e70f1SIgor Ostapenko model::metadata_builder::set_execenv(const std::string& name)
948*257e70f1SIgor Ostapenko {
949*257e70f1SIgor Ostapenko set< config::string_node >(_pimpl->props, "execenv", name);
950*257e70f1SIgor Ostapenko return *this;
951*257e70f1SIgor Ostapenko }
952*257e70f1SIgor Ostapenko
953*257e70f1SIgor Ostapenko
954*257e70f1SIgor Ostapenko /// Sets execenv jail(8) parameters string to run the test with.
955*257e70f1SIgor Ostapenko ///
956*257e70f1SIgor Ostapenko /// \param params String of jail parameters.
957*257e70f1SIgor Ostapenko ///
958*257e70f1SIgor Ostapenko /// \return A reference to this builder.
959*257e70f1SIgor Ostapenko ///
960*257e70f1SIgor Ostapenko /// \throw model::error If the value is invalid.
961*257e70f1SIgor Ostapenko model::metadata_builder&
set_execenv_jail_params(const std::string & params)962*257e70f1SIgor Ostapenko model::metadata_builder::set_execenv_jail_params(const std::string& params)
963*257e70f1SIgor Ostapenko {
964*257e70f1SIgor Ostapenko set< config::string_node >(_pimpl->props, "execenv_jail_params", params);
965*257e70f1SIgor Ostapenko return *this;
966*257e70f1SIgor Ostapenko }
967*257e70f1SIgor Ostapenko
968*257e70f1SIgor Ostapenko
969b0d29bc4SBrooks Davis /// Sets whether the test has a cleanup part or not.
970b0d29bc4SBrooks Davis ///
971b0d29bc4SBrooks Davis /// \param cleanup True if the test has a cleanup part; false otherwise.
972b0d29bc4SBrooks Davis ///
973b0d29bc4SBrooks Davis /// \return A reference to this builder.
974b0d29bc4SBrooks Davis ///
975b0d29bc4SBrooks Davis /// \throw model::error If the value is invalid.
976b0d29bc4SBrooks Davis model::metadata_builder&
set_has_cleanup(const bool cleanup)977b0d29bc4SBrooks Davis model::metadata_builder::set_has_cleanup(const bool cleanup)
978b0d29bc4SBrooks Davis {
979b0d29bc4SBrooks Davis set< config::bool_node >(_pimpl->props, "has_cleanup", cleanup);
980b0d29bc4SBrooks Davis return *this;
981b0d29bc4SBrooks Davis }
982b0d29bc4SBrooks Davis
983b0d29bc4SBrooks Davis
984b0d29bc4SBrooks Davis /// Sets whether the test is exclusive or not.
985b0d29bc4SBrooks Davis ///
986b0d29bc4SBrooks Davis /// \param exclusive True if the test is exclusive; false otherwise.
987b0d29bc4SBrooks Davis ///
988b0d29bc4SBrooks Davis /// \return A reference to this builder.
989b0d29bc4SBrooks Davis ///
990b0d29bc4SBrooks Davis /// \throw model::error If the value is invalid.
991b0d29bc4SBrooks Davis model::metadata_builder&
set_is_exclusive(const bool exclusive)992b0d29bc4SBrooks Davis model::metadata_builder::set_is_exclusive(const bool exclusive)
993b0d29bc4SBrooks Davis {
994b0d29bc4SBrooks Davis set< config::bool_node >(_pimpl->props, "is_exclusive", exclusive);
995b0d29bc4SBrooks Davis return *this;
996b0d29bc4SBrooks Davis }
997b0d29bc4SBrooks Davis
998b0d29bc4SBrooks Davis
999b0d29bc4SBrooks Davis /// Sets the list of configuration variables needed by the test.
1000b0d29bc4SBrooks Davis ///
1001b0d29bc4SBrooks Davis /// \param vars Set of configuration variables.
1002b0d29bc4SBrooks Davis ///
1003b0d29bc4SBrooks Davis /// \return A reference to this builder.
1004b0d29bc4SBrooks Davis ///
1005b0d29bc4SBrooks Davis /// \throw model::error If the value is invalid.
1006b0d29bc4SBrooks Davis model::metadata_builder&
set_required_configs(const model::strings_set & vars)1007b0d29bc4SBrooks Davis model::metadata_builder::set_required_configs(const model::strings_set& vars)
1008b0d29bc4SBrooks Davis {
1009b0d29bc4SBrooks Davis set< config::strings_set_node >(_pimpl->props, "required_configs", vars);
1010b0d29bc4SBrooks Davis return *this;
1011b0d29bc4SBrooks Davis }
1012b0d29bc4SBrooks Davis
1013b0d29bc4SBrooks Davis
1014b0d29bc4SBrooks Davis /// Sets the amount of free disk space required by the test.
1015b0d29bc4SBrooks Davis ///
1016b0d29bc4SBrooks Davis /// \param bytes Number of bytes.
1017b0d29bc4SBrooks Davis ///
1018b0d29bc4SBrooks Davis /// \return A reference to this builder.
1019b0d29bc4SBrooks Davis ///
1020b0d29bc4SBrooks Davis /// \throw model::error If the value is invalid.
1021b0d29bc4SBrooks Davis model::metadata_builder&
set_required_disk_space(const units::bytes & bytes)1022b0d29bc4SBrooks Davis model::metadata_builder::set_required_disk_space(const units::bytes& bytes)
1023b0d29bc4SBrooks Davis {
1024b0d29bc4SBrooks Davis set< bytes_node >(_pimpl->props, "required_disk_space", bytes);
1025b0d29bc4SBrooks Davis return *this;
1026b0d29bc4SBrooks Davis }
1027b0d29bc4SBrooks Davis
1028b0d29bc4SBrooks Davis
1029b0d29bc4SBrooks Davis /// Sets the list of files needed by the test.
1030b0d29bc4SBrooks Davis ///
1031b0d29bc4SBrooks Davis /// \param files Set of paths.
1032b0d29bc4SBrooks Davis ///
1033b0d29bc4SBrooks Davis /// \return A reference to this builder.
1034b0d29bc4SBrooks Davis ///
1035b0d29bc4SBrooks Davis /// \throw model::error If the value is invalid.
1036b0d29bc4SBrooks Davis model::metadata_builder&
set_required_files(const model::paths_set & files)1037b0d29bc4SBrooks Davis model::metadata_builder::set_required_files(const model::paths_set& files)
1038b0d29bc4SBrooks Davis {
1039b0d29bc4SBrooks Davis set< paths_set_node >(_pimpl->props, "required_files", files);
1040b0d29bc4SBrooks Davis return *this;
1041b0d29bc4SBrooks Davis }
1042b0d29bc4SBrooks Davis
1043b0d29bc4SBrooks Davis
1044b0d29bc4SBrooks Davis /// Sets the amount of memory required by the test.
1045b0d29bc4SBrooks Davis ///
1046b0d29bc4SBrooks Davis /// \param bytes Number of bytes.
1047b0d29bc4SBrooks Davis ///
1048b0d29bc4SBrooks Davis /// \return A reference to this builder.
1049b0d29bc4SBrooks Davis ///
1050b0d29bc4SBrooks Davis /// \throw model::error If the value is invalid.
1051b0d29bc4SBrooks Davis model::metadata_builder&
set_required_memory(const units::bytes & bytes)1052b0d29bc4SBrooks Davis model::metadata_builder::set_required_memory(const units::bytes& bytes)
1053b0d29bc4SBrooks Davis {
1054b0d29bc4SBrooks Davis set< bytes_node >(_pimpl->props, "required_memory", bytes);
1055b0d29bc4SBrooks Davis return *this;
1056b0d29bc4SBrooks Davis }
1057b0d29bc4SBrooks Davis
1058b0d29bc4SBrooks Davis
1059b0d29bc4SBrooks Davis /// Sets the list of programs needed by the test.
1060b0d29bc4SBrooks Davis ///
1061b0d29bc4SBrooks Davis /// \param progs Set of paths.
1062b0d29bc4SBrooks Davis ///
1063b0d29bc4SBrooks Davis /// \return A reference to this builder.
1064b0d29bc4SBrooks Davis ///
1065b0d29bc4SBrooks Davis /// \throw model::error If the value is invalid.
1066b0d29bc4SBrooks Davis model::metadata_builder&
set_required_programs(const model::paths_set & progs)1067b0d29bc4SBrooks Davis model::metadata_builder::set_required_programs(const model::paths_set& progs)
1068b0d29bc4SBrooks Davis {
1069b0d29bc4SBrooks Davis set< paths_set_node >(_pimpl->props, "required_programs", progs);
1070b0d29bc4SBrooks Davis return *this;
1071b0d29bc4SBrooks Davis }
1072b0d29bc4SBrooks Davis
1073b0d29bc4SBrooks Davis
1074b0d29bc4SBrooks Davis /// Sets the user required by the test.
1075b0d29bc4SBrooks Davis ///
1076b0d29bc4SBrooks Davis /// \param user One of unprivileged, root or empty.
1077b0d29bc4SBrooks Davis ///
1078b0d29bc4SBrooks Davis /// \return A reference to this builder.
1079b0d29bc4SBrooks Davis ///
1080b0d29bc4SBrooks Davis /// \throw model::error If the value is invalid.
1081b0d29bc4SBrooks Davis model::metadata_builder&
set_required_user(const std::string & user)1082b0d29bc4SBrooks Davis model::metadata_builder::set_required_user(const std::string& user)
1083b0d29bc4SBrooks Davis {
1084b0d29bc4SBrooks Davis set< user_node >(_pimpl->props, "required_user", user);
1085b0d29bc4SBrooks Davis return *this;
1086b0d29bc4SBrooks Davis }
1087b0d29bc4SBrooks Davis
1088b0d29bc4SBrooks Davis
1089b0d29bc4SBrooks Davis /// Sets a metadata property by name from its textual representation.
1090b0d29bc4SBrooks Davis ///
1091b0d29bc4SBrooks Davis /// \param key The property to set.
1092b0d29bc4SBrooks Davis /// \param value The value to set the property to.
1093b0d29bc4SBrooks Davis ///
1094b0d29bc4SBrooks Davis /// \return A reference to this builder.
1095b0d29bc4SBrooks Davis ///
1096b0d29bc4SBrooks Davis /// \throw model::error If the value is invalid or the key does not exist.
1097b0d29bc4SBrooks Davis model::metadata_builder&
set_string(const std::string & key,const std::string & value)1098b0d29bc4SBrooks Davis model::metadata_builder::set_string(const std::string& key,
1099b0d29bc4SBrooks Davis const std::string& value)
1100b0d29bc4SBrooks Davis {
1101b0d29bc4SBrooks Davis try {
1102b0d29bc4SBrooks Davis _pimpl->props.set_string(key, value);
1103b0d29bc4SBrooks Davis } catch (const config::unknown_key_error& e) {
1104b0d29bc4SBrooks Davis throw model::format_error(F("Unknown metadata property %s") % key);
1105b0d29bc4SBrooks Davis } catch (const config::value_error& e) {
1106b0d29bc4SBrooks Davis throw model::format_error(
1107b0d29bc4SBrooks Davis F("Invalid value for metadata property %s: %s") % key % e.what());
1108b0d29bc4SBrooks Davis }
1109b0d29bc4SBrooks Davis return *this;
1110b0d29bc4SBrooks Davis }
1111b0d29bc4SBrooks Davis
1112b0d29bc4SBrooks Davis
1113b0d29bc4SBrooks Davis /// Sets the timeout of the test.
1114b0d29bc4SBrooks Davis ///
1115b0d29bc4SBrooks Davis /// \param timeout The timeout to set.
1116b0d29bc4SBrooks Davis ///
1117b0d29bc4SBrooks Davis /// \return A reference to this builder.
1118b0d29bc4SBrooks Davis ///
1119b0d29bc4SBrooks Davis /// \throw model::error If the value is invalid.
1120b0d29bc4SBrooks Davis model::metadata_builder&
set_timeout(const datetime::delta & timeout)1121b0d29bc4SBrooks Davis model::metadata_builder::set_timeout(const datetime::delta& timeout)
1122b0d29bc4SBrooks Davis {
1123b0d29bc4SBrooks Davis set< delta_node >(_pimpl->props, "timeout", timeout);
1124b0d29bc4SBrooks Davis return *this;
1125b0d29bc4SBrooks Davis }
1126b0d29bc4SBrooks Davis
1127b0d29bc4SBrooks Davis
1128b0d29bc4SBrooks Davis /// Creates a new metadata object.
1129b0d29bc4SBrooks Davis ///
1130b0d29bc4SBrooks Davis /// \pre This has not yet been called. We only support calling this function
1131b0d29bc4SBrooks Davis /// once due to the way the internal tree works: we pass around references, not
1132b0d29bc4SBrooks Davis /// deep copies, so if we allowed a second build, we'd encourage reusing the
1133b0d29bc4SBrooks Davis /// same builder to construct different metadata objects, and this could have
1134b0d29bc4SBrooks Davis /// unintended consequences.
1135b0d29bc4SBrooks Davis ///
1136b0d29bc4SBrooks Davis /// \return The constructed metadata object.
1137b0d29bc4SBrooks Davis model::metadata
build(void) const1138b0d29bc4SBrooks Davis model::metadata_builder::build(void) const
1139b0d29bc4SBrooks Davis {
1140b0d29bc4SBrooks Davis PRE(!_pimpl->built);
1141b0d29bc4SBrooks Davis _pimpl->built = true;
1142b0d29bc4SBrooks Davis
1143b0d29bc4SBrooks Davis return metadata(_pimpl->props);
1144b0d29bc4SBrooks Davis }
1145