1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     test_Suite.cpp
4 
5   Copyright (C)2009 Nintendo Co., Ltd.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Rev: 29453 $
14  *---------------------------------------------------------------------------*/
15 
16 #include <nn/test/test_Suite.h>
17 #include <nn/test/test_Output.h>
18 #include <nn/test/test_Time.h>
19 #include <nn/test/test_Api.h>
20 #include <nn/dbg/dbg_PrintResult.h>
21 namespace nn{ namespace test{
22 
23     namespace {
24         Suite* s_CurrentSuite = 0;
25 
26 #ifdef NN_PROCESSOR_ARM946ES
27         const int NUM_RESULTHOLDER = 32;
28         const bit32 INVALID_THREADID = 0xffffffff;
29 
30         struct ThreadLocalStrageArm9 {
31             bit32 threadId;
32             uptr  value;
33         } s_ResultHolderArm9[NUM_RESULTHOLDER];
34 #endif
35     }
36 
Suite()37     Suite::Suite() :
38         m_pOutput(NULL), m_TotalTestsNum(0), m_pExitTestJumpBuffer(NULL),
39             m_IsSuccess(false), m_Continue(false), m_IsInitialized(false), m_MainThreadId(nn::os::Thread::GetCurrentId())
40     {
41 #ifdef NN_PROCESSOR_ARM946ES
42         for ( int i = 0; i < NUM_RESULTHOLDER; i++ )
43         {
44             s_ResultHolderArm9[i].threadId = INVALID_THREADID;
45             s_ResultHolderArm9[i].value = 0;
46         }
47 #endif
48     }
49 
~Suite()50     Suite::~Suite()
51     {
52     }
53 
IsOnMainThread() const54     bool Suite::IsOnMainThread() const
55     {
56         return m_MainThreadId == nn::os::Thread::GetCurrentId();
57     }
58 
AddSubSuite(Suite * pSuite)59     void Suite::AddSubSuite(Suite* pSuite)
60     {
61         m_SubSuites.PushBack(pSuite);
62         m_TotalTestsNum += pSuite->m_TotalTestsNum;
63     }
64 
Run(Output & output,bool isContinue)65     bool Suite::Run(Output& output, bool isContinue)
66     {
67         int total = TotalTests();               // サブスイートを含むテスト数
68         int subSuiteNum = m_SubSuites.GetNum();
69 
70         // テスト開始前の初期化
71         m_Continue = isContinue;
72         output.OnInitialize(total, (subSuiteNum+1));
73         Initialize();
74 
75         Time    time;
76         time.Start();
77         DoRun(&output, isContinue);
78         time.End();
79         output.OnFinished(total, time);
80         Finalize();
81         return m_IsSuccess;
82     }
83 
DoRun(Output * pOutput,bool isContinue)84     void Suite::DoRun(Output* pOutput, bool isContinue)
85     {
86         m_IsSuccess = true;
87         int testsNum = m_Tests.GetNum();        // サブスイートを含まないテスト数
88         m_pOutput = pOutput;
89 
90         // このスイートが保持するテストを実行
91         pOutput->OnSuiteStart(testsNum, m_TestName);
92         Time timeSuite;
93         timeSuite.Start();
94         while(!m_Tests.IsEmpty())
95         {
96             TestInfo info = m_Tests.PopFront();
97             bool testResult = DoRunSpecificTest(info, pOutput);
98             m_IsSuccess &= testResult;
99         }
100         timeSuite.End();
101         pOutput->OnSuiteEnd(testsNum, m_TestName, timeSuite);
102 
103         // 子スイートの実行
104         while(!m_SubSuites.IsEmpty())
105         {
106             Suite* pSuite = m_SubSuites.PopFront();
107             pSuite->Initialize();
108             pSuite->DoRun(pOutput, isContinue);
109             pSuite->Finalize();
110             m_IsSuccess &= pSuite->m_IsSuccess;
111         }
112     }
113 
AddAssertInfo(AssertInfo info)114     void Suite::AddAssertInfo(AssertInfo info)
115     {
116         m_pOutput->OnAssert(info);
117         // 1回でもアサートに引っかかっているならこのテストは失敗
118         m_IsTestSuccess = false;
119     }
120 
RegisterTest(TestFunc func,const String & name)121     void Suite::RegisterTest(TestFunc func, const String& name)
122     {
123         m_Tests.PushBack(TestInfo(func, name));
124         m_TotalTestsNum++;
125     }
126 
UnregisterTest(TestFunc func)127     void Suite::UnregisterTest(TestFunc func)
128     {
129         NN_TASSERT_(m_TotalTestsNum == m_Tests.GetNum());
130         for (int i = 0; i < m_TotalTestsNum; i++)
131         {
132             if (m_Tests.GetElement(i).testFunc == func)
133             {
134                 m_Tests.DeleteElement(i);
135                 i--;
136                 m_TotalTestsNum--;
137             }
138         }
139     }
140 
RegisterTestWithInfo(TestFunc func,const String & name,const String & info)141     void Suite::RegisterTestWithInfo(TestFunc func, const String& name, const String& info)
142     {
143         m_Tests.PushBack(TestInfo(func, name, info));
144         m_TotalTestsNum++;
145     }
146 
ExitCurrentTest()147     void Suite::ExitCurrentTest()
148     {
149         if (!IsOnMainThread())
150         {
151             // メインスレッドでなかったらスレッドを強制終了
152             nn::svc::ExitThread();
153             NN_TASSERT_(0);
154         }
155         if(m_pExitTestJumpBuffer)
156         {
157             ::std::longjmp(*m_pExitTestJumpBuffer, 1);
158         }
159         else
160         {
161             NN_TPANIC_("Failed long jump, Suite::ExitCurrentTest()");
162         }
163     }
164 
OnPanic(const char * pFilename,int lineNo,const char * pMessage)165     void Suite::OnPanic(const char* pFilename, int lineNo, const char* pMessage)
166     {
167         AddAssertInfo(AssertInfo(pFilename, lineNo, pMessage));
168         ExitCurrentTest();
169     }
170 
171     nn::os::ThreadLocalStorage Suite::ResultHolder::tls_pExpectedResult;
172 
GetCurrent()173     inline Suite::ResultHolder* Suite::ResultHolder::GetCurrent()
174     {
175 #ifndef NN_PROCESSOR_ARM946ES
176         return reinterpret_cast<Suite::ResultHolder*>(tls_pExpectedResult.GetValue());
177 #else
178         bit32 threadId = nn::os::Thread::GetCurrentId();
179         for ( int i = 0; i < NUM_RESULTHOLDER; i++ )
180         {
181             if ( threadId == s_ResultHolderArm9[i].threadId )
182             {
183                 return reinterpret_cast<Suite::ResultHolder*>(s_ResultHolderArm9[i].value);
184             }
185         }
186         return 0;
187 #endif
188     }
189 
SetCurrent(Suite::ResultHolder * result)190     inline void Suite::ResultHolder::SetCurrent(Suite::ResultHolder* result)
191     {
192 #ifndef NN_PROCESSOR_ARM946ES
193         tls_pExpectedResult.SetValue(reinterpret_cast<uptr>(result));
194 #else
195         bit32 threadId = nn::os::Thread::GetCurrentId();
196         int lastBlank = -1;
197         for ( int i = 0; i < NUM_RESULTHOLDER; i++ )
198         {
199             if ( threadId == s_ResultHolderArm9[i].threadId )
200             {
201                 s_ResultHolderArm9[i].value = reinterpret_cast<uptr>(result);
202                 return;
203             }
204             if ( s_ResultHolderArm9[i].threadId == INVALID_THREADID )
205             {
206                 lastBlank = i;
207             }
208         }
209         if ( lastBlank != -1 )
210         {
211             s_ResultHolderArm9[lastBlank].threadId = threadId;
212             s_ResultHolderArm9[lastBlank].value = reinterpret_cast<uptr>(result);
213             return;
214         }
215         NN_LOG("Is not empty ThreadLocalStorage for Arm9");
216         nn::svc::Break(nn::dbg::BREAK_REASON_PANIC);
217 #endif
218     }
219 
GetCurrentResult()220     Result Suite::ResultHolder::GetCurrentResult()
221     {
222         return GetCurrent()->m_Result;
223     }
224 
ResultHolder()225     Suite::ResultHolder::ResultHolder()
226     {
227         NN_TASSERT_(!GetCurrent());
228         SetCurrent(this);
229     }
230 
~ResultHolder()231     Suite::ResultHolder::~ResultHolder()
232     {
233         NN_TASSERT_(GetCurrent());
234 #ifndef NN_PROCESSOR_ARM946ES
235         SetCurrent(0);
236 #else
237         bit32 threadId = nn::os::Thread::GetCurrentId();
238         bool foundStorage = false;
239         for ( int i = 0; i < NUM_RESULTHOLDER; i++ )
240         {
241             if ( threadId == s_ResultHolderArm9[i].threadId )
242             {
243                 s_ResultHolderArm9[i].threadId = INVALID_THREADID;
244                 s_ResultHolderArm9[i].value = 0;
245                 foundStorage = true;
246             }
247         }
248         if ( !foundStorage )
249         {
250             NN_LOG("Not found ThreadLocalStorage for Arm9");
251             nn::svc::Break(nn::dbg::BREAK_REASON_PANIC);
252         }
253 #endif
254     }
255 
GetJmpbuf()256     ::std::jmp_buf* Suite::ResultHolder::GetJmpbuf()
257     {
258         return &m_Jmpbuf;
259     }
260 
ResultFailureHandler(Result result,const char * filename,int lineno,const char * fmt,::std::va_list vlist)261     void Suite::ResultHolder::ResultFailureHandler(Result result, const char* filename, int lineno, const char* fmt, ::std::va_list vlist)
262     {
263         if (GetCurrent())
264         {
265             GetCurrent()->m_Result = result;
266             longjmp(GetCurrent()->m_Jmpbuf, 1);
267             NN_TLOG_("longjmp failed.");
268             nn::svc::Break(nn::dbg::BREAK_REASON_PANIC);
269         }
270         else
271         {
272             char buf[256];
273             ::std::vsnprintf(buf, sizeof(buf), fmt, vlist);
274             NN_TLOG_("Result Failure\n");
275             nn::dbg::PrintResult(result);
276 
277             NN_TASSERT_(s_CurrentSuite);
278             s_CurrentSuite->OnPanic(filename, lineno, buf);
279             // 戻ってこないはず
280             NN_TLOG_("Failed OnPanic\n");
281             nn::svc::Break(nn::dbg::BREAK_REASON_PANIC);
282         }
283     }
284 
ResultPanicHandler(Result result,const char * filename,int lineno,const char * fmt,::std::va_list vlist)285     void Suite::ResultHolder::ResultPanicHandler(Result result, const char* filename, int lineno, const char* fmt, ::std::va_list vlist)
286     {
287         if (GetCurrent())
288         {
289             GetCurrent()->m_Result = result;
290             longjmp(GetCurrent()->m_Jmpbuf, 1);
291             NN_TLOG_("longjmp failed.");
292             nn::svc::Break(nn::dbg::BREAK_REASON_PANIC);
293         }
294         else
295         {
296             NN_TASSERT_(s_CurrentSuite);
297             char buf[256];
298             ::std::vsnprintf(buf, sizeof(buf), fmt, vlist);
299             NN_TLOG_("Panic Result\n");
300             nn::dbg::PrintResult(result);
301             s_CurrentSuite->OnPanic(filename, lineno, buf);
302             // 戻ってこないはず
303             NN_TLOG_("Failed OnPanic\n");
304             nn::svc::Break(nn::dbg::BREAK_REASON_PANIC);
305         }
306     }
307 
RunSpecificTestFunc(const char * testFuncName,Output & output,bool contAfterFail)308     bool    Suite::RunSpecificTestFunc(const char* testFuncName, Output& output, bool contAfterFail)
309     {
310         //該当するテスト関数の含んだTestInfoの取得
311         String funcNameStr = String(testFuncName);
312         TestInfo testInfo;
313         if(GetTestInfo(funcNameStr, testInfo) == false)
314         {
315             //Suiteに該当するテスト関数が登録されていない場合
316             return false;
317         }
318 
319         PreProcessForSpecificTest(&output, contAfterFail);
320         bool result = DoRunSpecificTest(testInfo, &output);
321         PostProcessForSpecificTest();
322 
323         return result;
324     }
325 
RunSpecificTestFunc(const char * subSuiteName,const char * testFuncName,Output & output,bool contAfterFail)326     bool    Suite::RunSpecificTestFunc(const char* subSuiteName, const char* testFuncName, Output& output, bool contAfterFail)
327     {
328         //サブSuiteの取得
329         Suite* correspondSuite = NULL;
330         String suiteNameStr = String(subSuiteName);
331         if(GetSubSuite(suiteNameStr, &correspondSuite) == false)
332         {
333             //指定されたサブSuiteが存在しない場合
334             return false;
335         }
336 
337         return correspondSuite->RunSpecificTestFunc(testFuncName, output, contAfterFail);
338     }
339 
RunSpecificTestFunc(s32 testFuncId,Output & output,bool contAfterFail)340     bool    Suite::RunSpecificTestFunc(s32 testFuncId, Output& output, bool contAfterFail)
341     {
342         //該当するテスト関数の含んだTestInfoの取得
343         TestInfo testInfo;
344         if(GetTestSuiteAndInfo(testFuncId, NULL, testInfo) == false)
345         {
346             //Suiteに該当するテスト関数が登録されていない場合
347             return false;
348         }
349 
350         PreProcessForSpecificTest(&output, contAfterFail);
351         bool result = DoRunSpecificTest(testInfo, &output);
352         PostProcessForSpecificTest();
353 
354         return result;
355     }
356 
GetTestFuncInfos(s32 testId,String & suiteName,String & testFuncName)357     bool Suite::GetTestFuncInfos(s32 testId, String& suiteName, String& testFuncName)
358     {
359        Suite* correspondSuite = NULL;
360        TestInfo correspondTestInfo;
361        bool resultGetInfo = GetTestSuiteAndInfo(testId, &correspondSuite, correspondTestInfo);
362        if(resultGetInfo == true)
363        {
364            suiteName = correspondSuite->GetTestName();
365            testFuncName = correspondTestInfo.testName;
366            return true;
367        }
368        else
369        {
370            return false;
371        }
372     }
373 
GetTestFuncInfos(s32 testId,String & suiteName,String & testFuncName,String & testInfo)374     bool Suite::GetTestFuncInfos(s32 testId, String& suiteName, String& testFuncName, String& testInfo)
375     {
376        Suite* correspondSuite = NULL;
377        TestInfo correspondTestInfo;
378        bool resultGetInfo = GetTestSuiteAndInfo(testId, &correspondSuite, correspondTestInfo);
379        if(resultGetInfo == true)
380        {
381            suiteName = correspondSuite->GetTestName();
382            testFuncName = correspondTestInfo.testName;
383            testInfo = correspondTestInfo.testInfo;
384            return true;
385        }
386        else
387        {
388            return false;
389        }
390     }
391 
392 
DoRunSpecificTest(Suite::TestInfo & testInfo,Output * pOutput)393     bool    Suite::DoRunSpecificTest(Suite::TestInfo& testInfo, Output* pOutput)
394     {
395         /*
396          * テストの成否は、m_IsTestSuccessに設定する。テスト開始前にm_IsTestSuccessをtrueに設定し、失敗時にはfalseを再設定する
397          */
398         m_IsTestSuccess = true;
399         Time timeCase;
400         bool testResult = true;
401 
402         SetUp();
403 
404         pOutput->OnTestStart(testInfo.testName);
405 
406         timeCase.Start();
407         ::std::jmp_buf jumpBuf;
408         m_pExitTestJumpBuffer = &jumpBuf;
409         s_CurrentSuite = this;
410         if(setjmp(jumpBuf) == 0)
411         {
412             (this->*testInfo.testFunc)();
413         }
414         else
415         {
416             /*
417                                       「assertにかかると、以降のテストを継続しない」モードのテストでは、ExitCurrentTest が呼ばれこのパスに入る。
418               (モードはRun()やRunSpecificTestFunc()の引数で指定)
419                                       「assertにかかっても、以降のテストを継続する」モードのテストでは、assert時はこのパスに入らない。
420                                       代わりにSuite::AddAssertInfo()に入り、m_IsTestSuccessを設定する。
421              */
422             m_IsTestSuccess = false;
423         }
424         m_pExitTestJumpBuffer = NULL;
425         s_CurrentSuite = 0;
426         timeCase.End();
427         pOutput->OnTestEnd(testInfo.testName, testResult, timeCase);
428 
429         TearDown();
430 
431         return m_IsTestSuccess;
432     }
433 
GetSubSuite(String & subSuiteName,Suite ** ppSuite)434     bool Suite::GetSubSuite(String& subSuiteName, Suite** ppSuite)
435     {
436         NN_TASSERT_(ppSuite != NULL);
437         bool isSuiteFound = false;
438         const u32 subSuiteNum = m_SubSuites.GetNum();
439 
440         for(unsigned int i = 0; i < subSuiteNum; ++i)
441         {
442             Suite* suitPos = m_SubSuites.GetElement(i);
443             if(suitPos->GetTestName() == subSuiteName)
444             {
445                 *ppSuite = suitPos;
446                 isSuiteFound = true;
447                 break;
448             }
449         }
450 
451         return isSuiteFound;
452     }
453 
GetTestSuiteAndInfo(s32 testId,Suite ** ppSuite,Suite::TestInfo & testInfoBuf)454     bool Suite::GetTestSuiteAndInfo(s32 testId, Suite** ppSuite, Suite::TestInfo& testInfoBuf)
455     {
456         //IDに該当するテスト関数が存在するかを確認
457          if(testId > m_TotalTestsNum)
458          {
459              //存在しない場合
460              return false;
461          }
462 
463          //IDに該当するテスト関数が、このSuite自身に存在するのか、サブSuite内に存在するかを確認
464          if(testId <= m_Tests.GetNum())
465          {
466              //このSuite自身に存在する場合
467              if(GetTestInfo(testId, testInfoBuf) == false)
468              {
469                  return false;
470              }
471 
472              if(ppSuite != NULL)
473              {
474                 *ppSuite = this;
475              }
476              return true;
477          }
478          else
479          {
480              //サブSuiteに存在する場合
481              u32 checkedIdMax = m_Tests.GetNum();//確認済みのIDの最大値。IDに該当する関数がどのサブSuiteに存在するかを調査するために用いる。//
482              const u32 subSuiteNum = m_SubSuites.GetNum();
483              for(unsigned int i = 0; i < subSuiteNum; ++i)
484              {
485                  Suite* pSuit = m_SubSuites.GetElement(i);
486                  const u32 subSuiteMaxId = checkedIdMax + pSuit->GetTotalTestNum();
487                  if(testId > subSuiteMaxId)
488                  {
489                      //pSuitが示すサブSuiteにIDが含まれないため、調査済みIDを更新し、次のサブSuiteの調査に移る。
490                      checkedIdMax = subSuiteMaxId;
491                  }
492                  else
493                  {
494                      /*
495                       * pSuitが示すサブSuiteにIDが含まれる場合は、そのサブSuiteのGetTestSuiteAndInfo()でSuiteとTestInfoを得る。
496                       * 引数のIDは、サブSuite基点でのtestIDに変換する。
497                       */
498                      const u32 testIdInSubSuite = testId - checkedIdMax;
499                      pSuit->GetTestSuiteAndInfo(testIdInSubSuite, ppSuite, testInfoBuf);
500                      break;
501                  }
502              }
503 
504              return true;
505          }
506     }
507 
508 
GetTestInfo(String funcName,Suite::TestInfo & testInfoBuf)509     bool Suite::GetTestInfo(String funcName, Suite::TestInfo& testInfoBuf)
510     {
511         bool isInfoFound = false;
512         const u32 infoNum = m_Tests.GetNum();
513         for(unsigned int i = 0; i < infoNum; ++i)
514         {
515             TestInfo pTestInfo = m_Tests.GetElement(i);
516             if(pTestInfo.testName == funcName)
517             {
518                 isInfoFound = true;
519                 testInfoBuf = pTestInfo;
520                 break;
521             }
522         }
523 
524         return isInfoFound;
525     }
526 
527 
GetTestInfo(s32 testInfoId,Suite::TestInfo & testInfoBuf)528     bool Suite::GetTestInfo(s32 testInfoId, Suite::TestInfo& testInfoBuf)
529     {
530         //IDに該当するTestInfoが存在するかを確認
531         if((testInfoId > m_Tests.GetNum()) || (testInfoId == 0))
532         {
533             //存在しない場合
534             return false;
535         }
536 
537         testInfoBuf = m_Tests.GetElement((testInfoId-1));
538         return true;
539     }
540 
Initialize()541     void Suite::Initialize()
542     {
543         if(m_IsInitialized == false)
544         {
545             InitializeSuite();
546             m_IsInitialized = true;
547         }
548     }
549 
Finalize()550     void Suite::Finalize()
551     {
552         if(m_IsInitialized == true)
553         {
554             FinalizeSuite();
555             m_IsInitialized = false;
556         }
557     }
558 
PreProcessForSpecificTest(Output * pOutput,bool contAfterFail)559     void Suite::PreProcessForSpecificTest(Output* pOutput, bool contAfterFail)
560     {
561         Initialize();
562         m_Continue = contAfterFail;
563         m_pOutput = pOutput;
564         m_pOutput->OnInitialize(1, 1);
565         m_pOutput->OnSuiteStart(1, GetTestName());
566     }
567 
PostProcessForSpecificTest()568     void Suite::PostProcessForSpecificTest()
569     {
570         Time time;//特定テストの実施では、Suiteとしての実施時間を計測して意味がない(テスト単体の実施時間がわかればよい)ため、実施時刻には0を出力する//
571         m_pOutput->OnSuiteEnd(1, GetTestName(), time);
572         m_pOutput->OnFinished(1, time);
573         Finalize();
574     }
575 
GetCurrentSuite()576     Suite* Suite::GetCurrentSuite()
577     {
578         if ( !s_CurrentSuite )
579         {
580             NN_PANIC("No running test suite");
581         }
582         return s_CurrentSuite;
583     }
584 }}
585 
nnResultFailureHandler(nnResult result,const char * filename,int lineno,const char * fmt,...)586 extern "C" int nnResultFailureHandler(nnResult result, const char* filename, int lineno, const char* fmt, ...)
587 {
588     va_list vlist;
589     va_start(vlist, fmt);
590     nn::test::Suite::ResultHolder::ResultFailureHandler(reinterpret_cast<nn::Result&>(result), filename, lineno, fmt, vlist);
591     va_end(vlist);
592     return 0;
593 }
594 
nnResultTFailureHandler(nnResult result,const char * filename,int lineno,const char * fmt,...)595 extern "C" int nnResultTFailureHandler(nnResult result, const char* filename, int lineno, const char* fmt, ...)
596 {
597     va_list vlist;
598     va_start(vlist, fmt);
599     nn::test::Suite::ResultHolder::ResultFailureHandler(reinterpret_cast<nn::Result&>(result), filename, lineno, fmt, vlist);
600     va_end(vlist);
601     return 0;
602 }
603 
nnResultPanicHandler(nnResult result,const char * filename,int lineno,const char * fmt,...)604 extern "C" int nnResultPanicHandler(nnResult result, const char* filename, int lineno, const char* fmt, ...)
605 {
606     va_list vlist;
607     va_start(vlist, fmt);
608     nn::test::Suite::ResultHolder::ResultPanicHandler(reinterpret_cast<nn::Result&>(result), filename, lineno, fmt, vlist);
609     va_end(vlist);
610     return 0;
611 }
612 
nnResultTPanicHandler(nnResult result,const char * filename,int lineno,const char * fmt,...)613 extern "C" int nnResultTPanicHandler(nnResult result, const char* filename, int lineno, const char* fmt, ...)
614 {
615     va_list vlist;
616     va_start(vlist, fmt);
617     nn::test::Suite::ResultHolder::ResultPanicHandler(reinterpret_cast<nn::Result&>(result), filename, lineno, fmt, vlist);
618     va_end(vlist);
619     return 0;
620 }
621 /*
622 void nn::dbg::Panic(const char* filename, int lineno, const char* fmt, va_list vlist)
623 {
624     nn::Result result = nnMakeInvalidResult();
625     nn::test::Suite::ResultHolder::ResultPanicHandler(reinterpret_cast<nn::Result&>(result), filename, lineno, fmt, vlist);
626 }
627 
628 void nn::dbg::TVPanic(const char* filename, int lineno, const char* fmt, va_list vlist)
629 {
630     nn::Result result = nnMakeInvalidResult();
631     nn::test::Suite::ResultHolder::ResultPanicHandler(reinterpret_cast<nn::Result&>(result), filename, lineno, fmt, vlist);
632 }
633 */
634