/* * 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/>. */ #include "caosdb/configuration.h" // for InsecureConnectionConfig... #include "caosdb/connection.h" // for Connection #include "caosdb/entity.h" // for Entity #include "caosdb/entity/v1alpha1/main.pb.h" // for Entity #include "caosdb/exceptions.h" // for ConnectionError #include "caosdb/status_code.h" #include "caosdb/transaction.h" // for Transaction, UniqueResult #include "caosdb/transaction_status.h" // for ConnectionError #include "caosdb_test_utility.h" // for EXPECT_THROW_MESSAGE #include "gtest/gtest-message.h" // for Message #include "gtest/gtest-test-part.h" // for SuiteApiResolver, TestPa... #include "gtest/gtest_pred_impl.h" // for Test, TestInfo, TEST #include <memory> // for allocator, unique_ptr #include <string> // for string, basic_string #include <utility> // for move #include <vector> // for vector namespace caosdb::transaction { using caosdb::configuration::InsecureConnectionConfiguration; using caosdb::connection::Connection; using caosdb::exceptions::ConnectionError; using caosdb::transaction::UniqueResult; using ProtoEntity = caosdb::entity::v1alpha1::Entity; using caosdb::entity::v1alpha1::RetrieveResponse; TEST(test_transaction, create_transaction) { const auto *host = "localhost"; auto configuration = InsecureConnectionConfiguration(host, 8000); Connection connection(configuration); auto transaction = connection.CreateTransaction(); ASSERT_EQ(StatusCode::GO_ON, transaction->RetrieveById("100")); EXPECT_THROW_MESSAGE( transaction->Execute(), ConnectionError, "The attempt to execute this transaction was not successful because the " "connection to the server could not be established."); } TEST(test_transaction, unique_result) { auto *entity = new ProtoEntity(); entity->set_id("test"); UniqueResult result(entity); EXPECT_EQ("test", result.GetEntity().GetId()); // DON'T DELETE! The caosdb::entity::Entity takes care of that // Try it yourself: // delete entity; } TEST(test_transaction, test_unavailable) { const auto *host = "localhost"; auto configuration = InsecureConnectionConfiguration(host, 8000); Connection connection(configuration); auto transaction = connection.CreateTransaction(); transaction->RetrieveById("100"); transaction->ExecuteAsynchronously(); EXPECT_EQ(transaction->GetRequestCount(), 1); auto status = transaction->WaitForIt(); EXPECT_EQ(status.GetCode(), StatusCode::CONNECTION_ERROR); } TEST(test_transaction, test_retrieve_by_ids) { const auto *host = "localhost"; auto configuration = InsecureConnectionConfiguration(host, 8000); Connection connection(configuration); auto transaction = connection.CreateTransaction(); std::vector<std::string> ids = {"100", "101", "102"}; transaction->RetrieveById(ids.begin(), ids.end()); EXPECT_EQ(transaction->GetRequestCount(), 3); } TEST(test_transaction, test_multi_result_set_empty) { std::vector<std::unique_ptr<Entity>> empty; MultiResultSet rs(std::move(empty)); EXPECT_EQ(rs.Size(), 0); } TEST(test_transaction, test_multi_result_iterator) { std::vector<std::unique_ptr<Entity>> one_elem; RetrieveResponse response; response.mutable_entity()->set_id("100"); one_elem.push_back(std::make_unique<Entity>(response.release_entity())); MultiResultSet rs(std::move(one_elem)); EXPECT_EQ(rs.Size(), 1); for (const Entity &entity : rs) { EXPECT_EQ(entity.GetId(), "100"); } } TEST(test_transaction, test_unique_result_iterator) { caosdb::entity::v1alpha1::Entity response; response.set_id("100"); UniqueResult rs(&response); EXPECT_EQ(rs.Size(), 1); for (const Entity &entity : rs) { EXPECT_EQ(entity.GetId(), "100"); } } TEST(test_transaction, test_multi_result_set_one) { std::vector<std::unique_ptr<Entity>> one_elem; RetrieveResponse response; response.mutable_entity()->set_id("100"); one_elem.push_back(std::make_unique<Entity>(response.release_entity())); MultiResultSet rs(std::move(one_elem)); EXPECT_EQ(rs.Size(), 1); EXPECT_EQ(rs.At(0).GetId(), "100"); } TEST(test_transaction, test_multi_result_set_three) { std::vector<std::unique_ptr<Entity>> three_elem; MultiTransactionResponse response; response.add_responses() ->mutable_retrieve_response() ->mutable_entity() ->set_id("100"); auto *entity_with_error = response.add_responses()->mutable_retrieve_response()->mutable_entity(); entity_with_error->set_id("101"); entity_with_error->add_errors()->set_code(1); response.add_responses() ->mutable_retrieve_response() ->mutable_entity() ->set_id("102"); auto *responses = response.mutable_responses(); std::vector<std::unique_ptr<Entity>> entities; for (auto sub_response : *responses) { three_elem.push_back(std::make_unique<Entity>( sub_response.mutable_retrieve_response()->release_entity())); } MultiResultSet rs(std::move(three_elem)); EXPECT_EQ(rs.Size(), 3); EXPECT_TRUE(rs.At(1).HasErrors()); } TEST(test_transaction, test_update_entity) { const auto *host = "localhost"; auto configuration = InsecureConnectionConfiguration(host, 8000); Connection connection(configuration); auto transaction = connection.CreateTransaction(); caosdb::entity::Entity update_entity; update_entity.SetRole("New role"); auto error = transaction->UpdateEntity(&update_entity); EXPECT_EQ(error, StatusCode::ORIGINAL_ENTITY_MISSING_ID); } TEST(test_transaction, test_multi_deletion) { const auto *host = "localhost"; auto configuration = InsecureConnectionConfiguration(host, 8000); Connection connection(configuration); auto transaction = connection.CreateTransaction(); EXPECT_EQ(transaction->GetStatus().GetCode(), StatusCode::INITIAL); for (int i = 0; i < 3; i++) { auto status = transaction->DeleteById("asdf"); EXPECT_EQ(status, StatusCode::GO_ON); } } } // namespace caosdb::transaction