46 if( aJson.is_number() )
48 int v = aJson.get<
int>();
52 else if( aJson.is_object() )
54 if( aJson.contains(
"exact" ) )
56 int v = aJson[
"exact"];
62 if( aJson.contains(
"min" ) )
63 matcher.
m_min = aJson[
"min"];
65 if( aJson.contains(
"max" ) )
66 matcher.
m_max = aJson[
"max"];
71 throw std::runtime_error(
"Invalid count expectation: " + aJson.dump() );
80 matcher.
m_min = aValue;
81 matcher.
m_max = aValue;
85 void Test(
int aActual )
const
97 return "exactly " + std::to_string( *
m_min );
102 desc +=
"at least " + std::to_string( *
m_min );
109 desc +=
"at most " + std::to_string( *
m_max );
132 static bool matchPredicate(
const std::string& aStr,
const std::string& aPattern )
134 return wxString( aStr ).Matches( aPattern );
167 return std::string(
"Footprint: " ) + (
m_Count.has_value() ?
m_Count->Describe() :
"N/A" );
179 static bool nameMatches(
const std::string& aName,
const std::string& aPattern )
181 return wxString( aName ).Matches( aPattern );
186 std::vector<const NETINFO_ITEM*> matches;
193 matches.push_back( net );
202 if(
nameMatches( net->GetNetname().ToStdString(), pattern ) )
204 matches.push_back( net );
215 wxASSERT(
m_Count.has_value() );
243 m_Count->Test(
static_cast<int>( matches.size() ) );
251 const auto& netMatchesPattern = [&](
const NETINFO_ITEM* n )
253 return nameMatches( n->GetNetname().ToStdString(), pattern );
256 bool found = std::any_of( matches.begin(), matches.end(), netMatchesPattern );
268 std::string desc =
"Net";
283 desc +=
" ['" + joined +
"']";
287 desc +=
" count: " +
m_Count->Describe();
317 std::vector<std::string> actualNames;
320 for(
const auto& layer : cuLayers )
322 actualNames.push_back( aBrd.
GetLayerName( layer ).ToStdString() );
327 for(
size_t i = 0; i <
m_CuNames.size(); ++i )
339 return std::string(
"Layers: " ) + (
m_CuCount.has_value() ?
m_CuCount->Describe() :
"N/A" );
346 auto footprintExpectation = std::make_unique<FOOTPRINT_EXPECTATION>();
348 if( aExpectationEntry.contains(
"count" ) )
350 const auto& countEntry = aExpectationEntry[
"count"];
352 footprintExpectation->m_Count = countMatcher;
355 return footprintExpectation;
361 std::vector<std::string>
result;
363 if( aJson.is_string() )
365 result.push_back( aJson );
367 else if( aJson.is_array() )
369 for(
const auto& entry : aJson )
371 if( !entry.is_string() )
373 throw std::runtime_error(
"Expected a string or an array of strings" );
376 result.push_back( entry );
381 throw std::runtime_error(
"Expected a string or an array of strings" );
390 auto netExpectation = std::make_unique<NET_EXPECTATION>();
392 if( aExpectationEntry.contains(
"count" ) )
394 const auto& countEntry = aExpectationEntry[
"count"];
398 if( aExpectationEntry.contains(
"name" ) )
400 const auto& expectedNetName = aExpectationEntry[
"name"];
401 netExpectation->m_NamePatterns =
getStringArray( expectedNetName );
404 return netExpectation;
410 auto layerExpectation = std::make_unique<LAYER_EXPECTATION>();
412 if( aExpectationEntry.contains(
"cuNames" ) )
414 const auto& cuNamesEntry = aExpectationEntry[
"cuNames"];
415 std::vector<std::string> cuNames =
getStringArray( cuNamesEntry );
416 layerExpectation->m_CuNames = std::move( cuNames );
419 if( aExpectationEntry.contains(
"count" ) )
421 const auto& countEntry = aExpectationEntry[
"cuCount"];
424 else if( layerExpectation->m_CuNames.size() > 0 )
427 layerExpectation->m_CuCount =
INT_MATCHER::Exact(
static_cast<int>( layerExpectation->m_CuNames.size() ) );
430 return layerExpectation;
435 const nlohmann::json& aBrdExpectations )
437 std::unique_ptr<BOARD_EXPECTATION_TEST>
test = std::make_unique<BOARD_EXPECTATION_TEST>( aBrdName );
439 if( !aBrdExpectations.is_array() )
441 throw std::runtime_error(
"Board expectations for board " + aBrdName +
" are not a valid JSON object" );
444 for(
const auto& expectationEntry : aBrdExpectations )
446 if( !expectationEntry.is_object() )
448 throw std::runtime_error(
"Expectation entry for board " + aBrdName +
" is not a valid JSON object" );
451 if( !expectationEntry.contains(
"type" ) || !expectationEntry[
"type"].is_string() )
453 throw std::runtime_error(
"Expectation entry for board " + aBrdName
454 +
" must have a string field named 'type'" );
457 const std::string expectationType = expectationEntry[
"type"];
459 std::unique_ptr<BOARD_EXPECTATION> expectation;
461 if( expectationType ==
"footprint" )
465 else if( expectationType ==
"net" )
469 else if( expectationType ==
"layers" )
475 throw std::runtime_error(
"Unsupported expectation type '" + expectationType +
"' for board " + aBrdName );
479 test->m_expectations.push_back( std::move( expectation ) );
490 BOOST_TEST_CONTEXT( wxString::Format(
"Checking expectation of type %s", expectation->GetName() ) )
492 expectation->RunTest( aBrd );
static std::unique_ptr< BOARD_EXPECTATION > createFootprintExpectation(const nlohmann::json &aExpectationEntry)
static std::unique_ptr< BOARD_EXPECTATION > createNetExpectation(const nlohmann::json &aExpectationEntry)
static std::unique_ptr< BOARD_EXPECTATION > createLayerExpectation(const nlohmann::json &aExpectationEntry)
static std::vector< std::string > getStringArray(const nlohmann::json &aJson)
Information pertinent to a Pcbnew printed circuit board.
const NETINFO_LIST & GetNetInfo() const
LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
int GetCopperLayerCount() const
const FOOTPRINTS & Footprints() const
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
unsigned GetNetCount() const
Simple binary expectation that checks if an integer value meets the expectation (exact,...
static INT_MATCHER Exact(int aValue)
std::string Describe() const
std::optional< int > m_min
std::optional< int > m_max
static INT_MATCHER FromJson(const nlohmann::json &aJson)
void Test(int aActual) const
std::vector< std::unique_ptr< BOARD_EXPECTATION > > m_expectations
static std::unique_ptr< BOARD_EXPECTATION_TEST > CreateFromJson(const std::string &aBrdName, const nlohmann::json &aBrdExpectations)
void RunTest(const BOARD &aBrd) const
Runs the test against the given board.
A single expectation about a board, which can be run as a test against a parsed BOARD.
std::string GetName() const override
void RunTest(const BOARD &aBrd) const override
std::vector< std::string > m_CuNames
std::optional< INT_MATCHER > m_CuCount
LSET is a set of PCB_LAYER_IDs.
static LSET AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
Handle the data for a net.
Container for NETINFO_ITEM elements, which are the nets.
std::optional< INT_MATCHER > m_Count
void RunTest(const BOARD &aBrd) const override
void doSimpleCountTest(const BOARD &aBrd) const
std::vector< std::string > m_NamePatterns
std::string GetName() const override
std::vector< const NETINFO_ITEM * > findMatchingNets(const BOARD &aBrd) const
static bool nameMatches(const std::string &aName, const std::string &aPattern)
static bool matchPredicate(const std::string &aStr, const std::string &aPattern)
void Test(const std::string &aStr) const
STRING_PATTERN_MATCHER(const std::string &aPattern)
BOOST_TEST(contains==c.ExpectedContains)
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_CHECK_PREDICATE(ArePolylineEndPointsNearCircle,(chain)(c.m_geom.m_center_point)(radius)(accuracy+epsilon))
BOOST_TEST_CONTEXT("Test Clearance")
wxString result
Test unit parsing edge cases and error handling.