Desurium/src/shared/uicore/code/gcUnitTestPage.cpp

348 lines
9.2 KiB
C++

/*
Desura is the leading indie game distribution platform
Copyright (C) 2011 Mark Chandler (Desura Net Pty Ltd)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#include "Common.h"
#include "gcUnitTestPage.h"
#include <wx/listctrl.h>
#include <gtest/gtest.h>
#include "managers/CVar.h"
using namespace testing;
#ifdef DEBUG
CVar g_bAssertOnFailure("unittest_assertonfailure", "true");
CVar g_bRunOnStartup("unittest_runonstartup", "true");
#else
CVar g_bAssertOnFailure("unittest_assertonfailure", "false");
CVar g_bRunOnStartup("unittest_runonstartup", "false");
#endif
CVar g_strUnitTestFilter("unittest_filter", "*");
class gcUnitTestWatcher : public EmptyTestEventListener
{
public:
void OnTestIterationStart(const UnitTest& unit_test, int iteration)
{
onStartEvent();
}
void OnTestIterationEnd(const UnitTest& unit_test, int iteration)
{
onEndEvent();
}
void OnTestStart(const TestInfo& test_info)
{
m_szLastTest = gcString("{0}/{1}", test_info.test_case_name(), test_info.name());
onTestStartEvent(m_szLastTest);
}
void OnTestPartResult(const TestPartResult& test_part_result)
{
if (test_part_result.failed() && g_bAssertOnFailure.getBool())
wxASSERT(FALSE);
}
void OnTestEnd(const TestInfo& test_info)
{
std::pair<gcString, bool> res = std::make_pair(m_szLastTest, test_info.result()->Passed());
std::pair<gcString, uint64> end = std::make_pair(m_szLastTest, (uint64)test_info.result()->elapsed_time());
onTestResultEvent(res);
onTestEndEnd(end);
}
gcString m_szLastTest;
EventV onStartEvent;
EventV onEndEvent;
Event<gcString> onTestStartEvent;
Event<std::pair<gcString,bool>> onTestResultEvent;
Event<std::pair<gcString,uint64>> onTestEndEnd;
};
class CUnitTestThread : public Thread::BaseThread
{
public:
CUnitTestThread()
: BaseThread("UnitTestThread")
{
}
void run()
{
m_strFilter = g_strUnitTestFilter.getString();
GTEST_FLAG(filter) = m_strFilter;
RUN_ALL_TESTS();
GTEST_FLAG(filter) = '\0';
#ifdef WIN32
//Reset this as gtest messes with it :'(
_set_error_mode(_OUT_TO_MSGBOX);
#endif
}
gcString m_strFilter;
};
static gcUnitTestWatcher* SetupTestWatcher()
{
gcUnitTestWatcher* pWatcher = new gcUnitTestWatcher();
TestEventListeners& listeners = UnitTest::GetInstance()->listeners();
listeners.Append(pWatcher);
#ifdef WIN32
UTIL::MISC::CMDArgs args(GetCommandLineA());
#else
char szCmdLine[255] = {0};
FILE* fh = fopen("/proc/self/cmdline", "r");
int nRead = fread(szCmdLine, 1, 255, fh);
for (int x = 0; x < nRead; ++x)
{
if (szCmdLine[x] == '\0')
szCmdLine[x] = ' ';
}
fclose(fh);
UTIL::MISC::CMDArgs args(szCmdLine);
#endif
int argc = args.getArgc();
InitGoogleTest(&argc, const_cast<char**>(args.getArgv()));
return pWatcher;
}
static gcUnitTestWatcher *g_pTestWatcher = SetupTestWatcher();
gcUnitTestForm::gcUnitTestForm(wxWindow* parent)
: gcDialog(parent, wxID_ANY, wxT("Unit Tests Results"), wxDefaultPosition, wxSize(500, 354), wxCAPTION | wxDEFAULT_FRAME_STYLE | wxTAB_TRAVERSAL)
, m_pThread(NULL)
, m_ImageList(16, 16)
, m_bShouldClose(false)
{
showEvent += guiDelegate(this, &gcUnitTestForm::onShow);
Bind(wxEVT_COMMAND_BUTTON_CLICKED, &gcUnitTestForm::onButtonClicked, this);
Bind(wxEVT_CLOSE_WINDOW, &gcUnitTestForm::OnClose, this);
this->SetSizeHints(wxDefaultSize, wxDefaultSize);
wxFlexGridSizer* fgSizer1;
fgSizer1 = new wxFlexGridSizer(4, 1, 0, 0);
fgSizer1->AddGrowableCol(0);
fgSizer1->AddGrowableRow(2);
fgSizer1->SetFlexibleDirection(wxBOTH);
fgSizer1->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_SPECIFIED);
wxBoxSizer* bSizer2;
bSizer2 = new wxBoxSizer(wxHORIZONTAL);
m_cbAssertOnError = new wxCheckBox(this, wxID_ANY, wxT("Assert On Error"), wxDefaultPosition, wxDefaultSize, 0);
m_cbAssertOnError->SetValue(true);
bSizer2->Add(m_cbAssertOnError, 0, wxALL, 5);
m_cbRunOnStartup = new wxCheckBox(this, wxID_ANY, wxT("Run On Startup"), wxDefaultPosition, wxDefaultSize, 0);
m_cbRunOnStartup->SetValue(true);
bSizer2->Add(m_cbRunOnStartup, 0, wxALL, 5);
fgSizer1->Add(bSizer2, 1, wxEXPAND, 5);
wxBoxSizer* bSizer1;
bSizer1 = new wxBoxSizer(wxHORIZONTAL);
m_staticText1 = new wxStaticText(this, wxID_ANY, wxT("Filter:"), wxDefaultPosition, wxDefaultSize, 0);
m_staticText1->Wrap(-1);
bSizer1->Add(m_staticText1, 0, wxALIGN_CENTER_VERTICAL | wxTOP | wxBOTTOM | wxLEFT, 5);
m_textCtrl1 = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0);
bSizer1->Add(m_textCtrl1, 1, wxEXPAND | wxALL, 5);
m_butRun = new wxButton(this, wxID_ANY, wxT("Run"), wxDefaultPosition, wxDefaultSize, 0);
bSizer1->Add(m_butRun, 0, wxTOP | wxBOTTOM | wxRIGHT, 5);
fgSizer1->Add(bSizer1, 1, wxEXPAND, 5);
m_lcUnitTests = new wxListCtrl(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_REPORT | wxLC_SORT_ASCENDING);
fgSizer1->Add(m_lcUnitTests, 1, wxEXPAND | wxBOTTOM | wxRIGHT | wxLEFT, 5);
m_butClose = new wxButton(this, wxID_ANY, wxT("Close"), wxDefaultPosition, wxDefaultSize, 0);
fgSizer1->Add(m_butClose, 0, wxALIGN_RIGHT | wxBOTTOM | wxRIGHT | wxLEFT, 5);
this->SetSizer(fgSizer1);
this->Layout();
this->Centre(wxBOTH);
m_cbRunOnStartup->SetValue(g_bRunOnStartup.getBool());
m_cbAssertOnError->SetValue(g_bAssertOnFailure.getBool());
m_textCtrl1->SetValue(g_strUnitTestFilter.getString());
m_cbRunOnStartup->Bind(wxEVT_COMMAND_CHECKBOX_CLICKED, &gcUnitTestForm::OnRunOnStartupClicked, this);
m_cbAssertOnError->Bind(wxEVT_COMMAND_CHECKBOX_CLICKED, &gcUnitTestForm::OnAssertOnErrorClicked, this);
m_textCtrl1->Bind(wxEVT_COMMAND_TEXT_UPDATED, &gcUnitTestForm::OnTextChanged, this);
m_icoTestGood = GetGCThemeManager()->getImageHandle("#test_good");
m_icoTestBad = GetGCThemeManager()->getImageHandle("#test_bad");
m_ImageList.Add(wxBitmap(m_icoTestBad.getImg()->Scale(16, 16)));
m_ImageList.Add(wxBitmap(m_icoTestGood.getImg()->Scale(16, 16)));
m_lcUnitTests->SetImageList(&m_ImageList, wxIMAGE_LIST_NORMAL);
m_lcUnitTests->SetImageList(&m_ImageList, wxIMAGE_LIST_SMALL);
g_pTestWatcher->onStartEvent += guiDelegate(this, &gcUnitTestForm::onStart);
g_pTestWatcher->onEndEvent += guiDelegate(this, &gcUnitTestForm::onEnd);
g_pTestWatcher->onTestStartEvent += guiDelegate(this, &gcUnitTestForm::onTestStart);
g_pTestWatcher->onTestResultEvent += guiDelegate(this, &gcUnitTestForm::onTestResult);
g_pTestWatcher->onTestEndEnd += guiDelegate(this, &gcUnitTestForm::onTestEnd);
if (g_bRunOnStartup.getBool())
runTests();
}
gcUnitTestForm::~gcUnitTestForm()
{
g_pTestWatcher->onStartEvent -= guiDelegate(this, &gcUnitTestForm::onStart);
g_pTestWatcher->onEndEvent -= guiDelegate(this, &gcUnitTestForm::onEnd);
g_pTestWatcher->onTestStartEvent -= guiDelegate(this, &gcUnitTestForm::onTestStart);
g_pTestWatcher->onTestResultEvent -= guiDelegate(this, &gcUnitTestForm::onTestResult);
g_pTestWatcher->onTestEndEnd -= guiDelegate(this, &gcUnitTestForm::onTestEnd);
if (m_pThread)
m_pThread->stop();
delete m_pThread;
}
void gcUnitTestForm::onButtonClicked(wxCommandEvent& event)
{
if (event.GetId() == m_butRun->GetId())
{
runTests();
}
else
{
Show(false);
}
}
void gcUnitTestForm::runTests()
{
m_butRun->Enable(false);
if (m_pThread)
m_pThread->stop();
delete m_pThread;
m_pThread = new CUnitTestThread();
m_pThread->start();
}
void gcUnitTestForm::onStart()
{
m_lcUnitTests->ClearAll();
m_lcUnitTests->InsertColumn(0, "", 0, 25);
m_lcUnitTests->InsertColumn(1, "Test Name", 0, 375);
m_lcUnitTests->InsertColumn(2, "Run Time");
m_mTestIndex.clear();
}
void gcUnitTestForm::onEnd()
{
m_butRun->Enable(true);
}
void gcUnitTestForm::onTestStart(gcString &strTest)
{
m_mTestIndex[strTest] = m_lcUnitTests->InsertItem(-1, "");
m_lcUnitTests->SetItem(m_mTestIndex[strTest], 1, strTest);
}
void gcUnitTestForm::onTestResult(std::pair<gcString, bool> &result)
{
m_lcUnitTests->SetItem(m_mTestIndex[result.first], 0, "", result.second);
}
void gcUnitTestForm::onTestEnd(std::pair<gcString, uint64> &time)
{
m_lcUnitTests->SetItem(m_mTestIndex[time.first], 2, gcString("{0}", time.second));
}
void gcUnitTestForm::OnRunOnStartupClicked(wxCommandEvent& event)
{
g_bRunOnStartup.setValue(m_cbRunOnStartup->IsChecked());
}
void gcUnitTestForm::OnAssertOnErrorClicked(wxCommandEvent& event)
{
g_bAssertOnFailure.setValue(m_cbAssertOnError->IsChecked());
}
void gcUnitTestForm::OnTextChanged(wxCommandEvent& event)
{
g_strUnitTestFilter.setValue((const char*)m_textCtrl1->GetValue());
}
void gcUnitTestForm::OnClose(wxCloseEvent& event)
{
if (!m_bShouldClose)
{
event.Veto();
Show(false);
}
else
{
event.Skip();
}
}
void gcUnitTestForm::canClose()
{
m_bShouldClose = true;
}
void gcUnitTestForm::onShow(uint32&)
{
Show(true);
Raise();
}
void gcUnitTestForm::postShowEvent()
{
uint32 res;
showEvent(res);
}