QA: Add coroutine unit test
This adds a simple unit test to qa_common to check coroutines produce expected events in the right order. This is an automated analogue to the user-facing tool in qa/common_tools.
This commit is contained in:
parent
6729842441
commit
b690658972
|
@ -37,6 +37,7 @@ set( common_srcs
|
|||
../../common/observable.cpp
|
||||
|
||||
test_color4d.cpp
|
||||
test_coroutine.cpp
|
||||
test_format_units.cpp
|
||||
test_hotkey_store.cpp
|
||||
test_title_block.cpp
|
||||
|
|
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2018 KiCad Developers, see CHANGELOG.TXT for contributors.
|
||||
*
|
||||
* 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 2
|
||||
* 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, you may find one here:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* or you may search the http://www.gnu.org website for the version 2 license,
|
||||
* or you may write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file test_coroutine.cpp
|
||||
* Test suite for coroutines.
|
||||
*
|
||||
* See also the coroutine utility in qa/common_tools for a command line
|
||||
* test utility.
|
||||
*/
|
||||
|
||||
#include <unit_test_utils/unit_test_utils.h>
|
||||
|
||||
#include <tool/coroutine.h>
|
||||
|
||||
#include <common.h>
|
||||
|
||||
|
||||
/**
|
||||
* An event in a simple coroutine harness.
|
||||
*/
|
||||
struct COROUTINE_TEST_EVENT
|
||||
{
|
||||
enum class TYPE
|
||||
{
|
||||
START,
|
||||
CALL,
|
||||
YIELD,
|
||||
RETURNED,
|
||||
END,
|
||||
};
|
||||
|
||||
TYPE m_type;
|
||||
int m_value;
|
||||
|
||||
bool operator==( const COROUTINE_TEST_EVENT& aOther ) const
|
||||
{
|
||||
return m_type == aOther.m_type && m_value == aOther.m_value;
|
||||
}
|
||||
|
||||
bool operator!=( const COROUTINE_TEST_EVENT& aOther ) const
|
||||
{
|
||||
return !operator==( aOther );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Define a stream function for logging this type.
|
||||
*
|
||||
* TODO: convert to boost_test_print_type when Boost minver > 1.64
|
||||
*/
|
||||
std::ostream& operator<<( std::ostream& os, const COROUTINE_TEST_EVENT& aObj )
|
||||
{
|
||||
os << "COROUTINE_TEST_EVENT[ type: " << (int) aObj.m_type << ", value: " << aObj.m_value
|
||||
<< " ]";
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Simple coroutine harness that runs a coroutine that increments a number up
|
||||
* to a pre-set limit, spitting out coroutine events as it goes.
|
||||
*
|
||||
* This can then be used to ensure the events are occurring as expected.
|
||||
*/
|
||||
class COROUTINE_INCREMENTING_HARNESS
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* The coroutine test take ints and returns them
|
||||
*/
|
||||
using TEST_COROUTINE = COROUTINE<int, int>;
|
||||
|
||||
using EVT_HANDLER = std::function<void( const COROUTINE_TEST_EVENT& )>;
|
||||
|
||||
COROUTINE_INCREMENTING_HARNESS( EVT_HANDLER aHandler, int aCount )
|
||||
: m_handler( aHandler ), m_count( aCount )
|
||||
{
|
||||
}
|
||||
|
||||
int CountTo( int n )
|
||||
{
|
||||
m_handler( { COROUTINE_TEST_EVENT::TYPE::START, 0 } );
|
||||
|
||||
for( int i = 1; i <= n; i++ )
|
||||
{
|
||||
m_handler( { COROUTINE_TEST_EVENT::TYPE::YIELD, i } );
|
||||
m_cofunc->KiYield( i );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Run()
|
||||
{
|
||||
m_cofunc =
|
||||
std::make_unique<TEST_COROUTINE>( this, &COROUTINE_INCREMENTING_HARNESS::CountTo );
|
||||
m_handler( { COROUTINE_TEST_EVENT::TYPE::CALL, m_count } );
|
||||
m_cofunc->Call( m_count );
|
||||
|
||||
int ret_val = 0;
|
||||
|
||||
while( m_cofunc->Running() )
|
||||
{
|
||||
ret_val = m_cofunc->ReturnValue();
|
||||
m_handler( { COROUTINE_TEST_EVENT::TYPE::RETURNED, ret_val } );
|
||||
m_cofunc->Resume();
|
||||
}
|
||||
|
||||
m_handler( { COROUTINE_TEST_EVENT::TYPE::END, ret_val } );
|
||||
}
|
||||
|
||||
EVT_HANDLER m_handler;
|
||||
std::unique_ptr<TEST_COROUTINE> m_cofunc;
|
||||
int m_count;
|
||||
};
|
||||
|
||||
/**
|
||||
* Declare the test suite
|
||||
*/
|
||||
BOOST_AUTO_TEST_SUITE( Coroutine )
|
||||
|
||||
|
||||
/**
|
||||
* A basic test to repeatedly call a coroutine and check that it yields
|
||||
* values as expected.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE( Increment )
|
||||
{
|
||||
const int count = 2;
|
||||
|
||||
const std::vector<COROUTINE_TEST_EVENT> exp_events = {
|
||||
{ COROUTINE_TEST_EVENT::TYPE::CALL, count },
|
||||
{ COROUTINE_TEST_EVENT::TYPE::START, 0 },
|
||||
{ COROUTINE_TEST_EVENT::TYPE::YIELD, 1 },
|
||||
{ COROUTINE_TEST_EVENT::TYPE::RETURNED, 1 },
|
||||
{ COROUTINE_TEST_EVENT::TYPE::YIELD, 2 },
|
||||
{ COROUTINE_TEST_EVENT::TYPE::RETURNED, 2 },
|
||||
{ COROUTINE_TEST_EVENT::TYPE::END, 2 },
|
||||
};
|
||||
|
||||
std::vector<COROUTINE_TEST_EVENT> received_events;
|
||||
|
||||
auto handler = [&]( const COROUTINE_TEST_EVENT& aEvent ) {
|
||||
received_events.push_back( aEvent );
|
||||
};
|
||||
|
||||
COROUTINE_INCREMENTING_HARNESS harness( handler, count );
|
||||
|
||||
harness.Run();
|
||||
|
||||
BOOST_CHECK_EQUAL_COLLECTIONS(
|
||||
received_events.begin(), received_events.end(), exp_events.begin(), exp_events.end() );
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
|
@ -35,6 +35,13 @@
|
|||
|
||||
typedef COROUTINE<int, int> MyCoroutine;
|
||||
|
||||
/**
|
||||
* A simple harness that counts to a preset value in a couroutine, yielding
|
||||
* each value.
|
||||
*
|
||||
* This is a user-facing version of the "Increment" unit test in the "Coroutine"
|
||||
* suite, in qa_common.
|
||||
*/
|
||||
class CoroutineExample
|
||||
{
|
||||
public:
|
||||
|
|
Loading…
Reference in New Issue