QA: Move contents qa_shape_poly_set_refactor to qa_common

The "refactor" element of qa_shape_poly_set_refactor has been
previously removed, so these tests are now just regular tests on
libcommon classes. These can therefore be moved to qa_common
and the qa_shape_poly_set_refactor unit test suit can finally be
totally removed.
This commit is contained in:
John Beard 2019-01-24 13:19:23 +00:00 committed by Wayne Stambaugh
parent e4b4230bcf
commit 11745f8f44
8 changed files with 177 additions and 260 deletions

View File

@ -21,7 +21,6 @@ add_subdirectory( unit_test_utils )
add_subdirectory( common )
add_subdirectory( pcbnew )
add_subdirectory( eeschema )
add_subdirectory( shape_poly_set_refactor )
# Utility/debugging/profiling programs
add_subdirectory( common_tools )

View File

@ -47,12 +47,15 @@ set( common_srcs
libeval/test_numeric_evaluator.cpp
geometry/test_fillet.cpp
geometry/test_segment.cpp
geometry/test_shape_arc.cpp
geometry/test_shape_poly_set_collision.cpp
geometry/test_shape_poly_set_iterator.cpp
view/test_zoom_controller.cpp
)
set( common_libs
set( common_libs
common
legacy_gal
polygon

View File

@ -22,14 +22,17 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __FIXTURES_H
#define __FIXTURES_H
#ifndef QA_COMMON_GEOMETRY_FIXTURES_GEOEMETRY__H
#define QA_COMMON_GEOMETRY_FIXTURES_GEOEMETRY__H
#include <geometry/shape_poly_set.h>
#include <geometry/shape_line_chain.h>
#include <geometry/shape_poly_set.h>
namespace KI_TEST
{
/**
* Common data for the tests:
* Common data for some of the #SHAPE_POLY_SET tests:
* 1. holeyPolySet: A polyset containing one single squared outline with two holes: a
* non-convex pentagon and a triangle.
* 2.solidPolySet: A polyset with three empty outlines and no holes.
@ -47,7 +50,7 @@ struct CommonTestData
// Vectors containing the information with which the polygons are populated.
std::vector<VECTOR2I> uniquePoints;
std::vector<VECTOR2I> holeyPoints;
std::vector<SEG> holeySegments;
std::vector<SEG> holeySegments;
/**
* Constructor.
@ -60,22 +63,22 @@ struct CommonTestData
// Populate the holey polygon set points with 12 points
// Square
holeyPoints.push_back( VECTOR2I( 100,100 ) );
holeyPoints.push_back( VECTOR2I( 0,100 ) );
holeyPoints.push_back( VECTOR2I( 0,0 ) );
holeyPoints.push_back( VECTOR2I( 100,0 ) );
holeyPoints.push_back( VECTOR2I( 100, 100 ) );
holeyPoints.push_back( VECTOR2I( 0, 100 ) );
holeyPoints.push_back( VECTOR2I( 0, 0 ) );
holeyPoints.push_back( VECTOR2I( 100, 0 ) );
// Pentagon
holeyPoints.push_back( VECTOR2I( 10,10 ) );
holeyPoints.push_back( VECTOR2I( 10,20 ) );
holeyPoints.push_back( VECTOR2I( 15,15 ) );
holeyPoints.push_back( VECTOR2I( 20,20 ) );
holeyPoints.push_back( VECTOR2I( 20,10 ) );
holeyPoints.push_back( VECTOR2I( 10, 10 ) );
holeyPoints.push_back( VECTOR2I( 10, 20 ) );
holeyPoints.push_back( VECTOR2I( 15, 15 ) );
holeyPoints.push_back( VECTOR2I( 20, 20 ) );
holeyPoints.push_back( VECTOR2I( 20, 10 ) );
// Triangle
holeyPoints.push_back( VECTOR2I( 40,10 ) );
holeyPoints.push_back( VECTOR2I( 40,20 ) );
holeyPoints.push_back( VECTOR2I( 60,10 ) );
holeyPoints.push_back( VECTOR2I( 40, 10 ) );
holeyPoints.push_back( VECTOR2I( 40, 20 ) );
holeyPoints.push_back( VECTOR2I( 60, 10 ) );
// Save the segments of the holeyPolySet.
holeySegments.push_back( SEG( holeyPoints[0], holeyPoints[1] ) );
@ -91,7 +94,7 @@ struct CommonTestData
holeySegments.push_back( SEG( holeyPoints[8], holeyPoints[4] ) );
// Triangle segments
holeySegments.push_back( SEG( holeyPoints[ 9], holeyPoints[10] ) );
holeySegments.push_back( SEG( holeyPoints[9], holeyPoints[10] ) );
holeySegments.push_back( SEG( holeyPoints[10], holeyPoints[11] ) );
holeySegments.push_back( SEG( holeyPoints[11], holeyPoints[9] ) );
@ -101,7 +104,7 @@ struct CommonTestData
// Create a polygon set with a unique vertex
polyLine.Append( uniquePoints[0] );
polyLine.SetClosed( true );
uniqueVertexPolySet.AddOutline(polyLine);
uniqueVertexPolySet.AddOutline( polyLine );
// Create a polygon set without holes
solidPolySet.NewOutline();
@ -118,7 +121,7 @@ struct CommonTestData
polyLine.SetClosed( true );
holeyPolySet.AddOutline(polyLine);
holeyPolySet.AddOutline( polyLine );
// Adds a new hole (a pentagon)
for( int i = 4; i < 9; i++ )
@ -137,105 +140,11 @@ struct CommonTestData
holeyPolySet.AddHole( hole );
}
~CommonTestData(){}
};
/**
* Fixture for the Collision test suite. It contains an instance of the common data and two
* vectors containing colliding and non-colliding points.
*/
struct CollisionFixture {
// Structure to store the common data.
struct CommonTestData common;
// Vectors containing colliding and non-colliding points
std::vector<VECTOR2I> collidingPoints, nonCollidingPoints;
/**
* Constructor
*/
CollisionFixture()
~CommonTestData()
{
// Create points colliding with the poly set.
// Inside the polygon
collidingPoints.push_back( VECTOR2I( 10,90 ) );
// Inside the polygon, but on a re-entrant angle of a hole
collidingPoints.push_back( VECTOR2I( 15,16 ) );
// On a hole edge => inside the polygon
collidingPoints.push_back( VECTOR2I( 40,25 ) );
// On the outline edge => inside the polygon
collidingPoints.push_back( VECTOR2I( 0,10 ) );
// Create points not colliding with the poly set.
// Completely outside of the polygon
nonCollidingPoints.push_back( VECTOR2I( 200,200 ) );
// Inside the outline and inside a hole => outside the polygon
nonCollidingPoints.push_back( VECTOR2I( 15,12 ) );
}
~CollisionFixture(){}
};
/**
* Fixture for the Iterator test suite. It contains an instance of the common data, three polysets with null segments and a vector containing their points.
*/
struct IteratorFixture {
// Structure to store the common data.
struct CommonTestData common;
} // namespace KI_TEST
// Polygons to test whether the RemoveNullSegments method works
SHAPE_POLY_SET lastNullSegmentPolySet;
SHAPE_POLY_SET firstNullSegmentPolySet;
SHAPE_POLY_SET insideNullSegmentPolySet;
// Null segments points
std::vector<VECTOR2I> nullPoints;
IteratorFixture()
{
nullPoints.push_back( VECTOR2I( 100,100 ) );
nullPoints.push_back( VECTOR2I( 0,100 ) );
nullPoints.push_back( VECTOR2I( 0, 0 ) );
// Create a polygon with its last segment null
SHAPE_LINE_CHAIN polyLine;
polyLine.Append( nullPoints[0] );
polyLine.Append( nullPoints[1] );
polyLine.Append( nullPoints[2] );
polyLine.Append( nullPoints[2], true );
polyLine.SetClosed( true );
lastNullSegmentPolySet.AddOutline(polyLine);
// Create a polygon with its first segment null
polyLine.Clear();
polyLine.Append( nullPoints[0] );
polyLine.Append( nullPoints[0], true );
polyLine.Append( nullPoints[1] );
polyLine.Append( nullPoints[2] );
polyLine.SetClosed( true );
firstNullSegmentPolySet.AddOutline(polyLine);
// Create a polygon with an inside segment null
polyLine.Clear();
polyLine.Append( nullPoints[0] );
polyLine.Append( nullPoints[1] );
polyLine.Append( nullPoints[1], true );
polyLine.Append( nullPoints[2] );
polyLine.SetClosed( true );
insideNullSegmentPolySet.AddOutline(polyLine);
}
~IteratorFixture(){}
};
#endif //__FIXTURES_H
#endif // QA_COMMON_GEOMETRY_FIXTURES_GEOEMETRY__H

View File

@ -3,6 +3,7 @@
*
* Copyright (C) 2017 CERN
* @author Alejandro García Montoro <alejandro.garciamontoro@gmail.com>
* Copyright (C) 2019 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
@ -22,42 +23,35 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <boost/test/unit_test.hpp>
#include <boost/test/test_case_template.hpp>
#include <unit_test_utils/unit_test_utils.h>
#include <geometry/seg.h>
#include <qa/data/fixtures_geometry.h>
BOOST_AUTO_TEST_SUITE( Segment )
/**
* Declares the IteratorFixture as the boost test suite fixture.
* Checks whether the construction of a segment referencing external points works
* and that the endpoints can be modified as normal points.
*/
BOOST_FIXTURE_TEST_SUITE( SegmentReference, CommonTestData )
/**
* Checks whether the construction of a segment referencing external points works.
*/
BOOST_AUTO_TEST_CASE( SegmentReference )
BOOST_AUTO_TEST_CASE( EndpointCtorMod )
{
VECTOR2I pointA( 10, 20 );
VECTOR2I pointB( 100, 200 );
const VECTOR2I pointA{ 10, 20 };
const VECTOR2I pointB{ 100, 200 };
// Build a segment referencing the previous points
SEG segment( pointA, pointB );
BOOST_CHECK_EQUAL( pointA, VECTOR2I( 10, 20) );
BOOST_CHECK_EQUAL( pointB, VECTOR2I( 100, 200) );
BOOST_CHECK_EQUAL( pointA, VECTOR2I( 10, 20 ) );
BOOST_CHECK_EQUAL( pointB, VECTOR2I( 100, 200 ) );
// Modify the ends of the segments
segment.A += VECTOR2I( 10, 10 );
segment.B += VECTOR2I( 100, 100 );
// Check that the original points are not modified
BOOST_CHECK_EQUAL( pointA, VECTOR2I( 10, 20) );
BOOST_CHECK_EQUAL( pointB, VECTOR2I( 100, 200) );
// Check that the ends in segment are modified
BOOST_CHECK_EQUAL( segment.A, VECTOR2I( 20, 30) );
BOOST_CHECK_EQUAL( segment.B, VECTOR2I( 200, 300) );
BOOST_CHECK_EQUAL( segment.A, VECTOR2I( 20, 30 ) );
BOOST_CHECK_EQUAL( segment.B, VECTOR2I( 200, 300 ) );
}
BOOST_AUTO_TEST_SUITE_END()

View File

@ -22,12 +22,57 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <boost/test/unit_test.hpp>
#include <boost/test/test_case_template.hpp>
#include <geometry/shape_poly_set.h>
#include <geometry/shape_line_chain.h>
#include <unit_test_utils/unit_test_utils.h>
#include <qa/data/fixtures_geometry.h>
#include <geometry/shape_line_chain.h>
#include <geometry/shape_poly_set.h>
#include "fixtures_geometry.h"
/**
* Fixture for the Collision test suite. It contains an instance of the common data and two
* vectors containing colliding and non-colliding points.
*/
struct CollisionFixture
{
// Structure to store the common data.
struct KI_TEST::CommonTestData common;
// Vectors containing colliding and non-colliding points
std::vector<VECTOR2I> collidingPoints, nonCollidingPoints;
/**
* Constructor
*/
CollisionFixture()
{
// Create points colliding with the poly set.
// Inside the polygon
collidingPoints.push_back( VECTOR2I( 10, 90 ) );
// Inside the polygon, but on a re-entrant angle of a hole
collidingPoints.push_back( VECTOR2I( 15, 16 ) );
// On a hole edge => inside the polygon
collidingPoints.push_back( VECTOR2I( 40, 25 ) );
// On the outline edge => inside the polygon
collidingPoints.push_back( VECTOR2I( 0, 10 ) );
// Create points not colliding with the poly set.
// Completely outside of the polygon
nonCollidingPoints.push_back( VECTOR2I( 200, 200 ) );
// Inside the outline and inside a hole => outside the polygon
nonCollidingPoints.push_back( VECTOR2I( 15, 12 ) );
}
~CollisionFixture()
{
}
};
/**
* Declares the CollisionFixture as the boost test suite fixture.
@ -40,7 +85,7 @@ BOOST_FIXTURE_TEST_SUITE( Collision, CollisionFixture )
BOOST_AUTO_TEST_CASE( HasHoles )
{
BOOST_CHECK( !common.solidPolySet.HasHoles() );
BOOST_CHECK( common.holeyPolySet.HasHoles() );
BOOST_CHECK( common.holeyPolySet.HasHoles() );
}
/**
@ -50,22 +95,22 @@ BOOST_AUTO_TEST_CASE( HasHoles )
BOOST_AUTO_TEST_CASE( PointOnEdge )
{
// Check points on corners
BOOST_CHECK( common.holeyPolySet.PointOnEdge( VECTOR2I( 0,50 ) ) );
BOOST_CHECK( common.holeyPolySet.PointOnEdge( VECTOR2I( 0, 50 ) ) );
// Check points on outline edges
BOOST_CHECK( common.holeyPolySet.PointOnEdge( VECTOR2I( 0,10 ) ) );
BOOST_CHECK( common.holeyPolySet.PointOnEdge( VECTOR2I( 0, 10 ) ) );
// Check points on hole edges
BOOST_CHECK( common.holeyPolySet.PointOnEdge( VECTOR2I( 10,11 ) ) );
BOOST_CHECK( common.holeyPolySet.PointOnEdge( VECTOR2I( 10, 11 ) ) );
// Check points inside a hole -> not in edge
BOOST_CHECK( !common.holeyPolySet.PointOnEdge( VECTOR2I( 12,12 ) ) );
BOOST_CHECK( !common.holeyPolySet.PointOnEdge( VECTOR2I( 12, 12 ) ) );
// Check points inside the polygon and outside any hole -> not on edge
BOOST_CHECK( !common.holeyPolySet.PointOnEdge( VECTOR2I( 90,90 ) ) );
BOOST_CHECK( !common.holeyPolySet.PointOnEdge( VECTOR2I( 90, 90 ) ) );
// Check points outside the polygon -> not on edge
BOOST_CHECK( !common.holeyPolySet.PointOnEdge( VECTOR2I( 200,200 ) ) );
BOOST_CHECK( !common.holeyPolySet.PointOnEdge( VECTOR2I( 200, 200 ) ) );
}
/**
@ -109,10 +154,10 @@ BOOST_AUTO_TEST_CASE( Collide )
// Checks with clearance > 0
// Point at the offset zone outside of the outline => collision!
BOOST_CHECK( common.holeyPolySet.Collide( VECTOR2I( -1,10 ), 5 ) );
BOOST_CHECK( common.holeyPolySet.Collide( VECTOR2I( -1, 10 ), 5 ) );
// Point at the offset zone outside of a hole => collision!
BOOST_CHECK( common.holeyPolySet.Collide( VECTOR2I( 11,11 ), 5 ) );
BOOST_CHECK( common.holeyPolySet.Collide( VECTOR2I( 11, 11 ), 5 ) );
}
/**
@ -143,7 +188,7 @@ BOOST_AUTO_TEST_CASE( CollideVertexWithClearance )
// Check that the set collides with the colliding points
for( const VECTOR2I& point : common.holeyPoints )
{
BOOST_CHECK( common.holeyPolySet.CollideVertex( point + VECTOR2I(1,1), cornerHit, 2 ) );
BOOST_CHECK( common.holeyPolySet.CollideVertex( point + VECTOR2I( 1, 1 ), cornerHit, 2 ) );
}
}

View File

@ -22,12 +22,70 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <boost/test/unit_test.hpp>
#include <boost/test/test_case_template.hpp>
#include <geometry/shape_poly_set.h>
#include <geometry/shape_line_chain.h>
#include <unit_test_utils/unit_test_utils.h>
#include <qa/data/fixtures_geometry.h>
#include <geometry/shape_line_chain.h>
#include <geometry/shape_poly_set.h>
#include "fixtures_geometry.h"
/**
* Fixture for the Iterator test suite. It contains an instance of the common data, three polysets with null segments and a vector containing their points.
*/
struct IteratorFixture
{
// Structure to store the common data.
struct KI_TEST::CommonTestData common;
// Polygons to test whether the RemoveNullSegments method works
SHAPE_POLY_SET lastNullSegmentPolySet;
SHAPE_POLY_SET firstNullSegmentPolySet;
SHAPE_POLY_SET insideNullSegmentPolySet;
// Null segments points
std::vector<VECTOR2I> nullPoints;
IteratorFixture()
{
nullPoints.push_back( VECTOR2I( 100, 100 ) );
nullPoints.push_back( VECTOR2I( 0, 100 ) );
nullPoints.push_back( VECTOR2I( 0, 0 ) );
// Create a polygon with its last segment null
SHAPE_LINE_CHAIN polyLine;
polyLine.Append( nullPoints[0] );
polyLine.Append( nullPoints[1] );
polyLine.Append( nullPoints[2] );
polyLine.Append( nullPoints[2], true );
polyLine.SetClosed( true );
lastNullSegmentPolySet.AddOutline( polyLine );
// Create a polygon with its first segment null
polyLine.Clear();
polyLine.Append( nullPoints[0] );
polyLine.Append( nullPoints[0], true );
polyLine.Append( nullPoints[1] );
polyLine.Append( nullPoints[2] );
polyLine.SetClosed( true );
firstNullSegmentPolySet.AddOutline( polyLine );
// Create a polygon with an inside segment null
polyLine.Clear();
polyLine.Append( nullPoints[0] );
polyLine.Append( nullPoints[1] );
polyLine.Append( nullPoints[1], true );
polyLine.Append( nullPoints[2] );
polyLine.SetClosed( true );
insideNullSegmentPolySet.AddOutline( polyLine );
}
~IteratorFixture()
{
}
};
/**
* Declares the IteratorFixture as the boost test suite fixture.
@ -40,7 +98,7 @@ BOOST_FIXTURE_TEST_SUITE( PolygonIterator, IteratorFixture )
BOOST_AUTO_TEST_CASE( VertexIterator )
{
SHAPE_POLY_SET::ITERATOR iterator;
int vertexIndex = 0;
int vertexIndex = 0;
for( iterator = common.holeyPolySet.IterateWithHoles(); iterator; iterator++ )
{
@ -55,9 +113,10 @@ BOOST_AUTO_TEST_CASE( VertexIterator )
BOOST_AUTO_TEST_CASE( SegmentIterator )
{
SHAPE_POLY_SET::SEGMENT_ITERATOR iterator;
int segmentIndex = 0;
int segmentIndex = 0;
for( iterator = common.holeyPolySet.IterateSegmentsWithHoles(); iterator; iterator++ ){
for( iterator = common.holeyPolySet.IterateSegmentsWithHoles(); iterator; iterator++ )
{
SEG segment = *iterator;
BOOST_CHECK_EQUAL( common.holeySegments[segmentIndex].A, segment.A );
@ -113,19 +172,18 @@ BOOST_AUTO_TEST_CASE( TotalVertices )
*/
BOOST_AUTO_TEST_CASE( RemoveNullSegments )
{
SHAPE_POLY_SET polygonSets[3] = {lastNullSegmentPolySet,
firstNullSegmentPolySet,
insideNullSegmentPolySet};
SHAPE_POLY_SET polygonSets[3] = { lastNullSegmentPolySet, firstNullSegmentPolySet,
insideNullSegmentPolySet };
for( SHAPE_POLY_SET polygonSet : polygonSets )
{
BOOST_CHECK_EQUAL( polygonSet.TotalVertices(), 4 );
BOOST_CHECK_EQUAL( polygonSet.RemoveNullSegments(), 1);
BOOST_CHECK_EQUAL( polygonSet.RemoveNullSegments(), 1 );
BOOST_CHECK_EQUAL( polygonSet.TotalVertices(), 3 );
BOOST_CHECK_EQUAL( polygonSet.CVertex(0), nullPoints[0] );
BOOST_CHECK_EQUAL( polygonSet.CVertex(1), nullPoints[1] );
BOOST_CHECK_EQUAL( polygonSet.CVertex(2), nullPoints[2] );
BOOST_CHECK_EQUAL( polygonSet.CVertex( 0 ), nullPoints[0] );
BOOST_CHECK_EQUAL( polygonSet.CVertex( 1 ), nullPoints[1] );
BOOST_CHECK_EQUAL( polygonSet.CVertex( 2 ), nullPoints[2] );
}
}

View File

@ -1,59 +0,0 @@
#
# This program source code file is part of KiCad, a free EDA CAD application.
#
# Copyright (C) 2017 CERN
# @author Alejandro García Montoro <alejandro.garciamontoro@gmail.com>
#
# 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
find_package(Boost COMPONENTS unit_test_framework REQUIRED)
find_package( wxWidgets 3.0.0 COMPONENTS gl aui adv html core net base xml stc REQUIRED )
add_definitions(-DBOOST_TEST_DYN_LINK)
add_executable( qa_shape_poly_set_refactor
test_module.cpp
test_collision.cpp
test_iterator.cpp
test_segment.cpp
)
include_directories(
${CMAKE_SOURCE_DIR}
${CMAKE_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/polygon
${CMAKE_SOURCE_DIR}/common/geometry
${Boost_INCLUDE_DIR}
)
target_link_libraries( qa_shape_poly_set_refactor
polygon
common
polygon
bitmaps
${Boost_FILESYSTEM_LIBRARY}
${Boost_SYSTEM_LIBRARY}
${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}
${wxWidgets_LIBRARIES}
)
add_dependencies( qa_shape_poly_set_refactor pcbnew )
add_test( NAME shape_poly_set_refactor
COMMAND qa_shape_poly_set_refactor
)

View File

@ -1,32 +0,0 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2017 CERN
* @author Alejandro García Montoro <alejandro.garciamontoro@gmail.com>
*
* 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
*/
/**
* Main file for the geometry tests to be compiled
*/
#define BOOST_TEST_MAIN
#define BOOST_TEST_MODULE "CPolyLine -> SHAPE_POLY_SET refactor module"
#include <boost/test/unit_test.hpp>