Merge branch 'fixes' into main/rendor-staging
[ryzomcore.git] / ryzom / common / src / game_share / sadge_tests.h
blob3422dd0fd95d1e75d92cb3b774e34b8425a57fbe
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #ifndef SADGE_TESTS_H
18 #define SADGE_TESTS_H
20 #include "nel/misc/sstring.h"
22 #ifdef ENABLE_TESTS
25 class CTestContext
27 public:
28 CTestContext(const NLMISC::CSString& title, const NLMISC::CSString& anticipatedResult)
30 _Title= title;
31 anticipatedResult.splitLines(_Lines);
32 _Index= 0;
33 _Errors= false;
34 _ErrorLine= ~0u;
36 // add self to top of the context stack
37 CTestContext*& theTopContext= _getTopContext();
38 _NextContext= theTopContext;
39 theTopContext= this;
42 virtual ~CTestContext()
44 // setup a ref to the pointer to this context in the context stack
45 CTestContext*& ptr= _getTopContext();
46 while (ptr!=this)
48 if (ptr==NULL)
49 return;
50 ptr= ptr->_NextContext;
53 // remove from the context stack...
54 ptr= _NextContext;
56 // make sure we reached the end of th test vector correctly
57 if (!_Errors && _Index!=_Lines.size())
59 _Errors= true;
60 _ErrorLine= _Index;
61 if (NLMISC::WarningLog!=NULL)
63 nlwarning("TEST FAILED: No more output but expecting: %s",_Lines[_Index].c_str());
67 // display success or failure message
68 if (NLMISC::InfoLog!=NULL)
70 nlinfo("TEST: %s: %s",_Title.c_str(),(_Errors?(NLMISC::toString("FAILED AT LINE %d",_ErrorLine).c_str()):"SUCCESS"));
71 if (_Errors)
73 // calculate the length of the lines...
74 uint32 lineLength=20;
75 for (uint32 i=0;i<_Lines.size();++i)
77 lineLength= std::max(lineLength,(uint32)_Lines[i].size()+3);
80 // display a header line
81 nlinfo(" %-*s %s",lineLength,"EXPECTED","FOUND");
83 // display the lines that exist in both lines and result vectors
84 uint32 line;
85 for (line=0;line<_Lines.size() && line<_Result.size();++line)
87 nlinfo("%4d %-*s %s",line,lineLength,_Lines[line].c_str(),_Result[line].c_str());
90 // display any remaining lines from the lines vector
91 for (;line<_Lines.size();++line)
93 nlinfo("%4d %s",line,_Lines[line].c_str());
96 // display any remaining lines from the result vector
97 for (;line<_Result.size();++line)
99 nlinfo("%4d %*s %s",line,lineLength,"",_Result[line].c_str());
105 static void testOutput(const char* file, uint32 line, const NLMISC::CSString& txt)
107 // if we're not in a test context then just quit
108 if(_getTopContext()==NULL)
110 #ifdef NL_DEBUG
111 NLMISC::DebugLog->displayNL("%s: %d: Test output with no context: %s",file,line,txt.c_str());
112 #endif
113 return;
116 _getTopContext()->_testOutput(file,line,txt);
119 static bool foundErrors()
121 if(_getTopContext()==NULL)
122 return false;
123 return _getTopContext()->_Errors;
126 protected:
127 virtual void _testOutput(const char* file, uint32 line, const NLMISC::CSString& txt)
129 // add the output to our result vector
130 _Result.push_back(txt);
132 // if there have already been errors then just display a warning
133 if (_Errors)
135 NLMISC::DebugLog->displayNL("%s: %d: After error: %s",file,line,txt.c_str());
136 return;
139 // check that this test doesn't provoke an error
140 if (_Index>=_Lines.size())
142 _Errors=true;
143 NLMISC::WarningLog->displayNL("%s: %d: TEST FAILED: Found extra output after end of test: %s",file,line,txt.c_str());
144 _ErrorLine=_Index;
145 return;
148 // check that this test doesn't provoke an error
149 if (txt!=_Lines[_Index])
151 _Errors=true;
152 NLMISC::WarningLog->displayNL("%s: %d: TEST FAILED: \n- EXPECTED - %s\n- FOUND - %s",file,line,_Lines[_Index].c_str(),txt.c_str());
153 _ErrorLine=_Index;
154 return;
157 // display the no-error message
158 nldebug("%s",txt.c_str());
159 // increment the index
160 ++_Index;
163 static CTestContext*& _getTopContext()
165 static CTestContext* topContext= NULL;
166 return topContext;
169 NLMISC::CSString _Title;
170 NLMISC::CVectorSString _Lines;
171 NLMISC::CVectorSString _Result;
172 uint32 _Index;
173 bool _Errors;
174 uint32 _ErrorLine;
175 CTestContext* _NextContext;
178 class CTestContextMute: public CTestContext
180 public:
181 CTestContextMute(): CTestContext("","")
185 protected:
186 virtual void _testOutput(const char* file, uint32 line, const NLMISC::CSString& txt)
191 #define DOTEST(cmd,result) { CTestContext tc(NLMISC::toString("TEST("__FILE__":%d)",__LINE__),result); cmd; TEST_ASSERT(!tc.foundErrors()) }
192 #define MUTETEST(cmd) { CTestContextMute tcm; cmd; }
193 #define TEST(txt_and_args) CTestContext::testOutput(__FILE__,__LINE__,NLMISC::toString txt_and_args )
195 #else // ENABLE_TESTS
197 #define DOTEST(cmd,result) while(0) {}
198 #define MUTETEST(cmd) while(0) {}
199 #define TEST(txt) while(0) {}
201 #endif // ENABLE_TESTS
203 #endif // HEADER FILE