Skip to content

Commit a943835

Browse files
alexvruadameat
authored andcommitted
Introduce strategy test KIKIMR-20527 (ydb-platform#779)
1 parent a3417ae commit a943835

File tree

4 files changed

+223
-0
lines changed

4 files changed

+223
-0
lines changed

ydb/core/blobstorage/dsproxy/log_acc.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ namespace NKikimr {
7373
const TString RequestPrefix;
7474
const NKikimrServices::EServiceKikimr LogComponent;
7575
TLogAccumulator LogAcc;
76+
bool SuppressLog = false;
7677

7778
TLogContext(NKikimrServices::EServiceKikimr logComponent, bool logAccEnabled)
7879
: RequestPrefix(Sprintf("[%016" PRIx64 "]", TAppData::RandomProvider->GenRand64()))
@@ -142,6 +143,9 @@ namespace NKikimr {
142143
#define A_LOG_LOG_SX(logCtx, isRelease, priority, marker, stream) \
143144
do { \
144145
auto& lc = (logCtx); \
146+
if (lc.SuppressLog) { \
147+
break; \
148+
} \
145149
A_LOG_LOG_S_IMPL(isRelease, lc.LogAcc, priority, lc.LogComponent, \
146150
lc.RequestPrefix << " " << stream << " Marker# " << marker); \
147151
} while (false)
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
#include <ydb/core/blobstorage/dsproxy/dsproxy_blackboard.h>
2+
#include <ydb/core/blobstorage/dsproxy/dsproxy_strategy_restore.h>
3+
#include <library/cpp/testing/unittest/registar.h>
4+
#include <util/stream/null.h>
5+
6+
using namespace NActors;
7+
using namespace NKikimr;
8+
9+
#define Ctest Cnull
10+
11+
class TGroupModel {
12+
TBlobStorageGroupInfo& Info;
13+
14+
struct TNotYet {};
15+
16+
struct TDiskState {
17+
bool InErrorState = false;
18+
std::map<TLogoBlobID, std::variant<TNotYet, TRope>> Blobs;
19+
};
20+
21+
std::vector<TDiskState> DiskStates;
22+
23+
public:
24+
TGroupModel(TBlobStorageGroupInfo& info)
25+
: Info(info)
26+
, DiskStates(Info.GetTotalVDisksNum())
27+
{
28+
for (auto& disk : DiskStates) {
29+
disk.InErrorState = RandomNumber(2 * DiskStates.size()) == 0;
30+
}
31+
}
32+
33+
TBlobStorageGroupInfo::TGroupVDisks GetFailedDisks() const {
34+
TBlobStorageGroupInfo::TGroupVDisks res = &Info.GetTopology();
35+
for (ui32 i = 0; i < DiskStates.size(); ++i) {
36+
if (DiskStates[i].InErrorState) {
37+
res |= {&Info.GetTopology(), Info.GetVDiskId(i)};
38+
}
39+
}
40+
return res;
41+
}
42+
43+
void ProcessBlackboardRequests(TBlackboard& blackboard) {
44+
for (ui32 i = 0; i < blackboard.GroupDiskRequests.DiskRequestsForOrderNumber.size(); ++i) {
45+
auto& r = blackboard.GroupDiskRequests.DiskRequestsForOrderNumber[i];
46+
Y_ABORT_UNLESS(i < DiskStates.size());
47+
auto& disk = DiskStates[i];
48+
for (auto& get : r.GetsToSend) {
49+
Ctest << "orderNumber# " << i << " get Id# " << get.Id;
50+
if (disk.InErrorState) {
51+
Ctest << " ERROR";
52+
blackboard.AddErrorResponse(get.Id, i);
53+
} else if (auto it = disk.Blobs.find(get.Id); it == disk.Blobs.end()) {
54+
Ctest << " NODATA";
55+
blackboard.AddNoDataResponse(get.Id, i);
56+
} else {
57+
std::visit(TOverloaded{
58+
[&](TNotYet&) {
59+
Ctest << " NOT_YET";
60+
blackboard.AddNotYetResponse(get.Id, i);
61+
},
62+
[&](TRope& buffer) {
63+
Ctest << " OK";
64+
size_t begin = Min<size_t>(get.Shift, buffer.size());
65+
size_t end = Min<size_t>(buffer.size(), begin + get.Size);
66+
TRope data(buffer.begin() + begin, buffer.begin() + end);
67+
blackboard.AddResponseData(get.Id, i, get.Shift, std::move(data));
68+
}
69+
}, it->second);
70+
}
71+
Ctest << Endl;
72+
}
73+
r.GetsToSend.clear();
74+
for (auto& put : r.PutsToSend) {
75+
Ctest << "orderNumber# " << i << " put Id# " << put.Id;
76+
if (disk.InErrorState) {
77+
Ctest << " ERROR";
78+
blackboard.AddErrorResponse(put.Id, i);
79+
} else {
80+
Ctest << " OK";
81+
disk.Blobs[put.Id] = std::move(put.Buffer);
82+
blackboard.AddPutOkResponse(put.Id, i);
83+
}
84+
Ctest << Endl;
85+
}
86+
r.PutsToSend.clear();
87+
}
88+
}
89+
};
90+
91+
template<typename T>
92+
void RunStrategyTest(TBlobStorageGroupType type) {
93+
TBlobStorageGroupInfo info(type);
94+
info.Ref();
95+
TGroupQueues groupQueues(info.GetTopology());
96+
groupQueues.Ref();
97+
98+
std::unordered_map<TString, std::tuple<EStrategyOutcome, TString>> transitions;
99+
100+
for (ui32 iter = 0; iter < 1'000'000; ++iter) {
101+
Ctest << "iteration# " << iter << Endl;
102+
103+
TBlackboard blackboard(&info, &groupQueues, NKikimrBlobStorage::UserData, NKikimrBlobStorage::FastRead);
104+
TString data(1000, 'x');
105+
TLogoBlobID id(1'000'000'000, 1, 1, 0, data.size(), 0);
106+
std::vector<TRope> parts(type.TotalPartCount());
107+
ErasureSplit(TBlobStorageGroupType::CrcModeNone, type, TRope(data), parts);
108+
blackboard.RegisterBlobForPut(id);
109+
for (ui32 i = 0; i < parts.size(); ++i) {
110+
blackboard.AddPartToPut(id, i, TRope(parts[i]));
111+
}
112+
blackboard[id].Whole.Data.Write(0, TRope(data));
113+
114+
TLogContext logCtx(NKikimrServices::BS_PROXY, false);
115+
logCtx.SuppressLog = true;
116+
117+
TGroupModel model(info);
118+
119+
auto sureFailedDisks = model.GetFailedDisks();
120+
auto failedDisks = sureFailedDisks;
121+
122+
auto& state = blackboard[id];
123+
for (ui32 idxInSubgroup = 0; idxInSubgroup < type.BlobSubgroupSize(); ++idxInSubgroup) {
124+
for (ui32 partIdx = 0; partIdx < type.TotalPartCount(); ++partIdx) {
125+
if (!type.PartFits(partIdx + 1, idxInSubgroup)) {
126+
continue;
127+
}
128+
const ui32 orderNumber = state.Disks[idxInSubgroup].OrderNumber;
129+
const TLogoBlobID partId(id, partIdx + 1);
130+
auto& item = state.Disks[idxInSubgroup].DiskParts[partIdx];
131+
TBlobStorageGroupInfo::TGroupVDisks diskMask = {&info.GetTopology(), info.GetVDiskId(orderNumber)};
132+
if (sureFailedDisks & diskMask) {
133+
if (RandomNumber(5u) == 0) {
134+
blackboard.AddErrorResponse(partId, orderNumber);
135+
}
136+
} else {
137+
switch (RandomNumber(100u)) {
138+
case 0:
139+
blackboard.AddErrorResponse(partId, orderNumber);
140+
break;
141+
142+
case 1:
143+
blackboard.AddNoDataResponse(partId, orderNumber);
144+
break;
145+
146+
case 2:
147+
blackboard.AddNotYetResponse(partId, orderNumber);
148+
break;
149+
150+
case 3:
151+
blackboard.AddResponseData(partId, orderNumber, 0, TRope(parts[partIdx]));
152+
break;
153+
}
154+
}
155+
if (item.Situation == TBlobState::ESituation::Error) {
156+
failedDisks |= diskMask;
157+
}
158+
}
159+
}
160+
161+
Ctest << "initial state# " << state.ToString() << Endl;
162+
163+
for (;;) {
164+
T strategy;
165+
166+
TString state = blackboard[id].ToString();
167+
168+
auto outcome = blackboard.RunStrategy(logCtx, strategy);
169+
170+
TString nextState = blackboard[id].ToString();
171+
if (const auto [it, inserted] = transitions.try_emplace(state, std::make_tuple(outcome, nextState)); !inserted) {
172+
Y_ABORT_UNLESS(it->second == std::make_tuple(outcome, nextState));
173+
}
174+
175+
if (outcome == EStrategyOutcome::IN_PROGRESS) {
176+
auto temp = blackboard.RunStrategy(logCtx, strategy);
177+
UNIT_ASSERT_EQUAL(temp, outcome);
178+
UNIT_ASSERT_VALUES_EQUAL(blackboard[id].ToString(), nextState);
179+
}
180+
181+
if (outcome == EStrategyOutcome::DONE) {
182+
Y_ABORT_UNLESS(info.GetQuorumChecker().CheckFailModelForGroup(sureFailedDisks));
183+
break;
184+
} else if (outcome == EStrategyOutcome::ERROR) {
185+
Y_ABORT_UNLESS(!info.GetQuorumChecker().CheckFailModelForGroup(failedDisks));
186+
break;
187+
} else if (outcome != EStrategyOutcome::IN_PROGRESS) {
188+
Y_ABORT("unexpected EStrategyOutcome");
189+
}
190+
191+
model.ProcessBlackboardRequests(blackboard);
192+
}
193+
}
194+
}
195+
196+
Y_UNIT_TEST_SUITE(DSProxyStrategyTest) {
197+
198+
Y_UNIT_TEST(Restore_block42) {
199+
RunStrategyTest<TRestoreStrategy>(TBlobStorageGroupType::Erasure4Plus2Block);
200+
}
201+
202+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
UNITTEST()
2+
3+
TIMEOUT(600)
4+
SIZE(MEDIUM)
5+
6+
PEERDIR(
7+
ydb/core/blobstorage/dsproxy
8+
)
9+
10+
YQL_LAST_ABI_VERSION()
11+
12+
SRCS(
13+
strategy_ut.cpp
14+
)
15+
16+
END()

ydb/core/blobstorage/dsproxy/ya.make

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,5 @@ RECURSE_FOR_TESTS(
7979
ut
8080
ut_fat
8181
ut_ftol
82+
ut_strategy
8283
)

0 commit comments

Comments
 (0)