From 303ac11ed5e1da3b0eacdddae7bdb2584d259c7c Mon Sep 17 00:00:00 2001
From: Timm Fitschen <t.fitschen@indiscale.com>
Date: Fri, 17 Sep 2021 17:25:50 +0200
Subject: [PATCH] TST: tests for mixed write transactions

---
 conanfile.txt             |   2 +-
 test/test_transaction.cpp | 156 +++++++++++++++++++++++++++++++++-----
 2 files changed, 139 insertions(+), 19 deletions(-)

diff --git a/conanfile.txt b/conanfile.txt
index 76399f5..b8287f5 100644
--- a/conanfile.txt
+++ b/conanfile.txt
@@ -1,5 +1,5 @@
 [requires]
-caosdb/0.0.17
+caosdb/0.0.19
 gtest/1.11.0
 
 [generators]
diff --git a/test/test_transaction.cpp b/test/test_transaction.cpp
index 70624de..e17f719 100644
--- a/test/test_transaction.cpp
+++ b/test/test_transaction.cpp
@@ -37,6 +37,7 @@
 #include <gtest/gtest-message.h>                  // for Message
 #include <gtest/gtest-test-part.h>                // for TestPartResult
 #include <gtest/gtest_pred_impl.h>                // for AssertionResult
+#include <initializer_list>                       // for initializer_list
 #include <iostream>                               // for operator<<, endl
 #include <limits>                                 // for numeric_limits
 #include <memory>                                 // for unique_ptr, allocator
