source: anotherchoice/tags/jsp-1.4.4-full-UTF8/cfg/base/clause.cpp@ 26

Last change on this file since 26 was 26, checked in by ykominami, 12 years ago

initial

File size: 33.9 KB
Line 
1/*
2 * TOPPERS/JSP Kernel
3 * Toyohashi Open Platform for Embedded Real-Time Systems/
4 * Just Standard Profile Kernel
5 *
6 * Copyright (C) 2003 by Embedded and Real-Time Systems Laboratory
7 * Toyohashi Univ. of Technology, JAPAN
8 *
9 * 上記著作権者
10は,以下の (1)〜(4) の条件か,Free Software Foundation
11 * によってå…
12¬è¡¨ã•ã‚Œã¦ã„ã‚‹ GNU General Public License の Version 2 に記
13 * 述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
14 * を改変したものを含む.以下同じ)を使用・複製・改変・再é…
15å¸ƒï¼ˆä»¥ä¸‹ï¼Œ
16 * 利用と呼ぶ)することを無償で許諾する.
17 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
18 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
19 * スコード中に含まれていること.
20 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
21 * 用できる形で再é…
22å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œå†é…
23å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨
24 * 者
25マニュアルなど)に,上記の著作権表示,この利用条件および下記
26 * の無保証規定を掲載すること.
27 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
28 * 用できない形で再é…
29å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œæ¬¡ã®ã„ずれかの条件を満たすこ
30 * と.
31 * (a) 再é…
32å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨è€…
33マニュアルなど)に,上記の著
34 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
35 * (b) 再é…
36å¸ƒã®å½¢æ…
37‹ã‚’,別に定める方法によって,TOPPERSプロジェクトに
38 * 報告すること.
39 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
40 * 害からも,上記著作権者
41およびTOPPERSプロジェクトをå…
42è²¬ã™ã‚‹ã“と.
43 *
44 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者
45お
46 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
47 * 含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
48 * 接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
49 *
50 * @(#) $Id: clause.cpp,v 1.3 2003/12/15 07:32:13 takayuki Exp $
51 */
52
53// $Header: /home/CVS/configurator/base/clause.cpp,v 1.3 2003/12/15 07:32:13 takayuki Exp $
54
55#include "base/clause.h"
56#include "base/message.h"
57
58using namespace std;
59
60/*
61 * 構文上の一節を処理するクラス
62 */
63
64 //指定した名前空間の節マップを取得
65Clause::map_type * Clause::getClauseMap(string name) throw()
66{
67 map_type * result = NULL;
68 Namespace::iterator scope;
69
70 Namespace * const ns = Singleton<Namespace>::getInstance(nothrow);
71 if(ns!= 0) {
72 scope = ns->find(name);
73 if(scope != ns->end())
74 result = &(scope->second);
75 }
76
77 return result;
78}
79
80 //節の登録
81void Clause::addClause(string _namespace, string _identifier) throw()
82{
83 if(isValid()) {
84 Namespace * const ns = Singleton<Namespace>::getInstance(nothrow);
85 if(ns != 0)
86 (*ns)[_namespace][_identifier] = this;
87// ns->operator [](_namespace).insert(map_type::value_type(_identifier, this)); //上書きさせない場合
88 }
89}
90
91 //トークンに対して節識別名を生成する
92string Clause::getClauseIdentifier(Token token) throw()
93{
94 string result;
95
96 switch(token.getType()) {
97 case Token::IDENTIFIER:
98 case Token::PUNCTUATOR:
99 result = token.getLiteral();
100 break;
101 case Token::INTEGER:
102 result.assign(INTEGER_CLAUSE_IDENTIFIER);
103 break;
104 case Token::LITERAL:
105 result.assign(LITERAL_CLAUSE_IDENTIFIER);
106 break;
107 case Token::OPERATOR:
108 result.assign(OPERATOR_CLAUSE_IDENTIFIER);
109 break;
110 default:
111 result = string();
112 }
113
114 return result;
115}
116
117 //節の解析
118bool Clause::parseClause(string ns, Parser & p)
119{
120 bool result = false;
121 map_type::iterator scope;
122 map_type * clause = getClauseMap(ns);
123
124 //ガード節
125 if(clause == 0 || p.eof())
126 return false;
127
128 //トークンから識別名を取り出す
129 Token token;
130 string identifier;
131
132 token = p.getToken();
133 identifier = getClauseIdentifier(token);
134
135 //節処理部の実行
136 scope = clause->find(identifier);
137 if(scope != clause->end()) {
138
139 //デバッグ用メッセージ出力
140 DebugMessage("Clause::parseClause(%) - %\n") << ns << identifier;
141
142 try {
143 scope->second->before(token, p);
144 scope->second->body(token, p); //ヒットしたものを実行
145 scope->second->after(token, p);
146 result = true;
147 }
148 catch(...) {
149 scope->second->onFail(token, p); //失敗したときの後始末をお願いする
150 throw;
151 }
152 }
153 else
154 p.putback(token); //識別子にマッチするものが登録されていない
155
156 return result;
157}
158
159 //firstで始まる節があるか
160bool Clause::hasClause(string ns, string first) throw()
161{
162 map_type * clause = getClauseMap(ns);
163 if(clause == 0)
164 return false;
165
166 return clause->find(first) != clause->end();
167}
168
169 //パース前処理
170void Clause::before(const Token &, Parser &)
171{}
172
173 //パース後処理
174void Clause::after(const Token &, Parser &)
175{}
176
177 //標準の例外発生時の後始末ルーチン
178void Clause::onFail(const Token &, Parser & p) throw()
179{
180 Token token;
181
182 //最後まで読みきる
183 while(!p.eof())
184 token = p.getToken();
185}
186
187 //節を複数の識別名に対応付ける
188void Clause::addMultipleClauses(string ns, string id_list) throw()
189{
190 string id;
191 string::size_type pos;
192 string::size_type prev;
193
194 //カンマで区切られた要素毎にaddClauseを発行
195 if(isValid()) {
196 prev = 0;
197 do {
198 pos = id_list.find_first_of(',', prev);
199 id = id_list.substr(prev, pos - prev);
200
201 addClause(ns, id);
202
203 prev = pos + 1;
204 } while(pos != string::npos);
205 }
206}
207
208 //[ヘルプ用] 登録されている節の一覧を作成する
209std::string Clause::makeClauseList(string ns, int width) throw()
210{
211 string result;
212 map_type::iterator scope;
213 map_type * clause = getClauseMap(ns);
214 size_t max_length = 0;
215
216 //最大の文字列長を求める
217 scope = clause->begin();
218 while(scope != clause->end()) {
219 size_t i = scope->first.size();
220 if(i > max_length)
221 max_length = i;
222 ++ scope;
223 }
224
225 //一覧を作成
226 size_t max_column = width/(max_length+1);
227 size_t column = 0;
228 scope = clause->begin();
229 while(scope != clause->end()) {
230 size_t i = scope->first.size();
231
232 result += scope->first;
233
234 ++ column;
235 ++ scope;
236
237 //末尾処理
238 if(column == max_column || scope == clause->end())
239 result += '\n';
240 else {
241 result += ',';
242 result += string(max_length - i, ' ');
243 }
244 }
245
246 return result;
247}
248
249
250 /*
251 * 静的API
252 */
253
254 //パース前処理
255void StaticAPI::before(const Token & first, Parser & p)
256{
257 Token token = p.getToken();
258 if(token != Token::LPAREN) {
259 ExceptionMessage("StaticAPI [%] lacks left-parenthesis '('.","静的API[%]には括弧'('が欠けている") << first.getLiteral() << throwException;
260 }
261}
262
263 //パース後処理
264void StaticAPI::after(const Token & first, Parser & p)
265{
266 Token token = p.getToken();
267 if(token != Token::RPAREN) {
268 ExceptionMessage("StaticAPI [%] lacks right-parenthesis ')'.","静的API[%]には括弧')'が欠けている") << first.getLiteral() << throwException;
269 }
270 else {
271 token = p.getToken();
272 if(token != ";")
273 ExceptionMessage("StaticAPI [%] lacks ';' at the end of declaration.","静的API[%]の末尾に';'が欠けている") << first.getLiteral() << throwException;
274 }
275}
276
277 //失敗時の回復処理
278void StaticAPI::onFail(const Token & , Parser & p) throw()
279{ skip(p, false); }
280
281
282 //スキップ
283 // invalid_api : 次に最初に読み出されるAPIは無効
284void StaticAPI::skip(Parser & p, bool invalid_api) throw()
285{
286 //セミコロン or 次の静的APIの出現まで
287 Token token;
288 bool condition; //アレ対策
289
290 if(invalid_api)
291 token = p.getToken(); //次のAPI名は読み飛ばす
292
293 do {
294 token = p.getToken(true);
295
296 condition = (!token.isValid()) || //無効なトークンか
297 (token == Token::PUNCTUATOR && token == ";") || //セミコロンか
298 (token == Token::IDENTIFIER && hasStaticAPI(token.getLiteral())); //静的APIか
299
300 } while(!condition);
301
302 if(token == Token::IDENTIFIER)
303 p.putback(token);
304}
305
306 /*
307 * プリプロセスディレクティブ
308 */
309
310 //パース後処理
311void Directives::after(const Token & first, Parser & p) throw(Exception)
312{
313 Token token = p.getToken(true);
314 if(!token.isValid() || !p.isLocatedonHeadofLine())
315 ExceptionMessage("Directive [%] has a wrong parameter or misses a new-line.","ディレクティブ[%]に不正な引数があるか、改行がない") << first.getLiteral() << throwException;
316}
317
318 //パース失敗時の回復処理
319void Directives::onFail(const Token & , Parser & p) throw()
320{
321 //次の改行まで読み飛ばす
322 Token token;
323
324 do {
325 token = p.getToken(true);
326 } while(token.isValid() && !p.isLocatedonHeadofLine());
327}
328
329/************************************************* テストスィート *************************************************/
330
331#ifdef TESTSUITE
332
333#include "coverage_undefs.h"
334#include <sstream>
335
336namespace {
337 class Clause_test : public Clause
338 {
339 public:
340 Token first;
341 Token second;
342 bool throw_exception;
343
344 Clause_test(void) throw() : first(Token::ERROR), throw_exception(false) {}
345
346 void body(const Token & _first, Parser & _p)
347 {
348 TestSuite::check("Clause_test::body");
349 first = _first;
350 second = _p.getToken();
351 if(throw_exception)
352 throw 0;
353 }
354
355 void before(const Token & , Parser & )
356 {
357 TestSuite::check("Clause_test::before");
358 }
359
360 void after(const Token &, Parser &)
361 {
362 TestSuite::check("Clause_test::after");
363 }
364
365 void onFail(const Token & _first, Parser & p) throw()
366 {
367 TestSuite::check("Clause_test::onFail");
368 first = _first;
369 }
370
371 void onFail_super(const Token & _first, Parser & p) throw()
372 { Clause::onFail(_first, p); }
373 };
374}
375
376TESTSUITE(main, Clause)
377{
378 SingletonBase::ContextChain chain;
379 chain.saveContext<Namespace>();
380
381 BEGIN_CASE("getClauseIdentifier","getClauseIdentifier") {
382 BEGIN_CASE("1","普通の識別子はそのままが中身になる") {
383 Token token(Token::IDENTIFIER, "test");
384
385 if(getClauseIdentifier(token).compare("test") != 0)
386 TEST_FAIL;
387 } END_CASE;
388
389 BEGIN_CASE("2","数値は中身に関係なく" INTEGER_CLAUSE_IDENTIFIER "が返る") {
390 Token token(Token::INTEGER, "", "", 0);
391
392 if(getClauseIdentifier(token).compare(INTEGER_CLAUSE_IDENTIFIER) != 0)
393 TEST_FAIL;
394 } END_CASE;
395
396 BEGIN_CASE("3","リテラルは中身に関係なく" LITERAL_CLAUSE_IDENTIFIER "が返る") {
397 Token token(Token::LITERAL, "");
398
399 if(getClauseIdentifier(token).compare(LITERAL_CLAUSE_IDENTIFIER) != 0)
400 TEST_FAIL;
401 } END_CASE;
402
403 BEGIN_CASE("4","演算子は中身に関係なく" OPERATOR_CLAUSE_IDENTIFIER "が返る") {
404 Token token(Token::OPERATOR);
405
406 if(getClauseIdentifier(token).compare(OPERATOR_CLAUSE_IDENTIFIER) != 0)
407 TEST_FAIL;
408 } END_CASE;
409
410 BEGIN_CASE("5","空白のトークンには空文字(==非受理)が返る") {
411 Token token(Token::SPACE);
412
413 if(!getClauseIdentifier(token).empty())
414 TEST_FAIL;
415 } END_CASE;
416
417 TEST_CASE("6","エラートークンには空文字(==非受理)が返る", getClauseIdentifier(Token(Token::ERROR)).empty());
418 TEST_CASE("7","EOSトークンには空文字(==非受理)が返る", getClauseIdentifier(Token(Token::END_OF_STREAM)).empty());
419
420 } END_CASE;
421
422 BEGIN_CASE("getClauseMap","getClauseMap") {
423 BEGIN_CASE("1","何も登録していない空間にはNULLが返る") {
424 chain.renewInstance();
425 if(Clause::getClauseMap("unknown") != 0)
426 TEST_FAIL;
427 } END_CASE;
428
429 BEGIN_CASE("2","要素があれば非0が返る") {
430 chain.renewInstance();
431 Singleton<Namespace>::getInstance()->operator []("test");
432
433 if(Clause::getClauseMap("test") == 0)
434 TEST_FAIL;
435 } END_CASE;
436 } END_CASE;
437
438 BEGIN_CASE("addClause","addClause") {
439 BEGIN_CASE("1","オブジェクトを登録できる") {
440 chain.renewInstance();
441 Clause_test ct;
442 Clause_test ct2;
443
444 BEGIN_CASE("1","普通に登録する") {
445 ct.addClause("test","first_literal");
446
447 TEST_CASE("1","名前空間が増えている", Singleton<Namespace>::getInstance()->size() == 1);
448 TEST_CASE("2","\"test\"という空間がある", Singleton<Namespace>::getInstance()->find("test") != Singleton<Namespace>::getInstance()->end());
449 TEST_CASE("3","getClauseでアドレスが取れる", Clause::getClauseMap("test") != 0);
450 TEST_CASE("4","名前空間の節の数は1", Clause::getClauseMap("test")->size() == 1);
451 TEST_CASE("5","\"first_literal\"のノードがある", Clause::getClauseMap("test")->find("first_literal") != Clause::getClauseMap("test")->end());
452 TEST_CASE("6","関連付けられた値が正しい", (*Clause::getClauseMap("test"))["first_literal"] == &ct);
453 } END_CASE;
454
455 BEGIN_CASE("2","2個目を登録する") {
456 ct2.addClause("test","second_literal");
457
458 TEST_CASE("1","名前空間が増えていない", Singleton<Namespace>::getInstance()->size() == 1);
459 TEST_CASE("2","\"test\"という空間がある", Singleton<Namespace>::getInstance()->find("test") != Singleton<Namespace>::getInstance()->end());
460 TEST_CASE("3","名前空間の節の数は2", Clause::getClauseMap("test")->size() == 2);
461 TEST_CASE("4","\"second_literal\"のノードがある", Clause::getClauseMap("test")->find("second_literal") != Clause::getClauseMap("test")->end());
462 TEST_CASE("5","関連付けられた値が正しい", (*Clause::getClauseMap("test"))["second_literal"] == &ct2);
463 } END_CASE;
464
465 BEGIN_CASE("3","2個目を1個目で上書き登録する") {
466 ct.addClause("test","second_literal");
467 TEST_CASE("1","上書きされている", (*Clause::getClauseMap("test"))["second_literal"] == &ct);
468 } END_CASE;
469
470 BEGIN_CASE("4","違う名前空間に登録する") {
471 ct.addClause("TEST","first_literal");
472
473 TEST_CASE("1","名前空間が増えている", Singleton<Namespace>::getInstance()->size() == 2);
474 TEST_CASE("2","\"TEST\"という空間がある", Singleton<Namespace>::getInstance()->find("TEST") != Singleton<Namespace>::getInstance()->end());
475 TEST_CASE("3","getClauseでアドレスが取れる", Clause::getClauseMap("TEST") != 0);
476 TEST_CASE("4","名前空間の節の数は1", Clause::getClauseMap("TEST")->size() == 1);
477 TEST_CASE("5","\"first_literal\"のノードがある", Clause::getClauseMap("TEST")->find("first_literal") != Clause::getClauseMap("TEST")->end());
478 TEST_CASE("6","関連付けられた値が正しい", (*Clause::getClauseMap("TEST"))["first_literal"] == &ct);
479 } END_CASE;
480
481 } END_CASE;
482
483 BEGIN_CASE("2","無効なオブジェクトは登録されない") {
484 chain.renewInstance();
485
486 ((Clause_test *)0)->addClause("test","first_literal");
487
488 TEST_CASE("1","名前空間が増えていない", Singleton<Namespace>::getInstance()->size() == 0);
489 } END_CASE;
490
491 } END_CASE;
492
493 BEGIN_CASE("hasClause","hasClause") {
494 Clause_test ct;
495 chain.renewInstance();
496
497 TEST_CASE("1","何も要素がないときにも正常に動作する", !Clause::hasClause("dummy","null"));
498
499 ct.addClause("test","first_literal");
500
501 TEST_CASE("2","登録した要素を探せ、trueが返る", Clause::hasClause("test","first_literal"));
502 TEST_CASE("3","存在しない要素にfalseが返る", !Clause::hasClause("dummy","null"));
503 } END_CASE;
504
505 BEGIN_CASE("addMultipleClauses","addMultipleClauses") {
506 BEGIN_CASE("1","単一の節を登録できる") {
507 chain.renewInstance();
508 Clause_test ct;
509
510 ct.addMultipleClauses("test","first");
511
512 TEST_CASE("1","登録した節がある", Clause::hasClause("test","first"));
513 } END_CASE;
514
515 BEGIN_CASE("2","複数の節を登録する") {
516 chain.renewInstance();
517 Clause_test ct;
518
519 ct.addMultipleClauses("test","first,second,third");
520
521 TEST_CASE("1","登録した節がある", Clause::hasClause("test","first"));
522 TEST_CASE("2","登録した節がある", Clause::hasClause("test","second"));
523 TEST_CASE("3","登録した節がある", Clause::hasClause("test","third"));
524 } END_CASE;
525
526 } END_CASE;
527
528 BEGIN_CASE("Clause::onFail","Clause::onFail") {
529 stringstream buf;
530 Parser p(&buf, "test");
531 Token token;
532 Clause_test ct;
533
534 buf.str("first second third 4 5 6 siebt acht neunt 0xa");
535
536 ct.onFail_super(token, p);
537 TEST_CASE("1","ストリームは最後まで進んでいる", p.eof());
538 } END_CASE;
539
540 BEGIN_CASE("parseClause","parseClause") {
541 chain.renewInstance();
542 Clause_test ct;
543
544 ct.addClause("test","first");
545
546 BEGIN_CASE("1","名前空間を選択して正しく節を実行できる") {
547 stringstream buf;
548 Parser p(&buf, "test");
549 buf.str("first second");
550
551 TestSuite::clearCheckpoints();
552 TEST_CASE("1","関数は成功する", Clause::parseClause("test", p));
553 TEST_CASE("2","Clause::beforeが実行されている", TestSuite::isReached("Clause_test::before"));
554 TEST_CASE("3","Clause::bodyが実行されている", TestSuite::isReached("Clause_test::body"));
555 TEST_CASE("4","bodyのfirstが正しい", ct.first == "first");
556 TEST_CASE("5","bodyで読み出したトークンが正しい", ct.second == "second");
557 TEST_CASE("6","Clause::afterが実行されている", TestSuite::isReached("Clause_test::after"));
558 } END_CASE;
559
560 BEGIN_CASE("2","節の処理中に例外が起こるとonFailが呼ばれる") {
561 stringstream buf;
562 Parser p(&buf, "test");
563 buf.str("first second");
564
565 ct.throw_exception = true;
566 TestSuite::clearCheckpoints();
567
568 bool result = false;
569 try { Clause::parseClause("test", p); }
570 catch(...){ result = true; }
571
572 TEST_CASE("1","例外が起こる", result);
573 TEST_CASE("2","Clause::bodyが実行されている", TestSuite::isReached("Clause_test::body"));
574 TEST_CASE("3","Clause::onFailが実行されている", TestSuite::isReached("Clause_test::onFail"));
575 } END_CASE;
576
577 BEGIN_CASE("3","存在しない名前空間を指定する") {
578 stringstream buf;
579 Parser p(&buf, "test");
580 buf.str("first second");
581
582 TEST_CASE("1","関数は失敗する", !Clause::parseClause("unknown", p));
583 } END_CASE;
584
585 BEGIN_CASE("4","EOFに達したストリームを指定する") {
586 stringstream buf;
587 Parser p(&buf, "test");
588 buf.str("");
589 buf.get();
590
591 TEST_CASE("0","[前提]ストリームは終端に達している", buf.eof());
592 TEST_CASE("1","関数は失敗する", !Clause::parseClause("unknown", p));
593 } END_CASE;
594 } END_CASE;
595
596 chain.restoreContext();
597}
598
599
600
601
602namespace {
603 class StaticAPI_test : public StaticAPI
604 {
605 public:
606 StaticAPI_test(void) throw() : StaticAPI() {}
607 StaticAPI_test(string src) throw() : StaticAPI(src) {}
608
609 void body(const Token & , Parser &) { TestSuite::check("StaticAPI::body"); }
610 void onFail_super(const Token & first, Parser & p) throw() { StaticAPI::onFail(first, p); }
611 };
612}
613
614TESTSUITE(main, StaticAPI)
615{
616 Singleton<Namespace>::Context context;
617 Singleton<Namespace>::saveContext(context);
618
619 Exception::setThrowControl(true);
620
621 BEGIN_CASE("regist","regist") {
622 BEGIN_CASE("1","単一の名前を指定して登録できる") {
623 Singleton<Namespace>::renewInstance();
624 StaticAPI_test api;
625
626 api.regist("VTST_API");
627
628 TEST_CASE("1","APIは正しく登録できている",StaticAPI::hasStaticAPI("VTST_API"));
629 } END_CASE;
630
631 BEGIN_CASE("2","複数の名前を指定して登録する") {
632 Singleton<Namespace>::renewInstance();
633 StaticAPI_test api;
634
635 api.regist("API_1,API_2,API_3");
636
637 TEST_CASE("1","APIは正しく登録できている",StaticAPI::hasStaticAPI("API_1"));
638 TEST_CASE("2","APIは正しく登録できている",StaticAPI::hasStaticAPI("API_2"));
639 TEST_CASE("3","APIは正しく登録できている",StaticAPI::hasStaticAPI("API_3"));
640 } END_CASE;
641
642 BEGIN_CASE("3","上書きする") {
643 Singleton<Namespace>::renewInstance();
644 StaticAPI_test api;
645 StaticAPI_test api2;
646 StaticAPI_test api3;
647
648 api.regist("test");
649 TEST_CASE("1","APIは正しく登録できている",StaticAPI::hasStaticAPI("test"));
650 TEST_CASE("2","APIハンドラが正しい", (*StaticAPI::getClauseMap(NAMESPACE_STATICAPI))["test"] == &api);
651
652 api2.regist("test");
653 TEST_CASE("3","APIハンドラが上書きされている", (*StaticAPI::getClauseMap(NAMESPACE_STATICAPI))["test"] == &api2);
654
655 api3.regist("test");
656 TEST_CASE("4","APIハンドラが上書きされている", (*StaticAPI::getClauseMap(NAMESPACE_STATICAPI))["test"] == &api3);
657 } END_CASE;
658
659 BEGIN_CASE("4","コンストラクタで登録") {
660 Singleton<Namespace>::renewInstance();
661 StaticAPI_test api("API1,API2,API3");
662
663 TEST_CASE("1","APIは正しく登録できている",StaticAPI::hasStaticAPI("API1"));
664 TEST_CASE("2","APIは正しく登録できている",StaticAPI::hasStaticAPI("API2"));
665 TEST_CASE("3","APIは正しく登録できている",StaticAPI::hasStaticAPI("API3"));
666 } END_CASE;
667 } END_CASE;
668
669 BEGIN_CASE("parseStaticAPI","parseStaticAPI") {
670 BEGIN_CASE("1","静的APIを正しく処理できる") {
671 Singleton<Namespace>::renewInstance();
672 stringstream buf;
673 StaticAPI_test api("API");
674
675 buf.str("API();");
676 Parser p(&buf, "test");
677
678 TestSuite::clearCheckpoints();
679 bool result = true;
680 try { StaticAPI::parseStaticAPI(p); }
681 catch(...) { result = false; }
682
683 TEST_CASE("1","例外は起らない", result);
684 TEST_CASE("2","静的APIの本体が呼ばれている", TestSuite::isReached("StaticAPI::body"));
685 } END_CASE;
686
687 BEGIN_CASE("2","'('忘れで例外") {
688 Singleton<Namespace>::renewInstance();
689 stringstream buf;
690 StaticAPI_test api("API");
691
692 buf.str("API);");
693 Parser p(&buf, "test");
694
695 TestSuite::clearCheckpoints();
696 bool result = false;
697 try { StaticAPI::parseStaticAPI(p); }
698 catch(...) { result = true; }
699
700 TEST_CASE("1","例外が起る", result);
701 TEST_CASE("2","静的APIの本体が呼ばれない", !TestSuite::isReached("StaticAPI::body"));
702 } END_CASE;
703
704 BEGIN_CASE("3","')'忘れで例外") {
705 Singleton<Namespace>::renewInstance();
706 stringstream buf;
707 StaticAPI_test api("API");
708
709 buf.str("API(; NEXT");
710 Parser p(&buf, "test");
711
712 TestSuite::clearCheckpoints();
713 bool result = false;
714 try { StaticAPI::parseStaticAPI(p); }
715 catch(...) { result = true; }
716
717 TEST_CASE("1","例外が起る", result);
718 TEST_CASE("2","静的APIの本体が呼ばれている", TestSuite::isReached("StaticAPI::body"));
719 } END_CASE;
720
721 BEGIN_CASE("4","';'忘れで例外") {
722 Singleton<Namespace>::renewInstance();
723 stringstream buf;
724 StaticAPI_test api("API");
725
726 buf.str("API() NEXT");
727 Parser p(&buf, "test");
728
729 TestSuite::clearCheckpoints();
730 bool result = false;
731 try { StaticAPI::parseStaticAPI(p); }
732 catch(...) { result = true; }
733
734 TEST_CASE("1","例外が起る", result);
735 TEST_CASE("2","静的APIの本体が呼ばれている", TestSuite::isReached("StaticAPI::body"));
736 } END_CASE;
737 } END_CASE;
738
739 BEGIN_CASE("onFail","onFail") {
740 BEGIN_CASE("1","セミコロンまで読み飛ばし") {
741 Singleton<Namespace>::renewInstance();
742 stringstream buf;
743 Parser p(&buf, "test");
744 StaticAPI_test api;
745 Token token;
746 buf.str("api parameter;next_api next_api_parameter;");
747
748 api.onFail_super(Token(), p);
749
750 TEST_CASE("1","セミコロンの次が読める", p.getToken() == "next_api");
751 } END_CASE;
752
753 BEGIN_CASE("2","次のAPIまで読み飛ばし") {
754 Singleton<Namespace>::renewInstance();
755 stringstream buf;
756 Parser p(&buf, "test");
757 StaticAPI_test api("api,next_api");
758 buf.str("api parameter_1 parameter_2 next_api next_api_parameter;");
759
760 api.onFail_super(p.getToken(), p);
761
762 TEST_CASE("1","次のAPI名が読める", p.getToken() == "next_api");
763 } END_CASE;
764 } END_CASE;
765
766 BEGIN_CASE("skip","skip") {
767 BEGIN_CASE("1","セミコロンまで読み飛ばし") {
768 Singleton<Namespace>::renewInstance();
769 stringstream buf;
770 Parser p(&buf, "test");
771 StaticAPI_test api;
772 Token token;
773 buf.str("api parameter;next_api next_api_parameter;");
774
775 StaticAPI::skip(p);
776
777 TEST_CASE("1","セミコロンの次が読める", p.getToken() == "next_api");
778 } END_CASE;
779
780 BEGIN_CASE("2","次のAPIまで読み飛ばし") {
781 Singleton<Namespace>::renewInstance();
782 stringstream buf;
783 Parser p(&buf, "test");
784 StaticAPI_test api("api,next_api");
785 buf.str("parameter_1 parameter_2 next_api next_api_parameter;");
786
787 StaticAPI::skip(p);
788
789 TEST_CASE("1","次のAPI名次が読める", p.getToken() == "next_api");
790 } END_CASE;
791
792 BEGIN_CASE("3","å…
793ˆé ­ãŒAPI名でも読み飛ばしできる") {
794 Singleton<Namespace>::renewInstance();
795 stringstream buf;
796 Parser p(&buf, "test");
797 StaticAPI_test api("api,next_api");
798 buf.str("api parameter_1 parameter_2 next_api next_api_parameter;");
799
800 StaticAPI::skip(p);
801
802 TEST_CASE("1","次のAPI名が読める", p.getToken() == "next_api");
803 } END_CASE;
804 } END_CASE;
805
806 Singleton<Namespace>::restoreContext(context);
807}
808
809
810namespace {
811 class Directives_test : public Directives
812 {
813 public:
814 bool throws;
815
816 Directives_test(void) throw() : Directives(), throws(false) {}
817 Directives_test(string src) throw() : Directives(src), throws(false) {}
818
819 void body(const Token & , Parser & ) throw(int)
820 {
821 TestSuite::check("Directives::body");
822 if(throws)
823 throw 0;
824 }
825 };
826}
827
828TESTSUITE(main, Directives)
829{
830 Singleton<Namespace>::Context context;
831 Singleton<Namespace>::saveContext(context);
832
833 Exception::setThrowControl(true);
834
835 BEGIN_CASE("regist","regist") {
836 BEGIN_CASE("1","単一の名前を指定して登録できる") {
837 Singleton<Namespace>::renewInstance();
838 Directives_test api;
839
840 api.regist("include");
841
842 TEST_CASE("1","APIは正しく登録できている",Directives::hasDirectives("include"));
843 } END_CASE;
844
845 BEGIN_CASE("2","複数の名前を指定して登録する") {
846 Singleton<Namespace>::renewInstance();
847 Directives_test api;
848
849 api.regist("pragma,define,endif");
850
851 TEST_CASE("1","ディレクティブは正しく登録できている",Directives::hasDirectives("pragma"));
852 TEST_CASE("2","ディレクティブは正しく登録できている",Directives::hasDirectives("define"));
853 TEST_CASE("3","ディレクティブは正しく登録できている",Directives::hasDirectives("endif"));
854 } END_CASE;
855
856 BEGIN_CASE("3","上書きする") {
857 Singleton<Namespace>::renewInstance();
858 Directives_test api;
859 Directives_test api2;
860 Directives_test api3;
861
862 api.regist("test");
863 TEST_CASE("1","ディレクティブは正しく登録できている",Directives::hasDirectives("test"));
864 TEST_CASE("2","ディレクティブハンドラが正しい", (*Directives::getClauseMap(NAMESPACE_DIRECTIVES))["test"] == &api);
865
866 api2.regist("test");
867 TEST_CASE("3","ディレクティブハンドラが上書きされている", (*Directives::getClauseMap(NAMESPACE_DIRECTIVES))["test"] == &api2);
868
869 api3.regist("test");
870 TEST_CASE("4","ディレクティブハンドラが上書きされている", (*Directives::getClauseMap(NAMESPACE_DIRECTIVES))["test"] == &api3);
871 } END_CASE;
872
873 BEGIN_CASE("4","コンストラクタで登録") {
874 Singleton<Namespace>::renewInstance();
875 Directives_test api("pragma,define,endif");
876
877 TEST_CASE("1","ディレクティブは正しく登録できている",Directives::hasDirectives("pragma"));
878 TEST_CASE("2","ディレクティブは正しく登録できている",Directives::hasDirectives("define"));
879 TEST_CASE("3","ディレクティブは正しく登録できている",Directives::hasDirectives("endif"));
880 } END_CASE;
881 } END_CASE;
882
883 BEGIN_CASE("parseDirectives","parseDirectives") {
884 BEGIN_CASE("1","ディレクティブを正しく処理できる") {
885 Singleton<Namespace>::renewInstance();
886 stringstream buf;
887 Directives_test api("pragma");
888
889 buf.str("pragma\nnext\n");
890 Parser p(&buf, "test");
891
892 TestSuite::clearCheckpoints();
893 bool result = true;
894 try { Directives::parseDirectives(p); }
895 catch(...) { result = false; }
896
897 TEST_CASE("1","例外は起らない", result);
898 TEST_CASE("2","ディレクティブの本体が呼ばれている", TestSuite::isReached("Directives::body"));
899 } END_CASE;
900
901 BEGIN_CASE("2","改行なし(不正パラメータ)で例外") {
902 Singleton<Namespace>::renewInstance();
903 stringstream buf;
904 Directives_test api("pragma");
905
906 buf.str("pragma next\n");
907 Parser p(&buf, "test");
908
909 TestSuite::clearCheckpoints();
910 bool result = false;
911 try { Directives::parseDirectives(p); }
912 catch(...) { result = true; }
913
914 TEST_CASE("1","例外が起る", result);
915 TEST_CASE("2","ディレクティブの本体が呼ばれている", TestSuite::isReached("Directives::body"));
916 } END_CASE;
917
918 BEGIN_CASE("3","改行なし(EOF)で例外") {
919 Singleton<Namespace>::renewInstance();
920 stringstream buf;
921 Directives_test api("pragma");
922
923 buf.str("pragma");
924 Parser p(&buf, "test");
925
926 TestSuite::clearCheckpoints();
927 bool result = false;
928 try { Directives::parseDirectives(p); }
929 catch(...) { result = true; }
930
931 TEST_CASE("1","例外が起る", result);
932 TEST_CASE("2","ディレクティブの本体が呼ばれている", TestSuite::isReached("Directives::body"));
933 } END_CASE;
934 } END_CASE;
935
936 BEGIN_CASE("onFail","onFail") {
937 BEGIN_CASE("1","bodyで例外が起るとonFailが次の改行まで読み飛ばす") {
938 Singleton<Namespace>::renewInstance();
939 stringstream buf;
940 Directives_test api("pragma");
941 buf.str("pragma parameter\nnext\n");
942 Parser p(&buf, "test");
943
944 api.throws = true;
945 bool result = false;
946 try { Directives::parseDirectives(p); }
947 catch(...) { result = true; }
948
949 TEST_CASE("1","例外が起る", result);
950 TEST_CASE("2","残った内
951容が正しい", p.getToken() == "next");
952 TEST_CASE("3","トークンは行頭", p.isHeadofLine());
953 } END_CASE;
954 } END_CASE;
955
956 Singleton<Namespace>::restoreContext(context);
957}
958
959#endif
960
961
962
Note: See TracBrowser for help on using the repository browser.