/* * This file is a part of the CaosDB Project. * * Copyright (C) 2021 IndiScale GmbH <info@indiscale.com> * Copyright (C) 2021 Daniel Hornung <d.hornung@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/>. */ #include "caosdb/connection.h" // for Connection, Connec... #include "caosdb/data_type.h" // for AtomicDataType #include "caosdb/entity.h" // for Entity, Parent, Role #include "caosdb/transaction.h" // for Transaction, Entity #include "caosdb/transaction_status.h" // for TransactionStatus #include <cstdint> // for int32_t #include <gtest/gtest-message.h> // for Message #include <gtest/gtest-spi.h> // for EXPECT_NONFATAL_FA... #include <gtest/gtest-test-part.h> // for TestPartResult #include <gtest/gtest_pred_impl.h> // for AssertionResult #include <iostream> // for operator<<, endl #include <memory> // for unique_ptr, allocator #include <string> // for operator+, operator<< #include <vector> // for vector namespace caosdb::transaction { using caosdb::entity::AtomicDataType; using caosdb::entity::Entity; using caosdb::entity::Parent; using caosdb::entity::Role; class test_issues : public ::testing::Test { public: // public utility functions // //////////////////////////////////////////////////////// static void DeleteEntities() { // delete all entities const auto &connection = caosdb::connection::ConnectionManager::GetDefaultConnection(); auto query_transaction(connection->CreateTransaction()); query_transaction->Query("FIND ENTITY WITH id > 99"); query_transaction->Execute(); if (query_transaction->GetResultSet().size() > 0) { std::cout << "Cleanup: Deleting " << query_transaction->GetResultSet().size() << " entities." << std::endl; auto delete_transaction(connection->CreateTransaction()); for (const Entity &entity : query_transaction->GetResultSet()) { delete_transaction->DeleteById(entity.GetId()); } delete_transaction->Execute(); } } protected: // Fixture methods ////////////////////////////////////////////////////////// void SetUp() override { DeleteEntities(); } void TearDown() override { DeleteEntities(); } }; /* * test error-prone updates */ TEST_F(test_issues, server_issue_170) { const auto &connection = caosdb::connection::ConnectionManager::GetDefaultConnection(); // Insert original auto insert_transaction(connection->CreateTransaction()); Entity original; original.SetRole(Role::PROPERTY); original.SetName("Prop 1"); original.SetDataType(AtomicDataType::DOUBLE); insert_transaction->InsertEntity(&original); insert_transaction->ExecuteAsynchronously(); auto insert_status = insert_transaction->WaitForIt(); ASSERT_TRUE(insert_status.IsTerminated()); ASSERT_FALSE(insert_status.IsError()); const auto &insert_result_set = insert_transaction->GetResultSet(); auto id = insert_result_set.at(0).GetId(); EXPECT_FALSE(id.empty()); // Retrieve original with ID auto retrieve_transaction(connection->CreateTransaction()); retrieve_transaction->RetrieveById(id); retrieve_transaction->Execute(); auto update_entity(retrieve_transaction->GetResultSet().at(0)); // UPDATE auto update_transaction(connection->CreateTransaction()); update_entity.SetDataType(AtomicDataType::INTEGER, true); update_entity.SetValue(std::vector<int32_t>{1, 1, 2, 3, 5, 8, 13}); update_transaction->UpdateEntity(&update_entity); update_transaction->ExecuteAsynchronously(); auto update_status = update_transaction->WaitForIt(); EXPECT_TRUE(update_status.IsTerminated()); EXPECT_FALSE(update_status.IsError()); } /* * Insert a Record with a parent, which has a wrong name. * * This must result in a server error. */ TEST_F(test_issues, server_issue_171) { const auto &connection = caosdb::connection::ConnectionManager::GetDefaultConnection(); auto insert_transaction(connection->CreateTransaction()); // insert RT Entity rt; rt.SetRole(Role::RECORD_TYPE); rt.SetName("Test_RT_Name"); insert_transaction->InsertEntity(&rt); insert_transaction->ExecuteAsynchronously(); auto insert_status = insert_transaction->WaitForIt(); ASSERT_TRUE(insert_status.IsTerminated()); ASSERT_FALSE(insert_status.IsError()); const auto &insert_result_set = insert_transaction->GetResultSet(); const auto &inserted_rt = insert_result_set.at(0); // create Record with parent Entity rec; rec.SetRole(Role::RECORD); rec.SetName("TestRec"); Parent parent; parent.SetId(inserted_rt.GetId()); parent.SetName(rt.GetName() + "_wrong"); rec.AppendParent(parent); // insert Record 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()); EXPECT_NONFATAL_FAILURE({ EXPECT_TRUE(rec_insert_status.IsError()); }, "rec_insert_status.IsError"); const auto &rec_result_set = rec_transaction->GetResultSet(); const auto &inserted_rec = rec_result_set.at(0); std::cout << inserted_rec.ToString() << std::endl; } /* * Inserting a non-file property with an empty file path should work. * * The file attributes should be ignored by the server. */ TEST_F(test_issues, server_issue_174) { const auto &connection = caosdb::connection::ConnectionManager::GetDefaultConnection(); auto insert_transaction(connection->CreateTransaction()); // Create and insert RT Entity rt; rt.SetRole(Role::RECORD_TYPE); rt.SetName("Not a FILE"); rt.SetFilePath(""); insert_transaction->InsertEntity(&rt); insert_transaction->ExecuteAsynchronously(); auto insert_status = insert_transaction->WaitForIt(); ASSERT_TRUE(insert_status.IsTerminated()); // TODO(tf) Remove the EXPECT_NONFATAL_FAILURE after fixing #174. EXPECT_NONFATAL_FAILURE(EXPECT_FALSE(insert_status.IsError()), ""); } } // namespace caosdb::transaction