Console: Replace Executor cwd handling with explicit path handling
[senf.git] / Console / Parse.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 Parse.test unit tests */
25
26 //#include "Parse.test.hh"
27 //#include "Parse.test.ih"
28
29 // #define BOOST_SPIRIT_DEBUG
30 // #define BOOST_SPIRIT_DEBUG_TRACENODE 0
31
32 // Custom includes
33 #include <sstream>
34 #include "Parse.hh"
35 #include "Parse.ih"
36 #include "../Utils/String.hh"
37
38 #include "../Utils/auto_unit_test.hh"
39 #include <boost/test/test_tools.hpp>
40
41 #define prefix_
42 ///////////////////////////////cc.p////////////////////////////////////////
43
44 namespace 
45 {
46     struct TestParseDispatcher 
47     {
48         TestParseDispatcher(std::ostream & os) : os_ (os) {}
49
50         std::ostream & os_;
51
52         void pushDirectory(std::vector<senf::console::Token> const & path)
53             { os_ << "pushDirectory( " << senf::stringJoin(path, "/") << " )\n"; }
54         void popDirectory()
55             { os_ << "popDirectory()\n"; }
56
57         void beginCommand(std::vector<senf::console::Token> const & command) 
58             { os_ << "beginCommand( " << senf::stringJoin(command, "/") << " )\n"; }
59         void endCommand() 
60             { os_ << "endCommand()\n"; }
61         
62         void pushToken(senf::console::Token token)
63             { os_ << "pushToken( " << token << " )\n"; }
64
65         void builtin_cd(std::vector<senf::console::Token> const & path)
66             { os_ << "builtin_cd( " << senf::stringJoin(path, "/") << " )\n"; }
67         void builtin_ls(std::vector<senf::console::Token> const & path)
68             { os_ << "builtin_ls( " << senf::stringJoin(path, "/") << " )\n"; }
69         void builtin_exit()
70             { os_ << "builtin_exit()\n"; }
71         void builtin_help(std::vector<senf::console::Token> const & path)
72             { os_ << "builtin_help( " << senf::stringJoin(path, "/") << " )\n"; }
73     };
74 }
75
76 BOOST_AUTO_UNIT_TEST(commandGrammar)
77 {
78     senf::console::detail::CommandGrammar<TestParseDispatcher>::Context context;
79     std::stringstream ss;
80     TestParseDispatcher dispatcher (ss);
81     
82     typedef senf::console::detail::CommandGrammar<TestParseDispatcher> Grammar;
83     Grammar grammar (dispatcher, context);
84
85     char text[] = 
86         "# Comment\n"
87         "doo / bii / doo arg"
88         "                flab::blub"
89         "                123.434>a"
90         "                (a,b;c (huhu/{haha}))"
91         "                \"foo\\\"bar\" #\n"
92         "                x\"01 02 # Inner comment\n"
93         "                   0304\";"
94         "ls /foo/bar;"
95         "cd /foo/bar;"
96         "exit;"
97         "foo/bar/ { ls; }"
98         "help /foo/bar";
99
100     BOOST_CHECK( boost::spirit::parse( 
101                      text, 
102                      grammar.use_parser<Grammar::CommandParser>(), 
103                      grammar.use_parser<Grammar::SkipParser>() ) . full );
104     BOOST_CHECK_EQUAL( ss.str(), 
105                        "beginCommand( Word('doo')/Word('bii')/Word('doo') )\n"
106                        "pushToken( Word('arg') )\n"
107                        "pushToken( Word('flab::blub') )\n"
108                        "pushToken( Word('123.434>a') )\n"
109                        "pushToken( ArgumentGroupOpen('(') )\n"
110                        "pushToken( Word('a') )\n"
111                        "pushToken( OtherPunctuation(',') )\n"
112                        "pushToken( Word('b') )\n"
113                        "pushToken( CommandTerminator(';') )\n"
114                        "pushToken( Word('c') )\n"
115                        "pushToken( ArgumentGroupOpen('(') )\n"
116                        "pushToken( Word('huhu') )\n"
117                        "pushToken( PathSeparator('/') )\n"
118                        "pushToken( DirectoryGroupOpen('{') )\n"
119                        "pushToken( Word('haha') )\n"
120                        "pushToken( DirectoryGroupClose('}') )\n"
121                        "pushToken( ArgumentGroupClose(')') )\n"
122                        "pushToken( ArgumentGroupClose(')') )\n"
123                        "pushToken( BasicString('foo\"bar') )\n"
124                        "pushToken( HexString('\x01\x02\x03\x04') )\n"
125                        "endCommand()\n"
126                        "builtin_ls( None('')/Word('foo')/Word('bar') )\n"
127                        "builtin_cd( None('')/Word('foo')/Word('bar') )\n"
128                        "builtin_exit()\n"
129                        "pushDirectory( Word('foo')/Word('bar')/None('') )\n"
130                        "builtin_ls(  )\n"
131                        "popDirectory()\n"
132                        "builtin_help( None('')/Word('foo')/Word('bar') )\n" );
133 }
134
135 namespace {
136     senf::console::ParseCommandInfo info;
137     void setInfo(senf::console::ParseCommandInfo const & i)
138     { info = i; }
139 }
140
141 BOOST_AUTO_UNIT_TEST(commandParser)
142 {
143     senf::console::CommandParser parser;
144
145     char const text[] = 
146         "# Comment\n"
147         "doo / bii / doo arg"
148         "                flab::blub"
149         "                123.434>a"
150         "                (a,b,c (huhu))"
151         "                \"foo\\\"bar\" #\n"
152         "                x\"01 02 # Inner comment\n"
153         "                   0304\"";
154
155     BOOST_CHECK( parser.parse(text, &setInfo) );
156
157     senf::console::Token path[] = { 
158         senf::console::Token(senf::console::Token::Word, "doo"), 
159         senf::console::Token(senf::console::Token::Word, "bii"),
160         senf::console::Token(senf::console::Token::Word, "doo")
161     };
162
163     BOOST_CHECK_EQUAL_COLLECTIONS( info.commandPath().begin(), info.commandPath().end(),
164                                    path, path + sizeof(path)/sizeof(path[0]) );
165     BOOST_CHECK_EQUAL( info.tokens().size(), 15u );
166
167     char const * tokens[] = { "arg", 
168                               "flab::blub", 
169                               "123.434>a", 
170                               "(", "a", ",", "b", ",", "c", "(", "huhu", ")", ")",
171                               "foo\"bar",
172                               "\x01\x02\x03\x04" };
173
174     senf::console::ParseCommandInfo::argument_iterator args (info.arguments().begin());
175     BOOST_REQUIRE( args != info.arguments().end() );
176     BOOST_REQUIRE_EQUAL( args->size(), 1u );
177     BOOST_CHECK_EQUAL( args->begin()->value(), tokens[0] );
178
179     ++ args;
180     BOOST_REQUIRE( args != info.arguments().end() );
181     BOOST_REQUIRE_EQUAL( args->size(), 1u );
182     BOOST_CHECK_EQUAL( args->begin()->value(), tokens[1] );
183                          
184     ++ args;
185     BOOST_REQUIRE( args != info.arguments().end() );
186     BOOST_REQUIRE_EQUAL( args->size(), 1u );
187     BOOST_CHECK_EQUAL( args->begin()->value(), tokens[2] );
188
189     ++ args;
190     BOOST_REQUIRE( args != info.arguments().end() );
191     BOOST_REQUIRE_EQUAL( args->size(), 8u );
192     for (unsigned i (0); i<8; ++i)
193         BOOST_CHECK_EQUAL( args->begin()[i].value(), tokens[4+i] );
194
195     ++ args;
196     BOOST_REQUIRE( args != info.arguments().end() );
197     BOOST_REQUIRE_EQUAL( args->size(), 1u );
198     BOOST_CHECK_EQUAL( args->begin()->value(), tokens[13] );
199
200     ++ args;
201     BOOST_REQUIRE( args != info.arguments().end() );
202     BOOST_REQUIRE_EQUAL( args->size(), 1u );
203     BOOST_CHECK_EQUAL( args->begin()->value(), tokens[14] );
204
205     ++ args;
206     BOOST_CHECK( args == info.arguments().end() );
207 }
208
209 namespace {
210     void parseArgs(senf::console::ParseCommandInfo::ArgumentsRange const & args)
211     {
212         senf::console::CheckedArgumentIteratorWrapper arg (args);
213         senf::console::ParseCommandInfo::TokensRange arg1 (*(arg++));
214         senf::console::ParseCommandInfo::TokensRange arg2 (*(arg++));
215     }
216 }
217
218 BOOST_AUTO_UNIT_TEST(checkedArgumentIterator)
219 {
220     senf::console::CommandParser parser;
221
222     BOOST_CHECK( parser.parse("foo a", &setInfo) );
223     BOOST_CHECK_THROW( parseArgs(info.arguments()), senf::console::SyntaxErrorException );
224
225     BOOST_CHECK( parser.parse("foo a b", &setInfo) );
226     BOOST_CHECK_NO_THROW( parseArgs(info.arguments()) );
227
228     BOOST_CHECK( parser.parse("foo a b c", &setInfo) );
229     BOOST_CHECK_THROW( parseArgs(info.arguments()), senf::console::SyntaxErrorException );
230     
231     senf::console::CheckedArgumentIteratorWrapper arg (info.arguments());
232     BOOST_CHECK( arg == info.arguments().begin() );
233     BOOST_CHECK( arg != info.arguments().end() );
234     BOOST_CHECK( arg );
235     ++ arg;
236     BOOST_CHECK( arg );
237     arg.clear();
238     BOOST_CHECK( arg.done() );
239
240     senf::console::ParseCommandInfo::ArgumentIterator i (arg);
241     BOOST_CHECK( i == info.arguments().end() );
242 }
243
244 ///////////////////////////////cc.e////////////////////////////////////////
245 #undef prefix_
246
247 \f
248 // Local Variables:
249 // mode: c++
250 // fill-column: 100
251 // comment-column: 40
252 // c-file-style: "senf"
253 // indent-tabs-mode: nil
254 // ispell-local-dictionary: "american"
255 // compile-command: "scons -u test"
256 // End: