27835bf5fd055458a562702c370ba8c953bc26e2
[senf.git] / senf / Utils / Console / ConfigFile.test.cc
1 // $Id$
2 //
3 // Copyright (C) 2008
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 //     Stefan Bund <g0dil@berlios.de>
7 //
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
23 /** \file
24     \brief ConfigFile unit tests */
25
26 //#include "ConfigFile.test.hh"
27 //#include "ConfigFile.test.ih"
28
29 // Custom includes
30 #include "Console.hh"
31 #include <fstream>
32 #include <boost/filesystem/operations.hpp>
33
34 #include <senf/Utils/auto_unit_test.hh>
35 #include <boost/test/test_tools.hpp>
36
37 #define prefix_
38 //-/////////////////////////////////////////////////////////////////////////////////////////////////
39
40 namespace {
41
42     int var1 (0);
43     bool var2 (false);
44
45     void fun1(int v) { var1 = v; }
46     void fun2() { var2 = true; }
47
48     class TempFile
49     {
50     public:
51         TempFile(std::string const & name) : name_ (name), file_ (name_.c_str()) {}
52         ~TempFile() { file_.close(); boost::filesystem::remove(name_); }
53
54         template <class T> TempFile & operator<<(T const & v) { file_ << v; return *this; }
55         enum Closer { close }; void operator<<(Closer) { file_.close(); }
56         std::string const & name() { return name_; }
57
58     private:
59         std::string name_;
60         std::ofstream file_;
61     };
62
63 }
64
65 #define SENF_CHECK_THROW_SYSTEMEXCEPTION( expr, errorNumber, msg)   \
66     try {                                                           \
67         BOOST_TEST_PASSPOINT();                                     \
68         expr;                                                       \
69         BOOST_ERROR( "senf::SystemException is expected");          \
70     } catch( senf::SystemException const & ex ) {                   \
71         BOOST_CHECK( ex.anyOf( errorNumber));                       \
72         BOOST_CHECK( ex.message().find(msg) != std::string::npos);  \
73     }                                                               \
74
75
76 SENF_AUTO_UNIT_TEST(configFile)
77 {
78     namespace fty = senf::console::factory;
79
80     TempFile cfgf ("test.cfg");
81     cfgf << "dir1/fun1 10;\n"
82          << TempFile::close;
83
84     senf::console::ScopedDirectory<> dir1;
85     senf::console::root().add("dir1", dir1);
86     dir1.add("fun1",fty::Command(&fun1));
87
88     {
89         senf::console::ConfigFile cfg (cfgf.name());
90
91         var1 = 0;
92         SENF_CHECK_NO_THROW( cfg.parse() );
93         BOOST_CHECK_EQUAL( var1, 10 );
94
95         var1 = 0;
96         SENF_CHECK_NO_THROW( cfg.parse() );
97         BOOST_CHECK_EQUAL( var1, 0 );
98
99         var1 = 0;
100         cfg.reset();
101         SENF_CHECK_NO_THROW( cfg.parse() );
102         BOOST_CHECK_EQUAL( var1, 10 );
103     }
104
105     {
106         senf::console::ConfigFile cfg ("i don't exist");
107         SENF_CHECK_THROW_SYSTEMEXCEPTION(cfg.parse(), ENOENT, "i don't exist");
108         cfg.ignoreMissing();
109         SENF_CHECK_NO_THROW( cfg.parse() );
110     }
111     {
112         std::string etc_shaddow ("/etc/shadow");
113         if (getuid() != 0 && boost::filesystem::exists(etc_shaddow)) {
114             senf::console::ConfigFile cfg (etc_shaddow);
115             SENF_CHECK_THROW_SYSTEMEXCEPTION( cfg.parse(), EACCES, etc_shaddow);
116         }
117     }
118 }
119
120 SENF_AUTO_UNIT_TEST(configFileRestrict)
121 {
122     namespace fty = senf::console::factory;
123
124     TempFile cfgf ("test.cfg");
125     cfgf << "dir1/fun1 10;\n"
126          << "dir2/fun2;\n"
127          << TempFile::close;
128
129     senf::console::ScopedDirectory<> dir1;
130     senf::console::root().add("dir1", dir1);
131     dir1.add("fun1",fty::Command(&fun1));
132
133     {
134         var1 = 0;
135         var2 = false;
136         senf::console::ConfigFile cfg (cfgf.name());
137         SENF_CHECK_NO_THROW( cfg.parse(dir1) );
138         BOOST_CHECK_EQUAL( var1, 10 );
139         BOOST_CHECK_EQUAL( var2, false );
140         BOOST_CHECK( cfg.parsed(dir1) );
141         BOOST_CHECK( ! cfg.complete() );
142
143         senf::console::ScopedDirectory<> dir2;
144         senf::console::root().add("dir2", dir2);
145         dir2.add("fun2",fty::Command(&fun2));
146
147         var1 = 0;
148         var2 = false;
149         SENF_CHECK_NO_THROW( cfg.parse() );
150         BOOST_CHECK_EQUAL( var1, 0 );
151         BOOST_CHECK_EQUAL( var2, true );
152         BOOST_CHECK( cfg.complete() );
153     }
154 }
155
156 SENF_AUTO_UNIT_TEST(configFileSkipGroup)
157 {
158     namespace fty = senf::console::factory;
159
160     TempFile cfgf ("test.cfg");
161     cfgf << "dir1/fun1 10;\n"
162          << "dir2 { dir3 { fun2; } fun1 5; }"
163          << TempFile::close;
164
165     senf::console::ScopedDirectory<> dir1;
166     senf::console::root().add("dir1", dir1);
167     dir1.add("fun1",fty::Command(&fun1));
168
169     senf::console::ScopedDirectory<> dir2;
170     senf::console::root().add("dir2", dir2);
171
172     dir2.add("dir3",fty::Directory()).add("fun2", fty::Command(&fun2));
173     dir2.add("fun1", fty::Command(&fun1));
174
175     {
176         var1 = 0;
177         var2 = false;
178         senf::console::ConfigFile cfg (cfgf.name());
179         SENF_CHECK_NO_THROW( cfg.parse(dir1) );
180         BOOST_CHECK_EQUAL( var1, 10 );
181         BOOST_CHECK_EQUAL( var2, false );
182         BOOST_CHECK( cfg.parsed(dir1) );
183
184         var1 = 0;
185         var2 = false;
186         SENF_CHECK_NO_THROW( cfg.parse(dir2["dir3"]) );
187         BOOST_CHECK_EQUAL( var1, 0 );
188         BOOST_CHECK_EQUAL( var2, true );
189         BOOST_CHECK( ! cfg.parsed(dir2) );
190
191         var1 = 0;
192         var2 = false;
193         SENF_CHECK_NO_THROW( cfg.parse() );
194         BOOST_CHECK_EQUAL( var1, 5 );
195         BOOST_CHECK_EQUAL( var2, false );
196     }
197 }
198
199 SENF_AUTO_UNIT_TEST(configRestrictAndLink)
200 {
201     namespace fty = senf::console::factory;
202
203     TempFile cfgf ("test.cfg");
204     cfgf << "dir1/fun1 10;\n"
205          << "link1 { dir3 { fun2; } fun1 5; }"
206          << TempFile::close;
207
208     senf::console::ScopedDirectory<> dir1;
209     senf::console::root().add("dir1", dir1);
210     dir1.add("fun1",fty::Command(&fun1));
211
212     senf::console::ScopedDirectory<> dir2;
213     dir1.add("dir2", dir2);
214
215     dir2.add("dir3",fty::Directory()).add("fun2", fty::Command(&fun2));
216     dir2.add("fun1", fty::Command(&fun1));
217
218     senf::console::ScopedDirectory<> dir4;
219     senf::console::root().add("dir4", dir4);
220     dir4.add("link1", fty::Link(dir2));
221
222     {
223         senf::console::ConfigFile cfg (cfgf.name(), dir4);
224
225         var1 = 0;
226         var2 = false;
227         SENF_CHECK_NO_THROW( cfg.parse(dir2["dir3"]) );
228         BOOST_CHECK_EQUAL( var1, 0 );
229         BOOST_CHECK_EQUAL( var2, true );
230
231         BOOST_CHECK_THROW( cfg.parse(), senf::console::SyntaxErrorException );
232     }
233 }
234
235 //-/////////////////////////////////////////////////////////////////////////////////////////////////
236 #undef prefix_
237
238 \f
239 // Local Variables:
240 // mode: c++
241 // fill-column: 100
242 // comment-column: 40
243 // c-file-style: "senf"
244 // indent-tabs-mode: nil
245 // ispell-local-dictionary: "american"
246 // compile-command: "scons -u test"
247 // End: