App/Toponaming: Basic tests and linter issues

This commit is contained in:
Chris Hennes
2023-07-06 10:12:55 -05:00
committed by Chris Hennes
parent 9ea7b6424b
commit e7f8f26bd5
10 changed files with 1138 additions and 580 deletions

View File

@@ -24,7 +24,7 @@
***************************************************************************/
#include "PreCompiled.h"
#include "PreCompiled.h"// NOLINT
#ifndef _PreComp_
# include <cstdlib>
@@ -41,21 +41,19 @@
#include <Base/Rotation.h>
#include <boost/iostreams/device/array.hpp>
#include <boost/iostreams/stream.hpp>
using namespace Data;
TYPESYSTEM_SOURCE_ABSTRACT(Data::Segment , Base::BaseClass)
TYPESYSTEM_SOURCE_ABSTRACT(Data::Segment , Base::BaseClass)// NOLINT
TYPESYSTEM_SOURCE_ABSTRACT(Data::ComplexGeoData , Base::Persistence)// NOLINT
TYPESYSTEM_SOURCE_ABSTRACT(Data::ComplexGeoData , Base::Persistence)
FC_LOG_LEVEL_INIT("ComplexGeoData", true,true)
FC_LOG_LEVEL_INIT("ComplexGeoData", true,true)// NOLINT
namespace bio = boost::iostreams;
using namespace Data;
// NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic)
ComplexGeoData::ComplexGeoData()
:Tag(0)
@@ -107,10 +105,10 @@ Base::Placement ComplexGeoData::getPlacement() const
{
Base::Matrix4D mat = getTransform();
return Base::Placement(Base::Vector3d(mat[0][3],
mat[1][3],
mat[2][3]),
Base::Rotation(mat));
return {Base::Vector3d(mat[0][3],
mat[1][3],
mat[2][3]),
Base::Rotation(mat)};
}
double ComplexGeoData::getAccuracy() const
@@ -118,19 +116,21 @@ double ComplexGeoData::getAccuracy() const
return 0.0;
}
void ComplexGeoData::getLinesFromSubElement(const Segment*,
void ComplexGeoData::getLinesFromSubElement(const Segment* segment,
std::vector<Base::Vector3d> &Points,
std::vector<Line> &lines) const
{
(void)segment;
(void)Points;
(void)lines;
}
void ComplexGeoData::getFacesFromSubElement(const Segment*,
void ComplexGeoData::getFacesFromSubElement(const Segment* segment,
std::vector<Base::Vector3d> &Points,
std::vector<Base::Vector3d> &PointNormals,
std::vector<Facet> &faces) const
{
(void)segment;
(void)Points;
(void)PointNormals;
(void)faces;
@@ -174,8 +174,9 @@ void ComplexGeoData::getFaces(std::vector<Base::Vector3d> &Points,
(void)flags;
}
bool ComplexGeoData::getCenterOfGravity(Base::Vector3d&) const
bool ComplexGeoData::getCenterOfGravity(Base::Vector3d& unused) const
{
(void)unused;
return false;
}
@@ -195,18 +196,21 @@ MappedName ComplexGeoData::getMappedName(const IndexedName & element,
bool allowUnmapped,
ElementIDRefs *sid) const
{
if (!element)
return MappedName();
if (!element) {
return {};
}
flushElementMap();
if(!_elementMap) {
if (allowUnmapped)
if (allowUnmapped) {
return MappedName(element);
return MappedName();
}
return {};
}
MappedName name = _elementMap->find(element, sid);
if (allowUnmapped && !name)
if (allowUnmapped && !name) {
return MappedName(element);
}
return name;
}
@@ -214,11 +218,12 @@ IndexedName ComplexGeoData::getIndexedName(const MappedName & name,
ElementIDRefs *sid) const
{
flushElementMap();
if (!name)
if (!name) {
return IndexedName();
}
if (!_elementMap) {
std::string s;
return IndexedName(name.appendToBuffer(s), getElementTypes());
std::string str;
return {name.appendToBuffer(str), getElementTypes()};
}
return _elementMap->find(name, sid);
}
@@ -229,24 +234,29 @@ ComplexGeoData::getElementName(const char *name,
bool copy) const
{
IndexedName element(name, getElementTypes());
if (element)
return MappedElement(getMappedName(element, false, sid), element);
if (element) {
return {getMappedName(element, false, sid), element};
}
const char * mapped = isMappedElement(name);
if (mapped)
if (mapped) {
name = mapped;
}
MappedElement res;
MappedElement result;
// Strip out the trailing '.XXXX' if any
const char *dot = strchr(name,'.');
if(dot)
res.name = MappedName(name, dot-name);
else if (copy)
res.name = name;
else
res.name = MappedName(name);
res.index = getIndexedName(res.name, sid);
return res;
if(dot) {
result.name = MappedName(name, dot - name);
}
else if (copy) {
result.name = name;
}
else {
result.name = MappedName(name);
}
result.index = getIndexedName(result.name, sid);
return result;
}
std::vector<std::pair<MappedName, ElementIDRefs> >
@@ -254,44 +264,30 @@ ComplexGeoData::getElementMappedNames(const IndexedName & element, bool needUnma
flushElementMap();
if(_elementMap) {
auto res = _elementMap->findAll(element);
if (!res.empty())
if (!res.empty()) {
return res;
}
}
if (!needUnmapped)
if (!needUnmapped) {
return {};
}
return {std::make_pair(MappedName(element), ElementIDRefs())};
}
std::vector<Data::MappedElement>
ComplexGeoData::getElementNamesWithPrefix(const char *prefix) const {
#if 0
std::vector<Data::MappedElement> names;
flushElementMap();
if(!prefix || !prefix[0] || !_elementMap)
return names;
const auto &p = elementMapPrefix();
if(boost::starts_with(prefix,p))
prefix += p.size();
names = _elementMap->findAllStartsWith(prefix);
return names;
#else
(void)prefix;
return {};
#endif
}
std::vector<MappedElement> ComplexGeoData::getElementMap() const {
flushElementMap();
if(!_elementMap)
if(!_elementMap) {
return {};
}
return _elementMap->getAll();
}
ElementMapPtr ComplexGeoData::elementMap(bool flush) const
{
if (flush)
if (flush) {
flushElementMap();
}
return _elementMap;
}
@@ -300,82 +296,93 @@ void ComplexGeoData::flushElementMap() const
}
void ComplexGeoData::setElementMap(const std::vector<MappedElement> &map) {
resetElementMap();
for(auto &v : map)
_elementMap->setElementName(v.index, v.name, Tag);
_elementMap = std::make_shared<Data::ElementMap>(); // Get rid of the old one, if any, but make
// sure the memory exists for the new data.
for(auto &element : map) {
_elementMap->setElementName(element.index, element.name, Tag);
}
}
char ComplexGeoData::elementType(const Data::MappedName &name) const
{
if(!name)
if(!name) {
return 0;
}
auto indexedName = getIndexedName(name);
if (indexedName)
if (indexedName) {
return elementType(indexedName);
}
char element_type=0;
if (name.findTagInElementName(0,0,0,&element_type) < 0)
if (name.findTagInElementName(nullptr,nullptr,nullptr,&element_type) < 0) {
return elementType(name.toIndexedName());
}
return element_type;
}
char ComplexGeoData::elementType(const Data::IndexedName &element) const
{
if(!element)
if(!element) {
return 0;
}
for(auto &type : getElementTypes()) {
if(boost::equals(element.getType(), type))
if(boost::equals(element.getType(), type)) {
return type[0];
}
}
return 0;
}
// The elementType function can take a char *, in which case it tries a sequence of checks to
// see what it got.
// 1) Check to see if it is an indexedName, and if so directly look up the type
// 2) If not:
// a) Remove any element map prefix that is present
// b) See if the name contains a dot:
// i) If yes, create a MappedName from the part before the dot, and set the type to the
// part after the dot
// ii) If no, create a MappedName from the whole name
// c) Try to get the elementType based on the MappedName. Return it if found
// 3) Check to make sure the discovered type is in the list of types, and return its first
// character if so.
char ComplexGeoData::elementType(const char *name) const {
if(!name)
if(!name) {
return 0;
}
const char *type = nullptr;
IndexedName element(name, getElementTypes());
if (element)
if (element) {
type = element.getType();
}
else {
const char * mapped = isMappedElement(name);
if (mapped)
if (mapped) {
name = mapped;
}
MappedName n;
MappedName mappedName;
const char *dot = strchr(name,'.');
if(dot) {
n = MappedName(name, dot-name);
mappedName = MappedName(name, dot-name);
type = dot+1;
}
else
n = MappedName::fromRawData(name);
char res = elementType(n);
if (res)
else {
mappedName = MappedName::fromRawData(name);
}
char res = elementType(mappedName);
if (res != 0) {
return res;
}
}
if(type && type[0]) {
for(auto &t : getElementTypes()) {
if(boost::starts_with(type, t))
for(auto &elementTypes : getElementTypes()) {
if(boost::starts_with(type, elementTypes)) {
return type[0];
}
}
}
return 0;
}
MappedName ComplexGeoData::renameDuplicateElement(int index,
const IndexedName & element,
const IndexedName & element2,
const MappedName & name,
ElementIDRefs &sids)
{
std::ostringstream ss;
ss << ELEMENT_MAP_PREFIX << 'D' << std::hex << index;
MappedName renamed(name);
this->elementMap()->encodeElementName(element.getType()[0],renamed,ss,&sids,Tag);
if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG))
FC_WARN("duplicate element mapping '" << name << " -> " << renamed << ' '
<< element << '/' << element2);
return renamed;
}
// NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)

View File

@@ -24,8 +24,8 @@
***************************************************************************/
#ifndef _AppComplexGeoData_h_
#define _AppComplexGeoData_h_
#ifndef APP_COMPLEX_GEO_DATA_H
#define APP_COMPLEX_GEO_DATA_H
#include <algorithm>
#include <Base/Handle.h>
@@ -45,7 +45,7 @@ namespace Base
{
class Placement;
class Rotation;
template <class _Precision> class BoundBox3;
template <class _Precision> class BoundBox3;// NOLINT
using BoundBox3d = BoundBox3<double>;
}
@@ -55,12 +55,12 @@ namespace Data
struct MappedChildElements;
/** Segments
* Subelement type of the ComplexGeoData type
* Sub-element type of the ComplexGeoData type
* It is used to split an object in further sub-parts.
*/
class AppExport Segment: public Base::BaseClass
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
TYPESYSTEM_HEADER_WITH_OVERRIDE();// NOLINT
public:
~Segment() override = default;
@@ -72,7 +72,7 @@ public:
*/
class AppExport ComplexGeoData: public Base::Persistence, public Base::Handled
{
TYPESYSTEM_HEADER_WITH_OVERRIDE();
TYPESYSTEM_HEADER_WITH_OVERRIDE();// NOLINT
public:
struct Line {uint32_t I1; uint32_t I2;};
@@ -87,17 +87,17 @@ public:
/// Destructor
~ComplexGeoData() override;
/** @name Subelement management */
/** @name Sub-element management */
//@{
/** Sub type list
* List of different subelement types
* its NOT a list of the subelements itself
* List of different sub-element types
* its NOT a list of the sub-elements itself
*/
virtual std::vector<const char*> getElementTypes() const=0;
virtual unsigned long countSubElements(const char* Type) const=0;
/// get the subelement by type and number
/// get the sub-element by type and number
virtual Segment* getSubElement(const char* Type, unsigned long) const=0;
/// get subelement by combined name
/// get sub-element by combined name
virtual Segment* getSubElementByName(const char* Name) const;
/** Get lines from segment */
virtual void getLinesFromSubElement(
@@ -203,8 +203,8 @@ public:
/** Return a pair of indexed name and mapped name
*
* @param name: the input name.
* @param sid: optional output of and App::StringID involved forming this
* mapped name
* @param sid: optional output of any App::StringID involved in forming
* this mapped name
* @param copy: if true, copy the name string, or else use it as constant
* string, and caller must make sure the memory is not freed.
*
@@ -221,9 +221,6 @@ public:
ElementIDRefs *sid = nullptr,
bool copy = false) const;
/** Get mapped element with a given prefix */
std::vector<MappedElement> getElementNamesWithPrefix(const char *prefix) const;
/** Get mapped element names
*
* @param element: original element name with \c Type + \c Index
@@ -237,7 +234,9 @@ public:
getElementMappedNames(const IndexedName & element, bool needUnmapped=false) const;
/// Append the Tag (if and only if it is non zero) into the element map
virtual void reTagElementMap(long tag, App::StringHasherRef hasher, const char *postfix=0) {
virtual void reTagElementMap(long tag,
App::StringHasherRef hasher,
const char *postfix=nullptr) {
(void)tag;
(void)hasher;
(void)postfix;
@@ -269,37 +268,13 @@ public:
/// Get the current element map size
size_t getElementMapSize(bool flush=true) const;
/// Check if the given subname only contains an element name
static bool isElementName(const char *subname) {
return subname && *subname && findElementName(subname)==subname;
/// Check if the given sub-name only contains an element name
static bool isElementName(const char *subName) {
return (subName != nullptr) && (*subName != 0) && findElementName(subName)==subName;
}
/** Element trace callback
*
* The callback has the following call signature
* (const std::string &name, size_t offset, long encodedTag, long tag) -> bool
*
* @param name: the current element name.
* @param offset: the offset skipping the encoded element name for the next iteration.
* @param encodedTag: the tag encoded inside the current element, which is usually the tag
* of the previous step in the shape history.
* @param tag: the tag of the current shape element.
*
* @sa traceElement()
*/
using TraceCallback = std::function<bool(const MappedName &, int, long, long)>;
/** Iterate through the history of the give element name with a given callback
*
* @param name: the input element name
* @param cb: trace callback with call signature.
* @sa TraceCallback
*/
void traceElement(const MappedName &name, TraceCallback cb) const;
/** Flush an internal buffering for element mapping */
virtual void flushElementMap() const;
virtual unsigned long getElementMapReserve() const { return 0; }
//@}
protected:
@@ -368,11 +343,6 @@ public:
mutable App::StringHasherRef Hasher;
protected:
virtual MappedName renameDuplicateElement(int index,
const IndexedName & element,
const IndexedName & element2,
const MappedName & name,
ElementIDRefs &sids);
/// from local to outside
inline Base::Vector3d transformToOutside(const Base::Vector3f& vec) const

File diff suppressed because it is too large Load Diff

View File

@@ -63,27 +63,27 @@ public:
ElementMap();
/** Ensures that naming is properly assigned. It then marks as "used" all the StringID
* that are used to make up this particular map and are stored in the hasher passed
* that are used to make up this particular map and are stored in the hasherRef passed
* as a parameter. Finally do this recursively for all childEelementMaps as well.
*
* @param hasher where all the StringID needed to build the map are stored.
* @param hasherRef where all the StringID needed to build the map are stored.
*/
// FIXME this should be made part of \c save, to achieve symmetry with the restore method
void beforeSave(const ::App::StringHasherRef& hasher) const;
void beforeSave(const ::App::StringHasherRef& hasherRef) const;
/** Serialize this map. Calls \c collectChildMaps to get \c childMapSet and
* \c postfixMap, then calls the other (private) save function with those parameters.
* @param s: serialized stream
* @param stream: serialized stream
*/
void save(std::ostream& s) const;
void save(std::ostream& stream) const;
/** Deserialize and restore this map. This function restores \c childMaps and
/** Deserialize and restore this map. This function restores \c childMaps and
* \c postfixes from the stream, then calls the other (private) restore function with those
* parameters.
* @param hasher: where all the StringIDs are stored
* @param s: stream to deserialize
* @param hasherRef: where all the StringIDs are stored
* @param stream: stream to deserialize
*/
ElementMapPtr restore(::App::StringHasherRef hasher, std::istream& s);
ElementMapPtr restore(::App::StringHasherRef hasherRef, std::istream& stream);
/** Add a sub-element name mapping.
@@ -187,20 +187,20 @@ public:
private:
/** Serialize this map
* @param s: serialized stream
* @param stream: serialized stream
* @param childMapSet: where all child element maps are stored
* @param postfixMap. where all postfixes are stored
*/
void save(std::ostream& s, int index, const std::map<const ElementMap*, int>& childMapSet,
void save(std::ostream& stream, int index, const std::map<const ElementMap*, int>& childMapSet,
const std::map<QByteArray, int>& postfixMap) const;
/** Deserialize and restore this map.
* @param hasher: where all the StringIDs are stored
* @param s: stream to deserialize
* @param hasherRef: where all the StringIDs are stored
* @param stream: stream to deserialize
* @param childMaps: where all child element maps are stored
* @param postfixes. where all postfixes are stored
*/
ElementMapPtr restore(::App::StringHasherRef hasher, std::istream& s,
ElementMapPtr restore(::App::StringHasherRef hasherRef, std::istream& stream,
std::vector<ElementMapPtr>& childMaps,
const std::vector<std::string>& postfixes);
@@ -224,9 +224,9 @@ private:
/* Note: the original proc passed `ComplexGeoData& master` for getting the `Tag`,
* now it just passes `long masterTag`.*/
virtual MappedName renameDuplicateElement(int index, const IndexedName& element,
const IndexedName& element2, const MappedName& name,
ElementIDRefs& sids, long masterTag);
MappedName renameDuplicateElement(int index, const IndexedName& element,
const IndexedName& element2, const MappedName& name,
ElementIDRefs& sids, long masterTag) const;
/** Convenience method to hash the main element name
*

View File

@@ -34,10 +34,11 @@
#include <QByteArray>
#include <QHash>
#include <QVector>
#include <utility>
#include "ElementNamingUtils.h"
#include "IndexedName.h"
#include "StringHasher.h"
#include "ElementNamingUtils.h"
namespace Data
@@ -92,8 +93,9 @@ public:
/// is appended as text to the MappedName. In that case the memory is *not* shared between the
/// original IndexedName and the MappedName.
explicit MappedName(const IndexedName& element)
: data(QByteArray::fromRawData(element.getType(), qstrlen(element.getType()))),
raw(true)
: data(QByteArray::fromRawData(element.getType(),
static_cast<int>(qstrlen(element.getType()))))
, raw(true)
{
if (element.getIndex() > 0) {
this->data += QByteArray::number(element.getIndex());
@@ -101,8 +103,8 @@ public:
}
}
explicit MappedName(const App::StringIDRef & sid)
:raw(false)
explicit MappedName(const App::StringIDRef& sid)
: raw(false)
{
sid.toBytes(this->data);
}
@@ -130,16 +132,16 @@ public:
/// \param other The mapped name to copy. Its data and postfix become the new MappedName's data
/// \param postfix The postfix for the new MappedName
MappedName(const MappedName& other, const char* postfix)
: data(other.data + other.postfix),
postfix(postfix),
raw(false)
: data(other.data + other.postfix)
, postfix(postfix)
, raw(false)
{}
/// Move constructor
MappedName(MappedName&& other) noexcept
: data(std::move(other.data)),
postfix(std::move(other.postfix)),
raw(other.raw)
: data(std::move(other.data))
, postfix(std::move(other.postfix))
, raw(other.raw)
{}
~MappedName() = default;
@@ -899,7 +901,7 @@ public:
///
/// \param tag: optional pointer to receive the extracted tag
/// \param len: optional pointer to receive the length field after the tag field.
/// This gives the length of the previous hashsed element name starting
/// This gives the length of the previous hashed element name starting
/// from the beginning of the give element name.
/// \param postfix: optional pointer to receive the postfix starting at the found tag field.
/// \param type: optional pointer to receive the element type character
@@ -908,8 +910,9 @@ public:
/// \param recursive: recursively find the last non-zero tag
///
/// \return Return the end position of the tag field, or return -1 if not found.
int findTagInElementName(long* tag = 0, int* len = 0, const char* postfix = 0, char* type = 0,
bool negative = false, bool recursive = true) const;
int findTagInElementName(long* tag = nullptr, int* len = nullptr, const char* postfix = nullptr,
char* type = nullptr, bool negative = false,
bool recursive = true) const;
/// Get a hash for this MappedName
std::size_t hash() const
@@ -924,7 +927,7 @@ private:
};
typedef QVector<::App::StringIDRef> ElementIDRefs;
using ElementIDRefs = QVector<::App::StringIDRef>;
struct MappedNameRef
{
@@ -934,25 +937,34 @@ struct MappedNameRef
MappedNameRef() = default;
MappedNameRef(const MappedName& name, const ElementIDRefs& sids = ElementIDRefs())
: name(name),
sids(sids)
~MappedNameRef() = default;
MappedNameRef(MappedName name, ElementIDRefs sids = ElementIDRefs())
: name(std::move(name))
, sids(std::move(sids))
{
compact();
}
MappedNameRef(const MappedNameRef& other)
: name(other.name),
sids(other.sids)
: name(other.name)
, sids(other.sids)
{}
MappedNameRef(MappedNameRef&& other)
: name(std::move(other.name)),
sids(std::move(other.sids)),
next(std::move(other.next))
MappedNameRef(MappedNameRef&& other) noexcept
: name(std::move(other.name))
, sids(std::move(other.sids))
, next(std::move(other.next))
{}
MappedNameRef& operator=(MappedNameRef&& other)
MappedNameRef& operator=(const MappedNameRef& other) noexcept
{
name = other.name;
sids = other.sids;
return *this;
}
MappedNameRef& operator=(MappedNameRef&& other) noexcept
{
name = std::move(other.name);
sids = std::move(other.sids);
@@ -965,22 +977,24 @@ struct MappedNameRef
return !name.empty();
}
void append(const MappedName& name, const ElementIDRefs sids = ElementIDRefs())
void append(const MappedName& _name, const ElementIDRefs _sids = ElementIDRefs())
{
if (!name)
if (!_name) {
return;
}
if (!this->name) {
this->name = name;
this->sids = sids;
this->name = _name;
this->sids = _sids;
compact();
return;
}
std::unique_ptr<MappedNameRef> n(new MappedNameRef(name, sids));
if (!this->next)
this->next = std::move(n);
std::unique_ptr<MappedNameRef> mappedName(new MappedNameRef(_name, _sids));
if (!this->next) {
this->next = std::move(mappedName);
}
else {
this->next.swap(n);
this->next->next = std::move(n);
this->next.swap(mappedName);
this->next->next = std::move(mappedName);
}
}
@@ -992,9 +1006,9 @@ struct MappedNameRef
}
}
bool erase(const MappedName& name)
bool erase(const MappedName& _name)
{
if (this->name == name) {
if (this->name == _name) {
this->name.clear();
this->sids.clear();
if (this->next) {
@@ -1007,11 +1021,11 @@ struct MappedNameRef
return true;
}
for (std::unique_ptr<MappedNameRef>* p = &this->next; *p; p = &(*p)->next) {
if ((*p)->name == name) {
for (std::unique_ptr<MappedNameRef>* ptr = &this->next; *ptr; ptr = &(*ptr)->next) {
if ((*ptr)->name == _name) {
std::unique_ptr<MappedNameRef> tmp;
tmp.swap(*p);
*p = std::move(tmp->next);
tmp.swap(*ptr);
*ptr = std::move(tmp->next);
return true;
}
}
@@ -1033,4 +1047,4 @@ struct MappedNameRef
}// namespace Data
#endif// APP_MAPPED_NAME_H
#endif// APP_MAPPED_NAME_H

View File

@@ -173,7 +173,7 @@ public:
}
/// Returns the data (prefix)
QByteArray data() const
const QByteArray& data() const
{
return _data;
}
@@ -556,6 +556,7 @@ public:
void toBytes(QByteArray& bytes) const
{
// TODO: return the QByteArray instead of passing in by reference
if (_sid) {
bytes = _sid->dataToBytes(_index);
}

View File

@@ -3,6 +3,7 @@ target_sources(
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/Application.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Branding.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ComplexGeoData.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Expression.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ElementMap.cpp
${CMAKE_CURRENT_SOURCE_DIR}/IndexedName.cpp

View File

@@ -0,0 +1,417 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
#include "gtest/gtest.h"
#include <array>
#include <fmt/core.h>
#include <App/Application.h>
#include <App/ComplexGeoData.h>
#include <Base/BoundBox.h>
class ConcreteComplexGeoDataForTesting: public Data::ComplexGeoData
{
public:
std::vector<const char*> getElementTypes() const override
{
return {"EDGE"};
}
unsigned long countSubElements(const char* Type) const override
{
(void)Type;
return 0;
}
Data::Segment* getSubElement(const char* Type, unsigned long number) const override
{
(void)number;
(void)Type;
return nullptr;
}
unsigned int getMemSize() const override
{
return 0;
}
void Save(Base::Writer& writer) const override
{
(void)writer;
}
void Restore(Base::XMLReader& reader) override
{
(void)reader;
}
void setTransform(const Base::Matrix4D& rclTrf) override
{
(void)rclTrf;
}
Base::Matrix4D getTransform() const override
{
return {};
}
void transformGeometry(const Base::Matrix4D& rclMat) override
{
(void)rclMat;
}
Base::BoundBox3d getBoundBox() const override
{
return Base::BoundBox3d();
}
};
class ComplexGeoDataTest: public ::testing::Test
{
protected:
static void SetUpTestSuite()
{
if (App::Application::GetARGC() == 0) {
constexpr int argc = 1;
std::array<char*, argc> argv {"FreeCAD"};
App::Application::Config()["ExeName"] = "FreeCAD";
App::Application::init(argc, argv.data());
}
}
void SetUp() override
{
_docName = App::GetApplication().getUniqueDocumentName("test");
App::GetApplication().newDocument(_docName.c_str(), "testUser");
}
void TearDown() override
{
App::GetApplication().closeDocument(_docName.c_str());
}
ConcreteComplexGeoDataForTesting& cgd()
{
return _complexGeoData;
}
std::tuple<Data::IndexedName, Data::MappedName> createMappedName(const std::string& name)
{
auto elementMap = std::make_shared<Data::ElementMap>();
cgd().resetElementMap(elementMap);
auto mappedName = Data::MappedName(name.c_str());
auto indexedName = Data::IndexedName(_complexGeoData.getElementTypes().front(), 1);
elementMap->setElementName(indexedName, mappedName, 0);
return std::make_tuple(indexedName, mappedName);
}
private:
ConcreteComplexGeoDataForTesting _complexGeoData;
std::string _docName;
};
// NOLINTBEGIN(readability-magic-numbers)
TEST_F(ComplexGeoDataTest, getIndexedNameNoName)// NOLINT
{
// Arrange & Act
auto result = cgd().getIndexedName(Data::MappedName());
// Assert
EXPECT_FALSE(result);
}
TEST_F(ComplexGeoDataTest, getIndexedNameNoElementMap)// NOLINT
{
// Arrange & Act
auto result = cgd().getIndexedName(Data::MappedName("TestName"));
// Assert
EXPECT_TRUE(result);
}
TEST_F(ComplexGeoDataTest, getMappedNameNoElement)// NOLINT
{
// Arrange & Act
auto result = cgd().getMappedName(Data::IndexedName {});
// Assert
EXPECT_FALSE(result);
}
TEST_F(ComplexGeoDataTest, getMappedNameDisallowUnmappedNoMap)// NOLINT
{
// Arrange & Act
auto result = cgd().getMappedName(Data::IndexedName {"TestName"}, false);
// Assert
EXPECT_FALSE(result);
}
TEST_F(ComplexGeoDataTest, getMappedNameDisallowUnmappedWithMap)// NOLINT
{
// Arrange
auto elementMap = std::make_shared<Data::ElementMap>();
cgd().resetElementMap(elementMap);
auto mappedName = Data::MappedName("TestMappedName");
auto indexedName = Data::IndexedName("EDGE", 1);
elementMap->setElementName(indexedName, mappedName, 0);
// Act
auto result = cgd().getMappedName(indexedName, false);
// Assert
EXPECT_TRUE(result);
EXPECT_EQ(mappedName, result);
}
TEST_F(ComplexGeoDataTest, getMappedNameDisallowUnmappedMissingFromMap)// NOLINT
{
// Arrange
auto mappedName = Data::MappedName("NotTheTestName");
cgd().getIndexedName(mappedName);// Put it in the map
// Act
auto result = cgd().getMappedName(Data::IndexedName {"TestName"}, false);
// Assert
EXPECT_FALSE(result);
}
TEST_F(ComplexGeoDataTest, getMappedNameAllowUnmapped)// NOLINT
{
// Arrange & Act
auto result = cgd().getMappedName(Data::IndexedName {"TestName"}, true);
// Assert
EXPECT_TRUE(result);
}
TEST_F(ComplexGeoDataTest, getElementNameGivenIndexedName)// NOLINT
{
// Arrange
const char* name {"EDGE123"};
auto indexedName = cgd().getIndexedName(Data::MappedName(name));
// Act
auto result = cgd().getElementName(name);
// Assert
EXPECT_EQ(result.index, indexedName);
}
TEST_F(ComplexGeoDataTest, getElementNameGivenMappedName)// NOLINT
{
// Arrange
const char* name {"EDGE123"};
auto mappedName = cgd().getMappedName(Data::IndexedName(name));
// Act
auto result = cgd().getElementName(name);
// Assert
EXPECT_EQ(result.name, mappedName);
}
TEST_F(ComplexGeoDataTest, getElementMappedNamesNoMapNoUnmapped)// NOLINT
{
// Arrange
// Do not create an element map
auto indexedName = Data::IndexedName("EDGE1");
// Act
auto result = cgd().getElementMappedNames(indexedName, false);
// Assert
EXPECT_TRUE(result.empty());
}
TEST_F(ComplexGeoDataTest, getElementMappedNamesWithMapNoUnmapped)// NOLINT
{
// Arrange
auto elementMap = std::make_shared<Data::ElementMap>();
cgd().resetElementMap(elementMap);
auto mappedName = Data::MappedName("TestMappedName");
auto indexedName = Data::IndexedName("EDGE", 1);
elementMap->setElementName(indexedName, mappedName, 0);
// Act
auto result = cgd().getElementMappedNames(indexedName, false);
// Assert
EXPECT_FALSE(result.empty());
EXPECT_EQ(result[0].first, mappedName);
}
TEST_F(ComplexGeoDataTest, getElementMappedNamesNoMapWithUnmapped)// NOLINT
{
// Do not create an element map
auto indexedName = Data::IndexedName("EDGE1");
// Act
auto result = cgd().getElementMappedNames(indexedName, true);
// Assert
EXPECT_FALSE(result.empty());
}
TEST_F(ComplexGeoDataTest, getElementMappedNamesWithMapWithUnmapped)// NOLINT
{
// Arrange
Data::MappedName mappedName;
Data::IndexedName indexedName;
std::tie(indexedName, mappedName) = createMappedName("TestMappedName");
auto unmappedName = Data::IndexedName("EDGE", 2);
// Act
auto result = cgd().getElementMappedNames(unmappedName, true);
// Assert
EXPECT_FALSE(result.empty());
EXPECT_NE(result[0].first, mappedName);
}
TEST_F(ComplexGeoDataTest, elementTypeValidIndexName)// NOLINT
{
// Arrange
auto indexedName = Data::IndexedName("EDGE", 1);
// Act
char elementType = cgd().elementType(indexedName);
// Assert
EXPECT_EQ(elementType, 'E');
}
TEST_F(ComplexGeoDataTest, elementTypeInvalidIndexedName)// NOLINT
{
// Arrange
auto indexedName = Data::IndexedName("INVALID", 1);// Not in the element type list
// Act
char elementType = cgd().elementType(indexedName);
// Assert
EXPECT_EQ(elementType, 0);
}
TEST_F(ComplexGeoDataTest, elementTypeCharEmptyName)// NOLINT
{
// Arrange & Act
char elementType = cgd().elementType(nullptr);
// Assert
EXPECT_EQ(elementType, 0);
}
TEST_F(ComplexGeoDataTest, elementTypeCharIndexedName)// NOLINT
{
// Arrange & Act
char elementType = cgd().elementType("EDGE1");
// Assert
EXPECT_EQ(elementType, 'E');
}
TEST_F(ComplexGeoDataTest, elementTypeCharMappedNameNoPrefix)// NOLINT
{
// Arrange
int size {0};
Data::MappedName mappedName;
Data::IndexedName indexedName;
std::tie(indexedName, mappedName) = createMappedName("TestMappedName:;");
// Act
char elementType = cgd().elementType(mappedName.toConstString(0, size));
// Assert
EXPECT_EQ(elementType, 'E');
}
TEST_F(ComplexGeoDataTest, elementTypeCharMappedNameWithPrefix)// NOLINT
{
// Arrange
int size {0};
Data::MappedName mappedName;
Data::IndexedName indexedName;
auto name = fmt::format("{}TestMappedElement:;", Data::ELEMENT_MAP_PREFIX);
std::tie(indexedName, mappedName) = createMappedName(name);
// Act
char elementType = cgd().elementType(mappedName.toConstString(0, size));
// Assert
EXPECT_EQ(elementType, 'E');
}
TEST_F(ComplexGeoDataTest, resetElementMapNoArgument)// NOLINT
{
// Arrange & Act
cgd().resetElementMap();
// Assert
EXPECT_EQ(cgd().getElementMapSize(), 0);
}
TEST_F(ComplexGeoDataTest, resetElementMapWithArgument)// NOLINT
{
// Arrange
auto elementMap = std::make_shared<Data::ElementMap>();
auto mappedName = Data::MappedName("TestMappedName");
auto indexedName = Data::IndexedName("EDGE", 1);
elementMap->setElementName(indexedName, mappedName, 0);
// Act
cgd().resetElementMap(elementMap);
// Assert
EXPECT_EQ(cgd().getElementMapSize(), 1);
}
TEST_F(ComplexGeoDataTest, setAndGetElementMap)// NOLINT
{
// Arrange
auto elementMap = std::make_shared<Data::ElementMap>();
cgd().resetElementMap(elementMap);
std::vector<Data::MappedElement> vecMappedElements;
auto mappedNameA = Data::MappedName("TestMappedNameA");
auto indexedNameA = Data::IndexedName("EDGE", 1);
vecMappedElements.emplace_back(indexedNameA, mappedNameA);
auto mappedNameB = Data::MappedName("TestMappedNameB");
auto indexedNameB = Data::IndexedName("EDGE", 2);
vecMappedElements.emplace_back(indexedNameB, mappedNameB);
// Act
auto emptyElementMap = cgd().getElementMap();
cgd().setElementMap(vecMappedElements);
auto resultingElementMap = cgd().getElementMap();
// Assert
EXPECT_TRUE(emptyElementMap.empty());
EXPECT_EQ(resultingElementMap.size(), vecMappedElements.size());
}
TEST_F(ComplexGeoDataTest, getElementMapSize)// NOLINT
{
// Arrange
auto elementMap = std::make_shared<Data::ElementMap>();
auto mappedName = Data::MappedName("TestMappedName");
auto indexedName = Data::IndexedName("EDGE", 1);
elementMap->setElementName(indexedName, mappedName, 0);
cgd().resetElementMap(elementMap);
// Act
auto result = cgd().getElementMapSize();
// Assert
EXPECT_EQ(result, 1);
}
TEST_F(ComplexGeoDataTest, flushElementMap)// NOLINT
{
// Does nothing in the base class
}
// NOLINTEND(readability-magic-numbers)

View File

@@ -45,21 +45,29 @@ class ElementMapTest: public ::testing::Test
protected:
static void SetUpTestSuite()
{
int argc = 1;
char* argv[] = {"FreeCAD"};
App::Application::Config()["ExeName"] = "FreeCAD";
App::Application::init(argc, argv);
if (App::Application::GetARGC() == 0) {
int argc = 1;
char* argv[] = {"FreeCAD"};
App::Application::Config()["ExeName"] = "FreeCAD";
App::Application::init(argc, argv);
}
}
void SetUp() override
{
App::GetApplication().newDocument("test", "testUser");
_docName = App::GetApplication().getUniqueDocumentName("test");
App::GetApplication().newDocument(_docName.c_str(), "testUser");
_sids = &_sid;
_hasher = Base::Reference<App::StringHasher>(new App::StringHasher);
ASSERT_EQ(_hasher.getRefCount(), 1);
}
// void TearDown() override {}
void TearDown() override
{
App::GetApplication().closeDocument(_docName.c_str());
}
std::string _docName;
Data::ElementIDRefs _sid;
QVector<App::StringIDRef>* _sids;
App::StringHasherRef _hasher;

View File

@@ -225,8 +225,11 @@ TEST(MappedName, fromRawData)
TEST(MappedName, fromRawDataQByteArray)
{
// Arrange
QByteArray testByteArray("TESTTEST", 10);
// Act
Data::MappedName mappedName = Data::MappedName::fromRawData(QByteArray("TESTTEST", 10));
Data::MappedName mappedName = Data::MappedName::fromRawData(testByteArray);
// Assert
EXPECT_EQ(mappedName.isRaw(), true);
@@ -239,7 +242,8 @@ TEST(MappedName, fromRawDataQByteArray)
TEST(MappedName, fromRawDataCopy)
{
// Arrange
Data::MappedName temp = Data::MappedName::fromRawData(QByteArray("TESTTEST", 10));
QByteArray testByteArray("TESTTEST", 10);
Data::MappedName temp = Data::MappedName::fromRawData(testByteArray);
temp.append("TESTPOSTFIX");
temp.compact();// Always call compact before accessing data!
@@ -257,7 +261,8 @@ TEST(MappedName, fromRawDataCopy)
TEST(MappedName, fromRawDataCopyStartposAndSize)
{
// Arrange
Data::MappedName temp = Data::MappedName::fromRawData(QByteArray("TESTTEST", 8));
QByteArray testByteArray("TESTTEST", 8);
Data::MappedName temp = Data::MappedName::fromRawData(testByteArray);
temp.append("ABCDEFGHIJKLM");// postfix
temp.compact(); // Always call compact before accessing data!
@@ -373,11 +378,12 @@ TEST(MappedName, additionOperators)
{
// Arrange
Data::MappedName mappedName(Data::MappedName("TEST"), "POSTFIXTEST");
QByteArray post3("POST3");
// Act
mappedName += "POST1";
mappedName += std::string("POST2");
mappedName += QByteArray("POST3");
mappedName += post3;
mappedName += Data::MappedName("POST4");
// Assert
@@ -389,12 +395,13 @@ TEST(MappedName, additionOperators)
// Arrange
mappedName = Data::MappedName(Data::MappedName("TEST"), "POSTFIXTEST");
QByteArray post8("POST8");
// Act
mappedName = mappedName + Data::MappedName("POST5");
mappedName = mappedName + "POST6";
mappedName = mappedName + std::string("POST7");
mappedName = mappedName + QByteArray("POST8");
mappedName = mappedName + post8;
// Assert
EXPECT_EQ(mappedName.isRaw(), false);