00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #pragma once
00012
00013 #include <set>
00014 #include <vector>
00015 #include <iostream>
00016 #include <iomanip>
00017 using namespace std;
00018
00019 #include "TestToolBox/CheckerForMultipleSequences.h"
00020 #include "TestToolBox/TestEvents.h"
00021 #include "TestToolBox/IEventReceiver.h"
00022 #include "TestToolBox/IProtocol.h"
00023
00024 #pragma warning( push )
00025 #pragma warning( disable : 4996 ) // vsprintf declared deprecated
00026
00027
00028
00029
00030
00031 #ifdef TTB_NOT_INLINE
00032 #define TTB_INLINE
00033 #else
00034 #define TTB_INLINE inline
00035 #endif
00036
00037 namespace TestToolBox
00038 {
00039
00040 const int WIDTH_SEQUENTIAL_ID = 15;
00041 const char* SEQUENTIAL_ID_EMPTY = " ";
00042
00043 class TestEvents;
00044
00045
00046
00047
00048
00049
00050 TTB_INLINE CheckerForMultipleSequences::CheckerForMultipleSequences(
00051 TestEvents & in_rTestEvents)
00052 : m_rTestEvents (in_rTestEvents)
00053 , m_numBestMatches (0)
00054 , m_detailedLog (true)
00055 {}
00056
00057
00058
00059
00060
00061
00062 TTB_INLINE void CheckerForMultipleSequences::DefineSequence (
00063 std::string const & in_nameSequence)
00064 {
00065 m_sequences.push_back(SequenceEntry(in_nameSequence));
00066
00067 }
00068
00069
00070
00071
00072
00073
00074 TTB_INLINE void CheckerForMultipleSequences::StoreExpectedEventWithinSelectedSequence(
00075 std::string const & in_expectedEvent,
00076 const char* in_fileName,
00077 const long in_lineNum)
00078 {
00079 m_sequences.back().m_events.push_back(EventEntry(
00080 in_expectedEvent,
00081 LastIndex(m_sequences), NumElements(m_sequences.back().m_events),
00082 in_fileName, in_lineNum));
00083 }
00084
00085
00086
00087
00088
00089
00090 TTB_INLINE void CheckerForMultipleSequences::CheckDefinedSequences (
00091 const char* in_fileName,
00092 const long in_lineNum)
00093 {
00094 AutoLock o (&m_rTestEvents);
00095
00096 SearchInfo searchInfo;
00097
00098
00099 m_recEv2SeqEv.resize(m_rTestEvents.m_events.size(),0);
00100
00101
00102 while (!searchInfo.searchSucceeded && !searchInfo.searchFailed)
00103 {
00104 CheckNextMatch(searchInfo);
00105 if (searchInfo.searchFailed) break;
00106
00107 if (searchInfo.undoLastMatch)
00108 {
00109 UndoLastMatch(searchInfo);
00110 }
00111 }
00112
00113 if (searchInfo.searchSucceeded)
00114 {
00115 MarkRecordedEventsAsChecked();
00116 }
00117
00118 if (searchInfo.searchFailed)
00119 {
00120
00121
00122 std::ostringstream fullInfoStr;
00123
00124
00125 m_sequences = m_sequencesBestMatch;
00126 m_recEv2SeqEv = m_recEv2SeqEvBestMatch;
00127
00128 std::string eventTxt;
00129 std::string fileName;
00130 long lineNum;
00131 if (FindFirstUnmatchedEvent(eventTxt, fileName, lineNum))
00132 {
00133 fullInfoStr << "\nNo match found for:\n" << eventTxt << endl;
00134 AddFileNameAndLineNumber (fullInfoStr, fileName.c_str(), lineNum);
00135 fullInfoStr << " (call location of error)" << endl;
00136 }
00137
00138 fullInfoStr << "\nCheckForMultipleSequences failed:" << endl;
00139 AddFileNameAndLineNumber (fullInfoStr, in_fileName, in_lineNum);
00140 fullInfoStr << " (call location of error)" << endl;
00141
00142 if (m_rTestEvents.m_pIEventReceiver)
00143 {
00144 m_rTestEvents.m_pIEventReceiver->Event (fullInfoStr. str());
00145 }
00146
00147
00148 if (m_rTestEvents.m_pIProtocol)
00149 {
00150 m_rTestEvents.m_pIProtocol->Writeln(OutputLevel::eERROR, OutputMode::M_ALL,
00151 "\n!!Error - CheckForMultipleSequences\n" + fullInfoStr. str());
00152 }
00153 m_rTestEvents.m_active = false;
00154 m_rTestEvents.StoreError (fullInfoStr.str(), "");
00155 }
00156
00157 if (searchInfo.searchFailed || m_detailedLog)
00158 {
00159 LogCheckResult(searchInfo.searchFailed
00160 ? "\nTestEvents with best match of multiple sequences:"
00161 : std::string(in_fileName) + " (" + ToString(in_lineNum) + ")\n"
00162 + "CheckForMultipleSequences - Found all matches:");
00163 }
00164
00165 ResetAll();
00166
00167 }
00168
00169
00170
00171
00172
00173
00174 TTB_INLINE void CheckerForMultipleSequences::ResetAll (void)
00175 {
00176 m_sequences.clear();
00177 m_attachedIndices.clear();
00178 m_recEv2SeqEv.clear();
00179 m_sequencesBestMatch.clear();
00180 m_recEv2SeqEvBestMatch.clear();
00181 m_numBestMatches = 0;
00182
00183 }
00184
00185
00186
00187
00188
00189
00190 TTB_INLINE void CheckerForMultipleSequences::CheckNextMatch (
00191 SearchInfo & io_searchInfo)
00192 {
00193
00194 int startPos = io_searchInfo.eventPos;
00195
00196 if (startPos >= static_cast<int>(NumElements(m_rTestEvents.m_events)))
00197 {
00198 if ((io_searchInfo.idxSequence == 0) && (io_searchInfo.idxEvent == 0))
00199 {
00200
00201 io_searchInfo.searchFailed = true;
00202 }
00203 else
00204 {
00205 io_searchInfo.searchSucceeded = false;
00206 io_searchInfo.undoLastMatch = true;
00207 }
00208 return;
00209 }
00210
00211
00212
00213 int curPos = startPos;
00214 bool entryFound = false;
00215 curPos = FindNextUncheckedPos(curPos);
00216
00217 while (!entryFound && curPos < NumElements(m_rTestEvents.m_events))
00218 {
00219 if (m_rTestEvents.m_events[curPos].second == m_sequences[io_searchInfo.idxSequence].
00220 m_events[io_searchInfo.idxEvent].m_eventTxt)
00221 {
00222 entryFound = true;
00223
00224 m_attachedIndices.insert(curPos);
00225 m_recEv2SeqEv[curPos]=&m_sequences[io_searchInfo.idxSequence].
00226 m_events[io_searchInfo.idxEvent];
00227 m_sequences[io_searchInfo.idxSequence].
00228 m_events[io_searchInfo.idxEvent].m_eventPosition = curPos;
00229
00230
00231 io_searchInfo.eventPos = curPos+1;
00232
00233 if (m_numBestMatches < NumElements(m_attachedIndices))
00234 {
00235 m_numBestMatches = NumElements(m_attachedIndices);
00236 m_sequencesBestMatch = m_sequences;
00237 m_recEv2SeqEvBestMatch = m_recEv2SeqEv;
00238 }
00239 }
00240 else
00241 {
00242 curPos = FindNextUncheckedPos(curPos+1);
00243 }
00244 }
00245
00246 if (entryFound)
00247 {
00248 io_searchInfo.idxEvent++;
00249 if (io_searchInfo.idxEvent >= NumElements(m_sequences[io_searchInfo.idxSequence].m_events))
00250 {
00251
00252 io_searchInfo.idxSequence++;
00253 io_searchInfo.idxEvent = 0;
00254 io_searchInfo.eventPos = 0;
00255
00256 if (io_searchInfo.idxSequence >= NumElements(m_sequences))
00257 {
00258
00259 io_searchInfo.searchSucceeded = true;
00260 }
00261 }
00262 }
00263 else
00264 {
00265 io_searchInfo.undoLastMatch = true;
00266 }
00267
00268 }
00269
00270
00271
00272
00273
00274
00275 TTB_INLINE void CheckerForMultipleSequences::UndoLastMatch (SearchInfo & io_searchInfo)
00276 {
00277
00278 if ((io_searchInfo.idxSequence == 0) && (io_searchInfo.idxEvent == 0))
00279 {
00280
00281 io_searchInfo.searchFailed = true;
00282 }
00283 else
00284 {
00285 if (io_searchInfo.idxEvent > 0)
00286 {
00287 --io_searchInfo.idxEvent;
00288 }
00289 else
00290 {
00291 --io_searchInfo.idxSequence;
00292 io_searchInfo.idxEvent = LastIndex(m_sequences[io_searchInfo.idxSequence].m_events);
00293 }
00294
00295
00296 int attachedIdx = m_sequences[io_searchInfo.idxSequence].
00297 m_events[io_searchInfo.idxEvent].m_eventPosition;
00298
00299 m_attachedIndices.erase(attachedIdx);
00300 m_recEv2SeqEv[attachedIdx] = 0;
00301 m_sequences[io_searchInfo.idxSequence].
00302 m_events[io_searchInfo.idxEvent].m_eventPosition = -1;
00303
00304
00305 io_searchInfo.eventPos = attachedIdx +1;
00306 }
00307
00308 io_searchInfo.undoLastMatch = false;
00309
00310 }
00311
00312
00313
00314
00315
00316
00317 TTB_INLINE int CheckerForMultipleSequences::FindNextUncheckedPos (int in_startPos)
00318 {
00319 int curPos = in_startPos;
00320
00321 while ( (curPos < NumElements(m_rTestEvents.m_events))
00322 && ( (m_rTestEvents.m_events [curPos]. first)
00323 || (m_attachedIndices.count(curPos))))
00324 ++curPos;
00325
00326 return curPos;
00327
00328 }
00329
00330
00331
00332
00333
00334
00335 TTB_INLINE void CheckerForMultipleSequences::MarkRecordedEventsAsChecked (void)
00336 {
00337 AutoLock o (&m_rTestEvents);
00338
00339 int idxRecordedEvents = 0;
00340
00341 for (SequenceEntries::iterator itSeq = m_sequences.begin();
00342 itSeq != m_sequences.end(); ++itSeq)
00343 {
00344 for (EventEntries::iterator itEv = itSeq->m_events.begin();
00345 itEv != itSeq->m_events.end(); ++itEv)
00346 {
00347
00348 m_rTestEvents.m_events[itEv->m_eventPosition].first = true;
00349 }
00350 }
00351
00352 }
00353
00354
00355
00356
00357
00358
00359 TTB_INLINE bool CheckerForMultipleSequences::FindFirstUnmatchedEvent(
00360 std::string & out_eventText,
00361 std::string & out_fileName,
00362 long & out_lineNum)
00363 {
00364 out_eventText = "";
00365 out_fileName = "";
00366 out_lineNum = 0;
00367
00368 for (SequenceEntries::iterator itSeq = m_sequences.begin();
00369 itSeq != m_sequences.end(); ++itSeq)
00370 {
00371 for (EventEntries::iterator itEv = itSeq->m_events.begin();
00372 itEv != itSeq->m_events.end(); ++itEv)
00373 {
00374 if (itEv->m_eventPosition < 0)
00375 {
00376 out_eventText = "Sequence: " + itSeq->m_name
00377 + "\nEvent : " + itEv->m_eventTxt;
00378 out_fileName = itEv->m_fileName;
00379 out_lineNum = itEv->m_lineNum;
00380 return true;
00381 }
00382 }
00383 }
00384 return false;
00385
00386 }
00387
00388
00389
00390
00391
00392
00393 TTB_INLINE void CheckerForMultipleSequences::LogCheckResult (std::string const & in_headLine)
00394 {
00395 AutoLock o (&m_rTestEvents);
00396
00397 std::ostringstream outStr;
00398
00399 outStr << in_headLine << std::endl << std::endl;
00400
00401 for (int idxRecEv = 0; idxRecEv < NumElements(m_rTestEvents.m_events); ++idxRecEv)
00402 {
00403 EventEntry* pSeqEv = m_recEv2SeqEv[idxRecEv];
00404 if (pSeqEv)
00405 {
00406 std::ostringstream seqIdStr;
00407 seqIdStr << m_sequences[pSeqEv->m_idxSequence].m_name << "-" << pSeqEv->m_idxEvent;
00408 outStr << std::left << std::setw(WIDTH_SEQUENTIAL_ID) << seqIdStr.str();
00409 m_rTestEvents.WriteEventEntry(idxRecEv, outStr);
00410 }
00411 else
00412 {
00413 m_rTestEvents.WriteEventEntry(idxRecEv, outStr, SEQUENTIAL_ID_EMPTY);
00414 }
00415 }
00416
00417 if (m_rTestEvents.m_pIEventReceiver)
00418 {
00419 m_rTestEvents.m_pIEventReceiver->Event (TestToolBox::CTX_INFO, outStr. str());
00420 }
00421
00422
00423 if (m_rTestEvents.m_pIProtocol)
00424 {
00425 m_rTestEvents.m_pIProtocol->SetMode(OutputMode::M_OUTFILE);
00426 m_rTestEvents.m_pIProtocol->Writeln();
00427 m_rTestEvents.m_pIProtocol->Writeln(outStr. str());
00428 }
00429
00430 }
00431
00432
00433
00434
00435
00436
00437 };
00438
00439
00440
00441
00442
00443 #pragma warning( pop )