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