25#include <boost/test/results_collector.hpp>
35#define MAX_DEFAULT_REL_ERROR 2e-2
51 *
m_log << aText <<
"\n";
62 std::shared_ptr<wxString>
m_log;
68 m_log(
std::make_shared<wxString>() ),
76 using namespace boost::unit_test;
83 test_case::id_t
id = framework::current_test_case().p_id;
84 test_results results = results_collector.results(
id );
88 if( !results.passed() )
97 fn.AppendDir(
"spice_netlists" );
98 fn.AppendDir( aBaseName );
99 fn.SetName( aBaseName );
107 wxFileName netFile =
m_schematic->Project().GetProjectFullName();
110 netFile.SetName( netFile.GetName() +
"_test" );
112 netFile.SetExt(
"spice" );
113 return netFile.GetFullPath();
119 BOOST_TEST_CHECKPOINT(
"Comparing netlist " << netlistPath );
129 wxFFile file( netlistPath,
"rt" );
136 ngspice->
Command(
"set ngbehavior=ps" );
137 ngspice->
Command(
"setseed 1" );
162 bool mif_error =
m_log->Find( wxT(
"MIF-ERROR" ) ) != wxNOT_FOUND;
164 BOOST_TEST_INFO(
"Cannot run ngspice. test skipped. Missing code model files?" );
165 BOOST_CHECK( !mif_error );
167 bool err_found =
m_log->Find( wxT(
"Error: circuit not parsed" ) ) != wxNOT_FOUND;
175 BOOST_CHECK( !err_found );
177 if( mif_error || err_found )
182 *
m_log <<
"Original Netlist\n";
183 *
m_log <<
"----------------\n";
190 ngspice->
Command(
"linearize" );
197 ngspice->
Command(
"echo Available Vectors" );
198 ngspice->
Command(
"echo -----------------" );
203 *
m_log <<
"Original Netlist\n";
204 *
m_log <<
"----------------\n";
208 ngspice->
Command(
"echo Expanded Netlist" );
209 ngspice->
Command(
"echo ----------------" );
210 ngspice->
Command(
"listing runnable" );
213 void TestOpPoint(
double aRefValue,
const std::string& aVectorName,
220 std::vector<double> vector = ngspice->
GetRealVector( aVectorName );
222 BOOST_REQUIRE_EQUAL( vector.size(), 1 );
224 double maxError = abs( aRefValue * aMaxRelError );
225 BOOST_CHECK_LE( abs( vector[0] - aRefValue ), aMaxRelError );
229 void TestPoint(
const std::string& aXVectorName,
double aXValue,
230 const std::map<const std::string, double> aTestVectorsAndValues,
241 std::vector<double> xVector = ngspice->
GetRealVector( aXVectorName );
244 for(; i < xVector.size(); ++i )
246 double inf = std::numeric_limits<double>::infinity();
248 double leftDelta = ( aXValue - ( i >= 1 ? xVector[i - 1] : -inf ) );
249 double middleDelta = ( aXValue - xVector[i] );
250 double rightDelta = ( aXValue - ( i < xVector.size() - 1 ? xVector[i + 1] : inf ) );
253 if( abs( middleDelta ) <= abs( leftDelta )
254 && abs( middleDelta ) <= abs( rightDelta ) )
260 BOOST_REQUIRE_LT( i, xVector.size() );
262 for(
auto& [vectorName, refValue] : aTestVectorsAndValues )
264 std::vector<double> yVector = ngspice->
GetGainVector( vectorName );
266 BOOST_REQUIRE_GE( yVector.size(), i + 1 );
269 <<
", Ref value: " << refValue
270 <<
", Actual value: " << yVector[i] )
272 double maxError = abs( refValue * aMaxRelError );
277 maxError = aMaxRelError;
280 BOOST_CHECK_LE( abs( yVector[i] - refValue ), maxError );
287 const std::map<const std::string, double> aTestVectorsAndValues,
290 TestPoint(
"time", aTime, aTestVectorsAndValues, aMaxRelError );
294 const std::map<const std::string, double> aTestVectorsAndValues,
297 TestPoint(
"frequency", aFrequency, aTestVectorsAndValues, aMaxRelError );
303 netlistPath.SetExt(
"csv" );
305 return netlistPath.GetFullPath();
std::unique_ptr< SCHEMATIC > m_schematic
@ OPTION_SAVE_ALL_CURRENTS
@ OPTION_SAVE_ALL_VOLTAGES
@ OPTION_SAVE_ALL_DISSIPATIONS
@ OPTION_ADJUST_INCLUDE_PATHS
bool Command(const std::string &aCmd) override final
bool IsRunning() override final
Execute a Spice command as if it was typed into console.
bool Run() override final
Halt the simulation.
bool LoadNetlist(const std::string &aNetlist) override final
Execute the simulation with currently loaded netlist.
std::vector< double > GetGainVector(const std::string &aName, int aMaxLen=-1) override final
Return a requested vector with phase values.
std::vector< double > GetRealVector(const std::string &aName, int aMaxLen=-1) override final
Return a requested vector with imaginary values.
Interface to receive simulation updates from SPICE_SIMULATOR class.
virtual void SetReporter(SIMULATOR_REPORTER *aReporter)
Set a SIMULATOR_REPORTER object to receive the simulation log.
bool HasMessage() const override
Returns true if any messages were reported.
SPICE_TEST_REPORTER(std::shared_ptr< wxString > aLog)
void OnSimStateChange(SIMULATOR *aObject, SIM_STATE aNewState) override
REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED) override
Report a string with a given severity.
std::shared_ptr< wxString > m_log
virtual ~TEST_NETLIST_EXPORTER_SPICE_FIXTURE()
std::shared_ptr< SPICE_SIMULATOR > m_simulator
void TestOpPoint(double aRefValue, const std::string &aVectorName, double aMaxRelError=MAX_DEFAULT_REL_ERROR)
void TestPoint(const std::string &aXVectorName, double aXValue, const std::map< const std::string, double > aTestVectorsAndValues, double aMaxRelError=MAX_DEFAULT_REL_ERROR)
wxFileName SchematicQAPath(const wxString &aBaseName) override
unsigned GetNetlistOptions() override
TEST_NETLIST_EXPORTER_SPICE_FIXTURE()
wxString GetResultsPath(bool aTest=false)
void TestTranPoint(double aTime, const std::map< const std::string, double > aTestVectorsAndValues, double aMaxRelError=MAX_DEFAULT_REL_ERROR)
std::shared_ptr< wxString > m_log
void TestACPoint(double aFrequency, const std::map< const std::string, double > aTestVectorsAndValues, double aMaxRelError=MAX_DEFAULT_REL_ERROR)
wxString GetNetlistPath(bool aTest=false) override
void CompareNetlists() override
std::unique_ptr< SPICE_TEST_REPORTER > m_reporter
static const std::string KiCadSchematicFileExtension
std::string GetEeschemaTestDataDir()
Get the configured location of Eeschema test data.
BOOST_REQUIRE(intersection.has_value()==c.ExpectedIntersection.has_value())
BOOST_TEST_INFO("Parsed: "<< path)
#define MAX_DEFAULT_REL_ERROR
BOOST_TEST_MESSAGE("\n=== Real-World Polygon PIP Benchmark ===\n"<< formatTable(table))
BOOST_TEST_CONTEXT("Test Clearance")