switch to new MPL based Fraunhofer FOKUS Public License
[senf.git] / senf / Utils / Console / ConfigFile.test.cc
1 // $Id$
2 //
3 // Copyright (C) 2008
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 //
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at 
9 // http://senf.berlios.de/license.html
10 //
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on, 
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
14 //
15 // Software distributed under the License is distributed on an "AS IS" basis, 
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
17 // for the specific language governing rights and limitations under the License.
18 //
19 // The Original Code is Fraunhofer FOKUS code.
20 //
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V. 
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 // All Rights Reserved.
24 //
25 // Contributor(s):
26 //   Stefan Bund <g0dil@berlios.de>
27
28 /** \file
29     \brief ConfigFile unit tests */
30
31 //#include "ConfigFile.test.hh"
32 //#include "ConfigFile.test.ih"
33
34 // Custom includes
35 #include "Console.hh"
36 #include <fstream>
37 #include <boost/filesystem/operations.hpp>
38
39 #include <senf/Utils/auto_unit_test.hh>
40 #include <boost/test/test_tools.hpp>
41
42 #define prefix_
43 //-/////////////////////////////////////////////////////////////////////////////////////////////////
44
45 namespace {
46
47     int var1 (0);
48     bool var2 (false);
49
50     void fun1(int v) { var1 = v; }
51     void fun2() { var2 = true; }
52
53     class TempFile
54     {
55     public:
56         TempFile(std::string const & name) : name_ (name), file_ (name_.c_str()) {}
57         ~TempFile() { file_.close(); boost::filesystem::remove(name_); }
58
59         template <class T> TempFile & operator<<(T const & v) { file_ << v; return *this; }
60         enum Closer { close }; void operator<<(Closer) { file_.close(); }
61         std::string const & name() { return name_; }
62
63     private:
64         std::string name_;
65         std::ofstream file_;
66     };
67
68 }
69
70 #define SENF_CHECK_THROW_SYSTEMEXCEPTION( expr, errorNumber, msg)   \
71     try {                                                           \
72         BOOST_TEST_PASSPOINT();                                     \
73         expr;                                                       \
74         BOOST_ERROR( "senf::SystemException is expected");          \
75     } catch( senf::SystemException const & ex ) {                   \
76         BOOST_CHECK( ex.anyOf( errorNumber));                       \
77         BOOST_CHECK( ex.message().find(msg) != std::string::npos);  \
78     }                                                               \
79
80
81 SENF_AUTO_UNIT_TEST(configFile)
82 {
83     namespace fty = senf::console::factory;
84
85     TempFile cfgf ("test.cfg");
86     cfgf << "dir1/fun1 10;\n"
87          << TempFile::close;
88
89     senf::console::ScopedDirectory<> dir1;
90     senf::console::root().add("dir1", dir1);
91     dir1.add("fun1",fty::Command(&fun1));
92
93     {
94         senf::console::ConfigFile cfg (cfgf.name());
95
96         var1 = 0;
97         SENF_CHECK_NO_THROW( cfg.parse() );
98         BOOST_CHECK_EQUAL( var1, 10 );
99
100         var1 = 0;
101         SENF_CHECK_NO_THROW( cfg.parse() );
102         BOOST_CHECK_EQUAL( var1, 0 );
103
104         var1 = 0;
105         cfg.reset();
106         SENF_CHECK_NO_THROW( cfg.parse() );
107         BOOST_CHECK_EQUAL( var1, 10 );
108     }
109
110     {
111         senf::console::ConfigFile cfg ("i don't exist");
112         SENF_CHECK_THROW_SYSTEMEXCEPTION(cfg.parse(), ENOENT, "i don't exist");
113         cfg.ignoreMissing();
114         SENF_CHECK_NO_THROW( cfg.parse() );
115     }
116     {
117         std::string etc_shaddow ("/etc/shadow");
118         if (getuid() != 0 && boost::filesystem::exists(etc_shaddow)) {
119             senf::console::ConfigFile cfg (etc_shaddow);
120             SENF_CHECK_THROW_SYSTEMEXCEPTION( cfg.parse(), EACCES, etc_shaddow);
121         }
122     }
123 }
124
125 SENF_AUTO_UNIT_TEST(configFileRestrict)
126 {
127     namespace fty = senf::console::factory;
128
129     TempFile cfgf ("test.cfg");
130     cfgf << "dir1/fun1 10;\n"
131          << "dir2/fun2;\n"
132          << TempFile::close;
133
134     senf::console::ScopedDirectory<> dir1;
135     senf::console::root().add("dir1", dir1);
136     dir1.add("fun1",fty::Command(&fun1));
137
138     {
139         var1 = 0;
140         var2 = false;
141         senf::console::ConfigFile cfg (cfgf.name());
142         SENF_CHECK_NO_THROW( cfg.parse(dir1) );
143         BOOST_CHECK_EQUAL( var1, 10 );
144         BOOST_CHECK_EQUAL( var2, false );
145         BOOST_CHECK( cfg.parsed(dir1) );
146         BOOST_CHECK( ! cfg.complete() );
147
148         senf::console::ScopedDirectory<> dir2;
149         senf::console::root().add("dir2", dir2);
150         dir2.add("fun2",fty::Command(&fun2));
151
152         var1 = 0;
153         var2 = false;
154         SENF_CHECK_NO_THROW( cfg.parse() );
155         BOOST_CHECK_EQUAL( var1, 0 );
156         BOOST_CHECK_EQUAL( var2, true );
157         BOOST_CHECK( cfg.complete() );
158     }
159 }
160
161 SENF_AUTO_UNIT_TEST(configFileSkipGroup)
162 {
163     namespace fty = senf::console::factory;
164
165     TempFile cfgf ("test.cfg");
166     cfgf << "dir1/fun1 10;\n"
167          << "dir2 { dir3 { fun2; } fun1 5; }"
168          << TempFile::close;
169
170     senf::console::ScopedDirectory<> dir1;
171     senf::console::root().add("dir1", dir1);
172     dir1.add("fun1",fty::Command(&fun1));
173
174     senf::console::ScopedDirectory<> dir2;
175     senf::console::root().add("dir2", dir2);
176
177     dir2.add("dir3",fty::Directory()).add("fun2", fty::Command(&fun2));
178     dir2.add("fun1", fty::Command(&fun1));
179
180     {
181         var1 = 0;
182         var2 = false;
183         senf::console::ConfigFile cfg (cfgf.name());
184         SENF_CHECK_NO_THROW( cfg.parse(dir1) );
185         BOOST_CHECK_EQUAL( var1, 10 );
186         BOOST_CHECK_EQUAL( var2, false );
187         BOOST_CHECK( cfg.parsed(dir1) );
188
189         var1 = 0;
190         var2 = false;
191         SENF_CHECK_NO_THROW( cfg.parse(dir2["dir3"]) );
192         BOOST_CHECK_EQUAL( var1, 0 );
193         BOOST_CHECK_EQUAL( var2, true );
194         BOOST_CHECK( ! cfg.parsed(dir2) );
195
196         var1 = 0;
197         var2 = false;
198         SENF_CHECK_NO_THROW( cfg.parse() );
199         BOOST_CHECK_EQUAL( var1, 5 );
200         BOOST_CHECK_EQUAL( var2, false );
201     }
202 }
203
204 SENF_AUTO_UNIT_TEST(configRestrictAndLink)
205 {
206     namespace fty = senf::console::factory;
207
208     TempFile cfgf ("test.cfg");
209     cfgf << "dir1/fun1 10;\n"
210          << "link1 { dir3 { fun2; } fun1 5; }"
211          << TempFile::close;
212
213     senf::console::ScopedDirectory<> dir1;
214     senf::console::root().add("dir1", dir1);
215     dir1.add("fun1",fty::Command(&fun1));
216
217     senf::console::ScopedDirectory<> dir2;
218     dir1.add("dir2", dir2);
219
220     dir2.add("dir3",fty::Directory()).add("fun2", fty::Command(&fun2));
221     dir2.add("fun1", fty::Command(&fun1));
222
223     senf::console::ScopedDirectory<> dir4;
224     senf::console::root().add("dir4", dir4);
225     dir4.add("link1", fty::Link(dir2));
226
227     {
228         senf::console::ConfigFile cfg (cfgf.name(), dir4);
229
230         var1 = 0;
231         var2 = false;
232         SENF_CHECK_NO_THROW( cfg.parse(dir2["dir3"]) );
233         BOOST_CHECK_EQUAL( var1, 0 );
234         BOOST_CHECK_EQUAL( var2, true );
235
236         BOOST_CHECK_THROW( cfg.parse(), senf::console::SyntaxErrorException );
237     }
238 }
239
240 //-/////////////////////////////////////////////////////////////////////////////////////////////////
241 #undef prefix_
242
243 \f
244 // Local Variables:
245 // mode: c++
246 // fill-column: 100
247 // comment-column: 40
248 // c-file-style: "senf"
249 // indent-tabs-mode: nil
250 // ispell-local-dictionary: "american"
251 // compile-command: "scons -u test"
252 // End: