Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrong property types issue #970

Open
wants to merge 17 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 114 additions & 0 deletions iModelCore/ECDb/Tests/NonPublished/ECSqlStatementTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1535,6 +1535,120 @@ TEST_F(ECSqlStatementTestFixture, IsNull)
}

//---------------------------------------------------------------------------------------
//@bsimethod
//---------------------------------------------------------------------------------------
TEST_F(ECSqlStatementTestFixture, UseOfWrongPropertyTags_ForAllVersions)
{
ASSERT_EQ(DbResult::BE_SQLITE_OK, SetupECDb("UseOfWrongPropertyTags.ecdb"));

unsigned int ecXmlMajorVersion;
unsigned int ecXmlMinorVersion;
ASSERT_EQ(ECObjectsStatus::Success, ECSchema::ParseECVersion(ecXmlMajorVersion, ecXmlMinorVersion, ECVersion::Latest));

for (const auto& [testCaseNumber, majorVersion, minorVersion, deserializationStatus] : std::vector<std::tuple<unsigned int, unsigned int, unsigned int, bool>>
{
{ 1, 2U, 0U, true }, // Older versions on encountering wrong property tags default to a safe type in this case, "string"
{ 2, 3U, 0U, true }, // Older versions on encountering wrong property tags default to a safe type in this case, "string"
{ 3, 3U, 1U, true }, // Older versions on encountering wrong property tags default to a safe type in this case, "string"
{ 4, ecXmlMajorVersion, ecXmlMinorVersion, false }, // Current version should always log an error on encountering wrong property tags with no deserialization and import
{ 5, ecXmlMajorVersion, ecXmlMinorVersion + 1U, true }, // Future versions should deserialize successfully, default to a safe type but, import should fail
})
{
ECSchemaPtr schema;
const auto context = ECSchemaReadContext::CreateContext();

//Below schema uses ECProperty tag for Struct property which is wrong. It should use ECStructProperty tag.
Utf8CP xmlSchema = R"xml(<ECSchema schemaName="TestSchema" alias="ts" version="1.0.0" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.%d.%d">
<ECSchemaReference name="ECDbMap" version="02.00.00" alias="ecdbmap" />
<ECStructClass typeName="PrimStruct">
<ECProperty propertyName="p2d" typeName="Point2d" />
<ECProperty propertyName="p3d" typeName="Point3d" />
</ECStructClass>
<ECEntityClass typeName="UseOfWrongPropertyTags">
<ECProperty propertyName="Struct" typeName="PrimStruct" />
<ECStructArrayProperty propertyName="Struct_Array" typeName="PrimStruct" />
</ECEntityClass>
</ECSchema>)xml";

if (testCaseNumber == 1)
{
//Below schema uses ECProperty tag for Struct property which is wrong. It should use ECStructProperty tag.
//Overwriting xmlSchema since, previous versions had different xml schema format.
xmlSchema = "<?xml version='1.0' encoding='UTF-8'?>"
"<ECSchema schemaName='TestSchema' version='1.0' nameSpacePrefix='test' xmlns='http://www.bentley.com/schemas/Bentley.ECXML.2.0'>"
" <ECClass typeName='PrimStruct' isStruct = 'true'>"
" <ECProperty propertyName='i' typeName='int' />"
" <ECArrayProperty propertyName='I' typeName='int' />"
" </ECClass>"
" <ECClass typeName='UseOfWrongPropertyTags'>"
" <ECProperty propertyName='Struct' typeName='PrimStruct' />"
" </ECClass>"
"</ECSchema>";
}
else if (testCaseNumber == 2)
{
//Below schema uses ECProperty tag for Struct property which is wrong. It should use ECStructProperty tag.
//Overwriting xmlSchema since, previous versions had different xml schema format.
xmlSchema = "<?xml version='1.0' encoding='utf-8'?>"
"<ECSchema schemaName='TestSchema' nameSpacePrefix='ts' version='1.0' xmlns='http://www.bentley.com/schemas/Bentley.ECXML.3.0'>"
"<ECSchemaReference name='ECDbMap' version='02.00' prefix='ecdbmap' />"
" <ECStructClass typeName='PrimStruct'>"
" <ECProperty propertyName='p2d' typeName='Point2d' />"
" <ECProperty propertyName='p3d' typeName='Point3d' />"
" </ECStructClass>"
" <ECEntityClass typeName='UseOfWrongPropertyTags'>"
" <ECProperty propertyName='Struct' typeName='PrimStruct' />"
" <ECStructArrayProperty propertyName='Struct_Array' typeName='PrimStruct' />"
" </ECEntityClass>"
"</ECSchema>";
}
else if (testCaseNumber == 3)
{
//Below schema uses ECProperty tag for Struct property which is wrong. It should use ECStructProperty tag.
//Overwriting xmlSchema since, previous versions had different xml schema format.
xmlSchema = R"xml(<ECSchema schemaName="TestSchema" alias="ts" version="1.0" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.3.1">
<ECSchemaReference name="ECDbMap" version="02.00" alias="ecdbmap" />
<ECStructClass typeName="PrimStruct">
<ECProperty propertyName="p2d" typeName="Point2d" />
<ECProperty propertyName="p3d" typeName="Point3d" />
</ECStructClass>
<ECEntityClass typeName="UseOfWrongPropertyTags">
<ECProperty propertyName="Struct" typeName="PrimStruct" />
<ECStructArrayProperty propertyName="Struct_Array" typeName="PrimStruct" />
</ECEntityClass>
</ECSchema>)xml";
}

