1 //===- skypat.cpp ---------------------------------------------------------===//
2 //
3 //                     The SkyPat Team
4 //
5 // This file is distributed under the New BSD License.
6 // See LICENSE for details.
7 //
8 //===----------------------------------------------------------------------===//
9 #include <skypat/skypat.h>
10 #include <skypat/Support/Timer.h>
11 #include <skypat/Support/Perf.h>
12 #include <skypat/Support/ManagedStatic.h>
13 #include <skypat/Support/OStrStream.h>
14 #include <vector>
15 #include <cassert>
16 #include <cstdlib>
17 #include <ios>
18 #include <ostream>
19 #include <iostream>
20 #include <stdint.h>
21 #include <algorithm>
22 #include <cstdio>
23 #include <time.h>
24 
25 #include <skypat/Config/Config.h>
26 
27 using namespace skypat;
28 
29 /* Define the numebr of iteration of performance loop */
30 #define SKYPAT_PERFORM_LOOP_TIMES 1
31 
32 namespace skypat{
33 /* Establish perf event string array */
34 char const *Perf_event_name[] = {
35   "CPU CYCLES", "INST   NUM",
36   "CACHE  REF", "CACHE MISS",
37   "BR    INST", "BR  MISSES",
38   "BUS CYCLES", "STALLFRONT",
39   "STALL BACK", "REF CYCLES",
40   "CPU  CLOCK", "TASK CLOCK",
41   "PAGEFAULTS", "CTX SWITCH",
42   "CPUMIGRATE", "PG FAULT m",
43   "PG FAULT M", "ALIGNFAULT",
44   "EMU  FAULT", "D U M M Y "
45 };
46 } // namespace of skypat
47 
48 //===----------------------------------------------------------------------===//
49 // Non-member function
50 //===----------------------------------------------------------------------===//
51 testing::TestInfo*
MakeAndRegisterTestInfo(const char * pCaseName,const char * pTestName,testing::TestFactoryBase * pFactory)52 testing::MakeAndRegisterTestInfo(const char* pCaseName, const char* pTestName,
53                                  testing::TestFactoryBase* pFactory)
54 {
55   return testing::UnitTest::self()->addTestInfo(pCaseName, pTestName, *pFactory);
56 }
57 
GetBoolAssertionFailureMessage(const skypat::testing::AssertionResult & pAssertionResult,const char * pExpressionText,const char * pActualPredicateValue,const char * pExpectedPredicateValue)58 std::string testing::GetBoolAssertionFailureMessage(
59     const skypat::testing::AssertionResult& pAssertionResult,
60     const char* pExpressionText,
61     const char* pActualPredicateValue,
62     const char* pExpectedPredicateValue)
63 {
64   std::string result;
65   OStrStream OS(result);
66   OS << "Value of: " << pExpressionText
67      << "\n  Actual:   " << pActualPredicateValue;
68   if (pAssertionResult.hasMessage())
69     OS << "(" << pAssertionResult.message() << ")";
70   OS << "\n  Expected: " << pExpectedPredicateValue;
71   return result;
72 }
73 
74 //===----------------------------------------------------------------------===//
75 // PerfIterator
76 //===----------------------------------------------------------------------===//
PerfIterator(const char * pFile,int pLine)77 testing::PerfIterator::PerfIterator(const char* pFile, int pLine)
78   : m_Counter(0),
79     m_pTimer(new internal::Timer()),
80     m_pPerf(new internal::Perf()),
81     m_pPerfResult(testing::UnitTest::self()->addPerfPartResult(pFile, pLine)) {
82 
83   m_pTimer->start();
84   m_pPerf->start();
85 }
86 
PerfIterator(const char * pFile,int pLine,enum PerfEvent pEvent)87 testing::PerfIterator::PerfIterator(const char* pFile, int pLine,\
88 									enum PerfEvent pEvent)
89   : m_Counter(0),
90     m_pTimer(new internal::Timer()),
91     m_pPerf(new internal::Perf(pEvent)),
92     m_pPerfResult(testing::UnitTest::self()->addPerfPartResult(pFile, pLine)) {
93 
94   m_pTimer->start();
95   m_pPerf->start();
96 }
97 
~PerfIterator()98 testing::PerfIterator::~PerfIterator()
99 {
100   delete m_pTimer;
101   delete m_pPerf;
102 }
103 
hasNext() const104 bool testing::PerfIterator::hasNext() const
105 {
106   if (m_Counter < SKYPAT_PERFORM_LOOP_TIMES)
107     return true;
108 
109   m_pTimer->stop();
110   m_pPerf->stop();
111 
112   m_pPerfResult->setTimerNum(m_pTimer->interval());
113   m_pPerfResult->setPerfEventNum(m_pPerf->interval());
114   m_pPerfResult->setPerfEventType(m_pPerf->eventType());
115   return false;
116 }
117 
next()118 testing::PerfIterator& testing::PerfIterator::next()
119 {
120   ++m_Counter;
121   return *this;
122 }
123 
124 //===----------------------------------------------------------------------===//
125 // PartResult
126 //===----------------------------------------------------------------------===//
PartResult(const std::string & pFileName,int pLoC)127 testing::PartResult::PartResult(const std::string& pFileName, int pLoC)
128   : m_FileName(pFileName), m_LoC(pLoC), m_Message() {
129 }
130 
PartResult(const std::string & pFileName,int pLoC,const std::string & pMessage)131 testing::PartResult::PartResult(const std::string& pFileName,
132                                 int pLoC,
133                                 const std::string& pMessage)
134   : m_FileName(pFileName), m_LoC(pLoC), m_Message(pMessage) {
135 }
136 
137 //===----------------------------------------------------------------------===//
138 // TestPartResult
139 //===----------------------------------------------------------------------===//
TestPartResult(Type pType,const std::string & pFileName,int pLoC,const std::string & pMessage)140 testing::TestPartResult::TestPartResult(Type pType,
141                                         const std::string& pFileName,
142                                         int pLoC,
143                                         const std::string& pMessage)
144   : PartResult(pFileName, pLoC, pMessage), m_Type(pType) {
145 }
146 
147 testing::TestPartResult&
appendUserMessage(const std::string & pMessage)148 testing::TestPartResult::appendUserMessage(const std::string& pMessage)
149 {
150   if (!pMessage.empty())
151     update_message(message() + "\n" + pMessage);
152   return *this;
153 }
154 
155 //===----------------------------------------------------------------------===//
156 // PerfPartResult
157 //===----------------------------------------------------------------------===//
PerfPartResult(const std::string & pFileName,int pLoC)158 testing::PerfPartResult::PerfPartResult(const std::string& pFileName,
159                                         int pLoC)
160   : PartResult(pFileName, pLoC) {
161 }
162 
getTimerNum() const163 testing::Interval testing::PerfPartResult::getTimerNum() const
164 {
165   return m_PerfTimerNum;
166 }
167 
getPerfEventNum() const168 testing::Interval testing::PerfPartResult::getPerfEventNum() const
169 {
170   return m_PerfEventNum;
171 }
172 
getPerfEventType() const173 testing::Interval testing::PerfPartResult::getPerfEventType() const
174 {
175   return m_PerfEventType;
176 }
177 
setTimerNum(testing::Interval pTimerNum)178 void testing::PerfPartResult::setTimerNum(testing::Interval pTimerNum)
179 {
180   m_PerfTimerNum = pTimerNum;
181   OStrStream os(m_Message);
182   os << pTimerNum << " ns;";
183 }
184 
setPerfEventNum(testing::Interval pEventNum)185 void testing::PerfPartResult::setPerfEventNum(testing::Interval pEventNum)
186 {
187   m_PerfEventNum = pEventNum;
188 }
189 
setPerfEventType(testing::Interval pEventType)190 void testing::PerfPartResult::setPerfEventType(testing::Interval pEventType)
191 {
192   m_PerfEventType = pEventType;
193 }
194 
195 //===----------------------------------------------------------------------===//
196 // TestResult
197 //===----------------------------------------------------------------------===//
TestResult(const TestInfo & pInfo)198 testing::TestResult::TestResult(const TestInfo& pInfo)
199   : m_Info(pInfo), m_Conclusion(kNotTested) {
200 }
201 
~TestResult()202 testing::TestResult::~TestResult()
203 {
204 }
205 
isPassed() const206 bool testing::TestResult::isPassed() const
207 {
208   return (kPassed == m_Conclusion);
209 }
210 
isFailed() const211 bool testing::TestResult::isFailed() const
212 {
213   return (kFailed == m_Conclusion);
214 }
215 
reliability() const216 const testing::TestResult::Reliability& testing::TestResult::reliability() const
217 {
218   return m_Info.getTestResults();
219 }
220 
performance() const221 const testing::TestResult::Performance& testing::TestResult::performance() const
222 {
223   return m_Info.getPerfResults();
224 }
225 
226 //===----------------------------------------------------------------------===//
227 // TestCase
228 //===----------------------------------------------------------------------===//
TestCase(const std::string & pCaseName)229 testing::TestCase::TestCase(const std::string& pCaseName)
230   : m_CaseName(pCaseName)
231 {
232 }
233 
~TestCase()234 testing::TestCase::~TestCase()
235 {
236   InfoList::iterator info, iEnd = m_InfoList.end();
237   for (info = m_InfoList.begin(); info != iEnd; ++info) {
238     delete (*info);
239   }
240 }
241 
242 testing::TestInfo*
addTestInfo(const std::string & pTestName,testing::TestFactoryBase & pFactory)243 testing::TestCase::addTestInfo(const std::string& pTestName,
244                                testing::TestFactoryBase& pFactory)
245 {
246   testing::TestInfo* info = new testing::TestInfo(this, pTestName, pFactory);
247   m_InfoList.push_back(info);
248   return info;
249 }
250 
251 //===----------------------------------------------------------------------===//
252 // TestInfo
253 //===----------------------------------------------------------------------===//
TestInfo(TestCase * pTestCase,const std::string & pTestName,testing::TestFactoryBase & pFactory)254 testing::TestInfo::TestInfo(TestCase* pTestCase,
255                             const std::string& pTestName,
256                             testing::TestFactoryBase& pFactory)
257   : m_pTestCase(pTestCase),
258     m_TestName(pTestName),
259     m_Result(*this),
260     m_pFactory(&pFactory) {
261 }
262 
~TestInfo()263 testing::TestInfo::~TestInfo()
264 {
265   delete m_pFactory;
266   TestPartResultList::iterator tt, tEnd = m_TestResultList.end();
267   for (tt = m_TestResultList.begin(); tt != tEnd; ++tt) {
268     delete (*tt);
269   }
270   PerfPartResultList::iterator pt, pEnd = m_PerfResultList.end();
271   for (pt = m_PerfResultList.begin(); pt != pEnd; ++pt) {
272     delete (*pt);
273   }
274 }
275 
run()276 void testing::TestInfo::run()
277 {
278   UnitTest& unittest = *UnitTest::self();
279   Repeater& repeater = unittest.repeater();
280   skypat::Test* test = m_pFactory->CreateTest();
281   if (NULL != test) {
282     repeater.OnSetUpStart(unittest);
283     test->SetUp();
284     repeater.OnSetUpEnd(unittest);
285 
286     repeater.OnTestStart(*this);
287     test->run();
288     repeater.OnTestEnd(*this);
289 
290     repeater.OnTearDownStart(unittest);
291     test->TearDown();
292     repeater.OnTearDownEnd(unittest);
293   }
294   delete test;
295 }
296 
addTestPartResult(const TestPartResult & pResult)297 void testing::TestInfo::addTestPartResult(const TestPartResult& pResult)
298 {
299   if (m_TestResultList.empty()) {
300     m_Result.setConclusion(testing::TestResult::kPassed);
301   }
302 
303   if (testing::TestPartResult::kSuccess != pResult.type()) {
304     m_Result.setConclusion(testing::TestResult::kFailed);
305     m_TestResultList.push_back(new TestPartResult(pResult));
306   }
307 }
308 
309 testing::PerfPartResult*
addPerfPartResult(const char * pFile,int pLine)310 testing::TestInfo::addPerfPartResult(const char* pFile, int pLine)
311 {
312   PerfPartResult* perf_pr = new PerfPartResult(pFile, pLine);
313   m_PerfResultList.push_back(perf_pr);
314   return perf_pr;
315 }
316 
317 //===----------------------------------------------------------------------===//
318 // AssertionResult
319 //===----------------------------------------------------------------------===//
AssertionResult(const AssertionResult & pOther)320 skypat::testing::AssertionResult::AssertionResult(const AssertionResult& pOther)
321   : m_bSuccess(pOther.m_bSuccess), m_Message(pOther.m_Message) {
322 }
323 
AssertionResult(bool pSuccess)324 skypat::testing::AssertionResult::AssertionResult(bool pSuccess)
325   : m_bSuccess(pSuccess) {
326 }
327 
328 skypat::testing::AssertionResult
operator !() const329 skypat::testing::AssertionResult::operator!() const
330 {
331   AssertionResult negative(!m_bSuccess);
332   negative << m_Message;
333   return negative;
334 }
335 
336 template <typename T> skypat::testing::AssertionResult&
operator <<(const T & pValue)337 skypat::testing::AssertionResult::operator<<(const T& pValue)
338 {
339   skypat::OStrStream OS(m_Message);
340   OS << pValue;
341   return *this;
342 }
343 
344 skypat::testing::AssertionResult&
operator <<(::std::ostream & (* basic_manipulator)(::std::ostream & stream))345 skypat::testing::AssertionResult::operator<<(
346                   ::std::ostream& (*basic_manipulator)(::std::ostream& stream))
347 {
348   skypat::OStrStream OS(m_Message);
349   OS << basic_manipulator;
350   return *this;
351 }
352 
353 //===----------------------------------------------------------------------===//
354 // Message
355 //===----------------------------------------------------------------------===//
Message()356 skypat::testing::Message::Message()
357   : m_Message(), m_OSS(m_Message) {
358 }
359 
360 //===----------------------------------------------------------------------===//
361 // AssertHelper
362 //===----------------------------------------------------------------------===//
AssertHelper(TestPartResult::Type pType,const std::string & pFile,int pLineOfCode,const std::string & pMessage)363 skypat::testing::AssertHelper::AssertHelper(TestPartResult::Type pType,
364                                          const std::string& pFile,
365                                          int pLineOfCode,
366                                          const std::string& pMessage)
367   : m_Result(pType, pFile, pLineOfCode, pMessage) {
368   // m_Result is a TestPartResult
369 }
370 
371 // Store a run-time result
operator =(const Message & pMesg)372 void skypat::testing::AssertHelper::operator=(const Message& pMesg)
373 {
374   m_Result.appendUserMessage(pMesg.str());
375   UnitTest::self()->addTestPartResult(m_Result);
376 }
377 
378 //===----------------------------------------------------------------------===//
379 // Log
380 //===----------------------------------------------------------------------===//
Log(Severity pSeverity,const std::string & pFileName,int pLoC)381 testing::Log::Log(Severity pSeverity,
382                   const std::string& pFileName,
383                   int pLoC)
384   : m_Severity(pSeverity) {
385   const char* const mesg =
386     kInfo    == pSeverity ? "[  INFO ]" :
387     kWarning == pSeverity ? "[WARNING]" :
388     kError   == pSeverity ? "[ ERROR ]" : "[ FATAL ]";
389 
390   getOStream() << std::endl << mesg << FormatFileLocation(pFileName, pLoC)
391                << ": ";
392 }
393 
~Log()394 testing::Log::~Log()
395 {
396   getOStream() << std::endl;
397   if (kFatal == m_Severity) {
398     shutdown();
399     fflush(stderr);
400     exit(1);
401   }
402 }
403 
getOStream()404 ::std::ostream& testing::Log::getOStream()
405 {
406   return ::std::cerr;
407 }
408 
409 std::string
FormatFileLocation(const std::string & pFileName,int pLoC)410 testing::Log::FormatFileLocation(const std::string& pFileName, int pLoC)
411 {
412   std::string result;
413   OStrStream OS(result);
414   if (pFileName.empty())
415     OS << "(unknown file)";
416   else
417     OS << pFileName;
418 
419   if (pLoC < 0) {
420     OS << ":";
421     return result;
422   }
423 #ifdef _MSC_VER
424   OS << "(" << pLoC << "):";
425 #else
426   OS << ":" << pLoC << ":";
427 #endif  // _MSC_VER
428   return result;
429 }
430