21#include <boost/test/results_collector.hpp>
30#define MAX_DEFAULT_REL_ERROR 2e-2
46 *
m_log << aText <<
"\n";
55 std::shared_ptr<wxString>
m_log;
61 m_log(
std::make_shared<wxString>() ),
85 for(
int i = 0; i < 200 &&
m_simulator->IsRunning(); ++i )
89 "Timed out waiting for ngspice to stop during teardown" );
100 test_case::id_t
id = framework::current_test_case().p_id;
101 test_results results = results_collector.results(
id );
105 if( !results.passed() )
114 fn.AppendDir(
"spice_netlists" );
115 fn.AppendDir( aBaseName );
116 fn.SetName( aBaseName );
124 wxFileName netFile =
m_schematic->Project().GetProjectFullName();
127 netFile.SetName( netFile.GetName() +
"_test" );
129 netFile.SetExt(
"spice" );
130 return netFile.GetFullPath();
136 BOOST_TEST_CHECKPOINT(
"Comparing netlist " << netlistPath );
149 wxFFile file( netlistPath,
"rt" );
155 ngspice->
Command(
"set ngbehavior=ps" );
156 ngspice->
Command(
"setseed 1" );
181 bool mif_error =
m_log->Find( wxT(
"MIF-ERROR" ) ) != wxNOT_FOUND;
183 BOOST_TEST_INFO(
"Cannot run ngspice. test skipped. Missing code model files?" );
184 BOOST_CHECK( !mif_error );
186 bool err_found =
m_log->Find( wxT(
"Error: circuit not parsed" ) ) != wxNOT_FOUND;
194 BOOST_CHECK( !err_found );
196 if( mif_error || err_found )
201 *
m_log <<
"Original Netlist\n";
202 *
m_log <<
"----------------\n";
209 ngspice->
Command(
"linearize" );
215 ngspice->
Command(
"echo Available Vectors" );
216 ngspice->
Command(
"echo -----------------" );
221 *
m_log <<
"Original Netlist\n";
222 *
m_log <<
"----------------\n";
226 ngspice->
Command(
"echo Expanded Netlist" );
227 ngspice->
Command(
"echo ----------------" );
228 ngspice->
Command(
"listing runnable" );
231 void TestOpPoint(
double aRefValue,
const std::string& aVectorName,
238 std::vector<double> vector = ngspice->
GetRealVector( aVectorName );
240 BOOST_REQUIRE_EQUAL( vector.size(), 1 );
242 double maxError = abs( aRefValue * aMaxRelError );
243 BOOST_CHECK_LE( abs( vector[0] - aRefValue ), aMaxRelError );
247 void TestPoint(
const std::string& aXVectorName,
double aXValue,
248 const std::map<const std::string, double> aTestVectorsAndValues,
259 std::vector<double> xVector = ngspice->
GetRealVector( aXVectorName );
262 for(; i < xVector.size(); ++i )
264 double inf = std::numeric_limits<double>::infinity();
266 double leftDelta = ( aXValue - ( i >= 1 ? xVector[i - 1] : -inf ) );
267 double middleDelta = ( aXValue - xVector[i] );
268 double rightDelta = ( aXValue - ( i < xVector.size() - 1 ? xVector[i + 1] : inf ) );
271 if( abs( middleDelta ) <= abs( leftDelta )
272 && abs( middleDelta ) <= abs( rightDelta ) )
278 BOOST_REQUIRE_LT( i, xVector.size() );
280 for(
auto& [vectorName, refValue] : aTestVectorsAndValues )
282 std::vector<double> yVector = ngspice->
GetGainVector( vectorName );
284 BOOST_REQUIRE_GE( yVector.size(), i + 1 );
287 <<
", Ref value: " << refValue
288 <<
", Actual value: " << yVector[i] )
290 double maxError = abs( refValue * aMaxRelError );
295 maxError = aMaxRelError;
298 BOOST_CHECK_LE( abs( yVector[i] - refValue ), maxError );
305 const std::map<const std::string, double> aTestVectorsAndValues,
308 TestPoint(
"time", aTime, aTestVectorsAndValues, aMaxRelError );
312 const std::map<const std::string, double> aTestVectorsAndValues,
315 TestPoint(
"frequency", aFrequency, aTestVectorsAndValues, aMaxRelError );
321 netlistPath.SetExt(
"csv" );
323 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
Execute a Spice command as if it was typed into console.
bool IsRunning() override final
Check if simulation is running at the moment.
bool Run() override final
Execute the simulation with currently loaded netlist.
bool LoadNetlist(const std::string &aNetlist) override final
Load a netlist for the simulation.
std::vector< double > GetGainVector(const std::string &aName, int aMaxLen=-1) override final
Return a requested vector with magnitude values.
std::vector< double > GetRealVector(const std::string &aName, int aMaxLen=-1) override final
Return a requested vector with real values.
void Clean() override final
Cleans simulation data (i.e.
virtual void SetReporter(REPORTER *aReporter)
Set a 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)
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("Two-port Series .op current = "<< iDevice)
#define MAX_DEFAULT_REL_ERROR
BOOST_TEST_CONTEXT("Test Clearance")
BOOST_TEST_MESSAGE("Polyline has "<< chain.PointCount()<< " points")