@@ -723,7 +724,7 @@ auto test_numeric_values_impl(AtomicDataType a_type) -> void {
     prop.SetValue(static_cast<S>(value));
     props_orig.push_back(prop);
     auto i_stat = insert_transaction->InsertEntity(&prop);
-    EXPECT_EQ(i_stat, StatusCode::READY);
+    EXPECT_EQ(i_stat, StatusCode::GO_ON);
     insert_transaction->ExecuteAsynchronously();
     auto t_stat = insert_transaction->WaitForIt();
     EXPECT_TRUE(t_stat.IsTerminated());
@@ -787,7 +788,7 @@ TEST_F(test_transaction, test_integer_out_of_range) {
     prop.SetValue(value);
 
     auto i_stat = insert_transaction->InsertEntity(&prop);
-    EXPECT_EQ(i_stat, StatusCode::READY);
+    EXPECT_EQ(i_stat, StatusCode::GO_ON);
 
     insert_transaction->ExecuteAsynchronously();
     auto t_stat = insert_transaction->WaitForIt();
@@ -802,22 +803,141 @@ TEST_F(test_transaction, test_integer_out_of_range) {
   }
 }
 
-// /*
-//  * test miscellaneous queries
-//  */
-// TEST_F(test_transaction, test_queries_misc) {
-//   const auto &connection =
-//       caosdb::connection::ConnectionManager::GetDefaultConnection();
-
-//   // query empty database
-//   auto query_transaction(connection->CreateTransaction());
-//   query_transaction->Query("FIND Property \"Prop *\"");
-//   query_transaction->ExecuteAsynchronously();
-//   auto t_stat = query_transaction->WaitForIt();
-//   std::cout << "status: " << t_stat.GetCode() << " // "
-//             << t_stat.GetDescription() << std::endl;
-//   EXPECT_TRUE(t_stat.GetCode() >= 0);
-// }
+/*
+ * Insert three record types in a single transaction.
+ */
+TEST_F(test_transaction, test_multi_insert_transactions) {
+  const auto &connection =
+    caosdb::connection::ConnectionManager::GetDefaultConnection();
+
+  auto insert_transaction(connection->CreateTransaction());
+
+  for (std::string name : {"RT1", "RT2", "RT3"}) {
+    Entity entity;
+    entity.SetRole(Role::RECORD_TYPE);
+    entity.SetName(name);
+    auto stat = insert_transaction->InsertEntity(&entity);
+    EXPECT_EQ(stat, StatusCode::GO_ON);
+  }
+  insert_transaction->Execute();
+  auto insert_status = insert_transaction->GetStatus();
+
+  ASSERT_TRUE(insert_status.IsTerminated());
+  ASSERT_FALSE(insert_status.IsError());
+
+  // TODO(tf) test end results
+}
+
+/*
+ * Update three record types in a single transaction.
+ */
+TEST_F(test_transaction, test_multi_update_transactions) {
+  const auto &connection =
+    caosdb::connection::ConnectionManager::GetDefaultConnection();
+
+  auto insert_transaction(connection->CreateTransaction());
+
+  for (std::string name : {"RT1", "RT2", "RT3"}) {
+    Entity entity;
+    entity.SetRole(Role::RECORD_TYPE);
+    entity.SetName(name);
+    insert_transaction->InsertEntity(&entity);
+  }
+  insert_transaction->Execute();
+
+  auto retrieve_transaction(connection->CreateTransaction());
+  for (const Entity &entity : insert_transaction->GetResultSet()) {
+    retrieve_transaction->RetrieveById(entity.GetId());
+  }
+  retrieve_transaction->Execute();
+
+  auto update_transaction(connection->CreateTransaction());
+  for (Entity entity : retrieve_transaction->GetResultSet()) {
+    entity.SetDescription("NewDescription");
+    ASSERT_EQ(update_transaction->UpdateEntity(&entity), StatusCode::GO_ON);
+  }
+  update_transaction->Execute();
+
+  auto update_status = update_transaction->GetStatus();
+
+  ASSERT_TRUE(update_status.IsTerminated());
+  ASSERT_FALSE(update_status.IsError());
+
+  // TODO(tf) test end results
+}
+
+/*
+ *
+ * Setup: Insert A, B, while A references B
+ *
+ * Complex transaction: Insert C, update A (remove reference to B, add reference
+ * to C), delete B.
+ */
+TEST_F(test_transaction, test_multi_write_transactions) {
+  const auto &connection =
+    caosdb::connection::ConnectionManager::GetDefaultConnection();
+
+  Entity entity_a;
+  Entity entity_b;
+  Entity entity_c;
+  Property reference_b;
+  Property reference_c;
+
+  // SETUP
+  entity_a.SetRole(Role::RECORD_TYPE);
+  entity_a.SetName("RTA");
+  entity_b.SetRole(Role::RECORD_TYPE);
+  entity_b.SetName("RTB");
+  reference_b.SetName("RTB");
+  entity_a.AppendProperty(reference_b);
+
+  auto insert_transaction(connection->CreateTransaction());
+  insert_transaction->InsertEntity(&entity_a);
+  insert_transaction->InsertEntity(&entity_b);
+  insert_transaction->ExecuteAsynchronously();
+  EXPECT_EQ("", insert_transaction->ResponseToString());
+  insert_transaction->WaitForIt();
+  ASSERT_TRUE(insert_transaction->GetStatus().IsTerminated());
+  ASSERT_FALSE(insert_transaction->GetStatus().IsError());
+  auto entity_a_id = insert_transaction->GetResultSet().at(0).GetId(); // entity_a
+  auto entity_b_id = insert_transaction->GetResultSet().at(1).GetId(); // entity_b
+
+  auto retrieve_transaction(connection->CreateTransaction());
+  retrieve_transaction->RetrieveById(entity_a_id);
+
+  retrieve_transaction->Execute();
+
+  // COMPLEX TRANSACTION
+  entity_c.SetRole(Role::RECORD_TYPE);
+  entity_c.SetName("RTC");
+  reference_c.SetName("RTC");
+
+  Entity entity_a_update(retrieve_transaction->GetResultSet().at(0));
+  EXPECT_EQ("", entity_a_update.ToString());
+  entity_a_update.RemoveProperty(0);
+  entity_a_update.AppendProperty(reference_c);
+
+  auto complex_transaction(connection->CreateTransaction());
+  ASSERT_EQ(complex_transaction->InsertEntity(&entity_c), StatusCode::GO_ON);
+  ASSERT_EQ(complex_transaction->DeleteById(entity_b_id), StatusCode::GO_ON);
+  ASSERT_EQ(complex_transaction->UpdateEntity(&entity_a_update),
+            StatusCode::GO_ON);
+  complex_transaction->ExecuteAsynchronously();
+  EXPECT_EQ("", complex_transaction->ResponseToString());
+  complex_transaction->WaitForIt();
+
+  EXPECT_TRUE(complex_transaction->GetStatus().IsTerminated());
+  EXPECT_FALSE(complex_transaction->GetStatus().IsError());
+
+  // TODO(tf) test end results
+  retrieve_transaction = connection->CreateTransaction();
+  ASSERT_EQ(retrieve_transaction->RetrieveById(entity_a_update.GetId()),
+            StatusCode::GO_ON);
+  retrieve_transaction->ExecuteAsynchronously();
+  EXPECT_EQ("", retrieve_transaction->ResponseToString());
+  retrieve_transaction->WaitForIt();
+  EXPECT_EQ("", retrieve_transaction->GetResultSet().at(0).ToString());
+}
 
 /*
  * insert three recordtypes and the submit multiple queries in different
-- 
GitLab