Home | History | Annotate | Line # | Download | only in tools
      1  1.1  jmmv //
      2  1.1  jmmv // Automated Testing Framework (atf)
      3  1.1  jmmv //
      4  1.1  jmmv // Copyright (c) 2007 The NetBSD Foundation, Inc.
      5  1.1  jmmv // All rights reserved.
      6  1.1  jmmv //
      7  1.1  jmmv // Redistribution and use in source and binary forms, with or without
      8  1.1  jmmv // modification, are permitted provided that the following conditions
      9  1.1  jmmv // are met:
     10  1.1  jmmv // 1. Redistributions of source code must retain the above copyright
     11  1.1  jmmv //    notice, this list of conditions and the following disclaimer.
     12  1.1  jmmv // 2. Redistributions in binary form must reproduce the above copyright
     13  1.1  jmmv //    notice, this list of conditions and the following disclaimer in the
     14  1.1  jmmv //    documentation and/or other materials provided with the distribution.
     15  1.1  jmmv //
     16  1.1  jmmv // THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
     17  1.1  jmmv // CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
     18  1.1  jmmv // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     19  1.1  jmmv // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     20  1.1  jmmv // IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
     21  1.1  jmmv // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     22  1.1  jmmv // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     23  1.1  jmmv // GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     24  1.1  jmmv // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
     25  1.1  jmmv // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     26  1.1  jmmv // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     27  1.1  jmmv // IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28  1.1  jmmv //
     29  1.1  jmmv 
     30  1.1  jmmv #include <cstdlib>
     31  1.1  jmmv #include <fstream>
     32  1.1  jmmv #include <vector>
     33  1.1  jmmv 
     34  1.1  jmmv #include "config.hpp"
     35  1.1  jmmv #include "config_file.hpp"
     36  1.1  jmmv #include "env.hpp"
     37  1.1  jmmv #include "fs.hpp"
     38  1.1  jmmv #include "parser.hpp"
     39  1.1  jmmv 
     40  1.1  jmmv namespace impl = tools::config_file;
     41  1.1  jmmv namespace detail = tools::config_file::detail;
     42  1.1  jmmv 
     43  1.1  jmmv namespace {
     44  1.1  jmmv 
     45  1.1  jmmv typedef std::map< std::string, std::string > vars_map;
     46  1.1  jmmv 
     47  1.1  jmmv namespace atf_config {
     48  1.1  jmmv 
     49  1.1  jmmv static const tools::parser::token_type eof_type = 0;
     50  1.1  jmmv static const tools::parser::token_type nl_type = 1;
     51  1.1  jmmv static const tools::parser::token_type text_type = 2;
     52  1.1  jmmv static const tools::parser::token_type dblquote_type = 3;
     53  1.1  jmmv static const tools::parser::token_type equal_type = 4;
     54  1.1  jmmv static const tools::parser::token_type hash_type = 5;
     55  1.1  jmmv 
     56  1.1  jmmv class tokenizer : public tools::parser::tokenizer< std::istream > {
     57  1.1  jmmv public:
     58  1.1  jmmv     tokenizer(std::istream& is, size_t curline) :
     59  1.1  jmmv         tools::parser::tokenizer< std::istream >
     60  1.1  jmmv             (is, true, eof_type, nl_type, text_type, curline)
     61  1.1  jmmv     {
     62  1.1  jmmv         add_delim('=', equal_type);
     63  1.1  jmmv         add_delim('#', hash_type);
     64  1.1  jmmv         add_quote('"', dblquote_type);
     65  1.1  jmmv     }
     66  1.1  jmmv };
     67  1.1  jmmv 
     68  1.1  jmmv } // namespace atf_config
     69  1.1  jmmv 
     70  1.1  jmmv class config_reader : public detail::atf_config_reader {
     71  1.1  jmmv     vars_map m_vars;
     72  1.1  jmmv 
     73  1.1  jmmv     void
     74  1.1  jmmv     got_var(const std::string& var, const std::string& name)
     75  1.1  jmmv     {
     76  1.1  jmmv         m_vars[var] = name;
     77  1.1  jmmv     }
     78  1.1  jmmv 
     79  1.1  jmmv public:
     80  1.1  jmmv     config_reader(std::istream& is) :
     81  1.1  jmmv         atf_config_reader(is)
     82  1.1  jmmv     {
     83  1.1  jmmv     }
     84  1.1  jmmv 
     85  1.1  jmmv     const vars_map&
     86  1.1  jmmv     get_vars(void)
     87  1.1  jmmv         const
     88  1.1  jmmv     {
     89  1.1  jmmv         return m_vars;
     90  1.1  jmmv     }
     91  1.1  jmmv };
     92  1.1  jmmv 
     93  1.1  jmmv template< class K, class V >
     94  1.1  jmmv static
     95  1.1  jmmv void
     96  1.1  jmmv merge_maps(std::map< K, V >& dest, const std::map< K, V >& src)
     97  1.1  jmmv {
     98  1.1  jmmv     for (typename std::map< K, V >::const_iterator iter = src.begin();
     99  1.1  jmmv          iter != src.end(); iter++)
    100  1.1  jmmv         dest[(*iter).first] = (*iter).second;
    101  1.1  jmmv }
    102  1.1  jmmv 
    103  1.1  jmmv static
    104  1.1  jmmv void
    105  1.1  jmmv merge_config_file(const tools::fs::path& config_path,
    106  1.1  jmmv                   vars_map& config)
    107  1.1  jmmv {
    108  1.1  jmmv     std::ifstream is(config_path.c_str());
    109  1.1  jmmv     if (is) {
    110  1.1  jmmv         config_reader reader(is);
    111  1.1  jmmv         reader.read();
    112  1.1  jmmv         merge_maps(config, reader.get_vars());
    113  1.1  jmmv     }
    114  1.1  jmmv }
    115  1.1  jmmv 
    116  1.1  jmmv static
    117  1.1  jmmv std::vector< tools::fs::path >
    118  1.1  jmmv get_config_dirs(void)
    119  1.1  jmmv {
    120  1.1  jmmv     std::vector< tools::fs::path > dirs;
    121  1.1  jmmv     dirs.push_back(tools::fs::path(tools::config::get("atf_confdir")));
    122  1.1  jmmv     if (tools::env::has("HOME"))
    123  1.1  jmmv         dirs.push_back(tools::fs::path(tools::env::get("HOME")) / ".atf");
    124  1.1  jmmv     return dirs;
    125  1.1  jmmv }
    126  1.1  jmmv 
    127  1.1  jmmv } // anonymous namespace
    128  1.1  jmmv 
    129  1.1  jmmv detail::atf_config_reader::atf_config_reader(std::istream& is) :
    130  1.1  jmmv     m_is(is)
    131  1.1  jmmv {
    132  1.1  jmmv }
    133  1.1  jmmv 
    134  1.1  jmmv detail::atf_config_reader::~atf_config_reader(void)
    135  1.1  jmmv {
    136  1.1  jmmv }
    137  1.1  jmmv 
    138  1.1  jmmv void
    139  1.1  jmmv detail::atf_config_reader::got_var(
    140  1.2  jmmv     const std::string& var __attribute__((__unused__)),
    141  1.2  jmmv     const std::string& val __attribute__((__unused__)))
    142  1.1  jmmv {
    143  1.1  jmmv }
    144  1.1  jmmv 
    145  1.1  jmmv void
    146  1.1  jmmv detail::atf_config_reader::got_eof(void)
    147  1.1  jmmv {
    148  1.1  jmmv }
    149  1.1  jmmv 
    150  1.1  jmmv void
    151  1.1  jmmv detail::atf_config_reader::read(void)
    152  1.1  jmmv {
    153  1.1  jmmv     using tools::parser::parse_error;
    154  1.1  jmmv     using namespace atf_config;
    155  1.1  jmmv 
    156  1.1  jmmv     std::pair< size_t, tools::parser::headers_map > hml =
    157  1.1  jmmv         tools::parser::read_headers(m_is, 1);
    158  1.1  jmmv     tools::parser::validate_content_type(hml.second,
    159  1.1  jmmv         "application/X-atf-config", 1);
    160  1.1  jmmv 
    161  1.1  jmmv     tokenizer tkz(m_is, hml.first);
    162  1.1  jmmv     tools::parser::parser< tokenizer > p(tkz);
    163  1.1  jmmv 
    164  1.1  jmmv     for (;;) {
    165  1.1  jmmv         try {
    166  1.1  jmmv             tools::parser::token t = p.expect(eof_type, hash_type, text_type,
    167  1.1  jmmv                                               nl_type,
    168  1.1  jmmv                                               "eof, #, new line or text");
    169  1.1  jmmv             if (t.type() == eof_type)
    170  1.1  jmmv                 break;
    171  1.1  jmmv 
    172  1.1  jmmv             if (t.type() == hash_type) {
    173  1.1  jmmv                 (void)p.rest_of_line();
    174  1.1  jmmv                 t = p.expect(nl_type, "new line");
    175  1.1  jmmv             } else if (t.type() == text_type) {
    176  1.1  jmmv                 std::string name = t.text();
    177  1.1  jmmv 
    178  1.1  jmmv                 t = p.expect(equal_type, "equal sign");
    179  1.1  jmmv 
    180  1.1  jmmv                 t = p.expect(text_type, "word or quoted string");
    181  1.1  jmmv                 ATF_PARSER_CALLBACK(p, got_var(name, t.text()));
    182  1.1  jmmv 
    183  1.1  jmmv                 t = p.expect(nl_type, hash_type, "new line or comment");
    184  1.1  jmmv                 if (t.type() == hash_type) {
    185  1.1  jmmv                     (void)p.rest_of_line();
    186  1.1  jmmv                     t = p.expect(nl_type, "new line");
    187  1.1  jmmv                 }
    188  1.1  jmmv             } else if (t.type() == nl_type) {
    189  1.1  jmmv             } else
    190  1.1  jmmv                 std::abort();
    191  1.1  jmmv         } catch (const parse_error& pe) {
    192  1.1  jmmv             p.add_error(pe);
    193  1.1  jmmv             p.reset(nl_type);
    194  1.1  jmmv         }
    195  1.1  jmmv     }
    196  1.1  jmmv 
    197  1.1  jmmv     ATF_PARSER_CALLBACK(p, got_eof());
    198  1.1  jmmv }
    199  1.1  jmmv 
    200  1.1  jmmv vars_map
    201  1.1  jmmv impl::merge_configs(const vars_map& lower,
    202  1.1  jmmv                     const vars_map& upper)
    203  1.1  jmmv {
    204  1.1  jmmv     vars_map merged = lower;
    205  1.1  jmmv     merge_maps(merged, upper);
    206  1.1  jmmv     return merged;
    207  1.1  jmmv }
    208  1.1  jmmv 
    209  1.1  jmmv vars_map
    210  1.1  jmmv impl::read_config_files(const std::string& test_suite_name)
    211  1.1  jmmv {
    212  1.1  jmmv     vars_map config;
    213  1.1  jmmv 
    214  1.1  jmmv     const std::vector< tools::fs::path > dirs = get_config_dirs();
    215  1.1  jmmv     for (std::vector< tools::fs::path >::const_iterator iter = dirs.begin();
    216  1.1  jmmv          iter != dirs.end(); iter++) {
    217  1.1  jmmv         merge_config_file((*iter) / "common.conf", config);
    218  1.1  jmmv         merge_config_file((*iter) / (test_suite_name + ".conf"), config);
    219  1.1  jmmv     }
    220  1.1  jmmv 
    221  1.1  jmmv     return config;
    222  1.1  jmmv }
    223