Skip to content
This repository was archived by the owner on Apr 17, 2019. It is now read-only.

Commit a3e6f62

Browse files
committed
StorageLimitTest
Signed-off-by: Mikhail Boldyrev <[email protected]>
1 parent 7663aa5 commit a3e6f62

File tree

2 files changed

+190
-0
lines changed

2 files changed

+190
-0
lines changed

test/module/irohad/multi_sig_transactions/CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,11 @@ target_link_libraries(mst_to_pcs_propagation_test
6666
shared_model_proto_backend
6767
test_logger
6868
)
69+
70+
AddTest(storage_limit_test storage_limit_test.cpp)
71+
target_link_libraries(storage_limit_test
72+
schema
73+
shared_model_interfaces_factories
74+
shared_model_proto_backend
75+
test_logger
76+
)
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
/**
2+
* Copyright Soramitsu Co., Ltd. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
#include "multi_sig_transactions/storage/storage_limit.hpp"
7+
8+
#include <gtest/gtest.h>
9+
#include "module/irohad/multi_sig_transactions/mst_test_helpers.hpp"
10+
#include "module/shared_model/interface_mocks.hpp"
11+
12+
using namespace iroha;
13+
using namespace testing;
14+
15+
class StorageLimitTest : public ::testing::Test {
16+
protected:
17+
std::shared_ptr<shared_model::interface::Transaction> makeTx() {
18+
return clone(txBuilder(tx_counter_++).build());
19+
}
20+
21+
std::shared_ptr<shared_model::interface::TransactionBatch> makeBatch(
22+
size_t num_txs) {
23+
shared_model::interface::types::SharedTxsCollectionType txs;
24+
std::generate_n(
25+
std::back_inserter(txs), num_txs, [this]() { return this->makeTx(); });
26+
return createMockBatchWithTransactions(txs, {});
27+
}
28+
29+
private:
30+
size_t tx_counter_{0};
31+
};
32+
33+
struct StorageImpl : public LimitableStorage {
34+
bool insert(BatchPtr batch) override {
35+
batches.emplace_back(std::move(batch));
36+
return true;
37+
}
38+
39+
std::vector<BatchPtr> batches;
40+
};
41+
42+
template <typename Limit>
43+
std::vector<std::shared_ptr<LimitedStorage<StorageImpl>>> generateStorages(
44+
std::shared_ptr<Limit> limit, size_t num_storages) {
45+
std::vector<std::shared_ptr<LimitedStorage<StorageImpl>>> storages;
46+
storages.reserve(num_storages);
47+
for (size_t i = 0; i < num_storages; ++i) {
48+
storages.emplace_back(std::make_shared<LimitedStorage<StorageImpl>>(
49+
limit, std::make_unique<StorageImpl>()));
50+
}
51+
return storages;
52+
}
53+
54+
/**
55+
* @given 5 storages with shared limit of 10 transactions
56+
* @when first a batch with 2 transactionsa batch with 2 transactions is
57+
* inserted to each storage, than a batch with single transactions is tried to
58+
* be inserted to each storage
59+
* @then first series of batches is inserted successfully and second is not
60+
*/
61+
TEST_F(StorageLimitTest, SharedLimitByTxs) {
62+
auto storages = generateStorages(std::make_shared<StorageLimitByTxs>(10), 5);
63+
64+
for (auto &storage : storages) {
65+
EXPECT_EQ(storage->batchesQuantity(), 0);
66+
EXPECT_EQ(storage->transactionsQuantity(), 0);
67+
EXPECT_TRUE(storage->insert(makeBatch(2)));
68+
EXPECT_EQ(storage->batchesQuantity(), 1);
69+
EXPECT_EQ(storage->transactionsQuantity(), 2);
70+
}
71+
72+
for (auto &storage : storages) {
73+
EXPECT_FALSE(storage->insert(makeBatch(1)));
74+
EXPECT_EQ(storage->batchesQuantity(), 1);
75+
EXPECT_EQ(storage->transactionsQuantity(), 2);
76+
}
77+
}
78+
79+
/**
80+
* @given a storage with shared limit of 10 transactions
81+
* @when another storage is created using its limit and is filled with 10
82+
* transactions, then transactions are tried to be inserted to the first storage
83+
* @then batches are not inserted to the first storage because it would violate
84+
* the shared limit
85+
*/
86+
TEST_F(StorageLimitTest, SharedLimitAddStorage) {
87+
LimitedStorage<StorageImpl> storage1{std::make_shared<StorageLimitByTxs>(10),
88+
std::make_unique<StorageImpl>()};
89+
LimitedStorage<StorageImpl> storage2{storage1.sharedLimit(),
90+
std::make_unique<StorageImpl>()};
91+
EXPECT_TRUE(storage2.insert(makeBatch(10)));
92+
EXPECT_FALSE(storage1.insert(makeBatch(1)));
93+
}
94+
95+
/**
96+
* @given 2 storages with shared limit of 10 transactions filled to limit
97+
* @when a batch with 3 transactions is removed from the first one
98+
* @then the second can accept batches with up to 3 transactions in total
99+
*/
100+
TEST_F(StorageLimitTest, SharedLimitRemoveAndAdd) {
101+
auto storages = generateStorages(std::make_shared<StorageLimitByTxs>(10), 2);
102+
EXPECT_TRUE(storages[0]->insert(makeBatch(3)));
103+
EXPECT_TRUE(storages[0]->insert(makeBatch(3)));
104+
EXPECT_TRUE(storages[1]->insert(makeBatch(4)));
105+
106+
storages[0]->extract([](auto &storage) {
107+
auto extracted_batch = std::move(*storage.batches.begin());
108+
storage.batches.erase(storage.batches.begin());
109+
return std::vector<BatchPtr>{extracted_batch};
110+
});
111+
EXPECT_EQ(storages[0]->batchesQuantity(), 1);
112+
EXPECT_EQ(storages[0]->transactionsQuantity(), 3);
113+
114+
EXPECT_TRUE(storages[1]->insert(makeBatch(1)));
115+
EXPECT_TRUE(storages[1]->insert(makeBatch(2)));
116+
EXPECT_FALSE(storages[1]->insert(makeBatch(1)));
117+
}
118+
119+
/**
120+
* @given 2 storages with shared limit of 10 transactions filled to limit
121+
* @when a batch with 3 transactions is moved from the first one
122+
* @then both storages do not accept any new batches
123+
* @and the second storage can accept the moved batch
124+
*/
125+
TEST_F(StorageLimitTest, SharedLimitMoveBatch) {
126+
auto storages = generateStorages(std::make_shared<StorageLimitByTxs>(10), 2);
127+
EXPECT_TRUE(storages[0]->insert(makeBatch(3)));
128+
EXPECT_TRUE(storages[0]->insert(makeBatch(3)));
129+
EXPECT_TRUE(storages[1]->insert(makeBatch(4)));
130+
131+
auto moved_batches = storages[0]->move([](auto &storage) {
132+
std::vector<BatchPtr> extracted_batches;
133+
extracted_batches.emplace_back(std::move(*storage.batches.begin()));
134+
storage.batches.erase(storage.batches.begin());
135+
return extracted_batches;
136+
});
137+
EXPECT_EQ(storages[0]->batchesQuantity(), 1);
138+
EXPECT_EQ(storages[0]->transactionsQuantity(), 3);
139+
140+
EXPECT_FALSE(storages[0]->insert(makeBatch(1)));
141+
EXPECT_FALSE(storages[1]->insert(makeBatch(1)));
142+
143+
ASSERT_EQ(moved_batches.size(), 1);
144+
EXPECT_TRUE(storages[1]->insert(moved_batches.front()));
145+
EXPECT_EQ(storages[1]->batchesQuantity(), 2);
146+
EXPECT_EQ(storages[1]->transactionsQuantity(), 7);
147+
148+
EXPECT_FALSE(storages[0]->insert(makeBatch(1)));
149+
EXPECT_FALSE(storages[1]->insert(makeBatch(1)));
150+
}
151+
152+
/**
153+
* @given 2 storages with shared limit of 10 transactions filled to limit
154+
* @when a batch with 3 transactions is moved from the first one and then is
155+
* destroyed without being inserted to any storage
156+
* @then both storages can accept new batches with up to 3 transactions in total
157+
*/
158+
TEST_F(StorageLimitTest, SharedLimitMovedBatchDestroyed) {
159+
auto storages = generateStorages(std::make_shared<StorageLimitByTxs>(10), 2);
160+
EXPECT_TRUE(storages[0]->insert(makeBatch(3)));
161+
EXPECT_TRUE(storages[0]->insert(makeBatch(3)));
162+
EXPECT_TRUE(storages[1]->insert(makeBatch(4)));
163+
164+
{
165+
auto moved_batches = storages[0]->move([](auto &storage) {
166+
std::vector<BatchPtr> extracted_batches;
167+
extracted_batches.emplace_back(std::move(*storage.batches.begin()));
168+
storage.batches.erase(storage.batches.begin());
169+
return extracted_batches;
170+
});
171+
EXPECT_EQ(moved_batches.size(), 1);
172+
173+
EXPECT_FALSE(storages[0]->insert(makeBatch(1)));
174+
EXPECT_FALSE(storages[1]->insert(makeBatch(1)));
175+
}
176+
177+
EXPECT_TRUE(storages[0]->insert(makeBatch(1)));
178+
EXPECT_TRUE(storages[1]->insert(makeBatch(2)));
179+
180+
EXPECT_FALSE(storages[0]->insert(makeBatch(1)));
181+
EXPECT_FALSE(storages[1]->insert(makeBatch(1)));
182+
}

0 commit comments

Comments
 (0)