Home | History | Annotate | Line # | Download | only in engine
      1  1.1   jmmv // Copyright 2010 Google Inc.
      2  1.1   jmmv // All rights reserved.
      3  1.1   jmmv //
      4  1.1   jmmv // Redistribution and use in source and binary forms, with or without
      5  1.1   jmmv // modification, are permitted provided that the following conditions are
      6  1.1   jmmv // met:
      7  1.1   jmmv //
      8  1.1   jmmv // * Redistributions of source code must retain the above copyright
      9  1.1   jmmv //   notice, this list of conditions and the following disclaimer.
     10  1.1   jmmv // * Redistributions in binary form must reproduce the above copyright
     11  1.1   jmmv //   notice, this list of conditions and the following disclaimer in the
     12  1.1   jmmv //   documentation and/or other materials provided with the distribution.
     13  1.1   jmmv // * Neither the name of Google Inc. nor the names of its contributors
     14  1.1   jmmv //   may be used to endorse or promote products derived from this software
     15  1.1   jmmv //   without specific prior written permission.
     16  1.1   jmmv //
     17  1.1   jmmv // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     18  1.1   jmmv // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     19  1.1   jmmv // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     20  1.1   jmmv // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     21  1.1   jmmv // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     22  1.1   jmmv // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     23  1.1   jmmv // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     24  1.1   jmmv // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     25  1.1   jmmv // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     26  1.1   jmmv // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     27  1.1   jmmv // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28  1.1   jmmv 
     29  1.1   jmmv #include "engine/config.hpp"
     30  1.1   jmmv 
     31  1.1   jmmv #if defined(HAVE_CONFIG_H)
     32  1.1   jmmv #   include "config.h"
     33  1.1   jmmv #endif
     34  1.1   jmmv 
     35  1.1   jmmv #include <stdexcept>
     36  1.1   jmmv 
     37  1.1   jmmv #include "engine/exceptions.hpp"
     38  1.1   jmmv #include "utils/config/exceptions.hpp"
     39  1.1   jmmv #include "utils/config/parser.hpp"
     40  1.1   jmmv #include "utils/config/tree.ipp"
     41  1.1   jmmv #include "utils/passwd.hpp"
     42  1.1   jmmv #include "utils/text/exceptions.hpp"
     43  1.1   jmmv #include "utils/text/operations.ipp"
     44  1.1   jmmv 
     45  1.1   jmmv namespace config = utils::config;
     46  1.1   jmmv namespace fs = utils::fs;
     47  1.1   jmmv namespace passwd = utils::passwd;
     48  1.1   jmmv namespace text = utils::text;
     49  1.1   jmmv 
     50  1.1   jmmv 
     51  1.1   jmmv namespace {
     52  1.1   jmmv 
     53  1.1   jmmv 
     54  1.1   jmmv /// Defines the schema of a configuration tree.
     55  1.1   jmmv ///
     56  1.1   jmmv /// \param [in,out] tree The tree to populate.  The tree should be empty on
     57  1.1   jmmv ///     entry to prevent collisions with the keys defined in here.
     58  1.1   jmmv static void
     59  1.1   jmmv init_tree(config::tree& tree)
     60  1.1   jmmv {
     61  1.1   jmmv     tree.define< config::string_node >("architecture");
     62  1.1   jmmv     tree.define< config::string_node >("platform");
     63  1.1   jmmv     tree.define< engine::user_node >("unprivileged_user");
     64  1.1   jmmv     tree.define_dynamic("test_suites");
     65  1.1   jmmv }
     66  1.1   jmmv 
     67  1.1   jmmv 
     68  1.1   jmmv /// Fills in a configuration tree with default values.
     69  1.1   jmmv ///
     70  1.1   jmmv /// \param [in,out] tree The tree to populate.  init_tree() must have been
     71  1.1   jmmv ///     called on it beforehand.
     72  1.1   jmmv static void
     73  1.1   jmmv set_defaults(config::tree& tree)
     74  1.1   jmmv {
     75  1.1   jmmv     tree.set< config::string_node >("architecture", KYUA_ARCHITECTURE);
     76  1.1   jmmv     tree.set< config::string_node >("platform", KYUA_PLATFORM);
     77  1.1   jmmv }
     78  1.1   jmmv 
     79  1.1   jmmv 
     80  1.1   jmmv /// Configuration parser specialization for Kyua configuration files.
     81  1.1   jmmv class config_parser : public config::parser {
     82  1.1   jmmv     /// Initializes the configuration tree.
     83  1.1   jmmv     ///
     84  1.1   jmmv     /// This is a callback executed when the configuration script invokes the
     85  1.1   jmmv     /// syntax() method.  We populate the configuration tree from here with the
     86  1.1   jmmv     /// schema version requested by the file.
     87  1.1   jmmv     ///
     88  1.1   jmmv     /// \param [in,out] tree The tree to populate.
     89  1.1   jmmv     /// \param syntax_version The version of the file format as specified in the
     90  1.1   jmmv     ///     configuration file.
     91  1.1   jmmv     ///
     92  1.1   jmmv     /// \throw config::syntax_error If the syntax_format/syntax_version
     93  1.1   jmmv     /// combination is not supported.
     94  1.1   jmmv     void
     95  1.1   jmmv     setup(config::tree& tree, const int syntax_version)
     96  1.1   jmmv     {
     97  1.1   jmmv         if (syntax_version < 1 || syntax_version > 2)
     98  1.1   jmmv             throw config::syntax_error(F("Unsupported config version %s") %
     99  1.1   jmmv                                        syntax_version);
    100  1.1   jmmv 
    101  1.1   jmmv         init_tree(tree);
    102  1.1   jmmv         set_defaults(tree);
    103  1.1   jmmv     }
    104  1.1   jmmv 
    105  1.1   jmmv public:
    106  1.1   jmmv     /// Initializes the parser.
    107  1.1   jmmv     ///
    108  1.1   jmmv     /// \param [out] tree_ The tree in which the results of the parsing will be
    109  1.1   jmmv     ///     stored when parse() is called.  Should be empty on entry.  Because
    110  1.1   jmmv     ///     we grab a reference to this object, the tree must remain valid for
    111  1.1   jmmv     ///     the existence of the parser object.
    112  1.1   jmmv     explicit config_parser(config::tree& tree_) :
    113  1.1   jmmv         config::parser(tree_)
    114  1.1   jmmv     {
    115  1.1   jmmv     }
    116  1.1   jmmv };
    117  1.1   jmmv 
    118  1.1   jmmv 
    119  1.1   jmmv }  // anonymous namespace
    120  1.1   jmmv 
    121  1.1   jmmv 
    122  1.1   jmmv /// Copies the node.
    123  1.1   jmmv ///
    124  1.1   jmmv /// \return A dynamically-allocated node.
    125  1.1   jmmv config::detail::base_node*
    126  1.1   jmmv engine::user_node::deep_copy(void) const
    127  1.1   jmmv {
    128  1.2  lukem     std::unique_ptr< user_node > new_node(new user_node());
    129  1.1   jmmv     new_node->_value = _value;
    130  1.1   jmmv     return new_node.release();
    131  1.1   jmmv }
    132  1.1   jmmv 
    133  1.1   jmmv 
    134  1.1   jmmv /// Pushes the node's value onto the Lua stack.
    135  1.1   jmmv ///
    136  1.1   jmmv /// \param state The Lua state onto which to push the value.
    137  1.1   jmmv void
    138  1.1   jmmv engine::user_node::push_lua(lutok::state& state) const
    139  1.1   jmmv {
    140  1.1   jmmv     state.push_string(value().name);
    141  1.1   jmmv }
    142  1.1   jmmv 
    143  1.1   jmmv 
    144  1.1   jmmv /// Sets the value of the node from an entry in the Lua stack.
    145  1.1   jmmv ///
    146  1.1   jmmv /// \param state The Lua state from which to get the value.
    147  1.1   jmmv /// \param value_index The stack index in which the value resides.
    148  1.1   jmmv ///
    149  1.1   jmmv /// \throw value_error If the value in state(value_index) cannot be
    150  1.1   jmmv ///     processed by this node.
    151  1.1   jmmv void
    152  1.1   jmmv engine::user_node::set_lua(lutok::state& state, const int value_index)
    153  1.1   jmmv {
    154  1.1   jmmv     if (state.is_number(value_index)) {
    155  1.1   jmmv         config::typed_leaf_node< passwd::user >::set(
    156  1.1   jmmv             passwd::find_user_by_uid(state.to_integer(-1)));
    157  1.1   jmmv     } else if (state.is_string(value_index)) {
    158  1.1   jmmv         config::typed_leaf_node< passwd::user >::set(
    159  1.1   jmmv             passwd::find_user_by_name(state.to_string(-1)));
    160  1.1   jmmv     } else
    161  1.1   jmmv         throw config::value_error("Invalid user identifier");
    162  1.1   jmmv }
    163  1.1   jmmv 
    164  1.1   jmmv 
    165  1.1   jmmv void
    166  1.1   jmmv engine::user_node::set_string(const std::string& raw_value)
    167  1.1   jmmv {
    168  1.1   jmmv     try {
    169  1.1   jmmv         config::typed_leaf_node< passwd::user >::set(
    170  1.1   jmmv             passwd::find_user_by_name(raw_value));
    171  1.1   jmmv     } catch (const std::runtime_error& e) {
    172  1.1   jmmv         int uid;
    173  1.1   jmmv         try {
    174  1.1   jmmv             uid = text::to_type< int >(raw_value);
    175  1.1   jmmv         } catch (const text::value_error& e2) {
    176  1.1   jmmv             throw error(F("Cannot find user with name '%s'") % raw_value);
    177  1.1   jmmv         }
    178  1.1   jmmv 
    179  1.1   jmmv         try {
    180  1.1   jmmv             config::typed_leaf_node< passwd::user >::set(
    181  1.1   jmmv                 passwd::find_user_by_uid(uid));
    182  1.1   jmmv         } catch (const std::runtime_error& e2) {
    183  1.1   jmmv             throw error(F("Cannot find user with UID %s") % uid);
    184  1.1   jmmv         }
    185  1.1   jmmv     }
    186  1.1   jmmv }
    187  1.1   jmmv 
    188  1.1   jmmv 
    189  1.1   jmmv std::string
    190  1.1   jmmv engine::user_node::to_string(void) const
    191  1.1   jmmv {
    192  1.1   jmmv     return config::typed_leaf_node< passwd::user >::value().name;
    193  1.1   jmmv }
    194  1.1   jmmv 
    195  1.1   jmmv 
    196  1.1   jmmv /// Constructs a config with the built-in settings.
    197  1.1   jmmv config::tree
    198  1.1   jmmv engine::default_config(void)
    199  1.1   jmmv {
    200  1.1   jmmv     config::tree tree;
    201  1.1   jmmv     init_tree(tree);
    202  1.1   jmmv     set_defaults(tree);
    203  1.1   jmmv     return tree;
    204  1.1   jmmv }
    205  1.1   jmmv 
    206  1.1   jmmv 
    207  1.1   jmmv /// Constructs a config with the built-in settings.
    208  1.1   jmmv config::tree
    209  1.1   jmmv engine::empty_config(void)
    210  1.1   jmmv {
    211  1.1   jmmv     config::tree tree;
    212  1.1   jmmv     init_tree(tree);
    213  1.1   jmmv     return tree;
    214  1.1   jmmv }
    215  1.1   jmmv 
    216  1.1   jmmv 
    217  1.1   jmmv /// Parses a test suite configuration file.
    218  1.1   jmmv ///
    219  1.1   jmmv /// \param file The file to parse.
    220  1.1   jmmv ///
    221  1.1   jmmv /// \return High-level representation of the configuration file.
    222  1.1   jmmv ///
    223  1.1   jmmv /// \throw load_error If there is any problem loading the file.  This includes
    224  1.1   jmmv ///     file access errors and syntax errors.
    225  1.1   jmmv config::tree
    226  1.1   jmmv engine::load_config(const utils::fs::path& file)
    227  1.1   jmmv {
    228  1.1   jmmv     config::tree tree;
    229  1.1   jmmv     try {
    230  1.1   jmmv         config_parser(tree).parse(file);
    231  1.1   jmmv     } catch (const config::error& e) {
    232  1.1   jmmv         throw load_error(file, e.what());
    233  1.1   jmmv     }
    234  1.1   jmmv     return tree;
    235  1.1   jmmv }
    236