Skip to content
Snippets Groups Projects
test_transaction.cpp 7.82 KiB
Newer Older
/*
 * This file is a part of the CaosDB Project.
 *
 * Copyright (C) 2021 Timm Fitschen <t.fitschen@indiscale.com>
 * Copyright (C) 2021 IndiScale GmbH <info@indiscale.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
 *
 */
Timm Fitschen's avatar
Timm Fitschen committed
#include "caosdb/connection.h"         // for Connection, ConnectionManager
#include "caosdb/entity.h"             // for Entity, Messages, Message
#include "caosdb/message_code.h"       // for ENTITY_DOES_NOT_EXIST, Messag...
#include "caosdb/status_code.h"        // for SUCCESS, StatusCode
#include "caosdb/transaction.h"        // for Entity, Transaction, UniqueRe...
#include "caosdb/transaction_status.h" // for TransactionStatus, StatusCode
#include "gtest/gtest-message.h"       // for Message
#include "gtest/gtest-test-part.h"     // for TestPartResult, SuiteApiResolver
#include "gtest/gtest_pred_impl.h"     // for Test, EXPECT_EQ, AssertionResult
florian's avatar
florian committed
#include <iostream>                     // for endl, basic_ostream, cout
Timm Fitschen's avatar
Timm Fitschen committed
#include <memory>                      // for unique_ptr, allocator, __shar...
Timm Fitschen's avatar
Timm Fitschen committed
#include <string>                      // for string

namespace caosdb::transaction {
Timm Fitschen's avatar
Timm Fitschen committed
using caosdb::entity::Entity;
Timm Fitschen's avatar
Timm Fitschen committed
using caosdb::entity::MessageCode;
using caosdb::entity::Parent;
Timm Fitschen's avatar
Timm Fitschen committed
class test_transaction : public ::testing::Test {
protected:
  void SetUp() override {}
Timm Fitschen's avatar
Timm Fitschen committed

