diff --git a/iModelCore/ECDb/Tests/NonPublished/ECSqlStatementTests.cpp b/iModelCore/ECDb/Tests/NonPublished/ECSqlStatementTests.cpp
index caf2eb73eda..ef4589fce24 100644
--- a/iModelCore/ECDb/Tests/NonPublished/ECSqlStatementTests.cpp
+++ b/iModelCore/ECDb/Tests/NonPublished/ECSqlStatementTests.cpp
@@ -1535,6 +1535,96 @@ 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;
+ EXPECT_EQ(ECObjectsStatus::Success, ECSchema::ParseECVersion(ecXmlMajorVersion, ecXmlMinorVersion, ECVersion::Latest));
+
+ //Below schema uses ECProperty tag for Struct property which is wrong. It should use ECStructProperty tag.
+ Utf8CP xmlSchema = R"xml(
+
+
+
+
+
+
+
+
+ )xml";
+
+ //Below schema uses ECProperty tag for Struct property which is wrong. It should use ECStructProperty tag.
+ //Declaring separate xmlSchema for version 2.0 since, previous versions had different xml schema format.
+ Utf8CP xmlSchemaFor_V2_0 = R"xml(
+
+
+
+
+
+
+
+ )xml";
+
+ //Below schema uses ECProperty tag for Struct property which is wrong. It should use ECStructProperty tag.
+ //Declaring separate xmlSchema for version 3.0 since, previous versions had different xml schema format.
+ Utf8CP xmlSchemaFor_V3_0 = R"xml(
+
+
+
+
+
+
+
+
+ )xml";
+
+ for (const auto& [testCaseNumber, majorVersion, minorVersion, xmlSchemaVar, deserializationStatus, importStatus] : std::vector>
+ {
+ { 1, 2U, 0U, xmlSchemaFor_V2_0, true , true }, // Older versions on encountering wrong property tags default to a safe type in this case, "string"
+ { 2, 3U, 0U, xmlSchemaFor_V3_0, true , true }, // Older versions on encountering wrong property tags default to a safe type in this case, "string"
+ { 3, 3U, 1U, xmlSchema, true , true }, // Older versions on encountering wrong property tags default to a safe type in this case, "string"
+ { 4, ecXmlMajorVersion, ecXmlMinorVersion, xmlSchema, false , false }, // Current version should always log an error on encountering wrong property tags with no deserialization and import
+ { 5, ecXmlMajorVersion, ecXmlMinorVersion + 1U, xmlSchema, true , false }, // Future versions should deserialize successfully, default to a safe type but, import should fail
+ })
+ {
+ ECSchemaPtr schema;
+ const auto context = ECSchemaReadContext::CreateContext();
+
+ // Schema should always be deserialized successfully irrespective of the ECXml version
+ ASSERT_EQ(deserializationStatus, SchemaReadStatus::Success == ECSchema::ReadFromXmlString(schema, Utf8PrintfString(xmlSchemaVar, 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 (deserializationStatus)
+ {
+ // Fetching the class pointer
+ auto classP = schema->GetClassCP("UseOfWrongPropertyTags");
+ ASSERT_TRUE(classP) << "Test case failed." << testCaseNumber << "failed to fetch class pointer.";
+ // Fetching the property pointer
+ auto propP = classP->GetPropertyByIndex(0);
+ ASSERT_TRUE(propP) << "Test case failed." << testCaseNumber << "failed to fetch property pointer.";
+ // Fetching property as primitive property
+ auto primProp = propP->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();
+ EXPECT_EQ(PRIMITIVETYPE_String, propType) << "Test case failed." << testCaseNumber << "did not default to string type.";
+ }
+
+
+ // Schema import should fail when ECXml version of the schema is greater than the current version that the ECDb supports
+ EXPECT_EQ(importStatus, m_ecdb.Schemas().ImportSchemas(context->GetCache().GetSchemas()) == SchemaImportResult::OK) << "Test case number " << testCaseNumber << " failed.";
+ if (importStatus)
+ EXPECT_NE(nullptr, m_ecdb.Schemas().GetSchema("TestSchema")) << "Test case number " << testCaseNumber << " failed.";
+ m_ecdb.AbandonChanges();
+
+ }
+ }
+//---------------------------------------------------------------------------------------
// @bsimethod
//+---------------+---------------+---------------+---------------+---------------+------
TEST_F(ECSqlStatementTestFixture, pragma_ecdb_version)
diff --git a/iModelCore/ecobjects/src/ECProperty.cpp b/iModelCore/ecobjects/src/ECProperty.cpp
index fd43b2c6519..014448faf47 100644
--- a/iModelCore/ecobjects/src/ECProperty.cpp
+++ b/iModelCore/ecobjects/src/ECProperty.cpp
@@ -44,6 +44,13 @@ 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().GetOriginalECXmlVersionAsString() == ECSchema::GetECVersionString(ECVersion::Latest))
+ {
+ LOG.errorv("Invalid ECSchemaXML: The Property '%s.%s' has a type name '%s' that can not be resolved to a known type.",
+ prop->GetClass().GetFullName(), prop->GetName().c_str(), typeName.c_str());
+ 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;
}
diff --git a/iModelCore/ecobjects/test/NonPublished/SchemaComparerTests.cpp b/iModelCore/ecobjects/test/NonPublished/SchemaComparerTests.cpp
index 1c81cb74c24..e4fa3b9d791 100644
--- a/iModelCore/ecobjects/test/NonPublished/SchemaComparerTests.cpp
+++ b/iModelCore/ecobjects/test/NonPublished/SchemaComparerTests.cpp
@@ -1121,6 +1121,54 @@ TEST_F(SchemaCompareTest, CompareECClassIdentical)
//----------------------------------------------------------------------------------------
// @bsimethod
//---------------+---------------+---------------+---------------+---------------+--------
+TEST_F(SchemaComparerXmlTests, CompareSchemasWithWrongPropertyTags)
+ {
+ //Test created for 3.1 version of schema specifically
+ //to observe defaulting behavior for and when the property tags are wrong
+ bvector firstSchemasXml {
+ R"schema(
+
+
+
+
+
+
+
+
+
+ )schema"
+ };
+
+ LoadSchemasIntoContext(m_firstContext, firstSchemasXml);
+
+ bvector secondSchemasXml {
+ R"schema(
+
+
+
+
+
+
+
+
+
+ )schema"
+ };
+
+ LoadSchemasIntoContext(m_secondContext, secondSchemasXml);
+
+ SchemaComparer comparer;
+ SchemaDiff changes;
+ comparer.Compare(changes, m_firstContext->GetCache().GetSchemas(), m_secondContext->GetCache().GetSchemas());
+
+ ASSERT_EQ(1, changes.Changes().Count());
+
+ // We default to string when the property tag is wrong therefore, property change should be observed.
+ ASSERT_TRUE(changes.Changes()[0].Classes()[0].Properties()[0].IsChanged());
+ }
+//----------------------------------------------------------------------------------------
+// @bsimethod
+//---------------+---------------+---------------+---------------+---------------+--------
TEST_F(SchemaCompareTest, CompareECSchemaClassPropertyDescriptionAgainstNull)
{
CreateFirstSchema();