diff --git a/iModelCore/ECDb/Tests/NonPublished/ECSqlStatementTests.cpp b/iModelCore/ECDb/Tests/NonPublished/ECSqlStatementTests.cpp
index 8401cca7b9c..de9b02ed7a6 100644
--- a/iModelCore/ECDb/Tests/NonPublished/ECSqlStatementTests.cpp
+++ b/iModelCore/ECDb/Tests/NonPublished/ECSqlStatementTests.cpp
@@ -11800,4 +11800,444 @@ TEST_F(ECSqlStatementTestFixture, SelectAnySomeAll)
ASSERT_EQ(expected, GetHelper().ExecuteSelectECSql(ecsql));
}
}
+
+//---------------------------------------------------------------------------------------
+// @bsimethod
+//+---------------+---------------+---------------+---------------+---------------+------
+TEST_F(ECSqlStatementTestFixture, UpdateToNullBinding)
+ {
+ ASSERT_EQ(BentleyStatus::SUCCESS, SetupECDb("ec_sql_update_to_null.ecdb", SchemaItem(R"xml(
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )xml")));
+
+ ///*** Insertable data
+ auto i = 123;
+ auto p2d = DPoint2d::From(23.22, 31.11);
+ auto st_p2d = DPoint2d::From(53.22, 31.11);
+ auto st_st_b = true;
+ auto st_st_i = 45;
+
+ //*** Update all values to null
+ {
+ Utf8String insertEcsql("INSERT INTO ts.TestClass (p2d, st, array_i) VALUES (?,?,?)");
+ ECSqlStatement stmt;
+ ASSERT_EQ(ECSqlStatus::Success, stmt.Prepare(m_ecdb, insertEcsql.c_str())) << insertEcsql.c_str();
+ stmt.BindPoint2d(1, p2d);
+ auto& st = stmt.GetBinder(2);
+ st["p2d"].BindPoint2d(st_p2d);
+ st["st"]["b"].BindBoolean(st_st_b);
+ st["st"]["i"].BindBoolean(st_st_i);
+ stmt.GetBinder(3).AddArrayElement().BindInt(i);
+
+ ECInstanceKey key;
+ ASSERT_EQ(BE_SQLITE_DONE, stmt.Step(key)) << stmt.GetECSql();
+ stmt.Finalize();
+
+ Utf8String updateEcsql("UPDATE ONLY ts.TestClass SET p2d=?, st=?, array_i=? WHERE ECInstanceId=?");
+ ASSERT_EQ(ECSqlStatus::Success, stmt.Prepare(m_ecdb, updateEcsql.c_str())) << updateEcsql.c_str();
+ for (int i = 1; i <= 3; ++i)
+ {
+ ASSERT_EQ(ECSqlStatus::Success, stmt.BindNull(i));
+ }
+ ASSERT_EQ(ECSqlStatus::Success, stmt.BindId(4, key.GetInstanceId()));
+
+ ASSERT_EQ(BE_SQLITE_DONE, stmt.Step()) << stmt.GetECSql();
+ stmt.Finalize();
+
+ Utf8String selectEcsql("SELECT p2d, p2d.X, p2d.Y, st, array_i FROM ts.TestClass WHERE ECInstanceId=?");
+ ASSERT_EQ(ECSqlStatus::Success, stmt.Prepare(m_ecdb, selectEcsql.c_str())) << selectEcsql.c_str();
+ ASSERT_EQ(ECSqlStatus::Success, stmt.BindId(1, key.GetInstanceId()));
+ ASSERT_EQ(BE_SQLITE_ROW, stmt.Step()) << stmt.GetECSql();
+ for (int i = 0; i < stmt.GetColumnCount(); ++i)
+ {
+ ASSERT_TRUE(stmt.IsValueNull(i)) << "no values bound to " << stmt.GetECSql();
+ }
+
+ const int expectedMembersCount = (int) m_ecdb.Schemas().GetClass("TestSchema", "ComplexStruct")->GetPropertyCount(true);
+ IECSqlValue const& structVal = stmt.GetValue(3);
+ int actualMembersCount = 0;
+ for (IECSqlValue const& memberVal : structVal.GetStructIterable())
+ {
+ actualMembersCount++;
+ ASSERT_TRUE(memberVal.IsNull());
+ }
+ ASSERT_EQ(expectedMembersCount, actualMembersCount);
+
+ IECSqlValue const& structArrayVal = stmt.GetValue(4);
+ ASSERT_EQ(0, structArrayVal.GetArrayLength());
+ }
+
+ //*** Update array to contain two null elements
+ {
+ Utf8String insertEcsql("INSERT INTO ts.TestClass (array_i) VALUES (?)");
+ ECSqlStatement stmt;
+ ASSERT_EQ(ECSqlStatus::Success, stmt.Prepare(m_ecdb, insertEcsql.c_str())) << insertEcsql.c_str();
+ stmt.GetBinder(1).AddArrayElement().BindInt(i);
+
+ ECInstanceKey key;
+ ASSERT_EQ(BE_SQLITE_DONE, stmt.Step(key)) << stmt.GetECSql();
+ stmt.Finalize();
+
+ Utf8String updateEcsql("UPDATE ONLY ts.TestClass SET array_i=? WHERE ECInstanceId=?");
+ ASSERT_EQ(ECSqlStatus::Success, stmt.Prepare(m_ecdb, updateEcsql.c_str())) << updateEcsql.c_str();
+ IECSqlBinder& arrayBinder = stmt.GetBinder(1);
+ ASSERT_EQ(ECSqlStatus::Success, arrayBinder.AddArrayElement().BindNull());
+ ASSERT_EQ(ECSqlStatus::Success, arrayBinder.AddArrayElement().BindNull());
+ ASSERT_EQ(ECSqlStatus::Success, stmt.BindId(2, key.GetInstanceId()));
+
+ ASSERT_EQ(BE_SQLITE_DONE, stmt.Step()) << stmt.GetECSql();
+ stmt.Finalize();
+
+ Utf8String selectEcsql("SELECT array_i FROM ts.TestClass WHERE ECInstanceId=?");
+ ASSERT_EQ(ECSqlStatus::Success, stmt.Prepare(m_ecdb, selectEcsql.c_str())) << selectEcsql.c_str();
+ ASSERT_EQ(ECSqlStatus::Success, stmt.BindId(1, key.GetInstanceId()));
+ ASSERT_EQ(BE_SQLITE_ROW, stmt.Step()) << stmt.GetECSql();
+
+ IECSqlValue const& val = stmt.GetValue(0);
+ ASSERT_FALSE(val.IsNull()) << stmt.GetECSql();
+ ASSERT_EQ(2, val.GetArrayLength());
+ for (IECSqlValue const& elementVal : val.GetArrayIterable())
+ {
+ ASSERT_TRUE(elementVal.IsNull()) << stmt.GetECSql();
+
+ if (val.GetColumnInfo().GetDataType().IsStructArray())
+ {
+ for (IECSqlValue const& memberVal : elementVal.GetStructIterable())
+ {
+ ASSERT_TRUE(memberVal.IsNull());
+ }
+ }
+ }
+ }
+
+ // Update points to be partially unset
+ {
+ Utf8String insertEcsql("INSERT INTO ts.TestClass (p2d, st) VALUES (?,?)");
+ ECSqlStatement stmt;
+ ASSERT_EQ(ECSqlStatus::Success, stmt.Prepare(m_ecdb, insertEcsql.c_str())) << insertEcsql.c_str();
+ stmt.BindPoint2d(1, p2d);
+ auto& st = stmt.GetBinder(2);
+ st["p2d"].BindPoint2d(st_p2d);
+
+ ECInstanceKey key;
+ ASSERT_EQ(BE_SQLITE_DONE, stmt.Step(key)) << stmt.GetECSql();
+ stmt.Finalize();
+
+ Utf8String updateEcsql("UPDATE ONLY ts.TestClass SET p2d.X=?, st.p2d.X=? WHERE ECInstanceId=?");
+ ASSERT_EQ(ECSqlStatus::Success, stmt.Prepare(m_ecdb, updateEcsql.c_str())) << updateEcsql.c_str();
+
+ ASSERT_EQ(ECSqlStatus::Success, stmt.BindNull(1));
+ ASSERT_EQ(ECSqlStatus::Success, stmt.BindNull(2));
+ ASSERT_EQ(ECSqlStatus::Success, stmt.BindId(3, key.GetInstanceId()));
+
+ ASSERT_EQ(BE_SQLITE_DONE, stmt.Step()) << stmt.GetECSql();
+ stmt.Finalize();
+
+ Utf8String selectEcsql("SELECT p2d, p2d.X, p2d.Y, st.p2d, st.p2d.X, st.p2d.Y FROM ts.TestClass WHERE ECInstanceId=?");
+ ASSERT_EQ(ECSqlStatus::Success, stmt.Prepare(m_ecdb, selectEcsql.c_str())) << selectEcsql.c_str();
+ ASSERT_EQ(ECSqlStatus::Success, stmt.BindId(1, key.GetInstanceId()));
+ ASSERT_EQ(BE_SQLITE_ROW, stmt.Step()) << stmt.GetECSql();
+
+ std::set nullItems { "p2d", "p2d.X", "st.p2d", "st.p2d.X" };
+ for (int i = 0; i < stmt.GetColumnCount(); i++)
+ {
+ IECSqlValue const& val = stmt.GetValue(i);
+ Utf8String propPath = val.GetColumnInfo().GetPropertyPath().ToString();
+ const bool expectedToBeNull = nullItems.find(propPath) != nullItems.end();
+ ASSERT_EQ(expectedToBeNull, val.IsNull()) << "Select clause item " << i << " in " << stmt.GetECSql();
+ }
+ }
+
+ //*** Update nested struct to be partially unset
+ {
+ Utf8String insertEcsql("INSERT INTO ts.TestClass (st) VALUES (?)");
+ ECSqlStatement stmt;
+ ASSERT_EQ(ECSqlStatus::Success, stmt.Prepare(m_ecdb, insertEcsql.c_str())) << insertEcsql.c_str();
+ auto& st = stmt.GetBinder(1);
+ st["st"]["b"].BindBoolean(st_st_b);
+ st["st"]["i"].BindBoolean(st_st_i);
+
+ ECInstanceKey key;
+ ASSERT_EQ(BE_SQLITE_DONE, stmt.Step(key)) << stmt.GetECSql();
+ stmt.Finalize();
+
+ Utf8String updateEcsql("UPDATE ONLY ts.TestClass SET st=? WHERE ECInstanceId=?");
+ ASSERT_EQ(ECSqlStatus::Success, stmt.Prepare(m_ecdb, updateEcsql.c_str())) << updateEcsql.c_str();
+
+ auto& elementBinder = stmt.GetBinder(1);
+ ASSERT_EQ(ECSqlStatus::Success, elementBinder["st"]["i"].BindNull()); // Set st.st.i = null
+ ASSERT_EQ(ECSqlStatus::Success, elementBinder["st"]["b"].BindBoolean(st_st_b)); // Set st.st.b = true, so that the whole structure doesn't become null
+ ASSERT_EQ(ECSqlStatus::Success, stmt.BindId(2, key.GetInstanceId()));
+
+ ASSERT_EQ(BE_SQLITE_DONE, stmt.Step()) << stmt.GetECSql();
+ stmt.Finalize();
+
+ Utf8String selectEcsql("SELECT st FROM ts.TestClass WHERE ECInstanceId=?");
+ ASSERT_EQ(ECSqlStatus::Success, stmt.Prepare(m_ecdb, selectEcsql.c_str())) << selectEcsql.c_str();
+ ASSERT_EQ(ECSqlStatus::Success, stmt.BindId(1, key.GetInstanceId()));
+ ASSERT_EQ(BE_SQLITE_ROW, stmt.Step()) << stmt.GetECSql();
+
+ ASSERT_FALSE(stmt.IsValueNull(0));
+ IECSqlValue const& structVal = stmt.GetValue(0);
+ for (IECSqlValue const& memberVal : structVal.GetStructIterable())
+ {
+ if (memberVal.GetColumnInfo().GetProperty()->GetName().Equals("st"))
+ {
+ int memberCount = 0;
+ for (IECSqlValue const& nestedMemberVal : memberVal.GetStructIterable())
+ {
+ memberCount++;
+ if (nestedMemberVal.GetColumnInfo().GetProperty()->GetName().Equals("b"))
+ ASSERT_FALSE(nestedMemberVal.IsNull());
+ else
+ ASSERT_TRUE(nestedMemberVal.IsNull());
+ }
+ ASSERT_EQ((int) memberVal.GetColumnInfo().GetStructType()->GetPropertyCount(true), memberCount);
+ }
+ else
+ ASSERT_TRUE(memberVal.IsNull());
+ }
+ }
+
+ //*** Update nested struct to have all properties null
+ {
+ Utf8String insertEcsql("INSERT INTO ts.TestClass (st) VALUES (?)");
+ ECSqlStatement stmt;
+ ASSERT_EQ(ECSqlStatus::Success, stmt.Prepare(m_ecdb, insertEcsql.c_str())) << insertEcsql.c_str();
+ auto& st = stmt.GetBinder(1);
+ st["st"]["i"].BindInt(st_st_i);
+ st["st"]["b"].BindBoolean(st_st_b);
+
+ ECInstanceKey key;
+ ASSERT_EQ(BE_SQLITE_DONE, stmt.Step(key)) << stmt.GetECSql();
+ stmt.Finalize();
+
+ Utf8String updateEcsql("UPDATE ONLY ts.TestClass SET st.p2d=?, st.st.i=?, st.st.b=? WHERE ECInstanceId=?");
+ ASSERT_EQ(ECSqlStatus::Success, stmt.Prepare(m_ecdb, updateEcsql.c_str())) << updateEcsql.c_str();
+ ASSERT_EQ(ECSqlStatus::Success, stmt.GetBinder(1).BindPoint2d(p2d)); // Make at least one arg in non-nested st not null.
+ ASSERT_EQ(ECSqlStatus::Success, stmt.GetBinder(2).BindNull());
+ ASSERT_EQ(ECSqlStatus::Success, stmt.GetBinder(3).BindNull());
+ ASSERT_EQ(ECSqlStatus::Success, stmt.BindId(4, key.GetInstanceId()));
+
+ ASSERT_EQ(BE_SQLITE_DONE, stmt.Step()) << stmt.GetECSql();
+ stmt.Finalize();
+
+ Utf8String selectEcsql("SELECT st FROM ts.TestClass WHERE ECInstanceId=?");
+ ASSERT_EQ(ECSqlStatus::Success, stmt.Prepare(m_ecdb, selectEcsql.c_str())) << selectEcsql.c_str();
+ ASSERT_EQ(ECSqlStatus::Success, stmt.BindId(1, key.GetInstanceId()));
+ ASSERT_EQ(BE_SQLITE_ROW, stmt.Step()) << stmt.GetECSql();
+
+ ASSERT_FALSE(stmt.IsValueNull(0));
+ IECSqlValue const& structVal = stmt.GetValue(0);
+ for (IECSqlValue const& memberVal : structVal.GetStructIterable())
+ {
+ if (memberVal.GetColumnInfo().GetProperty()->GetName().Equals("p2d"))
+ ASSERT_FALSE(memberVal.IsNull());
+ else
+ ASSERT_TRUE(memberVal.IsNull()); // st will fall under this check
+ }
+ }
+ }
+
+//---------------------------------------------------------------------------------------
+// @bsimethod
+//+---------------+---------------+---------------+---------------+---------------+------
+TEST_F(ECSqlStatementTestFixture, UpdateToNullInline)
+ {
+ ASSERT_EQ(BentleyStatus::SUCCESS, SetupECDb("ec_sql_update_to_null_inline.ecdb", SchemaItem(R"xml(
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )xml")));
+
+ ///*** Insertable data
+ auto i = 123;
+ auto p2d = DPoint2d::From(23.22, 31.11);
+ auto st_p2d = DPoint2d::From(53.22, 31.11);
+ auto st_st_b = true;
+ auto st_st_i = 45;
+
+ //*** Update all values to null
+ {
+ Utf8String insertEcsql("INSERT INTO ts.TestClass (p2d, st, array_i) VALUES (?,?,?)");
+ ECSqlStatement stmt;
+ ASSERT_EQ(ECSqlStatus::Success, stmt.Prepare(m_ecdb, insertEcsql.c_str())) << insertEcsql.c_str();
+ stmt.BindPoint2d(1, p2d);
+ auto& st = stmt.GetBinder(2);
+ st["p2d"].BindPoint2d(st_p2d);
+ st["st"]["b"].BindBoolean(st_st_b);
+ st["st"]["i"].BindBoolean(st_st_i);
+ stmt.GetBinder(3).AddArrayElement().BindInt(i);
+
+ ECInstanceKey key;
+ ASSERT_EQ(BE_SQLITE_DONE, stmt.Step(key)) << stmt.GetECSql();
+ stmt.Finalize();
+
+ SqlPrintfString updateEcsql("UPDATE ONLY ts.TestClass SET p2d=NULL, st=NULL, array_i=NULL WHERE ECInstanceId=%s", key.GetInstanceId().ToString().c_str());
+ ASSERT_EQ(ECSqlStatus::Success, stmt.Prepare(m_ecdb, updateEcsql.GetUtf8CP())) << updateEcsql.GetUtf8CP();
+ ASSERT_EQ(BE_SQLITE_DONE, stmt.Step()) << stmt.GetECSql();
+ stmt.Finalize();
+
+ SqlPrintfString selectEcsql("SELECT p2d, p2d.X, p2d.Y, st, array_i FROM ts.TestClass WHERE ECInstanceId=%s", key.GetInstanceId().ToString().c_str());
+ ASSERT_EQ(ECSqlStatus::Success, stmt.Prepare(m_ecdb, selectEcsql.GetUtf8CP())) << selectEcsql.GetUtf8CP();
+ ASSERT_EQ(BE_SQLITE_ROW, stmt.Step()) << stmt.GetECSql();
+ for (int i = 0; i < stmt.GetColumnCount(); ++i)
+ {
+ ASSERT_TRUE(stmt.IsValueNull(i)) << "no values bound to " << stmt.GetECSql();
+ }
+
+ const int expectedMembersCount = (int) m_ecdb.Schemas().GetClass("TestSchema", "ComplexStruct")->GetPropertyCount(true);
+ IECSqlValue const& structVal = stmt.GetValue(3);
+ int actualMembersCount = 0;
+ for (IECSqlValue const& memberVal : structVal.GetStructIterable())
+ {
+ actualMembersCount++;
+ ASSERT_TRUE(memberVal.IsNull());
+ }
+ ASSERT_EQ(expectedMembersCount, actualMembersCount);
+
+ IECSqlValue const& structArrayVal = stmt.GetValue(4);
+ ASSERT_EQ(0, structArrayVal.GetArrayLength());
+ }
+
+ // Update points to be partially unset
+ {
+ Utf8String insertEcsql("INSERT INTO ts.TestClass (p2d, st) VALUES (?,?)");
+ ECSqlStatement stmt;
+ ASSERT_EQ(ECSqlStatus::Success, stmt.Prepare(m_ecdb, insertEcsql.c_str())) << insertEcsql.c_str();
+ stmt.BindPoint2d(1, p2d);
+ auto& st = stmt.GetBinder(2);
+ st["p2d"].BindPoint2d(st_p2d);
+
+ ECInstanceKey key;
+ ASSERT_EQ(BE_SQLITE_DONE, stmt.Step(key)) << stmt.GetECSql();
+ stmt.Finalize();
+
+ SqlPrintfString updateEcsql("UPDATE ONLY ts.TestClass SET p2d.X=NULL, st.p2d.X=NULL WHERE ECInstanceId=%s", key.GetInstanceId().ToString().c_str());
+ ASSERT_EQ(ECSqlStatus::Success, stmt.Prepare(m_ecdb, updateEcsql.GetUtf8CP())) << updateEcsql.GetUtf8CP();
+ ASSERT_EQ(BE_SQLITE_DONE, stmt.Step()) << stmt.GetECSql();
+ stmt.Finalize();
+
+ SqlPrintfString selectEcsql("SELECT p2d, p2d.X, p2d.Y, st.p2d, st.p2d.X, st.p2d.Y FROM ts.TestClass WHERE ECInstanceId=%s", key.GetInstanceId().ToString().c_str());
+ ASSERT_EQ(ECSqlStatus::Success, stmt.Prepare(m_ecdb, selectEcsql.GetUtf8CP())) << selectEcsql.GetUtf8CP();
+ ASSERT_EQ(BE_SQLITE_ROW, stmt.Step()) << stmt.GetECSql();
+
+ std::set nullItems { "p2d", "p2d.X", "st.p2d", "st.p2d.X" };
+ for (int i = 0; i < stmt.GetColumnCount(); i++)
+ {
+ IECSqlValue const& val = stmt.GetValue(i);
+ Utf8String propPath = val.GetColumnInfo().GetPropertyPath().ToString();
+ const bool expectedToBeNull = nullItems.find(propPath) != nullItems.end();
+ ASSERT_EQ(expectedToBeNull, val.IsNull()) << "Select clause item " << i << " in " << stmt.GetECSql();
+ }
+ }
+
+ //*** Update nested struct to be partially unset
+ {
+ Utf8String insertEcsql("INSERT INTO ts.TestClass (st) VALUES (?)");
+ ECSqlStatement stmt;
+ ASSERT_EQ(ECSqlStatus::Success, stmt.Prepare(m_ecdb, insertEcsql.c_str())) << insertEcsql.c_str();
+
+ auto& st = stmt.GetBinder(1);
+ st["st"]["b"].BindBoolean(st_st_b);
+ st["st"]["i"].BindBoolean(st_st_i);
+
+ ECInstanceKey key;
+ ASSERT_EQ(BE_SQLITE_DONE, stmt.Step(key)) << stmt.GetECSql();
+ stmt.Finalize();
+
+ SqlPrintfString updateEcsql("UPDATE ONLY ts.TestClass SET st.st.i=NULL, st.st.b=TRUE WHERE ECInstanceId=%s", key.GetInstanceId().ToString().c_str());
+ ASSERT_EQ(ECSqlStatus::Success, stmt.Prepare(m_ecdb, updateEcsql.GetUtf8CP())) << updateEcsql.GetUtf8CP();
+ ASSERT_EQ(BE_SQLITE_DONE, stmt.Step()) << stmt.GetECSql();
+ stmt.Finalize();
+
+ SqlPrintfString selectEcsql("SELECT st FROM ts.TestClass WHERE ECInstanceId=%s", key.GetInstanceId().ToString().c_str());
+ ASSERT_EQ(ECSqlStatus::Success, stmt.Prepare(m_ecdb, selectEcsql.GetUtf8CP())) << selectEcsql.GetUtf8CP();
+ ASSERT_EQ(BE_SQLITE_ROW, stmt.Step()) << stmt.GetECSql();
+
+ ASSERT_FALSE(stmt.IsValueNull(0));
+ IECSqlValue const& structVal = stmt.GetValue(0);
+ for (IECSqlValue const& memberVal : structVal.GetStructIterable())
+ {
+ if (memberVal.GetColumnInfo().GetProperty()->GetName().Equals("st"))
+ {
+ int memberCount = 0;
+ for (IECSqlValue const& nestedMemberVal : memberVal.GetStructIterable())
+ {
+ memberCount++;
+ if (nestedMemberVal.GetColumnInfo().GetProperty()->GetName().Equals("b"))
+ ASSERT_FALSE(nestedMemberVal.IsNull());
+ else
+ ASSERT_TRUE(nestedMemberVal.IsNull());
+ }
+ ASSERT_EQ((int) memberVal.GetColumnInfo().GetStructType()->GetPropertyCount(true), memberCount);
+ }
+ else
+ ASSERT_TRUE(memberVal.IsNull());
+ }
+ }
+
+ //*** Update nested struct to have all properties null
+ {
+ Utf8String insertEcsql("INSERT INTO ts.TestClass (st) VALUES (?)");
+ ECSqlStatement stmt;
+ ASSERT_EQ(ECSqlStatus::Success, stmt.Prepare(m_ecdb, insertEcsql.c_str())) << insertEcsql.c_str();
+
+ auto& st = stmt.GetBinder(1);
+ st["p2d"].BindPoint2d(p2d);
+ st["st"]["i"].BindInt(st_st_i);
+ st["st"]["b"].BindBoolean(st_st_b);
+
+ ECInstanceKey key;
+ ASSERT_EQ(BE_SQLITE_DONE, stmt.Step(key)) << stmt.GetECSql();
+ stmt.Finalize();
+
+ SqlPrintfString updateEcsql("UPDATE ONLY ts.TestClass SET st.st.i=NULL, st.st.b=NULL WHERE ECInstanceId=%s", key.GetInstanceId().ToString().c_str());
+ ASSERT_EQ(ECSqlStatus::Success, stmt.Prepare(m_ecdb, updateEcsql.GetUtf8CP())) << updateEcsql.GetUtf8CP();
+ ASSERT_EQ(BE_SQLITE_DONE, stmt.Step()) << stmt.GetECSql();
+ stmt.Finalize();
+
+ SqlPrintfString selectEcsql("SELECT st FROM ts.TestClass WHERE ECInstanceId=%s", key.GetInstanceId().ToString().c_str());
+ ASSERT_EQ(ECSqlStatus::Success, stmt.Prepare(m_ecdb, selectEcsql.GetUtf8CP())) << selectEcsql.GetUtf8CP();
+ ASSERT_EQ(BE_SQLITE_ROW, stmt.Step()) << stmt.GetECSql();
+
+ ASSERT_FALSE(stmt.IsValueNull(0));
+ IECSqlValue const& structVal = stmt.GetValue(0);
+ for (IECSqlValue const& memberVal : structVal.GetStructIterable())
+ {
+ if (memberVal.GetColumnInfo().GetProperty()->GetName().Equals("p2d"))
+ ASSERT_FALSE(memberVal.IsNull());
+ else
+ ASSERT_TRUE(memberVal.IsNull()); // st will fall under this check
+ }
+ }
+ }
END_ECDBUNITTESTS_NAMESPACE
diff --git a/iModelCore/ECDb/Tests/NonPublished/JsonUpdaterTests.cpp b/iModelCore/ECDb/Tests/NonPublished/JsonUpdaterTests.cpp
index 9b79b2f108d..7016136d089 100644
--- a/iModelCore/ECDb/Tests/NonPublished/JsonUpdaterTests.cpp
+++ b/iModelCore/ECDb/Tests/NonPublished/JsonUpdaterTests.cpp
@@ -1021,4 +1021,97 @@ TEST_F(JsonUpdaterTests, UpdateTimeOfDayValues)
EXPECT_EQ(JsonValue("[{\"StartTime\": \"00:00:00.000\", \"EndTime\":\"23:59:59.999\"}]"), GetHelper().ExecuteSelectECSql(Utf8PrintfString("SELECT StartTime,EndTime FROM ts.CalendarEntry WHERE ECInstanceId=%s", key2.GetInstanceId().ToString().c_str()).c_str()));
}
+//---------------------------------------------------------------------------------------
+// @bsimethod
+//+---------------+---------------+---------------+---------------+---------------+------
+TEST_F(JsonUpdaterTests, UpdateStructPropertyToNull)
+ {
+ ASSERT_EQ(BentleyStatus::SUCCESS, SetupECDb("updateStructPropertyToNull.ecdb", SchemaItem(R"xml(
+
+
+
+
+
+
+
+
+ )xml")));
+
+ ECInstanceKey key;
+ {
+ // Insert test instance
+ ECSqlStatement stmt;
+ ASSERT_EQ(ECSqlStatus::Success, stmt.Prepare(m_ecdb, "INSERT INTO ts.TestClass(IntProp,ClassProp) VALUES(?,?)"));
+ ASSERT_EQ(ECSqlStatus::Success, stmt.BindInt(1, 15));
+ ASSERT_EQ(ECSqlStatus::Success, stmt.GetBinder(2)["MyStructNumber"].BindInt(17));
+ ASSERT_EQ(BE_SQLITE_DONE, stmt.Step(key));
+ }
+
+ // Check for correct ClassProp value to be stored
+ ECSqlStatement stmt;
+ ASSERT_EQ(ECSqlStatus::Success, stmt.Prepare(m_ecdb, "SELECT IntProp,ClassProp FROM ts.TestClass WHERE ECInstanceId=?"));
+ ASSERT_EQ(ECSqlStatus::Success, stmt.BindId(1, key.GetInstanceId()));
+ EXPECT_EQ(JsonValue("[{\"IntProp\":15,\"ClassProp\":{\"MyStructNumber\":17}}]"), GetHelper().ExecutePreparedECSql(stmt));
+
+ // Update test instance
+ ECClassCP testClass = m_ecdb.Schemas().GetClass("TestSchema", "TestClass");
+ ASSERT_TRUE(testClass != nullptr);
+ JsonUpdater updater(m_ecdb, *testClass, nullptr);
+ ASSERT_TRUE(updater.IsValid());
+ ASSERT_EQ(BE_SQLITE_OK, updater.Update(key.GetInstanceId(), JsonValue("{\"IntProp\": 6, \"ClassProp\": null}").m_value));
+
+ // Check for ClassProp to not exist (be null)
+ stmt.Reset();
+ EXPECT_EQ(JsonValue("[{\"IntProp\":6}]"), GetHelper().ExecutePreparedECSql(stmt));
+ }
+
+//---------------------------------------------------------------------------------------
+// @bsimethod
+//+---------------+---------------+---------------+---------------+---------------+------
+TEST_F(JsonUpdaterTests, UpdateArrayPropertyToNull)
+ {
+ ASSERT_EQ(BentleyStatus::SUCCESS, SetupECDb("updateArrayPropertyToNull.ecdb", SchemaItem(R"xml(
+
+
+
+
+
+
+
+
+
+ )xml")));
+
+ ECInstanceKey key;
+ {
+ // Insert test instance
+ ECSqlStatement stmt;
+ ASSERT_EQ(ECSqlStatus::Success, stmt.Prepare(m_ecdb, "INSERT INTO ts.TestClass(IntProp,ArrBoolProp,ArrStructProp) VALUES(?,?,?)"));
+ ASSERT_EQ(ECSqlStatus::Success, stmt.BindInt(1, 15));
+ ASSERT_EQ(ECSqlStatus::Success, stmt.GetBinder(2).AddArrayElement().BindBoolean(true));
+ ASSERT_EQ(ECSqlStatus::Success, stmt.GetBinder(2).AddArrayElement().BindBoolean(false));
+ ASSERT_EQ(ECSqlStatus::Success, stmt.GetBinder(3).AddArrayElement()["DeepNumber"].BindInt(17));
+ ASSERT_EQ(ECSqlStatus::Success, stmt.GetBinder(3).AddArrayElement()["DeepNumber"].BindInt(5));
+ ASSERT_EQ(ECSqlStatus::Success, stmt.GetBinder(3).AddArrayElement()["DeepNumber"].BindInt(12));
+ ASSERT_EQ(BE_SQLITE_DONE, stmt.Step(key));
+ }
+
+ // Check for correct ArrBoolProp and ArrStructProp values to be stored
+ ECSqlStatement stmt;
+ ASSERT_EQ(ECSqlStatus::Success, stmt.Prepare(m_ecdb, "SELECT IntProp,ArrBoolProp,ArrStructProp FROM ts.TestClass WHERE ECInstanceId=?"));
+ ASSERT_EQ(ECSqlStatus::Success, stmt.BindId(1, key.GetInstanceId()));
+ EXPECT_EQ(JsonValue("[{\"IntProp\":15,\"ArrBoolProp\":[true, false],\"ArrStructProp\":[{\"DeepNumber\":17},{\"DeepNumber\":5},{\"DeepNumber\":12}]}]"), GetHelper().ExecutePreparedECSql(stmt));
+
+ // Update test instance
+ ECClassCP testClass = m_ecdb.Schemas().GetClass("TestSchema", "TestClass");
+ ASSERT_TRUE(testClass != nullptr);
+ JsonUpdater updater(m_ecdb, *testClass, nullptr);
+ ASSERT_TRUE(updater.IsValid());
+ ASSERT_EQ(BE_SQLITE_OK, updater.Update(key.GetInstanceId(), JsonValue("{\"IntProp\":6,\"ArrBoolProp\": null, \"ArrStructProp\": null}").m_value));
+
+ // Check for ArrBoolProp and ArrStructProp to not exist (be null)
+ stmt.Reset();
+ EXPECT_EQ(JsonValue("[{\"IntProp\":6}]"), GetHelper().ExecutePreparedECSql(stmt));
+ }
+
END_ECDBUNITTESTS_NAMESPACE
diff --git a/iModelCore/ecobjects/PublicApi/ECObjects/ECJsonUtilities.h b/iModelCore/ecobjects/PublicApi/ECObjects/ECJsonUtilities.h
index d62997f1802..0b3c5d34e32 100644
--- a/iModelCore/ecobjects/PublicApi/ECObjects/ECJsonUtilities.h
+++ b/iModelCore/ecobjects/PublicApi/ECObjects/ECJsonUtilities.h
@@ -474,7 +474,7 @@ struct JsonECInstanceConverter final
~JsonECInstanceConverter() = delete;
//JsonCpp
- static BentleyStatus JsonToECInstance(ECN::IECInstanceR, BeJsConst, ECN::ECClassCR currentClass, Utf8StringCR currentAccessString, IECClassLocaterR, bool ignoreUnknownProperties = false, IECSchemaRemapperCP remapper = nullptr, std::function shouldSerializeProperty = nullptr);
+ static BentleyStatus JsonToECInstance(ECN::IECInstanceR, BeJsConst, ECN::ECClassCR currentClass, Utf8StringCR currentAccessString, IECClassLocaterR, bool ignoreUnknownProperties = false, IECSchemaRemapperCP remapper = nullptr, std::function shouldSerializeProperty = nullptr, bool isDeepNull = false);
static BentleyStatus JsonToPrimitiveECValue(ECN::ECValueR value, BeJsConst json, ECN::PrimitiveType type, Utf8CP extendedTypeName);
static BentleyStatus JsonToArrayECValue(ECN::IECInstanceR, BeJsConst, ECN::ArrayECPropertyCR, Utf8StringCR currentAccessString, IECClassLocaterR);
diff --git a/iModelCore/ecobjects/src/ECJsonUtilities.cpp b/iModelCore/ecobjects/src/ECJsonUtilities.cpp
index ea7edf7f045..3267e01de86 100644
--- a/iModelCore/ecobjects/src/ECJsonUtilities.cpp
+++ b/iModelCore/ecobjects/src/ECJsonUtilities.cpp
@@ -706,13 +706,66 @@ BentleyStatus JsonECInstanceConverter::JsonToECInstance(ECN::IECInstanceR instan
// @bsimethod
//---------------------------------------------------------------------------------------
BentleyStatus JsonECInstanceConverter::JsonToECInstance(IECInstanceR instance, BeJsConst jsonValue, ECClassCR currentClass, Utf8StringCR currentAccessString,
- IECClassLocaterR classLocater, bool ignoreUnknownProperties, IECSchemaRemapperCP remapper, std::function shouldSerializeProperty)
+ IECClassLocaterR classLocater, bool ignoreUnknownProperties, IECSchemaRemapperCP remapper, std::function shouldSerializeProperty, bool isDeepNull)
{
- if (!jsonValue.isObject())
+ if (!jsonValue.isObject() && !isDeepNull)
return ERROR;
bool checkShouldSerializeProperty = shouldSerializeProperty != nullptr;
BentleyStatus stat = SUCCESS;
+
+ if (isDeepNull)
+ {
+ ClassLayoutR classLayout = currentClass.GetDefaultStandaloneEnabler()->GetClassLayout();
+ uint32_t propIndex = 0;
+ if (ECObjectsStatus::Success != classLayout.GetPropertyIndex(propIndex, "")) // we need to select the root of the currentClass
+ return ERROR;
+
+ uint32_t childIndex = classLayout.GetFirstChildPropertyIndex(propIndex);
+ while (0 != childIndex)
+ {
+ Utf8CP innerMemberName;
+ if (ECObjectsStatus::Success != classLayout.GetAccessStringByIndex(innerMemberName, childIndex))
+ return ERROR;
+
+ ECPropertyP ecProperty = currentClass.GetPropertyP(innerMemberName);
+ Utf8String childAccessString = currentAccessString.empty() ? Utf8String(innerMemberName) : currentAccessString + "." + Utf8String(innerMemberName);
+ if (ecProperty->GetIsPrimitive())
+ {
+ ECValue ecValue;
+ ecValue.SetToNull();
+ ECObjectsStatus ecStatus = instance.SetInternalValue(childAccessString.c_str(), ecValue);
+ if (ecStatus != ECObjectsStatus::Success && ecStatus != ECObjectsStatus::PropertyValueMatchesNoChange)
+ {
+ stat = ERROR;
+ BeAssert(ecStatus == ECObjectsStatus::Success || ecStatus == ECObjectsStatus::PropertyValueMatchesNoChange);
+ }
+ }
+ else if (ecProperty->GetIsStruct())
+ {
+ BentleyStatus status = JsonToECInstance(instance, jsonValue, ecProperty->GetAsStructProperty()->GetType(), childAccessString, classLocater, ignoreUnknownProperties, remapper, nullptr, true);
+ if (status != SUCCESS)
+ {
+ stat = ERROR;
+ BeAssert(SUCCESS == status);
+ }
+ }
+ else if (ecProperty->GetIsArray())
+ {
+ ECObjectsStatus ecStatus = instance.ClearArray(childAccessString.c_str());
+ if (ECObjectsStatus::Success != ecStatus)
+ {
+ stat = ERROR;
+ BeAssert(ECObjectsStatus::Success == ecStatus);
+ }
+ }
+
+ childIndex = classLayout.GetNextChildPropertyIndex(propIndex, childIndex);
+ }
+
+ return stat;
+ }
+
jsonValue.ForEachProperty([&](Utf8CP memberName, BeJsConst childJsonValue) {
auto convertOne = [&]() {
@@ -747,19 +800,13 @@ BentleyStatus JsonECInstanceConverter::JsonToECInstance(IECInstanceR instance, B
}
else if (ecProperty->GetIsStruct())
{
- if (childJsonValue.isNull())
- return false;
-
- if (SUCCESS != JsonToECInstance(instance, childJsonValue, ecProperty->GetAsStructProperty()->GetType(), accessString, classLocater, ignoreUnknownProperties, remapper))
+ if (SUCCESS != JsonToECInstance(instance, childJsonValue, ecProperty->GetAsStructProperty()->GetType(), accessString, classLocater, ignoreUnknownProperties, remapper, nullptr, childJsonValue.isNull()))
return true;
return false;
}
else if (ecProperty->GetIsArray())
{
- if (childJsonValue.isNull())
- return false;
-
if (SUCCESS != JsonToArrayECValue(instance, childJsonValue, *ecProperty->GetAsArrayProperty(), accessString, classLocater))
return true;
}
@@ -995,28 +1042,21 @@ BentleyStatus JsonECInstanceConverter::JsonToPrimitiveECValue(ECValueR ecValue,
//---------------------------------------------------------------------------------------
BentleyStatus JsonECInstanceConverter::JsonToArrayECValue(IECInstanceR instance, BeJsConst jsonValue, ArrayECPropertyCR property, Utf8StringCR accessString, IECClassLocaterR classLocater)
{
- if (!jsonValue.isArray())
+ if (!jsonValue.isArray() && !jsonValue.isNull())
return ERROR;
- const uint32_t length = jsonValue.size();
-
ECValue arrayValue;
instance.GetValue(arrayValue, accessString.c_str());
- uint32_t currentLength = arrayValue.IsNull()? 0: arrayValue.GetArrayInfo().GetCount();
- if (length < currentLength)
- {
- // We need to shorten the array. Start by emptying it out.
- if (ECObjectsStatus::Success != instance.ClearArray(accessString.c_str()))
- return ERROR;
- currentLength = 0;
- // Now make the array the size we need
- }
- if (length > currentLength)
- {
- uint32_t xlength = length - currentLength;
- if (ECObjectsStatus::Success != instance.AddArrayElements(accessString.c_str(), xlength))
- return ERROR;
- }
+ uint32_t currentLength = arrayValue.IsNull() ? 0 : arrayValue.GetArrayInfo().GetCount();
+ if (currentLength != 0 && ECObjectsStatus::Success != instance.ClearArray(accessString.c_str()))
+ return ERROR;
+
+ if (jsonValue.isNull())
+ return SUCCESS;
+
+ const uint32_t length = jsonValue.size();
+ if (length > 0 && ECObjectsStatus::Success != instance.AddArrayElements(accessString.c_str(), length))
+ return ERROR;
if (property.GetIsStructArray())
{
diff --git a/iModelCore/ecobjects/test/NonPublished/ECJsonUtilitiesTests.cpp b/iModelCore/ecobjects/test/NonPublished/ECJsonUtilitiesTests.cpp
index 3a49a7a261a..e085513a33a 100644
--- a/iModelCore/ecobjects/test/NonPublished/ECJsonUtilitiesTests.cpp
+++ b/iModelCore/ecobjects/test/NonPublished/ECJsonUtilitiesTests.cpp
@@ -15,7 +15,7 @@ struct ECJsonUtilitiesTestFixture : ECTestFixture
{
protected:
- static BentleyStatus ParseJson(BeJsDocument& json, Utf8StringCR jsonStr) { json.Parse(jsonStr); return json.hasParseError() ? ERROR : SUCCESS; }
+ static BentleyStatus ParseJson(BeJsDocument& json, Utf8StringCR jsonStr) { json.Parse(jsonStr); return json.hasParseError() ? ERROR : SUCCESS; }
static BentleyStatus ParseJson(rapidjson::Document& json, Utf8StringCR jsonStr) { return json.Parse<0>(jsonStr.c_str()).HasParseError() ? ERROR : SUCCESS; }
};
@@ -29,71 +29,71 @@ void PrintTo(BeInt64Id id, std::ostream* os) { *os << id.GetValueUnchecked(); }
//+---------------+---------------+---------------+---------------+---------------+------
TEST_F(ECJsonUtilitiesTestFixture, JsonToId)
{
- BeJsDocument jsonDoc;
+ BeJsDocument jsonDoc;
rapidjson::Document rapidJson;
//Ids formatted numerically in JSON
Utf8CP jsonStr = "1234";
- ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
- EXPECT_EQ(BeInt64Id(UINT64_C(1234)), ECJsonUtilities::JsonToId(jsonDoc)) << jsonStr;
+ ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
+ EXPECT_EQ(BeInt64Id(UINT64_C(1234)), ECJsonUtilities::JsonToId(jsonDoc)) << jsonStr;
ASSERT_EQ(SUCCESS, ParseJson(rapidJson, jsonStr));
EXPECT_EQ(BeInt64Id(UINT64_C(1234)), ECJsonUtilities::JsonToId(rapidJson)) << jsonStr;
jsonStr = "-10"; // Not a valid value for an Id, but failing the method is not worth the overhead. So the test documents the behavior of the API
- ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
- EXPECT_EQ(BeInt64Id(uint64_t(-10)), ECJsonUtilities::JsonToId(jsonDoc)) << jsonStr;
+ ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
+ EXPECT_EQ(BeInt64Id(uint64_t(-10)), ECJsonUtilities::JsonToId(jsonDoc)) << jsonStr;
ASSERT_EQ(SUCCESS, ParseJson(rapidJson, jsonStr));
EXPECT_EQ(BeInt64Id(uint64_t(-10)), ECJsonUtilities::JsonToId(rapidJson)) << jsonStr;
jsonStr = "3.14"; // Not a valid value for an Id, but failing the method is not worth the overhead. So the test documents the behavior of the API
- ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
- EXPECT_EQ(BeInt64Id(3), ECJsonUtilities::JsonToId(jsonDoc)) << jsonStr << " floating numbers are rounded";
+ ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
+ EXPECT_EQ(BeInt64Id(3), ECJsonUtilities::JsonToId(jsonDoc)) << jsonStr << " floating numbers are rounded";
ASSERT_EQ(SUCCESS, ParseJson(rapidJson, jsonStr));
EXPECT_EQ(BeInt64Id(3), ECJsonUtilities::JsonToId(rapidJson)) << jsonStr << " floating numbers are rounded";
//Ids formatted as decimal strings in JSON
jsonStr = R"json("1234")json";
- ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
- EXPECT_EQ(BeInt64Id(UINT64_C(1234)), ECJsonUtilities::JsonToId(jsonDoc)) << jsonStr;
+ ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
+ EXPECT_EQ(BeInt64Id(UINT64_C(1234)), ECJsonUtilities::JsonToId(jsonDoc)) << jsonStr;
ASSERT_EQ(SUCCESS, ParseJson(rapidJson, jsonStr));
EXPECT_EQ(BeInt64Id(UINT64_C(1234)), ECJsonUtilities::JsonToId(rapidJson)) << jsonStr;
jsonStr = R"json("1099511627775")json";
- ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
- EXPECT_EQ(BeInt64Id(UINT64_C(1099511627775)), ECJsonUtilities::JsonToId(jsonDoc)) << jsonStr;
+ ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
+ EXPECT_EQ(BeInt64Id(UINT64_C(1099511627775)), ECJsonUtilities::JsonToId(jsonDoc)) << jsonStr;
ASSERT_EQ(SUCCESS, ParseJson(rapidJson, jsonStr));
EXPECT_EQ(BeInt64Id(UINT64_C(1099511627775)), ECJsonUtilities::JsonToId(rapidJson)) << jsonStr;
jsonStr = R"json("-10")json"; // Not a valid value for an Id, but failing the method is not worth the overhead. So the test documents the behavior of the API
- ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
- EXPECT_EQ(BeInt64Id(uint64_t(-10)), ECJsonUtilities::JsonToId(jsonDoc)) << jsonStr;
+ ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
+ EXPECT_EQ(BeInt64Id(uint64_t(-10)), ECJsonUtilities::JsonToId(jsonDoc)) << jsonStr;
ASSERT_EQ(SUCCESS, ParseJson(rapidJson, jsonStr));
EXPECT_EQ(BeInt64Id(uint64_t(-10)), ECJsonUtilities::JsonToId(rapidJson)) << jsonStr;
jsonStr = R"json("3.14")json"; // Not a valid value for an Id, but failing the method is not worth the overhead. So the test documents the behavior of the API
- ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
- EXPECT_EQ(BeInt64Id(3), ECJsonUtilities::JsonToId(jsonDoc)) << jsonStr << " floating numbers are rounded";
+ ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
+ EXPECT_EQ(BeInt64Id(3), ECJsonUtilities::JsonToId(jsonDoc)) << jsonStr << " floating numbers are rounded";
ASSERT_EQ(SUCCESS, ParseJson(rapidJson, jsonStr));
EXPECT_EQ(BeInt64Id(3), ECJsonUtilities::JsonToId(rapidJson)) << jsonStr << " floating numbers are rounded";
//Ids formatted as hexadecimal strings in JSON
jsonStr = R"json("0x123")json";
- ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
- EXPECT_EQ(BeInt64Id(UINT64_C(0x123)), ECJsonUtilities::JsonToId(jsonDoc)) << jsonStr;
+ ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
+ EXPECT_EQ(BeInt64Id(UINT64_C(0x123)), ECJsonUtilities::JsonToId(jsonDoc)) << jsonStr;
ASSERT_EQ(SUCCESS, ParseJson(rapidJson, jsonStr));
EXPECT_EQ(BeInt64Id(UINT64_C(0x123)), ECJsonUtilities::JsonToId(rapidJson)) << jsonStr;
jsonStr = R"json("0xFFFFFFFFFF")json";
- ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
- EXPECT_EQ(BeInt64Id(UINT64_C(0xFFFFFFFFFF)), ECJsonUtilities::JsonToId(jsonDoc)) << jsonStr;
+ ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
+ EXPECT_EQ(BeInt64Id(UINT64_C(0xFFFFFFFFFF)), ECJsonUtilities::JsonToId(jsonDoc)) << jsonStr;
ASSERT_EQ(SUCCESS, ParseJson(rapidJson, jsonStr));
EXPECT_EQ(BeInt64Id(UINT64_C(0xFFFFFFFFFF)), ECJsonUtilities::JsonToId(rapidJson)) << jsonStr;
@@ -104,14 +104,14 @@ TEST_F(ECJsonUtilitiesTestFixture, JsonToId)
//+---------------+---------------+---------------+---------------+---------------+------
TEST_F(ECJsonUtilitiesTestFixture, IdToJson)
{
- BeJsDocument jsonDoc;
+ BeJsDocument jsonDoc;
rapidjson::Document rapidJson;
BeInt64Id id(UINT64_C(1234));
- ASSERT_EQ(SUCCESS, ECJsonUtilities::IdToJson(jsonDoc, id)) << id.ToString();
- ASSERT_TRUE(jsonDoc.isString()) << id.ToString();
- ASSERT_STRCASEEQ("0x4d2", jsonDoc.asCString()) << id.ToString();
+ ASSERT_EQ(SUCCESS, ECJsonUtilities::IdToJson(jsonDoc, id)) << id.ToString();
+ ASSERT_TRUE(jsonDoc.isString()) << id.ToString();
+ ASSERT_STRCASEEQ("0x4d2", jsonDoc.asCString()) << id.ToString();
ASSERT_EQ(SUCCESS, ECJsonUtilities::IdToJson(rapidJson, id, rapidJson.GetAllocator())) << id.ToString();
ASSERT_TRUE(rapidJson.IsString()) << id.ToString();
@@ -119,9 +119,9 @@ TEST_F(ECJsonUtilitiesTestFixture, IdToJson)
id = BeInt64Id(UINT64_C(1099511627775));
- ASSERT_EQ(SUCCESS, ECJsonUtilities::IdToJson(jsonDoc, id)) << id.ToString();
- ASSERT_TRUE(jsonDoc.isString()) << id.ToString();
- ASSERT_STRCASEEQ("0xffffffffff", jsonDoc.asCString()) << id.ToString();
+ ASSERT_EQ(SUCCESS, ECJsonUtilities::IdToJson(jsonDoc, id)) << id.ToString();
+ ASSERT_TRUE(jsonDoc.isString()) << id.ToString();
+ ASSERT_STRCASEEQ("0xffffffffff", jsonDoc.asCString()) << id.ToString();
ASSERT_EQ(SUCCESS, ECJsonUtilities::IdToJson(rapidJson, id, rapidJson.GetAllocator())) << id.ToString();
ASSERT_TRUE(rapidJson.IsString()) << id.ToString();
@@ -133,7 +133,7 @@ TEST_F(ECJsonUtilitiesTestFixture, IdToJson)
//+---------------+---------------+---------------+---------------+---------------+------
TEST_F(ECJsonUtilitiesTestFixture, JsonToInt64)
{
- BeJsDocument jsonDoc;
+ BeJsDocument jsonDoc;
rapidjson::Document rapidJson;
Utf8CP jsonStr = nullptr;
@@ -141,8 +141,8 @@ TEST_F(ECJsonUtilitiesTestFixture, JsonToInt64)
//formatted numerically in JSON
jsonStr = "1234";
- ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
- EXPECT_EQ(SUCCESS, ECJsonUtilities::JsonToInt64(val, jsonDoc)) << jsonStr;
+ ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
+ EXPECT_EQ(SUCCESS, ECJsonUtilities::JsonToInt64(val, jsonDoc)) << jsonStr;
EXPECT_EQ(INT64_C(1234), val) << jsonStr;
ASSERT_EQ(SUCCESS, ParseJson(rapidJson, jsonStr));
@@ -150,8 +150,8 @@ TEST_F(ECJsonUtilitiesTestFixture, JsonToInt64)
EXPECT_EQ(INT64_C(1234), val) << jsonStr;
jsonStr = "-10";
- ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
- EXPECT_EQ(SUCCESS, ECJsonUtilities::JsonToInt64(val, jsonDoc)) << jsonStr;
+ ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
+ EXPECT_EQ(SUCCESS, ECJsonUtilities::JsonToInt64(val, jsonDoc)) << jsonStr;
EXPECT_EQ(INT64_C(-10), val) << jsonStr;
ASSERT_EQ(SUCCESS, ParseJson(rapidJson, jsonStr));
@@ -159,8 +159,8 @@ TEST_F(ECJsonUtilitiesTestFixture, JsonToInt64)
EXPECT_EQ(INT64_C(-10), val) << jsonStr;
jsonStr = "3.14";
- ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
- EXPECT_EQ(SUCCESS, ECJsonUtilities::JsonToInt64(val, jsonDoc)) << jsonStr << " floating numbers are rounded";
+ ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
+ EXPECT_EQ(SUCCESS, ECJsonUtilities::JsonToInt64(val, jsonDoc)) << jsonStr << " floating numbers are rounded";
EXPECT_EQ(INT64_C(3), val) << jsonStr;
ASSERT_EQ(SUCCESS, ParseJson(rapidJson, jsonStr));
@@ -169,8 +169,8 @@ TEST_F(ECJsonUtilitiesTestFixture, JsonToInt64)
//formatted as decimal strings in JSON
jsonStr = R"json("1234")json";
- ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
- EXPECT_EQ(SUCCESS, ECJsonUtilities::JsonToInt64(val, jsonDoc)) << jsonStr;
+ ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
+ EXPECT_EQ(SUCCESS, ECJsonUtilities::JsonToInt64(val, jsonDoc)) << jsonStr;
EXPECT_EQ(INT64_C(1234), val) << jsonStr;
ASSERT_EQ(SUCCESS, ParseJson(rapidJson, jsonStr));
@@ -178,8 +178,8 @@ TEST_F(ECJsonUtilitiesTestFixture, JsonToInt64)
EXPECT_EQ(INT64_C(1234), val) << jsonStr;
jsonStr = R"json("1099511627775")json";
- ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
- EXPECT_EQ(SUCCESS, ECJsonUtilities::JsonToInt64(val, jsonDoc)) << jsonStr;
+ ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
+ EXPECT_EQ(SUCCESS, ECJsonUtilities::JsonToInt64(val, jsonDoc)) << jsonStr;
EXPECT_EQ(INT64_C(1099511627775), val) << jsonStr;
ASSERT_EQ(SUCCESS, ParseJson(rapidJson, jsonStr));
@@ -187,8 +187,8 @@ TEST_F(ECJsonUtilitiesTestFixture, JsonToInt64)
EXPECT_EQ(INT64_C(1099511627775), val) << jsonStr;
jsonStr = R"json("-10")json";
- ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
- EXPECT_EQ(SUCCESS, ECJsonUtilities::JsonToInt64(val, jsonDoc)) << jsonStr;
+ ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
+ EXPECT_EQ(SUCCESS, ECJsonUtilities::JsonToInt64(val, jsonDoc)) << jsonStr;
EXPECT_EQ(INT64_C(-10), val) << jsonStr;
ASSERT_EQ(SUCCESS, ParseJson(rapidJson, jsonStr));
@@ -196,8 +196,8 @@ TEST_F(ECJsonUtilitiesTestFixture, JsonToInt64)
EXPECT_EQ(INT64_C(-10), val) << jsonStr;
jsonStr = R"json("3.14")json";
- ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
- EXPECT_EQ(SUCCESS, ECJsonUtilities::JsonToInt64(val, jsonDoc)) << jsonStr << " floating numbers are rounded";
+ ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
+ EXPECT_EQ(SUCCESS, ECJsonUtilities::JsonToInt64(val, jsonDoc)) << jsonStr << " floating numbers are rounded";
EXPECT_EQ(INT64_C(3), val) << jsonStr;
ASSERT_EQ(SUCCESS, ParseJson(rapidJson, jsonStr));
@@ -206,8 +206,8 @@ TEST_F(ECJsonUtilitiesTestFixture, JsonToInt64)
//Ids formatted as hexadecimal strings in JSON
jsonStr = R"json("0x123")json";
- ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
- EXPECT_EQ(SUCCESS, ECJsonUtilities::JsonToInt64(val, jsonDoc)) << jsonStr;
+ ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
+ EXPECT_EQ(SUCCESS, ECJsonUtilities::JsonToInt64(val, jsonDoc)) << jsonStr;
EXPECT_EQ(INT64_C(0x123), val) << jsonStr;
ASSERT_EQ(SUCCESS, ParseJson(rapidJson, jsonStr));
@@ -215,8 +215,8 @@ TEST_F(ECJsonUtilitiesTestFixture, JsonToInt64)
EXPECT_EQ(INT64_C(0x123), val) << jsonStr;
jsonStr = R"json("0xFFFFFFFFFF")json";
- ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
- EXPECT_EQ(SUCCESS, ECJsonUtilities::JsonToInt64(val, jsonDoc)) << jsonStr;
+ ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
+ EXPECT_EQ(SUCCESS, ECJsonUtilities::JsonToInt64(val, jsonDoc)) << jsonStr;
EXPECT_EQ(INT64_C(0xFFFFFFFFFF), val) << jsonStr;
ASSERT_EQ(SUCCESS, ParseJson(rapidJson, jsonStr));
@@ -229,32 +229,32 @@ TEST_F(ECJsonUtilitiesTestFixture, JsonToInt64)
//+---------------+---------------+---------------+---------------+---------------+------
TEST_F(ECJsonUtilitiesTestFixture, Int64ToJson)
{
- BeJsDocument jsonDoc;
+ BeJsDocument jsonDoc;
rapidjson::Document rapidJson;
int64_t val = INT64_C(1234);
- ECJsonUtilities::Int64ToJson(jsonDoc, val, ECJsonInt64Format::AsNumber);
- // TODO: add isIntegral() function
- // ASSERT_TRUE(jsonDoc.isIntegral()) << val;
- ASSERT_EQ(val, jsonDoc.asInt64()) << val;
+ ECJsonUtilities::Int64ToJson(jsonDoc, val, ECJsonInt64Format::AsNumber);
+ // TODO: add isIntegral() function
+ // ASSERT_TRUE(jsonDoc.isIntegral()) << val;
+ ASSERT_EQ(val, jsonDoc.asInt64()) << val;
ECJsonUtilities::Int64ToJson(rapidJson, val, rapidJson.GetAllocator(), ECJsonInt64Format::AsNumber);
ASSERT_TRUE(rapidJson.IsInt64()) << val;
ASSERT_EQ(val, rapidJson.GetInt64()) << val;
- ECJsonUtilities::Int64ToJson(jsonDoc, val, ECJsonInt64Format::AsDecimalString);
- ASSERT_TRUE(jsonDoc.isString()) << val;
- ASSERT_STRCASEEQ("1234", jsonDoc.asCString()) << val;
+ ECJsonUtilities::Int64ToJson(jsonDoc, val, ECJsonInt64Format::AsDecimalString);
+ ASSERT_TRUE(jsonDoc.isString()) << val;
+ ASSERT_STRCASEEQ("1234", jsonDoc.asCString()) << val;
ECJsonUtilities::Int64ToJson(rapidJson, val, rapidJson.GetAllocator(), ECJsonInt64Format::AsDecimalString);
ASSERT_TRUE(rapidJson.IsString()) << val;
ASSERT_STRCASEEQ("1234", rapidJson.GetString()) << val;
- ECJsonUtilities::Int64ToJson(jsonDoc, val, ECJsonInt64Format::AsHexadecimalString);
- ASSERT_TRUE(jsonDoc.isString()) << val;
- ASSERT_STRCASEEQ("0x4d2", jsonDoc.asCString()) << val;
+ ECJsonUtilities::Int64ToJson(jsonDoc, val, ECJsonInt64Format::AsHexadecimalString);
+ ASSERT_TRUE(jsonDoc.isString()) << val;
+ ASSERT_STRCASEEQ("0x4d2", jsonDoc.asCString()) << val;
ECJsonUtilities::Int64ToJson(rapidJson, val, rapidJson.GetAllocator(), ECJsonInt64Format::AsHexadecimalString);
ASSERT_TRUE(rapidJson.IsString()) << val;
@@ -262,27 +262,27 @@ TEST_F(ECJsonUtilitiesTestFixture, Int64ToJson)
val = INT64_C(0xffffffffff);
- ECJsonUtilities::Int64ToJson(jsonDoc, val, ECJsonInt64Format::AsNumber);
- // TODO: add isIntegral() function
- // ASSERT_TRUE(jsonDoc.isIntegral()) << val;
- ASSERT_EQ(val, jsonDoc.asInt64()) << val;
+ ECJsonUtilities::Int64ToJson(jsonDoc, val, ECJsonInt64Format::AsNumber);
+ // TODO: add isIntegral() function
+ // ASSERT_TRUE(jsonDoc.isIntegral()) << val;
+ ASSERT_EQ(val, jsonDoc.asInt64()) << val;
ECJsonUtilities::Int64ToJson(rapidJson, val, rapidJson.GetAllocator(), ECJsonInt64Format::AsNumber);
ASSERT_TRUE(rapidJson.IsInt64()) << val;
ASSERT_EQ(val, rapidJson.GetInt64()) << val;
- ECJsonUtilities::Int64ToJson(jsonDoc, val, ECJsonInt64Format::AsDecimalString);
- ASSERT_TRUE(jsonDoc.isString()) << val;
- ASSERT_STRCASEEQ("1099511627775", jsonDoc.asCString()) << val;
+ ECJsonUtilities::Int64ToJson(jsonDoc, val, ECJsonInt64Format::AsDecimalString);
+ ASSERT_TRUE(jsonDoc.isString()) << val;
+ ASSERT_STRCASEEQ("1099511627775", jsonDoc.asCString()) << val;
ECJsonUtilities::Int64ToJson(rapidJson, val, rapidJson.GetAllocator(), ECJsonInt64Format::AsDecimalString);
ASSERT_TRUE(rapidJson.IsString()) << val;
ASSERT_STRCASEEQ("1099511627775", rapidJson.GetString()) << val;
- ECJsonUtilities::Int64ToJson(jsonDoc, val, ECJsonInt64Format::AsHexadecimalString);
- ASSERT_TRUE(jsonDoc.isString()) << val;
- ASSERT_STRCASEEQ("0xffffffffff", jsonDoc.asCString()) << val;
+ ECJsonUtilities::Int64ToJson(jsonDoc, val, ECJsonInt64Format::AsHexadecimalString);
+ ASSERT_TRUE(jsonDoc.isString()) << val;
+ ASSERT_STRCASEEQ("0xffffffffff", jsonDoc.asCString()) << val;
ECJsonUtilities::Int64ToJson(rapidJson, val, rapidJson.GetAllocator(), ECJsonInt64Format::AsHexadecimalString);
ASSERT_TRUE(rapidJson.IsString()) << val;
@@ -291,18 +291,18 @@ TEST_F(ECJsonUtilitiesTestFixture, Int64ToJson)
val = INT64_C(-10);
- ECJsonUtilities::Int64ToJson(jsonDoc, val, ECJsonInt64Format::AsNumber);
- // TODO: add isIntegral() function
- // ASSERT_TRUE(jsonDoc.isIntegral()) << val;
- ASSERT_EQ(val, jsonDoc.asInt64()) << val;
+ ECJsonUtilities::Int64ToJson(jsonDoc, val, ECJsonInt64Format::AsNumber);
+ // TODO: add isIntegral() function
+ // ASSERT_TRUE(jsonDoc.isIntegral()) << val;
+ ASSERT_EQ(val, jsonDoc.asInt64()) << val;
ECJsonUtilities::Int64ToJson(rapidJson, val, rapidJson.GetAllocator(), ECJsonInt64Format::AsNumber);
ASSERT_TRUE(rapidJson.IsInt64()) << val;
ASSERT_EQ(val, rapidJson.GetInt64()) << val;
- ECJsonUtilities::Int64ToJson(jsonDoc, val, ECJsonInt64Format::AsDecimalString);
- ASSERT_TRUE(jsonDoc.isString()) << val;
- ASSERT_STRCASEEQ("-10", jsonDoc.asCString()) << val;
+ ECJsonUtilities::Int64ToJson(jsonDoc, val, ECJsonInt64Format::AsDecimalString);
+ ASSERT_TRUE(jsonDoc.isString()) << val;
+ ASSERT_STRCASEEQ("-10", jsonDoc.asCString()) << val;
ECJsonUtilities::Int64ToJson(rapidJson, val, rapidJson.GetAllocator(), ECJsonInt64Format::AsDecimalString);
ASSERT_TRUE(rapidJson.IsString()) << val;
@@ -314,15 +314,15 @@ TEST_F(ECJsonUtilitiesTestFixture, Int64ToJson)
//+---------------+---------------+---------------+---------------+---------------+------
TEST_F(ECJsonUtilitiesTestFixture, JsonToDateTime)
{
- BeJsDocument jsonDoc;
+ BeJsDocument jsonDoc;
rapidjson::Document rapidJson;
Utf8CP jsonStr = nullptr;
DateTime dt;
jsonStr = R"json("2017-11-20T10:45:32.111Z")json";
- ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
- EXPECT_EQ(SUCCESS, ECJsonUtilities::JsonToDateTime(dt, jsonDoc)) << jsonStr;
+ ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
+ EXPECT_EQ(SUCCESS, ECJsonUtilities::JsonToDateTime(dt, jsonDoc)) << jsonStr;
EXPECT_EQ(DateTime(DateTime::Kind::Utc, 2017, 11, 20, 10, 45, 32, 111), dt) << jsonStr;
ASSERT_EQ(SUCCESS, ParseJson(rapidJson, jsonStr));
@@ -330,8 +330,8 @@ TEST_F(ECJsonUtilitiesTestFixture, JsonToDateTime)
EXPECT_EQ(DateTime(DateTime::Kind::Utc, 2017, 11, 20, 10, 45, 32, 111), dt) << jsonStr;
jsonStr = R"json("2017-11-20 10:45:32.111Z")json";
- ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
- EXPECT_EQ(SUCCESS, ECJsonUtilities::JsonToDateTime(dt, jsonDoc)) << jsonStr;
+ ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
+ EXPECT_EQ(SUCCESS, ECJsonUtilities::JsonToDateTime(dt, jsonDoc)) << jsonStr;
EXPECT_EQ(DateTime(DateTime::Kind::Utc, 2017, 11, 20, 10, 45, 32, 111), dt) << jsonStr;
ASSERT_EQ(SUCCESS, ParseJson(rapidJson, jsonStr));
@@ -339,8 +339,8 @@ TEST_F(ECJsonUtilitiesTestFixture, JsonToDateTime)
EXPECT_EQ(DateTime(DateTime::Kind::Utc, 2017, 11, 20, 10, 45, 32, 111), dt) << jsonStr;
jsonStr = R"json("2017-11-20T10:45:32.111")json";
- ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
- EXPECT_EQ(SUCCESS, ECJsonUtilities::JsonToDateTime(dt, jsonDoc)) << jsonStr;
+ ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
+ EXPECT_EQ(SUCCESS, ECJsonUtilities::JsonToDateTime(dt, jsonDoc)) << jsonStr;
EXPECT_EQ(DateTime(DateTime::Kind::Unspecified, 2017, 11, 20, 10, 45, 32, 111), dt) << jsonStr;
ASSERT_EQ(SUCCESS, ParseJson(rapidJson, jsonStr));
@@ -348,8 +348,8 @@ TEST_F(ECJsonUtilitiesTestFixture, JsonToDateTime)
EXPECT_EQ(DateTime(DateTime::Kind::Unspecified, 2017, 11, 20, 10, 45, 32, 111), dt) << jsonStr;
jsonStr = R"json("2017-11-20 10:45:32.111")json";
- ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
- EXPECT_EQ(SUCCESS, ECJsonUtilities::JsonToDateTime(dt, jsonDoc)) << jsonStr;
+ ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
+ EXPECT_EQ(SUCCESS, ECJsonUtilities::JsonToDateTime(dt, jsonDoc)) << jsonStr;
EXPECT_EQ(DateTime(DateTime::Kind::Unspecified, 2017, 11, 20, 10, 45, 32, 111), dt) << jsonStr;
ASSERT_EQ(SUCCESS, ParseJson(rapidJson, jsonStr));
@@ -357,8 +357,8 @@ TEST_F(ECJsonUtilitiesTestFixture, JsonToDateTime)
EXPECT_EQ(DateTime(DateTime::Kind::Unspecified, 2017, 11, 20, 10, 45, 32, 111), dt) << jsonStr;
jsonStr = R"json("2017-11-20")json";
- ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
- EXPECT_EQ(SUCCESS, ECJsonUtilities::JsonToDateTime(dt, jsonDoc)) << jsonStr;
+ ASSERT_EQ(SUCCESS, ParseJson(jsonDoc, jsonStr));
+ EXPECT_EQ(SUCCESS, ECJsonUtilities::JsonToDateTime(dt, jsonDoc)) << jsonStr;
EXPECT_EQ(DateTime(2017, 11, 20), dt) << jsonStr;
ASSERT_EQ(SUCCESS, ParseJson(rapidJson, jsonStr));
@@ -371,14 +371,14 @@ TEST_F(ECJsonUtilitiesTestFixture, JsonToDateTime)
//+---------------+---------------+---------------+---------------+---------------+------
TEST_F(ECJsonUtilitiesTestFixture, DateTimeToJson)
{
- BeJsDocument jsonDoc;
+ BeJsDocument jsonDoc;
rapidjson::Document rapidJson;
DateTime dt(DateTime::Kind::Utc, 2017, 11, 20, 10, 45, 32, 111);
- ECJsonUtilities::DateTimeToJson(jsonDoc, dt);
- ASSERT_TRUE(jsonDoc.isString()) << dt.ToString();
- ASSERT_STRCASEEQ("2017-11-20T10:45:32.111Z", jsonDoc.asCString()) << dt.ToString();
+ ECJsonUtilities::DateTimeToJson(jsonDoc, dt);
+ ASSERT_TRUE(jsonDoc.isString()) << dt.ToString();
+ ASSERT_STRCASEEQ("2017-11-20T10:45:32.111Z", jsonDoc.asCString()) << dt.ToString();
ECJsonUtilities::DateTimeToJson(rapidJson, dt, rapidJson.GetAllocator());
ASSERT_TRUE(rapidJson.IsString()) << dt.ToString();
@@ -386,9 +386,9 @@ TEST_F(ECJsonUtilitiesTestFixture, DateTimeToJson)
dt = DateTime(DateTime::Kind::Unspecified, 2017, 11, 20, 10, 45, 32, 111);
- ECJsonUtilities::DateTimeToJson(jsonDoc, dt);
- ASSERT_TRUE(jsonDoc.isString()) << dt.ToString();
- ASSERT_STRCASEEQ("2017-11-20T10:45:32.111", jsonDoc.asCString()) << dt.ToString();
+ ECJsonUtilities::DateTimeToJson(jsonDoc, dt);
+ ASSERT_TRUE(jsonDoc.isString()) << dt.ToString();
+ ASSERT_STRCASEEQ("2017-11-20T10:45:32.111", jsonDoc.asCString()) << dt.ToString();
ECJsonUtilities::DateTimeToJson(rapidJson, dt, rapidJson.GetAllocator());
ASSERT_TRUE(rapidJson.IsString()) << dt.ToString();
@@ -396,9 +396,9 @@ TEST_F(ECJsonUtilitiesTestFixture, DateTimeToJson)
dt = DateTime(2017, 11, 20);
- ECJsonUtilities::DateTimeToJson(jsonDoc, dt);
- ASSERT_TRUE(jsonDoc.isString()) << dt.ToString();
- ASSERT_STRCASEEQ("2017-11-20", jsonDoc.asCString()) << dt.ToString();
+ ECJsonUtilities::DateTimeToJson(jsonDoc, dt);
+ ASSERT_TRUE(jsonDoc.isString()) << dt.ToString();
+ ASSERT_STRCASEEQ("2017-11-20", jsonDoc.asCString()) << dt.ToString();
ECJsonUtilities::DateTimeToJson(rapidJson, dt, rapidJson.GetAllocator());
ASSERT_TRUE(rapidJson.IsString()) << dt.ToString();
@@ -410,8 +410,8 @@ TEST_F(ECJsonUtilitiesTestFixture, DateTimeToJson)
//+---------------+---------------+---------------+---------------+---------------+------
TEST_F(ECJsonUtilitiesTestFixture, JsonToBinary)
{
- BeJsDocument jsonDocVal;
- BeJsValue jsonDoc(jsonDocVal);
+ BeJsDocument jsonDocVal;
+ BeJsValue jsonDoc(jsonDocVal);
rapidjson::Document rapidJsonVal;
BeJsValue rapidJson(rapidJsonVal);
@@ -422,11 +422,11 @@ TEST_F(ECJsonUtilitiesTestFixture, JsonToBinary)
bvector actualByteVector;
ByteStream actualByteStream;
- jsonDoc.SetBinary(expectedByteVector);
- EXPECT_EQ(SUCCESS, jsonDoc.GetBinary(actualByteVector));
+ jsonDoc.SetBinary(expectedByteVector);
+ EXPECT_EQ(SUCCESS, jsonDoc.GetBinary(actualByteVector));
EXPECT_EQ(0, memcmp(expectedByteVector.data(), actualByteVector.data(), expectedByteVector.size()));
- jsonDoc.SetBinary(expectedByteStream.data(), expectedByteStream.size());
- jsonDoc.GetBinary(actualByteStream);
+ jsonDoc.SetBinary(expectedByteStream.data(), expectedByteStream.size());
+ jsonDoc.GetBinary(actualByteStream);
EXPECT_EQ(0, memcmp(expectedByteStream.GetData(), actualByteStream.GetData(), expectedByteStream.GetSize()));
actualByteVector.clear();
@@ -436,15 +436,15 @@ TEST_F(ECJsonUtilitiesTestFixture, JsonToBinary)
EXPECT_EQ(0, memcmp(expectedByteVector.data(), actualByteVector.data(), expectedByteVector.size()));
rapidJson.GetBinary(actualByteStream);
EXPECT_EQ(0, memcmp(expectedByteStream.GetData(), actualByteStream.GetData(), expectedByteStream.GetSize()));
- EXPECT_EQ(jsonDoc, rapidJson);
+ EXPECT_EQ(jsonDoc, rapidJson);
- jsonDoc = "bad";
- jsonDoc.From(rapidJson);
- EXPECT_EQ(jsonDoc, rapidJson);
+ jsonDoc = "bad";
+ jsonDoc.From(rapidJson);
+ EXPECT_EQ(jsonDoc, rapidJson);
rapidJson = "bad";
- rapidJson.From(jsonDoc);
- EXPECT_EQ(jsonDoc, rapidJson);
+ rapidJson.From(jsonDoc);
+ EXPECT_EQ(jsonDoc, rapidJson);
}
//---------------------------------------------------------------------------------------
@@ -700,7 +700,7 @@ TEST_F(ECJsonUtilitiesTestFixture, IGeometryIModelJsonRoundTrip)
struct JsonECInstanceConverterTestFixture : ECJsonUtilitiesTestFixture
{
protected:
- BeJsDocument m_jsDoc;
+ BeJsDocument m_jsDoc;
rapidjson::Document m_rapidJson;
static IECInstancePtr CreateTestInstance(ECSchemaR schema, PrimitiveType propertyType)
@@ -725,12 +725,12 @@ struct JsonECInstanceConverterTestFixture : ECJsonUtilitiesTestFixture
{
if (SUCCESS == expectedStatus)
{
- ASSERT_EQ(SUCCESS, ParseJson(m_jsDoc, jsonString));
+ ASSERT_EQ(SUCCESS, ParseJson(m_jsDoc, jsonString));
ASSERT_EQ(SUCCESS, ParseJson(m_rapidJson, jsonString));
}
else
{
- ASSERT_NE(SUCCESS, ParseJson(m_jsDoc, jsonString));
+ ASSERT_NE(SUCCESS, ParseJson(m_jsDoc, jsonString));
ASSERT_NE(SUCCESS, ParseJson(m_rapidJson, jsonString));
}
}
@@ -755,6 +755,14 @@ struct JsonECInstanceConverterTestFixture : ECJsonUtilitiesTestFixture
ASSERT_EQ(ECObjectsStatus::Success, instance.GetValue(ecValue, accessString));
ASSERT_TRUE(ecValue.IsNull());
}
+
+ void AssertEmptyArray(IECInstanceCR instance, Utf8CP accessString)
+ {
+ ECValue ecValue;
+ ASSERT_EQ(ECObjectsStatus::Success, instance.GetValue(ecValue, accessString));
+ ASSERT_TRUE(ecValue.IsArray());
+ ASSERT_EQ(0, ecValue.GetArrayInfo().GetCount());
+ }
};
struct InSchemaClassLocater final : ECN::IECClassLocater
@@ -785,43 +793,43 @@ TEST_F(JsonECInstanceConverterTestFixture, JsonToECInstance_DoubleProperty)
};
ParsePropertyJson("100");
- EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*instance, m_jsDoc, classLocater));
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*instance, m_jsDoc, classLocater));
EXPECT_EQ(100, GetPropertyValue(*instance));
EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*instance, m_rapidJson, classLocater));
EXPECT_EQ(100, GetPropertyValue(*instance));
ParsePropertyJson("1.111111");
- EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*instance, m_jsDoc, classLocater));
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*instance, m_jsDoc, classLocater));
EXPECT_EQ(1.111111, GetPropertyValue(*instance));
EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*instance, m_rapidJson, classLocater));
EXPECT_EQ(1.111111, GetPropertyValue(*instance));
ParsePropertyJson("1000000000000000");
- EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*instance, m_jsDoc, classLocater));
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*instance, m_jsDoc, classLocater));
EXPECT_EQ(1.0e15, GetPropertyValue(*instance));
EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*instance, m_rapidJson, classLocater));
EXPECT_EQ(1.0e15, GetPropertyValue(*instance));
ParsePropertyJson("1000000000000");
- EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*instance, m_jsDoc, classLocater));
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*instance, m_jsDoc, classLocater));
EXPECT_EQ(1.0e12, GetPropertyValue(*instance));
EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*instance, m_rapidJson, classLocater));
EXPECT_EQ(1.0e12, GetPropertyValue(*instance));
ParsePropertyJson("1000000000");
- EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*instance, m_jsDoc, classLocater));
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*instance, m_jsDoc, classLocater));
EXPECT_EQ(1.0e9, GetPropertyValue(*instance));
EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*instance, m_rapidJson, classLocater));
EXPECT_EQ(1.0e9, GetPropertyValue(*instance));
ParsePropertyJson("1.0e18");
- EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*instance, m_jsDoc, classLocater));
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*instance, m_jsDoc, classLocater));
EXPECT_EQ(1.0e18, GetPropertyValue(*instance));
EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*instance, m_rapidJson, classLocater));
EXPECT_EQ(1.0e18, GetPropertyValue(*instance));
ParsePropertyJson("1.0e-24");
- EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*instance, m_jsDoc, classLocater));
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*instance, m_jsDoc, classLocater));
EXPECT_EQ(1.0e-24, GetPropertyValue(*instance));
EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*instance, m_rapidJson, classLocater));
EXPECT_EQ(1.0e-24, GetPropertyValue(*instance));
@@ -830,7 +838,7 @@ TEST_F(JsonECInstanceConverterTestFixture, JsonToECInstance_DoubleProperty)
ParsePropertyJson("\"ABCDE\"");
{
DISABLE_ASSERTS
- EXPECT_NE(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*instance, m_jsDoc, classLocater));
+ EXPECT_NE(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*instance, m_jsDoc, classLocater));
EXPECT_NE(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*instance, m_rapidJson, classLocater));
}
#endif
@@ -838,7 +846,7 @@ TEST_F(JsonECInstanceConverterTestFixture, JsonToECInstance_DoubleProperty)
ParsePropertyJson("\"1.111111\"");
{
DISABLE_ASSERTS
- EXPECT_NE(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*instance, m_jsDoc, classLocater));
+ EXPECT_NE(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*instance, m_jsDoc, classLocater));
EXPECT_NE(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*instance, m_rapidJson, classLocater));
}
}
@@ -863,7 +871,7 @@ TEST_F(JsonECInstanceConverterTestFixture, JsonToECInstance_Struct)
}
IECInstancePtr structInstance = structClass->GetDefaultStandaloneEnabler()->CreateInstance();
EXPECT_TRUE(structInstance.IsValid());
- EXPECT_NE(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*structInstance, m_jsDoc, classLocater)); // expect error when not initialized
+ EXPECT_NE(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*structInstance, m_jsDoc, classLocater)); // expect error when not initialized
EXPECT_NE(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*structInstance, m_rapidJson, classLocater)); // expect error when not initialized
// construct entity instance with a struct property
@@ -879,7 +887,7 @@ TEST_F(JsonECInstanceConverterTestFixture, JsonToECInstance_Struct)
}
IECInstancePtr testInstance = testClass->GetDefaultStandaloneEnabler()->CreateInstance();
EXPECT_TRUE(testInstance.IsValid());
- EXPECT_NE(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_jsDoc, classLocater)); // expect error when not initialized
+ EXPECT_NE(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_jsDoc, classLocater)); // expect error when not initialized
EXPECT_NE(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_rapidJson, classLocater)); // expect error when not initialized
// Test for expected JSON parse errors
@@ -892,11 +900,11 @@ TEST_F(JsonECInstanceConverterTestFixture, JsonToECInstance_Struct)
//-------------------------------------------------------------------------
ParseJsonString("null");
- EXPECT_NE(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*structInstance, m_jsDoc, classLocater));
+ EXPECT_NE(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*structInstance, m_jsDoc, classLocater));
EXPECT_NE(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*structInstance, m_rapidJson, classLocater));
ParseJsonString("{}");
- EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*structInstance, m_jsDoc, classLocater));
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*structInstance, m_jsDoc, classLocater));
AssertNullValue(*structInstance, "doubleProperty");
AssertNullValue(*structInstance, "stringProperty");
EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*structInstance, m_rapidJson, classLocater));
@@ -904,7 +912,7 @@ TEST_F(JsonECInstanceConverterTestFixture, JsonToECInstance_Struct)
AssertNullValue(*structInstance, "stringProperty");
ParseJsonString(Utf8Chars(u8R"*({ "doubleProperty": 1.1, "stringProperty": "S1" })*"));
- EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*structInstance, m_jsDoc, classLocater));
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*structInstance, m_jsDoc, classLocater));
AssertDoubleValue(*structInstance, "doubleProperty", 1.1);
AssertStringValue(*structInstance, "stringProperty", "S1");
EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*structInstance, m_rapidJson, classLocater));
@@ -916,11 +924,11 @@ TEST_F(JsonECInstanceConverterTestFixture, JsonToECInstance_Struct)
//-------------------------------------------------------------------------
ParseJsonString("null");
- EXPECT_NE(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_jsDoc, classLocater));
+ EXPECT_NE(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_jsDoc, classLocater));
EXPECT_NE(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_rapidJson, classLocater));
ParseJsonString("{}");
- EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_jsDoc, classLocater));
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_jsDoc, classLocater));
AssertNullValue(*testInstance, "doubleProperty");
AssertNullValue(*testInstance, "stringProperty");
AssertNullValue(*testInstance, "testStruct");
@@ -934,7 +942,7 @@ TEST_F(JsonECInstanceConverterTestFixture, JsonToECInstance_Struct)
AssertNullValue(*testInstance, "testStruct.stringProperty");
ParseJsonString(Utf8Chars(u8R"*({ "doubleProperty": null, "stringProperty": null })*"));
- EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_jsDoc, classLocater));
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_jsDoc, classLocater));
AssertNullValue(*testInstance, "doubleProperty");
AssertNullValue(*testInstance, "stringProperty");
AssertNullValue(*testInstance, "testStruct");
@@ -948,7 +956,7 @@ TEST_F(JsonECInstanceConverterTestFixture, JsonToECInstance_Struct)
AssertNullValue(*testInstance, "testStruct.stringProperty");
ParseJsonString(Utf8Chars(u8R"*({ "doubleProperty": 1.1, "stringProperty": "S1" })*"));
- EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_jsDoc, classLocater));
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_jsDoc, classLocater));
AssertNullValue(*testInstance, "testStruct");
AssertNullValue(*testInstance, "testStruct.doubleProperty");
AssertNullValue(*testInstance, "testStruct.stringProperty");
@@ -962,7 +970,7 @@ TEST_F(JsonECInstanceConverterTestFixture, JsonToECInstance_Struct)
AssertStringValue(*testInstance, "stringProperty", "S1");
ParseJsonString(Utf8Chars(u8R"*({ "doubleProperty": 1.1, "stringProperty": "S1", "testStruct": null })*"));
- EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_jsDoc, classLocater));
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_jsDoc, classLocater));
AssertNullValue(*testInstance, "testStruct");
AssertNullValue(*testInstance, "testStruct.doubleProperty");
AssertNullValue(*testInstance, "testStruct.stringProperty");
@@ -976,7 +984,7 @@ TEST_F(JsonECInstanceConverterTestFixture, JsonToECInstance_Struct)
AssertStringValue(*testInstance, "stringProperty", "S1");
ParseJsonString(Utf8Chars(u8R"*({ "doubleProperty": 1.1, "stringProperty": "S1", "testStruct": { "doubleProperty": 2.2, "stringProperty": "S2" } })*"));
- EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_jsDoc, classLocater));
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_jsDoc, classLocater));
AssertDoubleValue(*testInstance, "doubleProperty", 1.1);
AssertStringValue(*testInstance, "stringProperty", "S1");
AssertDoubleValue(*testInstance, "testStruct.doubleProperty", 2.2);
@@ -988,4 +996,468 @@ TEST_F(JsonECInstanceConverterTestFixture, JsonToECInstance_Struct)
AssertStringValue(*testInstance, "testStruct.stringProperty", "S2");
}
+//---------------------------------------------------------------------------------------
+// @bsimethod
+//---------------------------------------------------------------------------------------
+TEST_F(JsonECInstanceConverterTestFixture, JsonToECInstance_Struct_InitializedInstance)
+ {
+ ECSchemaPtr schema;
+ ECSchema::CreateSchema(schema, "Schema", "sch", 1, 0, 0);
+ InSchemaClassLocater classLocater(*schema);
+
+ // construct struct instance
+ ECStructClassP structClass;
+ {
+ PrimitiveECPropertyP doubleProperty;
+ PrimitiveECPropertyP stringProperty;
+ schema->CreateStructClass(structClass, "TestStruct");
+ structClass->CreatePrimitiveProperty(doubleProperty, "DoubleProperty", PRIMITIVETYPE_Double);
+ structClass->CreatePrimitiveProperty(stringProperty, "StringProperty", PRIMITIVETYPE_String);
+ }
+ IECInstancePtr structInstance = structClass->GetDefaultStandaloneEnabler()->CreateInstance();
+ EXPECT_TRUE(structInstance.IsValid());
+ EXPECT_NE(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*structInstance, m_jsDoc, classLocater)); // expect error when not initialized
+ EXPECT_NE(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*structInstance, m_rapidJson, classLocater)); // expect error when not initialized
+
+ // Initialize the struct instance with initial data
+ ECValue ecValue;
+ ecValue.SetDouble(22.2);
+ (*structInstance).SetInternalValue("DoubleProperty", ecValue);
+ ecValue.SetUtf8CP("TS.S1-Init");
+ (*structInstance).SetInternalValue("StringProperty", ecValue);
+
+ // construct entity instance with a struct property
+ ECEntityClassP testClass;
+ {
+ StructECPropertyP structProperty;
+ PrimitiveECPropertyP doubleProperty;
+ PrimitiveECPropertyP stringProperty;
+ schema->CreateEntityClass(testClass, "TestClass");
+ testClass->CreateStructProperty(structProperty, "TestStruct", *structClass);
+ testClass->CreatePrimitiveProperty(doubleProperty, "DoubleProperty", PRIMITIVETYPE_Double);
+ testClass->CreatePrimitiveProperty(stringProperty, "StringProperty", PRIMITIVETYPE_String);
+ }
+
+ IECInstancePtr testInstance = testClass->GetDefaultStandaloneEnabler()->CreateInstance();
+ EXPECT_TRUE(testInstance.IsValid());
+ EXPECT_NE(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_jsDoc, classLocater)); // expect error when not initialized
+ EXPECT_NE(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_rapidJson, classLocater)); // expect error when not initialized
+
+ // Initialize the test instance with initial data
+ ecValue.SetDouble(0.6);
+ (*testInstance).SetInternalValue("DoubleProperty", ecValue);
+ ecValue.SetUtf8CP("S1-Init");
+ (*testInstance).SetInternalValue("StringProperty", ecValue);
+ ecValue.SetDouble(22.2);
+ (*testInstance).SetInternalValue("TestStruct.DoubleProperty", ecValue);
+ ecValue.SetUtf8CP("TS.S1-Init");
+ (*testInstance).SetInternalValue("TestStruct.StringProperty", ecValue);
+
+ // Test for expected JSON parse errors
+ ParseJsonString(nullptr, ERROR);
+ ParseJsonString("", ERROR);
+ ParseJsonString("undefined", ERROR);
+
+ //-------------------------------------------------------------------------
+ // JSON --> struct instance tests
+ //-------------------------------------------------------------------------
+
+ ParseJsonString("null");
+ EXPECT_NE(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*structInstance, m_jsDoc, classLocater));
+ EXPECT_NE(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*structInstance, m_rapidJson, classLocater));
+
+ ParseJsonString("{}"); // properties should remain unchanged
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*structInstance, m_jsDoc, classLocater));
+ AssertDoubleValue(*structInstance, "doubleProperty", 22.2);
+ AssertStringValue(*structInstance, "stringProperty", "TS.S1-Init");
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*structInstance, m_rapidJson, classLocater));
+ AssertDoubleValue(*structInstance, "doubleProperty", 22.2);
+ AssertStringValue(*structInstance, "stringProperty", "TS.S1-Init");
+
+ ParseJsonString(Utf8Chars(u8R"*({ "doubleProperty": 22.3, "stringProperty": "TS.S1-New" })*"));
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*structInstance, m_jsDoc, classLocater));
+ AssertDoubleValue(*structInstance, "doubleProperty", 22.3);
+ AssertStringValue(*structInstance, "stringProperty", "TS.S1-New");
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*structInstance, m_rapidJson, classLocater));
+ AssertDoubleValue(*structInstance, "doubleProperty", 22.3);
+ AssertStringValue(*structInstance, "stringProperty", "TS.S1-New");
+
+ //-------------------------------------------------------------------------
+ // JSON --> entity instance with struct property tests
+ //-------------------------------------------------------------------------
+
+ ParseJsonString("null");
+ EXPECT_NE(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_jsDoc, classLocater));
+ EXPECT_NE(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_rapidJson, classLocater));
+
+ ParseJsonString("{}");
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_jsDoc, classLocater));
+ AssertDoubleValue(*testInstance, "doubleProperty", 0.6);
+ AssertStringValue(*testInstance, "stringProperty", "S1-Init");
+ AssertDoubleValue(*testInstance, "testStruct.doubleProperty", 22.2);
+ AssertStringValue(*testInstance, "testStruct.stringProperty", "TS.S1-Init");
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_rapidJson, classLocater));
+ AssertDoubleValue(*testInstance, "doubleProperty", 0.6);
+ AssertStringValue(*testInstance, "stringProperty", "S1-Init");
+ AssertDoubleValue(*testInstance, "testStruct.doubleProperty", 22.2);
+ AssertStringValue(*testInstance, "testStruct.stringProperty", "TS.S1-Init");
+
+ ParseJsonString(Utf8Chars(u8R"*({ "doubleProperty": null, "stringProperty": null })*"));
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_jsDoc, classLocater));
+ AssertNullValue(*testInstance, "doubleProperty");
+ AssertNullValue(*testInstance, "stringProperty");
+ AssertDoubleValue(*testInstance, "testStruct.doubleProperty", 22.2);
+ AssertStringValue(*testInstance, "testStruct.stringProperty", "TS.S1-Init");
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_rapidJson, classLocater));
+ AssertNullValue(*testInstance, "doubleProperty");
+ AssertNullValue(*testInstance, "stringProperty");
+ AssertDoubleValue(*testInstance, "testStruct.doubleProperty", 22.2);
+ AssertStringValue(*testInstance, "testStruct.stringProperty", "TS.S1-Init");
+
+ ParseJsonString(Utf8Chars(u8R"*({ "doubleProperty": 4.2, "stringProperty": "S1-new-new" })*"));
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_jsDoc, classLocater));
+ AssertDoubleValue(*testInstance, "doubleProperty", 4.2);
+ AssertStringValue(*testInstance, "stringProperty", "S1-new-new");
+ AssertDoubleValue(*testInstance, "testStruct.doubleProperty", 22.2);
+ AssertStringValue(*testInstance, "testStruct.stringProperty", "TS.S1-Init");
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_rapidJson, classLocater));
+ AssertDoubleValue(*testInstance, "doubleProperty", 4.2);
+ AssertStringValue(*testInstance, "stringProperty", "S1-new-new");
+ AssertDoubleValue(*testInstance, "testStruct.doubleProperty", 22.2);
+ AssertStringValue(*testInstance, "testStruct.stringProperty", "TS.S1-Init");
+
+ ParseJsonString(Utf8Chars(u8R"*({ "doubleProperty": 5.3, "stringProperty": "S1-new-new-new", "testStruct": null })*"));
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_jsDoc, classLocater));
+ AssertDoubleValue(*testInstance, "doubleProperty", 5.3);
+ AssertStringValue(*testInstance, "stringProperty", "S1-new-new-new");
+ AssertNullValue(*testInstance, "testStruct");
+ AssertNullValue(*testInstance, "testStruct.doubleProperty");
+ AssertNullValue(*testInstance, "testStruct.stringProperty");
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_rapidJson, classLocater));
+ AssertDoubleValue(*testInstance, "doubleProperty", 5.3);
+ AssertStringValue(*testInstance, "stringProperty", "S1-new-new-new");
+ AssertNullValue(*testInstance, "testStruct");
+ AssertNullValue(*testInstance, "testStruct.doubleProperty");
+ AssertNullValue(*testInstance, "testStruct.stringProperty");
+
+ ParseJsonString(Utf8Chars(u8R"*({ "doubleProperty": 111.1, "stringProperty": "S1", "testStruct": { "doubleProperty": 4.4, "stringProperty": "S2" } })*"));
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_jsDoc, classLocater));
+ AssertDoubleValue(*testInstance, "doubleProperty", 111.1);
+ AssertStringValue(*testInstance, "stringProperty", "S1");
+ AssertDoubleValue(*testInstance, "testStruct.doubleProperty", 4.4);
+ AssertStringValue(*testInstance, "testStruct.stringProperty", "S2");
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_rapidJson, classLocater));
+ AssertDoubleValue(*testInstance, "doubleProperty", 111.1);
+ AssertStringValue(*testInstance, "stringProperty", "S1");
+ AssertDoubleValue(*testInstance, "testStruct.doubleProperty", 4.4);
+ AssertStringValue(*testInstance, "testStruct.stringProperty", "S2");
+ }
+
+//---------------------------------------------------------------------------------------
+// @bsimethod
+//---------------------------------------------------------------------------------------
+TEST_F(JsonECInstanceConverterTestFixture, JsonToECInstance_Array)
+ {
+ ECSchemaPtr schema;
+ ECSchema::CreateSchema(schema, "Schema", "sch", 1, 0, 0);
+ InSchemaClassLocater classLocater(*schema);
+
+ // construct struct instance
+ ECStructClassP structClass;
+ {
+ PrimitiveECPropertyP doubleProperty;
+ PrimitiveECPropertyP stringProperty;
+ schema->CreateStructClass(structClass, "TestStruct");
+ structClass->CreatePrimitiveProperty(doubleProperty, "DoubleProperty", PRIMITIVETYPE_Double);
+ structClass->CreatePrimitiveProperty(stringProperty, "StringProperty", PRIMITIVETYPE_String);
+ }
+
+ ECEntityClassP testClass;
+ PrimitiveArrayECPropertyP testIntegerArrayProperty;
+ StructArrayECPropertyP testStructArrayProperty;
+ schema->CreateEntityClass(testClass, "TestClass");
+ testClass->CreatePrimitiveArrayProperty(testIntegerArrayProperty, "IntArrayProp", PRIMITIVETYPE_Integer);
+ testClass->CreateStructArrayProperty(testStructArrayProperty, "StructArrayProp", *structClass);
+
+ IECInstancePtr testInstance = testClass->GetDefaultStandaloneEnabler()->CreateInstance();
+ EXPECT_TRUE(testInstance.IsValid());
+ EXPECT_NE(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_jsDoc, classLocater)); // expect error when not initialized
+ EXPECT_NE(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_rapidJson, classLocater)); // expect error when not initialized
+
+ // Test for expected JSON parse errors
+ ParseJsonString(nullptr, ERROR);
+ ParseJsonString("", ERROR);
+ ParseJsonString("undefined", ERROR);
+
+ //-------------------------------------------------------------------------
+ // JSON --> entity instance with array property tests
+ //-------------------------------------------------------------------------
+
+ ParseJsonString("null");
+ EXPECT_NE(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_jsDoc, classLocater));
+ EXPECT_NE(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_rapidJson, classLocater));
+
+ ParseJsonString("{}");
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_jsDoc, classLocater));
+ AssertEmptyArray(*testInstance, "IntArrayProp");
+ AssertEmptyArray(*testInstance, "StructArrayProp");
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_rapidJson, classLocater));
+ AssertEmptyArray(*testInstance, "IntArrayProp");
+ AssertEmptyArray(*testInstance, "StructArrayProp");
+
+ ParseJsonString(Utf8Chars(u8R"*({ "IntArrayProp": null, "StructArrayProp": null })*"));
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_jsDoc, classLocater));
+ AssertEmptyArray(*testInstance, "IntArrayProp");
+ AssertEmptyArray(*testInstance, "StructArrayProp");
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_rapidJson, classLocater));
+ AssertEmptyArray(*testInstance, "IntArrayProp");
+ AssertEmptyArray(*testInstance, "StructArrayProp");
+
+ ParseJsonString(Utf8Chars(u8R"*({ "IntArrayProp": [], "StructArrayProp": [] })*"));
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_jsDoc, classLocater));
+ AssertEmptyArray(*testInstance, "IntArrayProp");
+ AssertEmptyArray(*testInstance, "StructArrayProp");
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_rapidJson, classLocater));
+ AssertEmptyArray(*testInstance, "IntArrayProp");
+ AssertEmptyArray(*testInstance, "StructArrayProp");
+
+ ParseJsonString(Utf8Chars(u8R"*({ "IntArrayProp": [4, 5, 6, 9, 12], "StructArrayProp": [{ "DoubleProperty": 3.41, "StringProperty": "NewVal1" }, { "DoubleProperty": 12.92, "StringProperty": null }] })*"));
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_jsDoc, classLocater));
+ {
+ ECValue intArrayProp;
+ ECValue structArrayProp;
+ IECInstancePtr structInst;
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(intArrayProp, "IntArrayProp"));
+ ASSERT_EQ(intArrayProp.GetArrayInfo().GetCount(), 5);
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(intArrayProp, "IntArrayProp", 0));
+ ASSERT_EQ(intArrayProp.GetInteger(), 4);
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(intArrayProp, "IntArrayProp", 1));
+ ASSERT_EQ(intArrayProp.GetInteger(), 5);
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(intArrayProp, "IntArrayProp", 2));
+ ASSERT_EQ(intArrayProp.GetInteger(), 6);
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(intArrayProp, "IntArrayProp", 3));
+ ASSERT_EQ(intArrayProp.GetInteger(), 9);
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(intArrayProp, "IntArrayProp", 4));
+ ASSERT_EQ(intArrayProp.GetInteger(), 12);
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(structArrayProp, "StructArrayProp"));
+ ASSERT_EQ(structArrayProp.GetArrayInfo().GetCount(), 2);
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(structArrayProp, "StructArrayProp", 0));
+ structInst = structArrayProp.GetStruct();
+ AssertDoubleValue(*structInst, "DoubleProperty", 3.41);
+ AssertStringValue(*structInst, "StringProperty", "NewVal1");
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(structArrayProp, "StructArrayProp", 1));
+ structInst = structArrayProp.GetStruct();
+ AssertDoubleValue(*structInst, "DoubleProperty", 12.92);
+ AssertNullValue(*structInst, "StringProperty");
+ }
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_rapidJson, classLocater));
+ {
+ ECValue intArrayProp;
+ ECValue structArrayProp;
+ IECInstancePtr structInst;
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(intArrayProp, "IntArrayProp"));
+ ASSERT_EQ(intArrayProp.GetArrayInfo().GetCount(), 5);
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(intArrayProp, "IntArrayProp", 0));
+ ASSERT_EQ(intArrayProp.GetInteger(), 4);
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(intArrayProp, "IntArrayProp", 1));
+ ASSERT_EQ(intArrayProp.GetInteger(), 5);
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(intArrayProp, "IntArrayProp", 2));
+ ASSERT_EQ(intArrayProp.GetInteger(), 6);
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(intArrayProp, "IntArrayProp", 3));
+ ASSERT_EQ(intArrayProp.GetInteger(), 9);
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(intArrayProp, "IntArrayProp", 4));
+ ASSERT_EQ(intArrayProp.GetInteger(), 12);
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(structArrayProp, "StructArrayProp"));
+ ASSERT_EQ(structArrayProp.GetArrayInfo().GetCount(), 2);
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(structArrayProp, "StructArrayProp", 0));
+ structInst = structArrayProp.GetStruct();
+ AssertDoubleValue(*structInst, "DoubleProperty", 3.41);
+ AssertStringValue(*structInst, "StringProperty", "NewVal1");
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(structArrayProp, "StructArrayProp", 1));
+ structInst = structArrayProp.GetStruct();
+ AssertDoubleValue(*structInst, "DoubleProperty", 12.92);
+ AssertNullValue(*structInst, "StringProperty");
+ }
+ }
+
+//---------------------------------------------------------------------------------------
+// @bsimethod
+//---------------------------------------------------------------------------------------
+TEST_F(JsonECInstanceConverterTestFixture, JsonToECInstance_Array_InitializedInstance)
+ {
+ ECSchemaPtr schema;
+ ECSchema::CreateSchema(schema, "Schema", "sch", 1, 0, 0);
+ InSchemaClassLocater classLocater(*schema);
+
+ // construct struct instance
+ ECStructClassP structClass;
+ {
+ PrimitiveECPropertyP doubleProperty;
+ PrimitiveECPropertyP stringProperty;
+ schema->CreateStructClass(structClass, "TestStruct");
+ structClass->CreatePrimitiveProperty(doubleProperty, "DoubleProperty", PRIMITIVETYPE_Double);
+ structClass->CreatePrimitiveProperty(stringProperty, "StringProperty", PRIMITIVETYPE_String);
+ }
+
+ ECEntityClassP testClass;
+ PrimitiveArrayECPropertyP testIntegerArrayProperty;
+ StructArrayECPropertyP testStructArrayProperty;
+ schema->CreateEntityClass(testClass, "TestClass");
+ testClass->CreatePrimitiveArrayProperty(testIntegerArrayProperty, "IntArrayProp", PRIMITIVETYPE_Integer);
+ testClass->CreateStructArrayProperty(testStructArrayProperty, "StructArrayProp", *structClass);
+ IECInstancePtr testInstance = testClass->GetDefaultStandaloneEnabler()->CreateInstance();
+ EXPECT_TRUE(testInstance.IsValid());
+ EXPECT_NE(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_jsDoc, classLocater)); // expect error when not initialized
+ EXPECT_NE(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_rapidJson, classLocater)); // expect error when not initialized
+
+ // Initialize the test instance with initial data
+ ECValue ecValue;
+ ecValue.SetInteger(9);
+ (*testInstance).AddArrayElements("IntArrayProp", 3);
+ (*testInstance).SetInternalValue("IntArrayProp", ecValue, 0);
+ ecValue.SetInteger(16);
+ (*testInstance).SetInternalValue("IntArrayProp", ecValue, 1);
+ ecValue.SetInteger(25);
+ (*testInstance).SetInternalValue("IntArrayProp", ecValue, 2);
+
+ (*testInstance).AddArrayElements("StructArrayProp", 1);
+ IECInstancePtr structInstance = structClass->GetDefaultStandaloneEnabler()->CreateInstance();
+ EXPECT_TRUE(structInstance.IsValid());
+ ecValue.SetDouble(22.2);
+ (*structInstance).SetInternalValue("DoubleProperty", ecValue);
+ ecValue.SetUtf8CP("TS1-Init");
+ (*structInstance).SetInternalValue("StringProperty", ecValue);
+ ecValue.SetStruct(structInstance.get());
+ (*testInstance).SetInternalValue("StructArrayProp", ecValue, 0);
+
+ // Test for expected JSON parse errors
+ ParseJsonString(nullptr, ERROR);
+ ParseJsonString("", ERROR);
+ ParseJsonString("undefined", ERROR);
+
+ //-------------------------------------------------------------------------
+ // JSON --> entity instance with array property tests
+ //-------------------------------------------------------------------------
+
+ ParseJsonString("null");
+ EXPECT_NE(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_jsDoc, classLocater));
+ EXPECT_NE(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_rapidJson, classLocater));
+
+ ParseJsonString("{}");
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_jsDoc, classLocater));
+ {
+ ECValue intArrayProp;
+ ECValue structArrayProp;
+ IECInstancePtr structInst;
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(intArrayProp, "IntArrayProp"));
+ ASSERT_EQ(intArrayProp.GetArrayInfo().GetCount(), 3);
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(intArrayProp, "IntArrayProp", 0));
+ ASSERT_EQ(intArrayProp.GetInteger(), 9);
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(intArrayProp, "IntArrayProp", 1));
+ ASSERT_EQ(intArrayProp.GetInteger(), 16);
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(intArrayProp, "IntArrayProp", 2));
+ ASSERT_EQ(intArrayProp.GetInteger(), 25);
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(structArrayProp, "StructArrayProp"));
+ ASSERT_EQ(structArrayProp.GetArrayInfo().GetCount(), 1);
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(structArrayProp, "StructArrayProp", 0));
+ structInst = structArrayProp.GetStruct();
+ AssertDoubleValue(*structInst, "DoubleProperty", 22.2);
+ AssertStringValue(*structInst, "StringProperty", "TS1-Init");
+ }
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_rapidJson, classLocater));
+ {
+ ECValue intArrayProp;
+ ECValue structArrayProp;
+ IECInstancePtr structInst;
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(intArrayProp, "IntArrayProp"));
+ ASSERT_EQ(intArrayProp.GetArrayInfo().GetCount(), 3);
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(intArrayProp, "IntArrayProp", 0));
+ ASSERT_EQ(intArrayProp.GetInteger(), 9);
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(intArrayProp, "IntArrayProp", 1));
+ ASSERT_EQ(intArrayProp.GetInteger(), 16);
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(intArrayProp, "IntArrayProp", 2));
+ ASSERT_EQ(intArrayProp.GetInteger(), 25);
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(structArrayProp, "StructArrayProp"));
+ ASSERT_EQ(structArrayProp.GetArrayInfo().GetCount(), 1);
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(structArrayProp, "StructArrayProp", 0));
+ structInst = structArrayProp.GetStruct();
+ AssertDoubleValue(*structInst, "DoubleProperty", 22.2);
+ AssertStringValue(*structInst, "StringProperty", "TS1-Init");
+ }
+
+ ParseJsonString(Utf8Chars(u8R"*({ "IntArrayProp": null, "StructArrayProp": null })*"));
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_jsDoc, classLocater));
+ AssertEmptyArray(*testInstance, "IntArrayProp");
+ AssertEmptyArray(*testInstance, "StructArrayProp");
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_rapidJson, classLocater));
+ AssertEmptyArray(*testInstance, "IntArrayProp");
+ AssertEmptyArray(*testInstance, "StructArrayProp");
+
+ ParseJsonString(Utf8Chars(u8R"*({ "IntArrayProp": [4, 5, 6, 9, 12], "StructArrayProp": [{ "DoubleProperty": 3.41, "StringProperty": "NewVal1" }, { "DoubleProperty": 12.92, "StringProperty": null }] })*"));
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_jsDoc, classLocater));
+ {
+ ECValue intArrayProp;
+ ECValue structArrayProp;
+ IECInstancePtr structInst;
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(intArrayProp, "IntArrayProp"));
+ ASSERT_EQ(intArrayProp.GetArrayInfo().GetCount(), 5);
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(intArrayProp, "IntArrayProp", 0));
+ ASSERT_EQ(intArrayProp.GetInteger(), 4);
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(intArrayProp, "IntArrayProp", 1));
+ ASSERT_EQ(intArrayProp.GetInteger(), 5);
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(intArrayProp, "IntArrayProp", 2));
+ ASSERT_EQ(intArrayProp.GetInteger(), 6);
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(intArrayProp, "IntArrayProp", 3));
+ ASSERT_EQ(intArrayProp.GetInteger(), 9);
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(intArrayProp, "IntArrayProp", 4));
+ ASSERT_EQ(intArrayProp.GetInteger(), 12);
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(structArrayProp, "StructArrayProp"));
+ ASSERT_EQ(structArrayProp.GetArrayInfo().GetCount(), 2);
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(structArrayProp, "StructArrayProp", 0));
+ structInst = structArrayProp.GetStruct();
+ AssertDoubleValue(*structInst, "DoubleProperty", 3.41);
+ AssertStringValue(*structInst, "StringProperty", "NewVal1");
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(structArrayProp, "StructArrayProp", 1));
+ structInst = structArrayProp.GetStruct();
+ AssertDoubleValue(*structInst, "DoubleProperty", 12.92);
+ AssertNullValue(*structInst, "StringProperty");
+ }
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_rapidJson, classLocater));
+ {
+ ECValue intArrayProp;
+ ECValue structArrayProp;
+ IECInstancePtr structInst;
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(intArrayProp, "IntArrayProp"));
+ ASSERT_EQ(intArrayProp.GetArrayInfo().GetCount(), 5);
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(intArrayProp, "IntArrayProp", 0));
+ ASSERT_EQ(intArrayProp.GetInteger(), 4);
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(intArrayProp, "IntArrayProp", 1));
+ ASSERT_EQ(intArrayProp.GetInteger(), 5);
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(intArrayProp, "IntArrayProp", 2));
+ ASSERT_EQ(intArrayProp.GetInteger(), 6);
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(intArrayProp, "IntArrayProp", 3));
+ ASSERT_EQ(intArrayProp.GetInteger(), 9);
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(intArrayProp, "IntArrayProp", 4));
+ ASSERT_EQ(intArrayProp.GetInteger(), 12);
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(structArrayProp, "StructArrayProp"));
+ ASSERT_EQ(structArrayProp.GetArrayInfo().GetCount(), 2);
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(structArrayProp, "StructArrayProp", 0));
+ structInst = structArrayProp.GetStruct();
+ AssertDoubleValue(*structInst, "DoubleProperty", 3.41);
+ AssertStringValue(*structInst, "StringProperty", "NewVal1");
+ ASSERT_EQ(ECObjectsStatus::Success, (*testInstance).GetValue(structArrayProp, "StructArrayProp", 1));
+ structInst = structArrayProp.GetStruct();
+ AssertDoubleValue(*structInst, "DoubleProperty", 12.92);
+ AssertNullValue(*structInst, "StringProperty");
+ }
+
+ ParseJsonString(Utf8Chars(u8R"*({ "IntArrayProp": [], "StructArrayProp": [] })*"));
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_jsDoc, classLocater));
+ AssertEmptyArray(*testInstance, "IntArrayProp");
+ AssertEmptyArray(*testInstance, "StructArrayProp");
+ EXPECT_EQ(SUCCESS, JsonECInstanceConverter::JsonToECInstance(*testInstance, m_rapidJson, classLocater));
+ AssertEmptyArray(*testInstance, "IntArrayProp");
+ AssertEmptyArray(*testInstance, "StructArrayProp");
+ }
+
END_BENTLEY_ECN_TEST_NAMESPACE
\ No newline at end of file