  void TearDown() override {
    // TODO(tf): delete all created entities
  }
};

Timm Fitschen's avatar
Timm Fitschen committed
TEST(test_transaction, DISABLED_retrieve_manufacturer_by_id) {
  const auto &connection =
    caosdb::connection::ConnectionManager::GetDefaultConnection();
  const auto *id = "107";
  const auto *role = "RecordType";
  const auto *name = "Manufacturer";
  const auto *description = "A generic manufacturer of all kinds of products";
  const auto *version = "0bea8f7b17f0130fa5701a6c3849b9f8bfa0651b";

  auto transaction(connection->CreateTransaction());
  transaction->RetrieveById(id);
  transaction->Execute();

  const auto &result_set =
    dynamic_cast<const UniqueResult &>(transaction->GetResultSet());

  const auto &entity = result_set.GetEntity();
  EXPECT_EQ(id, entity.GetId());
  EXPECT_EQ(name, entity.GetName());
  EXPECT_EQ(role, entity.GetRole());
  EXPECT_EQ(description, entity.GetDescription());
Timm Fitschen's avatar
Timm Fitschen committed
  EXPECT_EQ(version, entity.GetVersionId());
Timm Fitschen's avatar
Timm Fitschen committed
TEST(test_transaction, retrieve_non_existing) {
  const auto &connection =
    caosdb::connection::ConnectionManager::GetDefaultConnection();

  auto transaction(connection->CreateTransaction());

  const auto *id = "non-existing-id";
  transaction->RetrieveById(id);
Timm Fitschen's avatar
Timm Fitschen committed
  transaction->ExecuteAsynchronously();
Timm Fitschen's avatar
Timm Fitschen committed
  auto status = transaction->WaitForIt();
Timm Fitschen's avatar
Timm Fitschen committed
  EXPECT_EQ(status.GetCode(), TransactionStatus::TRANSACTION_ERROR().GetCode());
  ASSERT_EQ(status.GetCode(), StatusCode::GENERIC_TRANSACTION_ERROR);
Timm Fitschen's avatar
Timm Fitschen committed
  const auto &result_set =
    dynamic_cast<const UniqueResult &>(transaction->GetResultSet());
Timm Fitschen's avatar
Timm Fitschen committed

  const auto &entity = result_set.GetEntity();
  EXPECT_EQ(id, entity.GetId());
  EXPECT_TRUE(entity.HasErrors());
  ASSERT_EQ(entity.GetErrors().Size(), 1);
  EXPECT_EQ(entity.GetErrors().At(0).GetCode(),
            MessageCode::ENTITY_DOES_NOT_EXIST);
florian's avatar
florian committed
// TODO(fspreck) cognitive complexity > 25 (threshold)
TEST(test_transaction, insert_delete) { // NOLINT
Timm Fitschen's avatar
Timm Fitschen committed
  const auto &connection =
    caosdb::connection::ConnectionManager::GetDefaultConnection();

Timm Fitschen's avatar
Timm Fitschen committed
  auto insert_transaction(connection->CreateTransaction());
Timm Fitschen's avatar
Timm Fitschen committed

  Entity entity;
  entity.SetRole("RecordType");
  entity.SetName("RT1");
Timm Fitschen's avatar
Timm Fitschen committed
  insert_transaction->InsertEntity(&entity);
  insert_transaction->ExecuteAsynchronously();
Timm Fitschen's avatar
Timm Fitschen committed
  auto insert_status = insert_transaction->WaitForIt();
Timm Fitschen's avatar
Timm Fitschen committed
  ASSERT_TRUE(insert_status.IsTerminated());
  ASSERT_FALSE(insert_status.IsError());
Timm Fitschen's avatar
Timm Fitschen committed
  const auto &insert_result_set =
    dynamic_cast<const UniqueResult &>(insert_transaction->GetResultSet());
Timm Fitschen's avatar
Timm Fitschen committed
  const auto &new_entity = insert_result_set.GetEntity();
Timm Fitschen's avatar
Timm Fitschen committed
  EXPECT_FALSE(new_entity.GetId().empty());
  EXPECT_FALSE(new_entity.HasErrors());
florian's avatar
florian committed
  // Should have a warning since it has no properties
  EXPECT_TRUE(new_entity.HasWarnings());
  EXPECT_EQ(new_entity.GetWarnings().Size(), 1);
Timm Fitschen's avatar
Timm Fitschen committed
  EXPECT_EQ(new_entity.GetWarnings().At(0).GetCode(),
            MessageCode::ENTITY_HAS_NO_PROPERTIES);
Timm Fitschen's avatar
Timm Fitschen committed

  auto delete_transaction(connection->CreateTransaction());

  delete_transaction->DeleteById(new_entity.GetId());
  delete_transaction->ExecuteAsynchronously();

  auto delete_status = delete_transaction->WaitForIt();

  ASSERT_TRUE(delete_status.IsTerminated());
  ASSERT_FALSE(delete_status.IsError());

  const auto &delete_result_set =
    dynamic_cast<const UniqueResult &>(delete_transaction->GetResultSet());
Timm Fitschen's avatar
Timm Fitschen committed

  const auto &deleted_entity = delete_result_set.GetEntity();
  EXPECT_EQ(deleted_entity.GetId(), new_entity.GetId());
  EXPECT_FALSE(deleted_entity.HasErrors());
// TODO(fspreck) Simplify inserts and deletes once we have
florian's avatar
florian committed
// multi-entity operations, also cognitive complexity > threshold
TEST(test_transaction, insert_delete_with_parent) { // NOLINT
florian's avatar
florian committed
  const auto &connection =
    caosdb::connection::ConnectionManager::GetDefaultConnection();

  auto insert_transaction(connection->CreateTransaction());

  Entity rt;
  rt.SetRole("RecordType");
  rt.SetName("TestRT");
  insert_transaction->InsertEntity(&rt);
florian's avatar
florian committed
  insert_transaction->ExecuteAsynchronously();

  auto insert_status = insert_transaction->WaitForIt();

  ASSERT_TRUE(insert_status.IsTerminated());
  ASSERT_FALSE(insert_status.IsError());

  const auto &insert_result_set =
    dynamic_cast<const UniqueResult &>(insert_transaction->GetResultSet());

  const auto &inserted_rt = insert_result_set.GetEntity();
  Entity rec;
  rec.SetRole("Record");
  rec.SetName("TestRec");

  Parent parent;
florian's avatar
florian committed
  parent.SetName(inserted_rt.GetName());
  parent.SetId(inserted_rt.GetId());
  rec.AppendParent(parent);

  auto rec_transaction(connection->CreateTransaction());
  rec_transaction->InsertEntity(&rec);
  rec_transaction->ExecuteAsynchronously();

  auto rec_insert_status = rec_transaction->WaitForIt();

  ASSERT_TRUE(rec_insert_status.IsTerminated());
florian's avatar
florian committed
  std::cout << rec.ToString() << std::endl;
  std::cout << rec_insert_status.GetCode() << std::endl;
  ASSERT_FALSE(rec_insert_status.IsError());

  const auto &rec_result_set =
    dynamic_cast<const UniqueResult &>(rec_transaction->GetResultSet());

  const auto &inserted_rec = rec_result_set.GetEntity();
florian's avatar
florian committed
  std::cout << inserted_rec.ToString() << std::endl;
  
  EXPECT_EQ(inserted_rec.GetName(), rec.GetName());
  EXPECT_EQ(inserted_rec.GetParents().Size(), 1);
  EXPECT_EQ(inserted_rec.GetParents().At(0).GetId(), inserted_rt.GetId());
  EXPECT_EQ(inserted_rec.GetParents().At(0).GetName(), inserted_rt.GetName());

  auto rec_deletion(connection->CreateTransaction());

  rec_deletion->DeleteById(inserted_rec.GetId());
  rec_deletion->ExecuteAsynchronously();

  auto rec_delete_status = rec_deletion->WaitForIt();

  ASSERT_TRUE(rec_delete_status.IsTerminated());
  ASSERT_FALSE(rec_delete_status.IsError());

  auto rt_deletion(connection->CreateTransaction());

  rt_deletion->DeleteById(inserted_rt.GetId());
  rt_deletion->ExecuteAsynchronously();

  auto rt_delete_status = rt_deletion->WaitForIt();

  ASSERT_TRUE(rt_delete_status.IsTerminated());
  ASSERT_FALSE(rt_delete_status.IsError());
florian's avatar
florian committed
}

// TODO(fspreck) Insert a Record with a parent and a Property. Check
// for success and delete everything.

} // namespace caosdb::transaction