diff --git a/docs/doxy.config.in b/docs/doxy.config.in index 02bc95282..ff978d3f1 100644 --- a/docs/doxy.config.in +++ b/docs/doxy.config.in @@ -107,7 +107,7 @@ BRIEF_MEMBER_DESC = YES # brief descriptions will be completely suppressed. # The default value is: YES. -REPEAT_BRIEF = YES +REPEAT_BRIEF = NO # This tag implements a quasi-intelligent brief description abbreviator that is # used to form the text in various listings. Each string in this list, if found diff --git a/src/api/libcellml/error.h b/src/api/libcellml/error.h index 2874cba04..d15dc1b8e 100644 --- a/src/api/libcellml/error.h +++ b/src/api/libcellml/error.h @@ -34,7 +34,7 @@ class LIBCELLML_EXPORT Error public: Error(); /**< Constructor */ virtual ~Error(); /**< Destructor */ - Error(const Error& rhs); /**< Copy constructor */ + Error(const Error &rhs); /**< Copy constructor */ Error(Error &&rhs); /**< Move constructor */ Error& operator=(Error rhs); /**< Assignment operator */ @@ -129,7 +129,7 @@ class LIBCELLML_EXPORT Error * * @param description The @c std::string error description to set. */ - void setDescription(const std::string& description); + void setDescription(const std::string &description); /** * @brief Get the description for this error. diff --git a/src/api/libcellml/importsource.h b/src/api/libcellml/importsource.h index ecb27b9e0..fd515f124 100644 --- a/src/api/libcellml/importsource.h +++ b/src/api/libcellml/importsource.h @@ -36,26 +36,57 @@ class LIBCELLML_EXPORT ImportSource: public Entity ~ImportSource() override; /**< Destructor */ ImportSource(const ImportSource &rhs); /**< Copy constructor */ ImportSource(ImportSource &&rhs); /**< Move constructor */ - ImportSource& operator=(ImportSource m); /**< Assignment operator */ + ImportSource& operator=(ImportSource rhs); /**< Assignment operator */ /** - * @brief Set the imported model source. + * @brief Get the source @c Model's URL. * - * Set the imported model source that this import source refers to. + * Get the source @c Model's URL set in this instance. If no source @c Model + * URL is set then return an empty string. * - * @param source The source of the model as a @c std::string. + * @return The URL of the source @c Model if set otherwise the emtpy string. */ - void setSource(const std::string &source); + std::string getUrl() const; /** - * @brief Get the imported model source. + * @brief Set the source @c Model's URL. * - * Get the imported model source set in this instance. If no imported source - * is set then return an empty string. + * Set the source @c Model's URL that this @c ImportSource refers to. * - * @return The imported model source as a @c std::string, if set, otherwise the empty string. + * @param source The source @c Model's URL. */ - std::string getSource() const; + void setUrl(const std::string &url); + + /** + * @brief Get the @c Model that resolves the import. + * + * Get the @c Model which has been assigned to resolve this @c ImportSource. If no @c Model + * has been assigned then return the @c nullptr. + * + * @return The @c Model used to resolve this @c ImportSource. + */ + libcellml::ModelPtr getModel() const; + + /** + * @brief Provide the @c Model used to resolve this import. + * + * Uses the provided @c Model to resolve this @c ImportSource, which should correspond + * to the @c ImportSource identified by this import. + * + * @param model The @c Model to use in resolving this @c ImportSource. + */ + void setModel(libcellml::ModelPtr model); + + /** + * @brief Test if this @c ImportSource is resolved. + * + * Method to test if this @c ImportSource has been resolved, i.e., the source @c Model has + * been assigned. Returns @c true if the @c ImportSource is resolved otherwise returns + * @c false. + * + * @return @c true if the @c ImportSource has been resolved, @c false otherwise. + */ + bool hasModel() const; private: void swap(ImportSource &rhs); /**< Swap method required for C++ 11 move semantics. */ diff --git a/src/api/libcellml/model.h b/src/api/libcellml/model.h index c9ae5a4aa..aef2b1339 100644 --- a/src/api/libcellml/model.h +++ b/src/api/libcellml/model.h @@ -21,6 +21,10 @@ limitations under the License. #include "libcellml/componententity.h" #include "libcellml/exportdefinitions.h" +#ifndef SWIG +template class LIBCELLML_EXPORT std::weak_ptr; +#endif + //! Everything in libCellML is in this namespace. namespace libcellml { @@ -30,6 +34,9 @@ namespace libcellml { * The Model class is for representing a CellML Model. */ class LIBCELLML_EXPORT Model: public ComponentEntity +#ifndef SWIG + , public std::enable_shared_from_this +#endif { public: Model(); /**< Constructor */ @@ -224,6 +231,26 @@ class LIBCELLML_EXPORT Model: public ComponentEntity */ size_t unitsCount() const; + /** + * @brief Resolve all imports in this model. + * + * Resolve all @c Component and @c Units imports by loading the models + * from local disk through relative URLs. The @p baseFile is used to determine + * the full path to the source model relative to this one. + * + * @param baseFile The @c std::string location on local disk of the source @c Model. + */ + void resolveImports(const std::string &baseFile); + + /** + * @brief Test if this model has unresolved imports. + * + * Test if this model has unresolved imports. + * + * @return True if the @c Model has unresolved imports and false otherwise. + */ + bool hasUnresolvedImports(); + private: void doAddComponent(const ComponentPtr &c) override; void swap(Model &rhs); /**< Swap method required for C++ 11 move semantics. */ diff --git a/src/api/libcellml/types.h b/src/api/libcellml/types.h index f7fcba232..b6eade1d4 100644 --- a/src/api/libcellml/types.h +++ b/src/api/libcellml/types.h @@ -25,20 +25,24 @@ class Parser; /**< Forward declaration of Parser class. */ class Validator; /**< Forward declaration of Validator class. */ // CellML entities. -class Model; /**< Forward declaration of Model class. */ -typedef std::shared_ptr ModelPtr; /**< Type definition for shared model pointer. */ class Component; /**< Forward declaration of Component class. */ typedef std::shared_ptr ComponentPtr; /**< Type definition for shared component pointer. */ +class ComponentEntity; /**< Forward declaration of ComponentEntity class. */ +typedef std::shared_ptr ComponentEntityPtr; /**< Type definition for shared component entity pointer. */ class Error; /**< Forward declaration of Error class. */ typedef std::shared_ptr ErrorPtr; /**< Type definition for shared error pointer. */ +class ImportedEntity; /**< Forward declaration of ImportedEntity class. */ +typedef std::shared_ptr ImportedEntityPtr; /**< Type definition for shared imported entity pointer. */ class ImportSource; /**< Forward declaration of ImportSource class. */ typedef std::shared_ptr ImportSourcePtr; /**< Type definition for shared import source pointer. */ +class Model; /**< Forward declaration of Model class. */ +typedef std::shared_ptr ModelPtr; /**< Type definition for shared model pointer. */ +class Reset; /**< Forward declaration of Reset class. */ +typedef std::shared_ptr ResetPtr; /**< Type definition for shared reset pointer. */ class Units; /**< Forward declaration of Units class. */ typedef std::shared_ptr UnitsPtr; /**< Type definition for shared units pointer. */ class Variable; /**< Forward declaration of Variable class. */ typedef std::shared_ptr VariablePtr; /**< Type definition for shared variable pointer. */ class When; /**< Forward declaration of When class. */ typedef std::shared_ptr WhenPtr; /**< Type definition for shared when pointer. */ -class Reset; /**< Forward declaration of Reset class. */ -typedef std::shared_ptr ResetPtr; /**< Type definition for shared reset pointer. */ } diff --git a/src/bindings/interface/component.i b/src/bindings/interface/component.i index 371f3bc81..0a82fe462 100644 --- a/src/bindings/interface/component.i +++ b/src/bindings/interface/component.i @@ -5,20 +5,6 @@ %import "types.i" %import "componententity.i" -#if defined(SWIGPYTHON) - // Treat negative size_t as invalid index (instead of unknown method) - %extend libcellml::Component { - VariablePtr getVariable(long index) const { - if(index < 0) return nullptr; - return $self->getVariable(size_t(index)); - } - bool removeVariable(long index) { - if(index < 0) return false; - return $self->removeVariable(size_t(index)); - } - } -#endif - %feature("docstring") libcellml::Component "Represents a CellML component."; @@ -94,6 +80,20 @@ range for the index is [0, #resets)."; resets. Returns True if the :param: reset is in this component's resets and False otherwise."; +#if defined(SWIGPYTHON) + // Treat negative size_t as invalid index (instead of unknown method) + %extend libcellml::Component { + VariablePtr getVariable(long index) const { + if(index < 0) return nullptr; + return $self->getVariable(size_t(index)); + } + bool removeVariable(long index) { + if(index < 0) return false; + return $self->removeVariable(size_t(index)); + } + } +#endif + %{ #include "libcellml/component.h" %} diff --git a/src/bindings/interface/componententity.i b/src/bindings/interface/componententity.i index 95b25b301..f9f274c8e 100644 --- a/src/bindings/interface/componententity.i +++ b/src/bindings/interface/componententity.i @@ -5,32 +5,6 @@ %import "types.i" %import "importedentity.i" -#if defined(SWIGPYTHON) - // Allow any type of input to be converted to bool - %typemap(typecheck,precedence=SWIG_TYPECHECK_BOOL) bool { $1 = 1; } - %typemap(in) bool { $1 = PyObject_IsTrue($input) == 1; } - - // Treat negative size_t as invalid index (instead of unknown method) - %extend libcellml::ComponentEntity { - ComponentPtr getComponent(long index) const { - if(index < 0) return nullptr; - return $self->getComponent(size_t(index)); - } - bool removeComponent(long index) { - if(index < 0) return false; - return $self->removeComponent(size_t(index)); - } - ComponentPtr takeComponent(long index) { - if(index < 0) return nullptr; - return $self->takeComponent(size_t(index)); - } - bool replaceComponent(long index, const ComponentPtr &c) { - if(index < 0) return false; - return $self->replaceComponent(size_t(index), c); - } - } -#endif - %feature("docstring") libcellml::ComponentEntity "Abstract class that provides component managing functionality."; @@ -85,6 +59,51 @@ Returns `True` on success."; %feature("docstring") libcellml::ComponentEntity::componentCount "Returns the number of components the component contains. "; +%feature("docstring") libcellml::ComponentEntity::getEncapsulationId +"Returns the encapsulation id for this entity. + +The encapsulation Id is placed on the XML element for this entity. For the +:class:`Model` class this is the ``encapsulation`` element that is the root +element for the model's structure. For the :class:`Component` class this is +the ``component_ref`` element that references the component it represents in +the structure." + +%feature("docstring") libcellml::ComponentEntity::setEncapsulationId +"Sets the encapsulation id for this entity. + +The encapsulation Id is placed on the XML element for this entity. For the +:class:`Model` class this is the ``encapsulation`` element that is the root +element for the model's structure. For the :class:`Component` class this is +the ``component_ref`` element that references the component it represents in +the structure." + + +#if defined(SWIGPYTHON) + // Allow any type of input to be converted to bool + %typemap(typecheck,precedence=SWIG_TYPECHECK_BOOL) bool { $1 = 1; } + %typemap(in) bool { $1 = PyObject_IsTrue($input) == 1; } + + // Treat negative size_t as invalid index (instead of unknown method) + %extend libcellml::ComponentEntity { + ComponentPtr getComponent(long index) const { + if(index < 0) return nullptr; + return $self->getComponent(size_t(index)); + } + bool removeComponent(long index) { + if(index < 0) return false; + return $self->removeComponent(size_t(index)); + } + ComponentPtr takeComponent(long index) { + if(index < 0) return nullptr; + return $self->takeComponent(size_t(index)); + } + bool replaceComponent(long index, const ComponentPtr &c) { + if(index < 0) return false; + return $self->replaceComponent(size_t(index), c); + } + } +#endif + %{ #include "libcellml/componententity.h" %} diff --git a/src/bindings/interface/error.i b/src/bindings/interface/error.i index 2119dbfaa..1a0ecb27b 100644 --- a/src/bindings/interface/error.i +++ b/src/bindings/interface/error.i @@ -16,54 +16,66 @@ "Sets a string description for why this error was raised."; %feature("docstring") libcellml::Error::getKind -"Get the `kind` of this error. If no kind has been set for this error, will +"Get the ``kind`` of this error. If no kind has been set for this error, will return Kind::UNDEFINED."; %feature("docstring") libcellml::Error::isKind -"Tests if this error matches the given `kind`."; +"Tests if this error matches the given ``kind``."; %feature("docstring") libcellml::Error::setKind -"Sets the `kind` of this error."; +"Sets the ``kind`` of this error."; %feature("docstring") libcellml::Error::getRule -"Get the `SpecificationRule` of this error."; +"Get the :class:`SpecificationRule` of this error."; %feature("docstring") libcellml::Error::setRule -"Sets the `SpecificationRule` for this error."; +"Sets the :class:`SpecificationRule` for this error."; %feature("docstring") libcellml::Error::getSpecificationHeading "Returns the CellML 2.0 Specification heading associated with the -SpecificationRule for this error (empty string if not set)."; +:class:`SpecificationRule` for this error (empty string if not set)."; %feature("docstring") libcellml::Error::getComponent -"Returns the Component that this error is relevant to (or `None`)."; +"Returns the :class:`Component` that this error is relevant to (or ``None``)."; %feature("docstring") libcellml::Error::setComponent -"Sets the Component that this error is relevant to (`None` to unset)."; +"Sets the :class:`Component` that this error is relevant to (``None`` to unset)."; %feature("docstring") libcellml::Error::getImportSource -"Returns the ImportSource that this error is relevant to (or `None`)."; +"Returns the :class:`ImportSource` that this error is relevant to (or ``None``)."; %feature("docstring") libcellml::Error::setImportSource -"Sets the ImportSource that this error is relevant to (`None` to unset)."; +"Sets the :class:`ImportSource` that this error is relevant to (``None`` to unset)."; %feature("docstring") libcellml::Error::getModel -"Returns the Model that this error is relevant to (or `None`)."; +"Returns the :class:`Model` that this error is relevant to (or ``None``)."; %feature("docstring") libcellml::Error::setModel -"Sets the Model that this error is relevant to (`None` to unset)."; +"Sets the :class:`Model` that this error is relevant to (``None`` to unset)."; %feature("docstring") libcellml::Error::getUnits -"Get the Units that this error is relevant to (or `None`)."; +"Get the :class:`Units` that this error is relevant to (or ``None``)."; %feature("docstring") libcellml::Error::setUnits -"Sets the Units that this error is relevant to (`None` to unset)."; +"Sets the :class`Units` that this error is relevant to (``None`` to unset)."; %feature("docstring") libcellml::Error::getVariable -"Get the variable that this error is relevant to (or `None`)."; +"Get the :class:`Variable` that this error is relevant to (or ``None``)."; %feature("docstring") libcellml::Error::setVariable -"Sets the Variable that this error is relevant to (`None` to unset)."; +"Sets the :class:`Variable` that this error is relevant to (``None`` to unset)."; + +%feature("docstring") libcellml::Error::getReset +"Get the :class:`Reset` that this error is relevant to (or ``None``)."; + +%feature("docstring") libcellml::Error::setReset +"Sets the :class:`Reset` that this error is relevant to (``None`` to unset)."; + +%feature("docstring") libcellml::Error::getWhen +"Get the :class:`When` that this error is relevant to (or ``None``)."; + +%feature("docstring") libcellml::Error::setWhen +"Sets the :class:`When` that this error is relevant to (``None`` to unset)."; %{ #include "libcellml/error.h" diff --git a/src/bindings/interface/importsource.i b/src/bindings/interface/importsource.i index 975c93b16..08a806a6a 100644 --- a/src/bindings/interface/importsource.i +++ b/src/bindings/interface/importsource.i @@ -11,14 +11,22 @@ expected to be obtainable (the 'source'). The `ImportSource` also acts as a handle to indicate that imported entities originate from the same instance of that imported source."; -%feature("docstring") libcellml::ImportSource::getSource -"Returns the imported model source set in this instance (empty string if not -set)."; +%feature("docstring") libcellml::ImportSource::getUrl +"Returns the URL of the source model (empty string if not set)."; -%feature("docstring") libcellml::ImportSource::setSource -"Sets the imported model source that this import source refers to (string to +%feature("docstring") libcellml::ImportSource::setUrl +"Sets the source model URL that this import source refers to (empty string to unset)."; +%feature("docstring") libcellml::ImportSource::getModel +"Returns the Model that has been assigned to resolve this ImportSource."; + +%feature("docstring") libcellml::ImportSource::setModel +"Sets the Model to resolve this ImportSource."; + +%feature("docstring") libcellml::ImportSource::hasModel +"Returns True if this ImportSource has been resolved, False otherwise."; + %{ #include "libcellml/importsource.h" %} diff --git a/src/bindings/interface/logger.i b/src/bindings/interface/logger.i index 34b0a1090..85328a751 100644 --- a/src/bindings/interface/logger.i +++ b/src/bindings/interface/logger.i @@ -4,16 +4,6 @@ %import "types.i" -#if defined(SWIGPYTHON) - // Treat negative size_t as invalid index (instead of unknown method) - %extend libcellml::Logger { - ErrorPtr getError(long index) { - if(index < 0) return nullptr; - return $self->getError(size_t(index)); - } - } -#endif - %feature("docstring") libcellml::Logger "Base class for all serialisable libCellML classes."; @@ -29,6 +19,16 @@ %feature("docstring") libcellml::Logger::errorCount "Returns the number of errors currently stored in the logger."; +#if defined(SWIGPYTHON) + // Treat negative size_t as invalid index (instead of unknown method) + %extend libcellml::Logger { + ErrorPtr getError(long index) { + if(index < 0) return nullptr; + return $self->getError(size_t(index)); + } + } +#endif + %{ #include "libcellml/logger.h" %} diff --git a/src/bindings/interface/model.i b/src/bindings/interface/model.i index f01bb9098..372297fde 100644 --- a/src/bindings/interface/model.i +++ b/src/bindings/interface/model.i @@ -5,28 +5,6 @@ %import "types.i" %import "componententity.i" -#if defined(SWIGPYTHON) - // Treat negative size_t as invalid index (instead of unknown method) - %extend libcellml::Model { - bool removeUnits(long index) { - if(index < 0) return false; - return $self->removeUnits(size_t(index)); - } - UnitsPtr getUnits(long index) const { - if(index < 0) return nullptr; - return $self->getUnits(size_t(index)); - } - UnitsPtr takeUnits(long index) { - if(index < 0) return nullptr; - return $self->takeUnits(size_t(index)); - } - bool replaceUnits(long index, UnitsPtr &units) { - if(index < 0) return false; - return $self->replaceUnits(size_t(index), units); - } - } -#endif - %feature("docstring") libcellml::Model "Represents a CellML model."; @@ -67,6 +45,39 @@ Only the first matching Units is removed and returned."; %feature("docstring") libcellml::Model::unitsCount "Returns the number of units this model contains."; +%feature("docstring") libcellml::Model::resolveImports +"Resolves all imports in this model. + +Resolves all :class:`Component` and :class:`Units` imports by loading the +models from local disk through relative urls. The ``baseFile`` is used to +determine the full path to the source model relative to this one."; + +%feature("docstring") libcellml::Model::hasUnresolvedImports +"Tests if this model has unresolved imports."; + + +#if defined(SWIGPYTHON) + // Treat negative size_t as invalid index (instead of unknown method) + %extend libcellml::Model { + bool removeUnits(long index) { + if(index < 0) return false; + return $self->removeUnits(size_t(index)); + } + UnitsPtr getUnits(long index) const { + if(index < 0) return nullptr; + return $self->getUnits(size_t(index)); + } + UnitsPtr takeUnits(long index) { + if(index < 0) return nullptr; + return $self->takeUnits(size_t(index)); + } + bool replaceUnits(long index, UnitsPtr &units) { + if(index < 0) return false; + return $self->replaceUnits(size_t(index), units); + } + } +#endif + %{ #include "libcellml/model.h" %} diff --git a/src/bindings/interface/printer.i b/src/bindings/interface/printer.i index 50b803c9c..7b785b102 100644 --- a/src/bindings/interface/printer.i +++ b/src/bindings/interface/printer.i @@ -23,6 +23,9 @@ %feature("docstring") libcellml::Printer::printVariable "Serialises the given :class:`Variable` to an XML string."; +%feature("docstring") libcellml::Printer::printReset +"Serialises the given :class:`Reset` to an XML string."; + %{ #include "libcellml/printer.h" %} diff --git a/src/bindings/interface/units.i b/src/bindings/interface/units.i index 63ff8e824..f548c14bb 100644 --- a/src/bindings/interface/units.i +++ b/src/bindings/interface/units.i @@ -30,16 +30,6 @@ // but: addUnit(1, 1) --> (StandardUnit, Prefix, default=1, default=1) %ignore libcellml::Units::addUnit(StandardUnit standardRef, double exponent); -#if defined(SWIGPYTHON) - // Treat negative size_t as invalid index (instead of unknown method) - %extend libcellml::Units { - bool removeUnit(long index) { - if(index < 0) return false; - return $self->removeUnit((size_t)index); - } - } -#endif - %feature("docstring") libcellml::Units "Represents a CellML Units definition."; @@ -85,6 +75,16 @@ StandardUnit."; "Makes this Units an imported units by defining an `ImportSource` from which to extract the units with the given `name`."; +#if defined(SWIGPYTHON) + // Treat negative size_t as invalid index (instead of unknown method) + %extend libcellml::Units { + bool removeUnit(long index) { + if(index < 0) return false; + return $self->removeUnit((size_t)index); + } + } +#endif + %{ #include "libcellml/units.h" %} diff --git a/src/bindings/interface/variable.i b/src/bindings/interface/variable.i index 47ca949df..588b65a94 100644 --- a/src/bindings/interface/variable.i +++ b/src/bindings/interface/variable.i @@ -5,16 +5,6 @@ %import "types.i" %import "namedentity.i" -#if defined(SWIGPYTHON) - // Treat negative size_t as invalid index (instead of unknown method) - %extend libcellml::Variable { - VariablePtr getEquivalentVariable(long index) { - if(index < 0) return nullptr; - return $self->getEquivalentVariable(size_t(index)); - } - } -#endif - %feature("docstring") libcellml::Variable "Represents a CellML Variable entity"; @@ -62,6 +52,16 @@ reference."; "Sets this variable's interfacetype to the given type specified as string or InterfaceType."; +#if defined(SWIGPYTHON) + // Treat negative size_t as invalid index (instead of unknown method) + %extend libcellml::Variable { + VariablePtr getEquivalentVariable(long index) { + if(index < 0) return nullptr; + return $self->getEquivalentVariable(size_t(index)); + } + } +#endif + %{ #include "libcellml/variable.h" %} diff --git a/src/component.cpp b/src/component.cpp index 910163c9f..dc5a17561 100644 --- a/src/component.cpp +++ b/src/component.cpp @@ -45,19 +45,19 @@ struct Component::ComponentImpl std::vector::iterator Component::ComponentImpl::findVariable(const std::string &name) { return std::find_if(mVariables.begin(), mVariables.end(), - [=](const VariablePtr& v) -> bool { return v->getName() == name; }); + [=](const VariablePtr &v) -> bool { return v->getName() == name; }); } std::vector::iterator Component::ComponentImpl::findVariable(const VariablePtr &variable) { return std::find_if(mVariables.begin(), mVariables.end(), - [=](const VariablePtr& v) -> bool { return v == variable; }); + [=](const VariablePtr &v) -> bool { return v == variable; }); } std::vector::iterator Component::ComponentImpl::findReset(const ResetPtr &reset) { return std::find_if(mResets.begin(), mResets.end(), - [=](const ResetPtr& r) -> bool { return r == reset; }); + [=](const ResetPtr &r) -> bool { return r == reset; }); } Component::Component() @@ -75,7 +75,7 @@ Component::~Component() delete mPimpl; } -Component::Component(const Component& rhs) +Component::Component(const Component &rhs) : ComponentEntity(rhs) , ImportedEntity(rhs) , mPimpl(new ComponentImpl()) diff --git a/src/componententity.cpp b/src/componententity.cpp index 850b8a213..a7ac5d487 100644 --- a/src/componententity.cpp +++ b/src/componententity.cpp @@ -43,13 +43,13 @@ struct ComponentEntity::ComponentEntityImpl std::vector::iterator ComponentEntity::ComponentEntityImpl::findComponent(const std::string &name) { return std::find_if(mComponents.begin(), mComponents.end(), - [=](const ComponentPtr& c) -> bool { return c->getName() == name; }); + [=](const ComponentPtr &c) -> bool { return c->getName() == name; }); } std::vector::iterator ComponentEntity::ComponentEntityImpl::findComponent(const ComponentPtr &component) { return std::find_if(mComponents.begin(), mComponents.end(), - [=](const ComponentPtr& c) -> bool { return c == component; }); + [=](const ComponentPtr &c) -> bool { return c == component; }); } // Interface class Model implementation diff --git a/src/entity.cpp b/src/entity.cpp index e05e987bc..27d3f9f75 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -45,7 +45,7 @@ Entity::~Entity() delete mPimpl; } -Entity::Entity(const Entity& rhs) +Entity::Entity(const Entity &rhs) : mPimpl(new EntityImpl()) { mPimpl->mParentComponent = rhs.mPimpl->mParentComponent; diff --git a/src/error.cpp b/src/error.cpp index 3ef5dea94..029e4a7cc 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -52,7 +52,7 @@ Error::~Error() delete mPimpl; } -Error::Error(const Error& rhs) +Error::Error(const Error &rhs) : mPimpl(new ErrorImpl()) { mPimpl->mDescription = rhs.mPimpl->mDescription; diff --git a/src/importedentity.cpp b/src/importedentity.cpp index 3960de790..f401d3bac 100644 --- a/src/importedentity.cpp +++ b/src/importedentity.cpp @@ -41,7 +41,7 @@ ImportedEntity::~ImportedEntity() delete mPimpl; } -ImportedEntity::ImportedEntity(const ImportedEntity& rhs) +ImportedEntity::ImportedEntity(const ImportedEntity &rhs) : mPimpl(new ImportedEntityImpl()) { mPimpl->mImportSource = rhs.mPimpl->mImportSource; diff --git a/src/importsource.cpp b/src/importsource.cpp index ab1ff744d..26222235a 100644 --- a/src/importsource.cpp +++ b/src/importsource.cpp @@ -15,6 +15,7 @@ limitations under the License. */ #include "libcellml/importsource.h" +#include "libcellml/model.h" namespace libcellml { @@ -25,12 +26,14 @@ namespace libcellml { */ struct ImportSource::ImportSourceImpl { - std::string mSource; + std::string mUrl; + libcellml::ModelPtr mModel; }; ImportSource::ImportSource() : mPimpl(new ImportSourceImpl()) { + mPimpl->mModel = nullptr; } ImportSource::~ImportSource() @@ -38,11 +41,12 @@ ImportSource::~ImportSource() delete mPimpl; } -ImportSource::ImportSource(const ImportSource& rhs) +ImportSource::ImportSource(const ImportSource &rhs) : Entity(rhs) , mPimpl(new ImportSourceImpl()) { - mPimpl->mSource = rhs.mPimpl->mSource; + mPimpl->mUrl = rhs.mPimpl->mUrl; + mPimpl->mModel = rhs.mPimpl->mModel; } ImportSource::ImportSource(ImportSource &&rhs) @@ -52,10 +56,10 @@ ImportSource::ImportSource(ImportSource &&rhs) rhs.mPimpl = nullptr; } -ImportSource& ImportSource::operator=(ImportSource e) +ImportSource& ImportSource::operator=(ImportSource rhs) { - Entity::operator= (e); - e.swap(*this); + Entity::operator= (rhs); + rhs.swap(*this); return *this; } @@ -64,14 +68,29 @@ void ImportSource::swap(ImportSource &rhs) std::swap(this->mPimpl, rhs.mPimpl); } -void ImportSource::setSource(const std::string &source) +std::string ImportSource::getUrl() const { - mPimpl->mSource = source; + return mPimpl->mUrl; } -std::string ImportSource::getSource() const +void ImportSource::setUrl(const std::string &url) { - return mPimpl->mSource; + mPimpl->mUrl = url; +} + +ModelPtr ImportSource::getModel() const +{ + return mPimpl->mModel; +} + +void ImportSource::setModel(ModelPtr model) +{ + mPimpl->mModel = model; +} + +bool ImportSource::hasModel() const +{ + return mPimpl->mModel != nullptr; } } diff --git a/src/logger.cpp b/src/logger.cpp index 2bf92f61d..62922fd45 100644 --- a/src/logger.cpp +++ b/src/logger.cpp @@ -45,7 +45,7 @@ Logger::~Logger() delete mPimpl; } -Logger::Logger(const Logger& rhs) +Logger::Logger(const Logger &rhs) : mPimpl(new LoggerImpl()) { mPimpl->mErrors = rhs.mPimpl->mErrors; diff --git a/src/model.cpp b/src/model.cpp index 748919a41..a90001242 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -17,13 +17,16 @@ limitations under the License. #include "libcellml/model.h" #include +#include #include +#include #include #include #include #include "libcellml/component.h" #include "libcellml/importsource.h" +#include "libcellml/parser.h" #include "libcellml/variable.h" #include "libcellml/units.h" @@ -46,17 +49,22 @@ struct Model::ModelImpl std::vector::iterator Model::ModelImpl::findUnits(const std::string &name) { return std::find_if(mUnits.begin(), mUnits.end(), - [=](const UnitsPtr& u) -> bool { return u->getName() == name; }); + [=](const UnitsPtr &u) -> bool { return u->getName() == name; }); } std::vector::iterator Model::ModelImpl::findUnits(const UnitsPtr &units) { return std::find_if(mUnits.begin(), mUnits.end(), - [=](const UnitsPtr& u) -> bool { return u == units; }); + [=](const UnitsPtr &u) -> bool { return u == units; }); } Model::Model() +#ifndef SWIG + : std::enable_shared_from_this() + , mPimpl(new ModelImpl()) +#else : mPimpl(new ModelImpl()) +#endif { } @@ -65,8 +73,11 @@ Model::~Model() delete mPimpl; } -Model::Model(const Model& rhs) +Model::Model(const Model &rhs) : ComponentEntity(rhs) +#ifndef SWIG + , std::enable_shared_from_this() +#endif , mPimpl(new ModelImpl()) { mPimpl->mUnits = rhs.mPimpl->mUnits; @@ -74,6 +85,9 @@ Model::Model(const Model& rhs) Model::Model(Model &&rhs) : ComponentEntity(std::move(rhs)) +#ifndef SWIG + , std::enable_shared_from_this() +#endif ,mPimpl(rhs.mPimpl) { rhs.mPimpl = nullptr; @@ -100,7 +114,7 @@ void Model::doAddComponent(const ComponentPtr &c) } } -void Model::addUnits(const UnitsPtr & units) +void Model::addUnits(const UnitsPtr &units) { mPimpl->mUnits.push_back(units); } @@ -219,4 +233,125 @@ size_t Model::unitsCount() const return mPimpl->mUnits.size(); } +/** + * @brief Resolve the path of the given filename using the given base. + * + * Resolves the full path to the given @p filename using the @p base. + * + * This function is only intended to work with local files. It may not + * work with bases that use the 'file://' prefix. + * + * @param filename The @c std::string relative path from the base path. + * @param base The @c std::string location on local disk for determining the full path from. + * @return The full path from the @p base location to the @p filename + */ +std::string resolvePath(const std::string &filename, const std::string &base) +{ + // We can be naive here as we know what we are dealing with + std::string path = base.substr(0, base.find_last_of('/')+1) + filename; + return path; +} + +void resolveImport(ImportedEntityPtr importedEntity, + const std::string &baseFile) +{ + if (importedEntity->isImport()) { + libcellml::ImportSourcePtr importSource = importedEntity->getImportSource(); + if (!importSource->hasModel()) { + std::string url = resolvePath(importSource->getUrl(), baseFile); + std::ifstream file(url); + if (file.good()) { + std::stringstream buffer; + buffer << file.rdbuf(); + libcellml::Parser parser; + libcellml::ModelPtr model = parser.parseModel(buffer.str()); + importSource->setModel(model); + model->resolveImports(url); + } + } + } +} + +void resolveComponentImports(ComponentEntityPtr parentComponentEntity, const std::string &baseFile) +{ + for (size_t n = 0; n < parentComponentEntity->componentCount(); ++n) + { + libcellml::ComponentPtr component = parentComponentEntity->getComponent(n); + if (component->isImport()) { + resolveImport(component, baseFile); + } else { + resolveComponentImports(component, baseFile); + } + } +} + +void Model::resolveImports(const std::string &baseFile) +{ + for (size_t n = 0; n < unitsCount(); ++n) + { + libcellml::UnitsPtr units = getUnits(n); + resolveImport(units, baseFile); + } + resolveComponentImports(shared_from_this(), baseFile); +} + +bool isUnresolvedImport(ImportedEntityPtr importedEntity) +{ + bool unresolvedImport = false; + if (importedEntity->isImport()) { + libcellml::ImportSourcePtr importedSource = importedEntity->getImportSource(); + if (!importedSource->hasModel()) { + unresolvedImport = true; + } + } + return unresolvedImport; +} + +bool hasUnresolvedComponentImports(ComponentEntityPtr parentComponentEntity); + +bool doHasUnresolvedComponentImports(libcellml::ComponentPtr component) +{ + bool unresolvedImports = false; + if (component->isImport()) { + unresolvedImports = isUnresolvedImport(component); + if (!unresolvedImports) { + // Check that the imported component can import all it needs from its model. + libcellml::ImportSourcePtr importedSource = component->getImportSource(); + if (importedSource->hasModel()) { + ModelPtr importedModel = importedSource->getModel(); + ComponentPtr importedComponent = importedModel->getComponent(component->getImportReference()); + unresolvedImports = doHasUnresolvedComponentImports(importedComponent); + } + } + } else { + unresolvedImports = hasUnresolvedComponentImports(component); + } + return unresolvedImports; +} + +bool hasUnresolvedComponentImports(ComponentEntityPtr parentComponentEntity) +{ + bool unresolvedImports = false; + for (size_t n = 0; n < parentComponentEntity->componentCount() && !unresolvedImports; ++n) + { + libcellml::ComponentPtr component = parentComponentEntity->getComponent(n); + unresolvedImports = doHasUnresolvedComponentImports(component); + } + return unresolvedImports; +} + +bool Model::hasUnresolvedImports() +{ + bool unresolvedImports = false; + for (size_t n = 0; n < unitsCount() && !unresolvedImports; ++n) + { + libcellml::UnitsPtr units = getUnits(n); + unresolvedImports = isUnresolvedImport(units); + } + if (!unresolvedImports) { + unresolvedImports = hasUnresolvedComponentImports(shared_from_this()); + } + return unresolvedImports; +} + } diff --git a/src/namedentity.cpp b/src/namedentity.cpp index 94ed48997..491e5f394 100644 --- a/src/namedentity.cpp +++ b/src/namedentity.cpp @@ -42,7 +42,7 @@ NamedEntity::~NamedEntity() delete mPimpl; } -NamedEntity::NamedEntity(const NamedEntity& rhs) +NamedEntity::NamedEntity(const NamedEntity &rhs) : Entity(rhs) , mPimpl(new NamedEntityImpl()) { diff --git a/src/orderedentity.cpp b/src/orderedentity.cpp index 580187945..822166e9b 100644 --- a/src/orderedentity.cpp +++ b/src/orderedentity.cpp @@ -43,7 +43,7 @@ OrderedEntity::~OrderedEntity() delete mPimpl; } -OrderedEntity::OrderedEntity(const OrderedEntity& rhs) +OrderedEntity::OrderedEntity(const OrderedEntity &rhs) : Entity(rhs) , mPimpl(new OrderedEntityImpl()) { diff --git a/src/parser.cpp b/src/parser.cpp index f1e975d78..72392c703 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -191,7 +191,7 @@ Parser::~Parser() delete mPimpl; } -Parser::Parser(const Parser& rhs) +Parser::Parser(const Parser &rhs) : Logger(rhs) , mPimpl(new ParserImpl()) { @@ -1119,7 +1119,7 @@ void Parser::ParserImpl::loadImport(const ImportSourcePtr &importSource, const M XmlAttributePtr attribute = node->getFirstAttribute(); while (attribute) { if (attribute->isType("href")) { - importSource->setSource(attribute->getValue()); + importSource->setUrl(attribute->getValue()); } else if (attribute->isType("id")) { importSource->setId(attribute->getValue()); } else if (attribute->isType("xlink")) { diff --git a/src/printer.cpp b/src/printer.cpp index dd5e64768..6dd4869fd 100644 --- a/src/printer.cpp +++ b/src/printer.cpp @@ -63,7 +63,7 @@ Printer::~Printer() delete mPimpl; } -Printer::Printer(const Printer& rhs) +Printer::Printer(const Printer &rhs) : Logger(rhs) , mPimpl(new PrinterImpl()) { @@ -93,7 +93,7 @@ std::string Printer::printUnits(UnitsPtr units) const std::string repr = ""; if (units->getName().length()) { if (units->isImport()) { - repr += "getImportSource()->getSource() + "\" xmlns:xlink=\"http://www.w3.org/1999/xlink\""; + repr += "getImportSource()->getUrl() + "\" xmlns:xlink=\"http://www.w3.org/1999/xlink\""; if (units->getImportSource()->getId().length()) { repr += " id=\"" + units->getImportSource()->getId() + "\""; } @@ -486,7 +486,7 @@ std::string Printer::printModel(ModelPtr model) const for (ImportMapIterator iter = importMap.begin(); iter != importMap.end(); ++iter) { - repr += "first->getSource() + "\" xmlns:xlink=\"http://www.w3.org/1999/xlink\""; + repr += "first->getUrl() + "\" xmlns:xlink=\"http://www.w3.org/1999/xlink\""; if (iter->first->getId().length() > 0) { repr += " id=\"" + iter->first->getId() + "\""; } diff --git a/src/reset.cpp b/src/reset.cpp index 8953d504d..2311d2765 100644 --- a/src/reset.cpp +++ b/src/reset.cpp @@ -39,7 +39,7 @@ struct Reset::ResetImpl std::vector::iterator Reset::ResetImpl::findWhen(const WhenPtr &when) { return std::find_if(mWhens.begin(), mWhens.end(), - [=](const WhenPtr& w) -> bool { return w == when; }); + [=](const WhenPtr &w) -> bool { return w == when; }); } Reset::Reset() @@ -52,7 +52,7 @@ Reset::~Reset() delete mPimpl; } -Reset::Reset(const Reset& rhs) +Reset::Reset(const Reset &rhs) : OrderedEntity(rhs) , mPimpl(new ResetImpl()) { diff --git a/src/units.cpp b/src/units.cpp index 0bc82abdc..2cf6b96ca 100644 --- a/src/units.cpp +++ b/src/units.cpp @@ -127,7 +127,7 @@ struct Units::UnitsImpl std::vector::iterator Units::UnitsImpl::findUnit(const std::string &reference) { return std::find_if(mUnits.begin(), mUnits.end(), - [=](const Unit& u) -> bool { return u.mReference == reference; }); + [=](const Unit &u) -> bool { return u.mReference == reference; }); } Units::Units() @@ -140,7 +140,7 @@ Units::~Units() delete mPimpl; } -Units::Units(const Units& rhs) +Units::Units(const Units &rhs) : NamedEntity(rhs) , ImportedEntity(rhs) , mPimpl(new UnitsImpl()) diff --git a/src/validator.cpp b/src/validator.cpp index f98a83e09..6157e8495 100644 --- a/src/validator.cpp +++ b/src/validator.cpp @@ -242,7 +242,7 @@ Validator::~Validator() delete mPimpl; } -Validator::Validator(const Validator& rhs) +Validator::Validator(const Validator &rhs) : Logger(rhs) , mPimpl(new ValidatorImpl()) { @@ -293,7 +293,7 @@ void Validator::validateModel(const ModelPtr &model) if (component->isImport()) { // Check for a component_ref. std::string componentRef = component->getImportReference(); - std::string importSource = component->getImportSource()->getSource(); + std::string importSource = component->getImportSource()->getUrl(); bool foundImportError = false; if (!mPimpl->isCellmlIdentifier(componentRef)) { ErrorPtr err = std::make_shared(); @@ -359,7 +359,7 @@ void Validator::validateModel(const ModelPtr &model) if (units->isImport()) { // Check for a units_ref. std::string unitsRef = units->getImportReference(); - std::string importSource = units->getImportSource()->getSource(); + std::string importSource = units->getImportSource()->getUrl(); bool foundImportError = false; if (!mPimpl->isCellmlIdentifier(unitsRef)) { ErrorPtr err = std::make_shared(); diff --git a/src/variable.cpp b/src/variable.cpp index f6d3bf80a..33d874685 100644 --- a/src/variable.cpp +++ b/src/variable.cpp @@ -180,7 +180,7 @@ Variable::~Variable() delete mPimpl; } -Variable::Variable(const Variable& rhs) +Variable::Variable(const Variable &rhs) : NamedEntity(rhs) , mPimpl(new VariableImpl()) { diff --git a/src/when.cpp b/src/when.cpp index b046d88d5..61a5413a4 100644 --- a/src/when.cpp +++ b/src/when.cpp @@ -39,7 +39,7 @@ When::~When() delete mPimpl; } -When::When(const When& rhs) +When::When(const When &rhs) : OrderedEntity(rhs) , mPimpl(new WhenImpl()) { @@ -66,7 +66,7 @@ void When::swap(When &rhs) std::swap(this->mPimpl, rhs.mPimpl); } -void When::setCondition(const std::string& condition) +void When::setCondition(const std::string &condition) { mPimpl->mCondition = condition; } @@ -76,7 +76,7 @@ std::string When::getCondition() const return mPimpl->mCondition; } -void When::setValue(const std::string& value) +void When::setValue(const std::string &value) { mPimpl->mValue = value; } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 1a46dda2f..2ab60a976 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -21,6 +21,7 @@ include(model/tests.cmake) include(parser/tests.cmake) include(printer/tests.cmake) include(reset/tests.cmake) +include(resolve_imports/tests.cmake) include(units/tests.cmake) include(validator/tests.cmake) include(variable/tests.cmake) diff --git a/tests/bindings/python/CMakeLists.txt b/tests/bindings/python/CMakeLists.txt index f56a9e5ab..da5e839d4 100644 --- a/tests/bindings/python/CMakeLists.txt +++ b/tests/bindings/python/CMakeLists.txt @@ -18,6 +18,7 @@ set(TEST_SRCS test_validator.py test_version.py test_when.py + test_docstrings.py ) foreach(_TEST ${TEST_SRCS}) diff --git a/tests/bindings/python/test_component.py b/tests/bindings/python/test_component.py index 27217d685..14046b66f 100644 --- a/tests/bindings/python/test_component.py +++ b/tests/bindings/python/test_component.py @@ -42,9 +42,9 @@ def test_set_source(self): x = Component() i = ImportSource() - i.setSource('bonjour') + i.setUrl('bonjour') x.setSourceComponent(i, 'camembert') - self.assertEqual(x.getImportSource().getSource(), 'bonjour') + self.assertEqual(x.getImportSource().getUrl(), 'bonjour') self.assertEqual(x.getImportReference(), 'camembert') def test_math(self): diff --git a/tests/bindings/python/test_component_entity.py b/tests/bindings/python/test_component_entity.py index 442100ba7..51442b323 100644 --- a/tests/bindings/python/test_component_entity.py +++ b/tests/bindings/python/test_component_entity.py @@ -387,6 +387,25 @@ def test_component_count(self): self.assertTrue(x.removeComponent(0)) self.assertEqual(x.componentCount(), 0) + def test_set_encapsulation_id(self): + from libcellml import ComponentEntity + + # void setEncapsulationId(const std::string &id); + x = ComponentEntity() + x.setEncapsulationId('Hello') + x.setEncapsulationId('') + + def test_get_encapsulation_id(self): + from libcellml import ComponentEntity + + # std::string getEncapsulationId() const; + x = ComponentEntity() + self.assertEqual(x.getEncapsulationId(), '') + x.setEncapsulationId('Hello') + self.assertEqual(x.getEncapsulationId(), 'Hello') + x.setEncapsulationId('') + self.assertEqual(x.getEncapsulationId(), '') + if __name__ == '__main__': unittest.main() diff --git a/tests/bindings/python/test_docstrings.py b/tests/bindings/python/test_docstrings.py new file mode 100644 index 000000000..eb142aeb3 --- /dev/null +++ b/tests/bindings/python/test_docstrings.py @@ -0,0 +1,36 @@ +# +# Tests if all CellML bindings have docstrings set. +# +import unittest +import types + + +class DocstringTestCase(unittest.TestCase): + + def test_docstrings(self): + import libcellml + + # Scan for missing or empty docstrings + def scan(root, missing, prefix=''): + prefix += root.__name__ + if not root.__doc__: + missing.append(prefix) + prefix += '.' + # Scan children, using dict instead of dir to avoid inherited + # methods. + for x in root.__dict__: + if x[:1] != '_' and x is not root: + child = getattr(root, x) + if isinstance(child, (type, types.FunctionType)): + scan(child, missing, prefix) + + missing = [] + scan(libcellml, missing) + if missing: + raise Exception( + 'Missing (' + str(len(missing)) + ') docstrings, for: ' + + ', '.join(missing)) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/bindings/python/test_error.py b/tests/bindings/python/test_error.py index de5c4d1b5..50ed31fb8 100644 --- a/tests/bindings/python/test_error.py +++ b/tests/bindings/python/test_error.py @@ -108,7 +108,7 @@ def test_specification_rule_enum(self): def test_set_description(self): from libcellml import Error - # void setDescription(const std::string& description) + # void setDescription(const std::string &description) e = Error() e.setDescription('hello') e.setDescription('') @@ -269,6 +269,46 @@ def test_get_variable(self): self.assertIsInstance(e.getVariable(), Variable) self.assertEqual(e.getVariable().getName(), name) + def test_set_reset(self): + from libcellml import Error, Reset + + # void setReset(const ResetPtr &reset); + e = Error() + e.setReset(Reset()) + + def test_get_reset(self): + from libcellml import Error, Reset + + # ResetPtr getReset() const; + e = Error() + self.assertIsNone(e.getReset()) + name = 'res' + r = Reset() + r.setId(name) + e.setReset(r) + self.assertIsInstance(e.getReset(), Reset) + self.assertEqual(e.getReset().getId(), name) + + def test_set_when(self): + from libcellml import Error, When + + # void setWhen(const WhenPtr &when); + e = Error() + e.setWhen(When()) + + def test_get_when(self): + from libcellml import Error, When + + # WhenPtr getWhen() const; + e = Error() + self.assertIsNone(e.getWhen()) + name = 'var' + w = When() + w.setId(name) + e.setWhen(w) + self.assertIsInstance(e.getWhen(), When) + self.assertEqual(e.getWhen().getId(), name) + if __name__ == '__main__': unittest.main() diff --git a/tests/bindings/python/test_import_source.py b/tests/bindings/python/test_import_source.py index 1f5e9a742..7ea7d0d35 100644 --- a/tests/bindings/python/test_import_source.py +++ b/tests/bindings/python/test_import_source.py @@ -22,26 +22,59 @@ def test_inheritance(self): x = ImportSource() self.assertIsInstance(x, libcellml.Entity) - def test_set_source(self): + def test_set_url(self): from libcellml import ImportSource - # void setSource(const std::string &reference) + # void setUrl(const std::string &reference) x = ImportSource() - x.setSource('') - x.setSource('hello') - x.setSource('') + x.setUrl('') + x.setUrl('hello') + x.setUrl('') - def test_get_source(self): + def test_get_url(self): from libcellml import ImportSource - # std::string getSource() + # std::string getUrl() source = 'cheers' x = ImportSource() - self.assertEqual(x.getSource(), '') - x.setSource(source) - self.assertEqual(x.getSource(), source) - x.setSource('') - self.assertEqual(x.getSource(), '') + self.assertEqual(x.getUrl(), '') + x.setUrl(source) + self.assertEqual(x.getUrl(), source) + x.setUrl('') + self.assertEqual(x.getUrl(), '') + + def test_set_model(self): + from libcellml import ImportSource, Model + + # void setModel(libcellml::ModelPtr model); + x = ImportSource() + x.setModel(None) + x.setModel(Model()) + x.setModel(None) + + def test_get_model(self): + from libcellml import ImportSource, Model + + # libcellml::ModelPtr getModel() const; + model = Model() + model.setName('bert') + x = ImportSource() + self.assertIsNone(x.getModel()) + x.setModel(model) + self.assertEqual(x.getModel().getName(), model.getName()) + x.setModel(None) + self.assertIsNone(x.getModel()) + + def test_has_model(self): + from libcellml import ImportSource, Model + + # bool hasModel() const; + x = ImportSource() + self.assertFalse(x.hasModel()) + x.setModel(Model()) + self.assertTrue(x.hasModel()) + x.setModel(None) + self.assertFalse(x.hasModel()) if __name__ == '__main__': diff --git a/tests/bindings/python/test_imported_entity.py b/tests/bindings/python/test_imported_entity.py index 05efd6f0c..4125cc8bc 100644 --- a/tests/bindings/python/test_imported_entity.py +++ b/tests/bindings/python/test_imported_entity.py @@ -40,12 +40,12 @@ def test_get_import_source(self): # ImportSourcePtr getImportSource() i = ImportSource() source = 'hello' - i.setSource(source) + i.setUrl(source) x = ImportedEntity() self.assertIsNone(x.getImportSource()) x.setImportSource(i) self.assertIsNotNone(x.getImportSource()) - self.assertEqual(x.getImportSource().getSource(), source) + self.assertEqual(x.getImportSource().getUrl(), source) def test_set_import_reference(self): from libcellml import ImportedEntity diff --git a/tests/bindings/python/test_model.py b/tests/bindings/python/test_model.py index b62c3b3c2..817f643e5 100644 --- a/tests/bindings/python/test_model.py +++ b/tests/bindings/python/test_model.py @@ -225,6 +225,24 @@ def test_units_count(self): self.assertEqual(m.unitsCount(), 0) del(m) + def test_has_unresolved_imports(self): + from libcellml import Model, Component, ImportSource + + # bool hasUnresolvedImports(); + m = Model() + self.assertFalse(m.hasUnresolvedImports()) + c = Component() + m.addComponent(c) + self.assertFalse(m.hasUnresolvedImports()) + c.setImportSource(ImportSource()) + self.assertTrue(m.hasUnresolvedImports()) + + def test_resolve_imports(self): + from libcellml import Model + + m = Model() + m.resolveImports('file.txt') + if __name__ == '__main__': unittest.main() diff --git a/tests/bindings/python/test_printer.py b/tests/bindings/python/test_printer.py index f24165624..e03427a14 100644 --- a/tests/bindings/python/test_printer.py +++ b/tests/bindings/python/test_printer.py @@ -72,6 +72,16 @@ def test_print_component(self): # This method shadows printComponent(ComponentPtr) so wasn't added # std::string printComponent(Component component) + def test_print_reset(self): + from libcellml import Printer, Reset + + # std::string printReset(ResetPtr reset) const; + p = Printer() + self.assertIsInstance(p.printReset(Reset()), str) + + # This method shadows printReset(ResetPtr) so wasn't added + # std::string printReset(Reset reset) const; + if __name__ == '__main__': unittest.main() diff --git a/tests/bindings/python/test_units.py b/tests/bindings/python/test_units.py index 218dc2d63..d221fa2e6 100644 --- a/tests/bindings/python/test_units.py +++ b/tests/bindings/python/test_units.py @@ -210,7 +210,7 @@ def test_add_unit(self): def test_get_unit_attributes(self): from libcellml import Units - # void getUnitAttributes(size_t index, std::string& reference, + # void getUnitAttributes(size_t index, std::string &reference, # std::string &prefix, double &exponent, double &multiplier, std::string &id) u = Units() x = u.getUnitAttributes(0) diff --git a/tests/connection/connection.cpp b/tests/connection/connection.cpp index 12e8171b7..bfb21f048 100644 --- a/tests/connection/connection.cpp +++ b/tests/connection/connection.cpp @@ -934,7 +934,7 @@ TEST(Connection, importedComponentConnectionAndParse) { libcellml::VariablePtr variableImported = std::make_shared(); libcellml::VariablePtr variableBob = std::make_shared(); - imp->setSource("some-other-model.xml"); + imp->setUrl("some-other-model.xml"); componentImported->setName("component_in_this_model"); componentImported->setSourceComponent(imp, "component_in_that_model"); componentBob->setName("component_bob"); diff --git a/tests/model/component_import.cpp b/tests/model/component_import.cpp index 8bd7d9a9f..46ead7c60 100644 --- a/tests/model/component_import.cpp +++ b/tests/model/component_import.cpp @@ -31,7 +31,7 @@ TEST(ComponentImport, basics) { const std::string e = ""; libcellml::ImportSourcePtr imp = std::make_shared(); - imp->setSource("a-model.xml"); + imp->setUrl("a-model.xml"); libcellml::ComponentPtr c = std::make_shared(); @@ -60,7 +60,7 @@ TEST(ComponentImport, singleImportA) { libcellml::Model m; libcellml::ImportSourcePtr imp = std::make_shared(); - imp->setSource("some-other-model.xml"); + imp->setUrl("some-other-model.xml"); libcellml::ComponentPtr importedComponent = std::make_shared(); @@ -91,7 +91,7 @@ TEST(ComponentImport, singleImportB) { libcellml::Model m; libcellml::ImportSourcePtr imp = std::make_shared(); - imp->setSource("some-other-model.xml"); + imp->setUrl("some-other-model.xml"); libcellml::ComponentPtr importedComponent = std::make_shared(); importedComponent->setName("component_in_this_model"); @@ -115,7 +115,7 @@ TEST(ComponentImport, nonExistentURLAndParse) { libcellml::Model m; libcellml::ImportSourcePtr imp = std::make_shared(); - imp->setSource("http://someplace.world/cellml/model.xml"); + imp->setUrl("http://someplace.world/cellml/model.xml"); libcellml::ComponentPtr importedComponent = std::make_shared(); @@ -170,7 +170,7 @@ TEST(ComponentImport, multipleImportAndParse) { libcellml::Model m; libcellml::ImportSourcePtr imp = std::make_shared(); - imp->setSource("some-other-model.xml"); + imp->setUrl("some-other-model.xml"); libcellml::ComponentPtr c1 = std::make_shared(); c1->setName("c1"); c1->setSourceComponent(imp, "cc1"); @@ -181,7 +181,7 @@ TEST(ComponentImport, multipleImportAndParse) { m.addComponent(c2); libcellml::ImportSourcePtr imp2 = std::make_shared(); - imp2->setSource("some-other-model.xml"); + imp2->setUrl("some-other-model.xml"); libcellml::ComponentPtr c3 = std::make_shared(); c3->setName("c3"); c3->setSourceComponent(imp2, "cc1"); @@ -220,7 +220,7 @@ TEST(ComponentImport, hierarchicalImportAndParse) { libcellml::Model m; libcellml::ImportSourcePtr imp = std::make_shared(); - imp->setSource("some-other-model.xml"); + imp->setUrl("some-other-model.xml"); libcellml::ComponentPtr dave = std::make_shared(); dave->setName("dave"); @@ -277,7 +277,7 @@ TEST(ComponentImport, complexImportAndParse) { libcellml::Model m; libcellml::ImportSourcePtr imp = std::make_shared(); - imp->setSource("some-other-model.xml"); + imp->setUrl("some-other-model.xml"); libcellml::ComponentPtr dave = std::make_shared(); dave->setName("dave"); diff --git a/tests/model/model.cpp b/tests/model/model.cpp index 0dfd0f101..cf25db84a 100644 --- a/tests/model/model.cpp +++ b/tests/model/model.cpp @@ -320,21 +320,21 @@ struct structure std::cout << "structure constructor: " << m_data->id << std::endl; } - structure(const structure& rhs) + structure(const structure &rhs) : m_data{new big_and_complicated{}} { std::cout << "structure copy constructor: " << rhs.m_data->id << std::endl; m_data->id = rhs.m_data->id; } - structure(structure&& rhs) + structure(structure &&rhs) : m_data(rhs.m_data) { std::cout << "structure move constructor: " << m_data->id << std::endl; rhs.m_data = nullptr; } - structure &operator=(structure r) + structure& operator=(structure r) { r.swap(*this); return *this; @@ -496,10 +496,10 @@ TEST(Model, setAndCheckIdsAllEntities) { libcellml::ResetPtr r1 = std::make_shared(); libcellml::WhenPtr w1 = std::make_shared(); - i1->setSource("some-other-model.xml"); + i1->setUrl("some-other-model.xml"); c1->setSourceComponent(i1, "a_component_in_that_model"); - i2->setSource("some-other-model.xml"); + i2->setUrl("some-other-model.xml"); u1->setSourceUnits(i2, "a_units_in_that_model"); m.setName("mname"); diff --git a/tests/model/units_import.cpp b/tests/model/units_import.cpp index f0359c285..86e056118 100644 --- a/tests/model/units_import.cpp +++ b/tests/model/units_import.cpp @@ -22,7 +22,7 @@ TEST(UnitsImport, basics) { const std::string e = ""; libcellml::ImportSourcePtr imp = std::make_shared(); - imp->setSource("a-model.xml"); + imp->setUrl("a-model.xml"); libcellml::UnitsPtr u = std::make_shared(); @@ -51,7 +51,7 @@ TEST(UnitsImport, importValidName) { libcellml::Model m; libcellml::ImportSourcePtr imp = std::make_shared(); - imp->setSource("some-other-model.xml"); + imp->setUrl("some-other-model.xml"); libcellml::UnitsPtr importedUnits = std::make_shared(); @@ -84,7 +84,7 @@ TEST(UnitsImport, importInvalidName) { libcellml::Model m; libcellml::ImportSourcePtr imp = std::make_shared(); - imp->setSource("some-other-model.xml"); + imp->setUrl("some-other-model.xml"); libcellml::UnitsPtr importedUnits = std::make_shared(); @@ -113,7 +113,7 @@ TEST(UnitsImport, nonExistentURL) { libcellml::Model m; libcellml::ImportSourcePtr imp = std::make_shared(); - imp->setSource("http://someplace.world/cellml/model.xml"); + imp->setUrl("http://someplace.world/cellml/model.xml"); libcellml::UnitsPtr importedUnits = std::make_shared(); @@ -156,7 +156,7 @@ TEST(UnitsImport, importModifyAndParse) { libcellml::Model m; libcellml::ImportSourcePtr imp = std::make_shared(); - imp->setSource("some-other-model.xml"); + imp->setUrl("some-other-model.xml"); libcellml::UnitsPtr importedUnits = std::make_shared(); importedUnits->setName("units_in_this_model"); diff --git a/tests/resolve_imports/file_parser.cpp b/tests/resolve_imports/file_parser.cpp new file mode 100644 index 000000000..cffe5bffb --- /dev/null +++ b/tests/resolve_imports/file_parser.cpp @@ -0,0 +1,124 @@ +/* +Copyright libCellML Contributors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include "gtest/gtest.h" + +#include +#include +#include +#include +#include +#include + +// generated with test resource locations +#include "test_resources.h" + +TEST(ResolveImports, resolveSineModelFromFile) { + std::ifstream t(TestResources::getLocation( + TestResources::CELLML_SINE_MODEL_RESOURCE)); + + std::stringstream buffer; + buffer << t.rdbuf(); + + libcellml::Parser p; + libcellml::ModelPtr model = p.parseModel(buffer.str()); + + EXPECT_EQ(0u, p.errorCount()); + EXPECT_FALSE(model->hasUnresolvedImports()); +} + +TEST(ResolveImports, resolveSineImportsModelFromFile) { + std::string sineModelLocation = TestResources::getLocation( + TestResources::CELLML_SINE_IMPORTS_MODEL_RESOURCE); + std::ifstream t(sineModelLocation); + std::stringstream buffer; + buffer << t.rdbuf(); + + libcellml::Parser p; + libcellml::ModelPtr model = p.parseModel(buffer.str()); + EXPECT_EQ(0u, p.errorCount()); + + EXPECT_TRUE(model->hasUnresolvedImports()); + model->resolveImports(sineModelLocation); + EXPECT_FALSE(model->hasUnresolvedImports()); +} + +TEST(ResolveImports, resolveComplexImportsModelFromFile) { + std::string modelLocation = TestResources::getLocation( + TestResources::CELLML_COMPLEX_IMPORTS_MODEL_RESOURCE); + std::ifstream t(modelLocation); + std::stringstream buffer; + buffer << t.rdbuf(); + + libcellml::Parser p; + libcellml::ModelPtr model = p.parseModel(buffer.str()); + EXPECT_EQ(0u, p.errorCount()); + + EXPECT_TRUE(model->hasUnresolvedImports()); + model->resolveImports(modelLocation); + EXPECT_FALSE(model->hasUnresolvedImports()); +} + +TEST(ResolveImports, resolveUnitsImportFromFile) { + std::string modelLocation = TestResources::getLocation( + TestResources::CELLML_UNITS_IMPORT_MODEL_RESOURCE); + std::ifstream t(modelLocation); + std::stringstream buffer; + buffer << t.rdbuf(); + + libcellml::Parser p; + libcellml::ModelPtr model = p.parseModel(buffer.str()); + + EXPECT_EQ(0u, p.errorCount()); + + EXPECT_TRUE(model->hasUnresolvedImports()); + model->resolveImports(modelLocation); + EXPECT_FALSE(model->hasUnresolvedImports()); +} + +TEST(ResolveImports, resolveImportsFromFileLevel0) { + std::string modelLocation = TestResources::getLocation( + TestResources::CELLML_IMPORT_LEVEL0_MODEL_RESOURCE); + std::ifstream t(modelLocation); + std::stringstream buffer; + buffer << t.rdbuf(); + + libcellml::Parser p; + libcellml::ModelPtr model = p.parseModel(buffer.str()); + + EXPECT_EQ(0u, p.errorCount()); + + EXPECT_TRUE(model->hasUnresolvedImports()); + model->resolveImports(modelLocation); + EXPECT_FALSE(model->hasUnresolvedImports()); +} + +TEST(ResolveImports, resolveImportsFromFileLevel0Unresolvable) { + std::string modelLocation = TestResources::getLocation( + TestResources::CELLML_IMPORT_LEVEL0_UNRESOLVABLE_MODEL_RESOURCE); + std::ifstream t(modelLocation); + std::stringstream buffer; + buffer << t.rdbuf(); + + libcellml::Parser p; + libcellml::ModelPtr model = p.parseModel(buffer.str()); + + EXPECT_EQ(0u, p.errorCount()); + + EXPECT_TRUE(model->hasUnresolvedImports()); + model->resolveImports(modelLocation); + EXPECT_TRUE(model->hasUnresolvedImports()); +} diff --git a/tests/resolve_imports/tests.cmake b/tests/resolve_imports/tests.cmake new file mode 100644 index 000000000..f213ecefe --- /dev/null +++ b/tests/resolve_imports/tests.cmake @@ -0,0 +1,17 @@ + +# Set the test name, 'test_' will be prepended to the +# name set here +set(CURRENT_TEST resolve_imports) +# Set a category name to enable running commands like: +# ctest -R +# which will run the tests matching this category-label. +# Can be left empty (or just not set) +set(${CURRENT_TEST}_CATEGORY io) +list(APPEND LIBCELLML_TESTS ${CURRENT_TEST}) +# Using absolute path relative to this file +set(${CURRENT_TEST}_SRCS + ${CMAKE_CURRENT_LIST_DIR}/file_parser.cpp +) +#set(${CURRENT_TEST}_HDRS +# ${CMAKE_CURRENT_LIST_DIR}/ +#) diff --git a/tests/resources/complex_imports.xml b/tests/resources/complex_imports.xml new file mode 100644 index 000000000..98a2e7fd4 --- /dev/null +++ b/tests/resources/complex_imports.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/resources/deriv_approx_sin.xml b/tests/resources/deriv_approx_sin.xml new file mode 100644 index 000000000..692de9cb0 --- /dev/null +++ b/tests/resources/deriv_approx_sin.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + x + sin + + + x + + + + + + diff --git a/tests/resources/import_units_model.cellml b/tests/resources/import_units_model.cellml new file mode 100644 index 000000000..82fa52bed --- /dev/null +++ b/tests/resources/import_units_model.cellml @@ -0,0 +1,6 @@ + + + + + + diff --git a/tests/resources/level0-broken-imports.xml b/tests/resources/level0-broken-imports.xml new file mode 100644 index 000000000..e1c7e0dfb --- /dev/null +++ b/tests/resources/level0-broken-imports.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/resources/level0.xml b/tests/resources/level0.xml new file mode 100644 index 000000000..109b0ef2e --- /dev/null +++ b/tests/resources/level0.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/resources/level1-3.xml b/tests/resources/level1-3.xml new file mode 100644 index 000000000..5108cd640 --- /dev/null +++ b/tests/resources/level1-3.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/resources/level1.xml b/tests/resources/level1.xml new file mode 100644 index 000000000..93d19a3e5 --- /dev/null +++ b/tests/resources/level1.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/resources/level2.xml b/tests/resources/level2.xml new file mode 100644 index 000000000..de3240fa1 --- /dev/null +++ b/tests/resources/level2.xml @@ -0,0 +1,26 @@ + + + + + + + + + + time + cosine + + + + parameter + time + + + + + + + + + + diff --git a/tests/resources/parabolic_approx_sin.xml b/tests/resources/parabolic_approx_sin.xml new file mode 100644 index 000000000..713d0e631 --- /dev/null +++ b/tests/resources/parabolic_approx_sin.xml @@ -0,0 +1,182 @@ + + + + + + + + + + + + + + + + k2_oPi + + 2.0 + + + + + k2Pi + + 2.0 + + + + + kPi_2 + + + 2.0 + + + + kPi + + + + kPi_32 + + + 3.0 + + + 2.0 + + + + + z + + + + + x + k2_oPi + + 0.5 + + + x + kPi_2 + + + + + + + + x + + k2_oPi + + 0.5 + + + x + kPi + + + + + + + x + + + k2_oPi + + 0.5 + + + x + kPi_32 + + + + + + + k2Pi + x + + k2_oPi + + 0.5 + + + + + + + sin + + + + + + z + z + + + C + z + + + x + kPi_2 + + + + + + + z + z + + + C + z + + + x + kPi + + + + + + + z + z + + C + + z + + + x + kPi_32 + + + + + + + z + z + + C + + z + + + + + + + + diff --git a/tests/resources/sin.xml b/tests/resources/sin.xml new file mode 100644 index 000000000..ca5721418 --- /dev/null +++ b/tests/resources/sin.xml @@ -0,0 +1,17 @@ + + + + + + + + + sin + + x + + + + + + diff --git a/tests/resources/sine_approximations.xml b/tests/resources/sine_approximations.xml index db0a74219..32b578f64 100644 --- a/tests/resources/sine_approximations.xml +++ b/tests/resources/sine_approximations.xml @@ -1,10 +1,10 @@ - - - - - + + + + + diff --git a/tests/resources/sine_approximations_import.xml b/tests/resources/sine_approximations_import.xml index 89c0cf191..f765cd3c6 100644 --- a/tests/resources/sine_approximations_import.xml +++ b/tests/resources/sine_approximations_import.xml @@ -13,11 +13,11 @@ - - - - - + + + + + diff --git a/tests/resources/units_definitions.cellml b/tests/resources/units_definitions.cellml new file mode 100644 index 000000000..7f0bf7aa5 --- /dev/null +++ b/tests/resources/units_definitions.cellml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tests/test_resources.cmake b/tests/test_resources.cmake index d3ace7535..06062597d 100644 --- a/tests/test_resources.cmake +++ b/tests/test_resources.cmake @@ -2,9 +2,14 @@ set(CELLML_SINE_MODEL_RESOURCE "${CMAKE_CURRENT_SOURCE_DIR}/resources/sine_approximations.xml") set(CELLML_SINE_IMPORTS_MODEL_RESOURCE "${CMAKE_CURRENT_SOURCE_DIR}/resources/sine_approximations_import.xml") set(CELLML_COMPLEX_ENCAPSULATION_MODEL_RESOURCE "${CMAKE_CURRENT_SOURCE_DIR}/resources/complex_encapsulation.xml") +set(CELLML_COMPLEX_IMPORT_HIERARCHY_MODEL_RESOURCE "${CMAKE_CURRENT_SOURCE_DIR}/resources/complex_imports.xml") set(CELLML_ORD_MODEL_RESOURCE "${CMAKE_CURRENT_SOURCE_DIR}/resources/Ohara_Rudy_2011.cellml") set(CELLML_A_PLUS_B_MODEL_RESOURCE "${CMAKE_CURRENT_SOURCE_DIR}/resources/a_plus_b.cellml") set(CELLML_INVALID_MODEL_RESOURCE "${CMAKE_CURRENT_SOURCE_DIR}/resources/invalid_cellml_2.0.xml") +set(CELLML_UNITS_DEFINITIONS_RESOURCE "${CMAKE_CURRENT_SOURCE_DIR}/resources/units_definitions.cellml") +set(CELLML_UNITS_IMPORT_MODEL_RESOURCE "${CMAKE_CURRENT_SOURCE_DIR}/resources/import_units_model.cellml") +set(CELLML_IMPORT_LEVEL0_MODEL_RESOURCE "${CMAKE_CURRENT_SOURCE_DIR}/resources/level0.xml") +set(CELLML_IMPORT_LEVEL0_UNRESOLVABLE_MODEL_RESOURCE "${CMAKE_CURRENT_SOURCE_DIR}/resources/level0-broken-imports.xml") set(TEST_RESOURCE_HEADER ${CMAKE_CURRENT_BINARY_DIR}/test_resources.h) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/test_resources.h.in ${TEST_RESOURCE_HEADER}) diff --git a/tests/test_resources.h.in b/tests/test_resources.h.in index 24abaf07d..f892cd777 100644 --- a/tests/test_resources.h.in +++ b/tests/test_resources.h.in @@ -14,6 +14,11 @@ public: CELLML_ORD_MODEL_RESOURCE = 4, CELLML_COMPLEX_ENCAPSULATION_MODEL_RESOURCE = 5, CELLML_A_PLUS_B_MODEL_RESOURCE = 6, + CELLML_COMPLEX_IMPORTS_MODEL_RESOURCE = 7, + CELLML_UNITS_DEFINITIONS_RESOURCE = 8, + CELLML_UNITS_IMPORT_MODEL_RESOURCE = 9, + CELLML_IMPORT_LEVEL0_MODEL_RESOURCE = 10, + CELLML_IMPORT_LEVEL0_UNRESOLVABLE_MODEL_RESOURCE = 11 }; TestResources() @@ -32,6 +37,10 @@ public: { return "@CELLML_SINE_IMPORTS_MODEL_RESOURCE@"; } + if (resourceName == TestResources::CELLML_COMPLEX_IMPORTS_MODEL_RESOURCE) + { + return "@CELLML_COMPLEX_IMPORT_HIERARCHY_MODEL_RESOURCE@"; + } if (resourceName == TestResources::CELLML_COMPLEX_ENCAPSULATION_MODEL_RESOURCE) { return "@CELLML_COMPLEX_ENCAPSULATION_MODEL_RESOURCE@"; @@ -48,6 +57,26 @@ public: { return "@CELLML_A_PLUS_B_MODEL_RESOURCE@"; } + if (resourceName == TestResources::CELLML_UNITS_DEFINITIONS_RESOURCE) + { + return "@CELLML_UNITS_DEFINITIONS_RESOURCE@"; + } + if (resourceName == TestResources::CELLML_UNITS_IMPORT_MODEL_RESOURCE) + { + return "@CELLML_UNITS_IMPORT_MODEL_RESOURCE@"; + } + if (resourceName == TestResources::CELLML_UNITS_IMPORT_MODEL_RESOURCE) + { + return "@CELLML_UNITS_IMPORT_MODEL_RESOURCE@"; + } + if (resourceName == TestResources::CELLML_IMPORT_LEVEL0_MODEL_RESOURCE) + { + return "@CELLML_IMPORT_LEVEL0_MODEL_RESOURCE@"; + } + if (resourceName == TestResources::CELLML_IMPORT_LEVEL0_UNRESOLVABLE_MODEL_RESOURCE) + { + return "@CELLML_IMPORT_LEVEL0_UNRESOLVABLE_MODEL_RESOURCE@"; + } return 0; } }; diff --git a/tests/validator/validator.cpp b/tests/validator/validator.cpp index b2df1495b..9d4ea25a3 100644 --- a/tests/validator/validator.cpp +++ b/tests/validator/validator.cpp @@ -261,7 +261,7 @@ TEST(Validator, importUnits) { // Valid units import libcellml::ImportSourcePtr imp = std::make_shared(); - imp->setSource("some-other-model.xml"); + imp->setUrl("some-other-model.xml"); libcellml::UnitsPtr importedUnits = std::make_shared(); importedUnits->setName("valid_imported_units_in_this_model"); importedUnits->setSourceUnits(imp, "units_in_that_model"); @@ -280,7 +280,7 @@ TEST(Validator, importUnits) { // Invalid units import - duplicate refs libcellml::ImportSourcePtr imp3 = std::make_shared(); - imp3->setSource("some-other-model.xml"); + imp3->setUrl("some-other-model.xml"); libcellml::UnitsPtr importedUnits3 = std::make_shared(); importedUnits3->setName("duplicate_imported_units_in_this_model"); importedUnits3->setSourceUnits(imp3, "units_in_that_model"); @@ -290,7 +290,7 @@ TEST(Validator, importUnits) { // Invalid units import - unnamed units libcellml::ImportSourcePtr imp4 = std::make_shared(); - imp4->setSource("some-other-different-model.xml"); + imp4->setUrl("some-other-different-model.xml"); libcellml::UnitsPtr importedUnits4 = std::make_shared(); importedUnits4->setSourceUnits(imp4, "units_in_that_model"); m->addUnits(importedUnits4); @@ -319,7 +319,7 @@ TEST(Validator, importComponents) { // Valid component import libcellml::ImportSourcePtr imp = std::make_shared(); - imp->setSource("some-other-model.xml"); + imp->setUrl("some-other-model.xml"); libcellml::ComponentPtr importedComponent = std::make_shared(); importedComponent->setName("valid_imported_component_in_this_model"); importedComponent->setSourceComponent(imp, "component_in_that_model"); @@ -338,7 +338,7 @@ TEST(Validator, importComponents) { // Invalid component import - duplicate refs libcellml::ImportSourcePtr imp3 = std::make_shared(); - imp3->setSource("some-other-model.xml"); + imp3->setUrl("some-other-model.xml"); libcellml::ComponentPtr importedComponent3 = std::make_shared(); importedComponent3->setName("duplicate_imported_component_in_this_model"); importedComponent3->setSourceComponent(imp3, "component_in_that_model"); @@ -348,7 +348,7 @@ TEST(Validator, importComponents) { // Invalid component import - unnamed component libcellml::ImportSourcePtr imp4 = std::make_shared(); - imp4->setSource("some-other-different-model.xml"); + imp4->setUrl("some-other-different-model.xml"); libcellml::ComponentPtr importedComponent4 = std::make_shared(); importedComponent4->setSourceComponent(imp4, "component_in_that_model"); m->addComponent(importedComponent4); diff --git a/tests/variable/variable.cpp b/tests/variable/variable.cpp index dda703853..a15b187dc 100644 --- a/tests/variable/variable.cpp +++ b/tests/variable/variable.cpp @@ -720,3 +720,72 @@ TEST(Variable, modelWithComponentWithFourNamedVariablesWithInterfacesAndParse) { const std::string a = printer.printModel(model); EXPECT_EQ(e, a); } + +TEST(Variable, modelWithComponentWithFiveNamedVariablesWithInterfacesAndParse) { + const std::string e = + "\n" + "" + "" + "" + "" + "" + "" + "" + "" + ""; + + libcellml::Model m; + + libcellml::ComponentPtr c = std::make_shared(); + c->setName("valid_name"); + m.addComponent(c); + + libcellml::VariablePtr v1 = std::make_shared(); + v1->setName("variable1"); + v1->setInterfaceType(libcellml::Variable::InterfaceType::NONE); + c->addVariable(v1); + + libcellml::VariablePtr v2 = std::make_shared(); + v2->setName("variable2"); + v2->setInterfaceType("public"); + c->addVariable(v2); + + libcellml::VariablePtr v3 = std::make_shared(); + v3->setName("variable3"); + v3->setInterfaceType(libcellml::Variable::InterfaceType::PRIVATE); + c->addVariable(v3); + + libcellml::VariablePtr v4 = std::make_shared(); + v4->setName("variable4"); + v4->setInterfaceType(libcellml::Variable::InterfaceType::PUBLIC_AND_PRIVATE); + c->addVariable(v4); + + libcellml::VariablePtr v5 = std::make_shared(); + v5->setName("variable4"); + v5->setInterfaceType("other"); + c->addVariable(v5); + + libcellml::Parser parser; + libcellml::ModelPtr model = parser.parseModel(e); + libcellml::Printer printer; + const std::string a = printer.printModel(model); + EXPECT_EQ(e, a); +} + +TEST(Variable, modelUnitsAttributeBeforeNameAttribute) { + const std::string e = + "\n" + "" + "" + "" + "" + "" + "" + ""; + + libcellml::Model m; + + libcellml::Parser parser; + parser.parseModel(e); + EXPECT_EQ(0u, parser.errorCount()); +}