// Schema should always be deserialized successfully irrespective of the ECXml version
ASSERT_EQ(deserializationStatus, SchemaReadStatus::Success == ECSchema::ReadFromXmlString(schema, Utf8PrintfString(xmlSchema, majorVersion, minorVersion).c_str(), *context)) << "Test case number " << testCaseNumber << " failed at deserializing.";
ASSERT_EQ(deserializationStatus, schema.IsValid()) << "Test case number: " << testCaseNumber << " failed due to invalid schemas.";

// Checking if the wrong property tags are defaulted to string type
if (testCaseNumber != 4)
RohitPtnkr1996 marked this conversation as resolved.
Show resolved Hide resolved
{
// Fetching the class pointer
auto propP = schema->GetClassCP("UseOfWrongPropertyTags");
ASSERT_TRUE(propP) << "Test case failed." << testCaseNumber << "failed to fetch class pointer.";
// Fetching the property pointer
auto prop = propP->GetPropertyByIndex(0);
ASSERT_TRUE(prop) << "Test case failed." << testCaseNumber << "failed to fetch property pointer.";
// Fetching property as primitive property
auto primProp = prop->GetAsPrimitiveProperty();
ASSERT_TRUE(primProp) << "Test case failed." << testCaseNumber << "failed to fetch the primitive property";
// Checking for equality of primivite property type to string
auto propType = primProp->GetType();
ASSERT_EQ(PRIMITIVETYPE_String, propType) << "Test case failed." << testCaseNumber << "did not default to string type.";
}

if (testCaseNumber == 5)
{
// Schema import should fail when ECXml version of the schema is greater than the current version that the ECDb supports
ASSERT_EQ(false, m_ecdb.Schemas().ImportSchemas(context->GetCache().GetSchemas()) == SchemaImportResult::OK) << "Test case number " << testCaseNumber << " failed since, the schema was imported.";
RohitPtnkr1996 marked this conversation as resolved.
Show resolved Hide resolved
m_ecdb.AbandonChanges();
}
}
}
//---------------------------------------------------------------------------------------
// @bsimethod
//+---------------+---------------+---------------+---------------+---------------+------
TEST_F(ECSqlStatementTestFixture, pragma_ecdb_version)
Expand Down
5 changes: 5 additions & 0 deletions iModelCore/ecobjects/src/ECProperty.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ SchemaReadStatus ReadTypeNameWithPruning(pugi::xml_node node, ECPropertyP prop,
// must come after prune check to make sure we don't default to string properties that should be pruned
if (setTypeStatus == ECObjectsStatus::ParseError && ignoreParseErrors)
{
// Unknown type encounter in the schema for the current version returning ERROR status
if (!(prop->GetClass().GetSchema().OriginalECXmlVersionGreaterThan(ECVersion::Latest)) && !(prop->GetClass().GetSchema().OriginalECXmlVersionLessThan(ECVersion::Latest)))
RohitPtnkr1996 marked this conversation as resolved.
Show resolved Hide resolved
{
return SchemaReadStatus::InvalidECSchemaXml;
}
LOG.warningv ("Defaulting the type of ECProperty '%s' to '%s' in reaction to non-fatal parse error.", prop->GetName().c_str(), prop->GetTypeName().c_str());
return SchemaReadStatus::Success;
}
Expand Down