This repository has been archived by the owner on Apr 17, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 297
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Mikhail Boldyrev <[email protected]>
- Loading branch information
Showing
2 changed files
with
190 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
182 changes: 182 additions & 0 deletions
182
test/module/irohad/multi_sig_transactions/storage_limit_test.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,182 @@ | ||
/** | ||
* Copyright Soramitsu Co., Ltd. All Rights Reserved. | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include "multi_sig_transactions/storage/storage_limit.hpp" | ||
|
||
#include <gtest/gtest.h> | ||
#include "module/irohad/multi_sig_transactions/mst_test_helpers.hpp" | ||
#include "module/shared_model/interface_mocks.hpp" | ||
|
||
using namespace iroha; | ||
using namespace testing; | ||
|
||
class StorageLimitTest : public ::testing::Test { | ||
protected: | ||
std::shared_ptr<shared_model::interface::Transaction> makeTx() { | ||
return clone(txBuilder(tx_counter_++).build()); | ||
} | ||
|
||
std::shared_ptr<shared_model::interface::TransactionBatch> makeBatch( | ||
size_t num_txs) { | ||
shared_model::interface::types::SharedTxsCollectionType txs; | ||
std::generate_n( | ||
std::back_inserter(txs), num_txs, [this]() { return this->makeTx(); }); | ||
return createMockBatchWithTransactions(txs, {}); | ||
} | ||
|
||
private: | ||
size_t tx_counter_{0}; | ||
}; | ||
|
||
struct StorageImpl : public LimitableStorage { | ||
bool insert(BatchPtr batch) override { | ||
batches.emplace_back(std::move(batch)); | ||
return true; | ||
} | ||
|
||
std::vector<BatchPtr> batches; | ||
}; | ||
|
||
template <typename Limit> | ||
std::vector<std::shared_ptr<LimitedStorage<StorageImpl>>> generateStorages( | ||
std::shared_ptr<Limit> limit, size_t num_storages) { | ||
std::vector<std::shared_ptr<LimitedStorage<StorageImpl>>> storages; | ||
storages.reserve(num_storages); | ||
for (size_t i = 0; i < num_storages; ++i) { | ||
storages.emplace_back(std::make_shared<LimitedStorage<StorageImpl>>( | ||
limit, std::make_unique<StorageImpl>())); | ||
} | ||
return storages; | ||
} | ||
|
||
/** | ||
* @given 5 storages with shared limit of 10 transactions | ||
* @when first a batch with 2 transactionsa batch with 2 transactions is | ||
* inserted to each storage, than a batch with single transactions is tried to | ||
* be inserted to each storage | ||
* @then first series of batches is inserted successfully and second is not | ||
*/ | ||
TEST_F(StorageLimitTest, SharedLimitByTxs) { | ||
auto storages = generateStorages(std::make_shared<StorageLimitByTxs>(10), 5); | ||
|
||
for (auto &storage : storages) { | ||
EXPECT_EQ(storage->batchesQuantity(), 0); | ||
EXPECT_EQ(storage->transactionsQuantity(), 0); | ||
EXPECT_TRUE(storage->insert(makeBatch(2))); | ||
EXPECT_EQ(storage->batchesQuantity(), 1); | ||
EXPECT_EQ(storage->transactionsQuantity(), 2); | ||
} | ||
|
||
for (auto &storage : storages) { | ||
EXPECT_FALSE(storage->insert(makeBatch(1))); | ||
EXPECT_EQ(storage->batchesQuantity(), 1); | ||
EXPECT_EQ(storage->transactionsQuantity(), 2); | ||
} | ||
} | ||
|
||
/** | ||
* @given a storage with shared limit of 10 transactions | ||
* @when another storage is created using its limit and is filled with 10 | ||
* transactions, then transactions are tried to be inserted to the first storage | ||
* @then batches are not inserted to the first storage because it would violate | ||
* the shared limit | ||
*/ | ||
TEST_F(StorageLimitTest, SharedLimitAddStorage) { | ||
LimitedStorage<StorageImpl> storage1{std::make_shared<StorageLimitByTxs>(10), | ||
std::make_unique<StorageImpl>()}; | ||
LimitedStorage<StorageImpl> storage2{storage1.sharedLimit(), | ||
std::make_unique<StorageImpl>()}; | ||
EXPECT_TRUE(storage2.insert(makeBatch(10))); | ||
EXPECT_FALSE(storage1.insert(makeBatch(1))); | ||
} | ||
|
||
/** | ||
* @given 2 storages with shared limit of 10 transactions filled to limit | ||
* @when a batch with 3 transactions is removed from the first one | ||
* @then the second can accept batches with up to 3 transactions in total | ||
*/ | ||
TEST_F(StorageLimitTest, SharedLimitRemoveAndAdd) { | ||
auto storages = generateStorages(std::make_shared<StorageLimitByTxs>(10), 2); | ||
EXPECT_TRUE(storages[0]->insert(makeBatch(3))); | ||
EXPECT_TRUE(storages[0]->insert(makeBatch(3))); | ||
EXPECT_TRUE(storages[1]->insert(makeBatch(4))); | ||
|
||
storages[0]->extract([](auto &storage) { | ||
auto extracted_batch = std::move(*storage.batches.begin()); | ||
storage.batches.erase(storage.batches.begin()); | ||
return std::vector<BatchPtr>{extracted_batch}; | ||
}); | ||
EXPECT_EQ(storages[0]->batchesQuantity(), 1); | ||
EXPECT_EQ(storages[0]->transactionsQuantity(), 3); | ||
|
||
EXPECT_TRUE(storages[1]->insert(makeBatch(1))); | ||
EXPECT_TRUE(storages[1]->insert(makeBatch(2))); | ||
EXPECT_FALSE(storages[1]->insert(makeBatch(1))); | ||
} | ||
|
||
/** | ||
* @given 2 storages with shared limit of 10 transactions filled to limit | ||
* @when a batch with 3 transactions is moved from the first one | ||
* @then both storages do not accept any new batches | ||
* @and the second storage can accept the moved batch | ||
*/ | ||
TEST_F(StorageLimitTest, SharedLimitMoveBatch) { | ||
auto storages = generateStorages(std::make_shared<StorageLimitByTxs>(10), 2); | ||
EXPECT_TRUE(storages[0]->insert(makeBatch(3))); | ||
EXPECT_TRUE(storages[0]->insert(makeBatch(3))); | ||
EXPECT_TRUE(storages[1]->insert(makeBatch(4))); | ||
|
||
auto moved_batches = storages[0]->move([](auto &storage) { | ||
std::vector<BatchPtr> extracted_batches; | ||
extracted_batches.emplace_back(std::move(*storage.batches.begin())); | ||
storage.batches.erase(storage.batches.begin()); | ||
return extracted_batches; | ||
}); | ||
EXPECT_EQ(storages[0]->batchesQuantity(), 1); | ||
EXPECT_EQ(storages[0]->transactionsQuantity(), 3); | ||
|
||
EXPECT_FALSE(storages[0]->insert(makeBatch(1))); | ||
EXPECT_FALSE(storages[1]->insert(makeBatch(1))); | ||
|
||
ASSERT_EQ(moved_batches.size(), 1); | ||
EXPECT_TRUE(storages[1]->insert(moved_batches.front())); | ||
EXPECT_EQ(storages[1]->batchesQuantity(), 2); | ||
EXPECT_EQ(storages[1]->transactionsQuantity(), 7); | ||
|
||
EXPECT_FALSE(storages[0]->insert(makeBatch(1))); | ||
EXPECT_FALSE(storages[1]->insert(makeBatch(1))); | ||
} | ||
|
||
/** | ||
* @given 2 storages with shared limit of 10 transactions filled to limit | ||
* @when a batch with 3 transactions is moved from the first one and then is | ||
* destroyed without being inserted to any storage | ||
* @then both storages can accept new batches with up to 3 transactions in total | ||
*/ | ||
TEST_F(StorageLimitTest, SharedLimitMovedBatchDestroyed) { | ||
auto storages = generateStorages(std::make_shared<StorageLimitByTxs>(10), 2); | ||
EXPECT_TRUE(storages[0]->insert(makeBatch(3))); | ||
EXPECT_TRUE(storages[0]->insert(makeBatch(3))); | ||
EXPECT_TRUE(storages[1]->insert(makeBatch(4))); | ||
|
||
{ | ||
auto moved_batches = storages[0]->move([](auto &storage) { | ||
std::vector<BatchPtr> extracted_batches; | ||
extracted_batches.emplace_back(std::move(*storage.batches.begin())); | ||
storage.batches.erase(storage.batches.begin()); | ||
return extracted_batches; | ||
}); | ||
EXPECT_EQ(moved_batches.size(), 1); | ||
|
||
EXPECT_FALSE(storages[0]->insert(makeBatch(1))); | ||
EXPECT_FALSE(storages[1]->insert(makeBatch(1))); | ||
} | ||
|
||
EXPECT_TRUE(storages[0]->insert(makeBatch(1))); | ||
EXPECT_TRUE(storages[1]->insert(makeBatch(2))); | ||
|
||
EXPECT_FALSE(storages[0]->insert(makeBatch(1))); | ||
EXPECT_FALSE(storages[1]->insert(makeBatch(1))); | ||
} |