1
0
mirror of https://github.com/apple/foundationdb.git synced 2025-05-25 17:00:05 +08:00

Add some correctness tests

This commit is contained in:
A.J. Beamon 2020-05-04 10:15:18 -07:00
parent bb3d4b6b89
commit 80a235aa80
7 changed files with 323 additions and 1 deletions

@ -308,6 +308,9 @@ public:
UniqueOrderedOptionList<FDBTransactionOptions> transactionDefaults;
std::shared_ptr<SpecialKeySpace> specialKeySpace;
std::shared_ptr<ConflictingKeysImpl> cKImpl;
static bool debugUseTags;
static const std::vector<std::string> debugTransactionTagChoices;
};
#endif

@ -2118,9 +2118,41 @@ Future<Standalone<RangeResultRef>> getRange( Database const& cx, Future<Version>
return getRange(cx, Reference<TransactionLogInfo>(), fVersion, begin, end, limits, Promise<std::pair<Key, Key>>(), true, reverse, info, tags);
}
bool DatabaseContext::debugUseTags = true;
const std::vector<std::string> DatabaseContext::debugTransactionTagChoices = { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t" };
void debugAddTags(Transaction *tr) {
int numTags = deterministicRandom()->randomInt(0, 11);
for(int i = 0; i < numTags; ++i) {
TransactionTag tag;
if(deterministicRandom()->random01() < 0.7) {
tag = TransactionTagRef(deterministicRandom()->randomChoice(DatabaseContext::debugTransactionTagChoices));
}
else {
int length = deterministicRandom()->randomInt(1, CLIENT_KNOBS->MAX_TRANSACTION_TAG_LENGTH+1);
uint8_t* s = new (tag.arena()) uint8_t[length];
for(int j = 0; j < length; ++j) {
s[j] = (uint8_t)deterministicRandom()->randomInt(0, 256);
}
tag.contents() = TransactionTagRef(s, length);
}
if(deterministicRandom()->coinflip()) {
tr->options.readTags.addTag(tag);
}
tr->options.tags.addTag(tag);
}
}
Transaction::Transaction( Database const& cx )
: cx(cx), info(cx->taskID), backoff(CLIENT_KNOBS->DEFAULT_BACKOFF), committedVersion(invalidVersion), versionstampPromise(Promise<Standalone<StringRef>>()), options(cx), numErrors(0), trLogInfo(createTrLogInfoProbabilistically(cx))
{}
{
if(DatabaseContext::debugUseTags) {
debugAddTags(this);
}
}
Transaction::~Transaction() {
flushTrLogsIfEnabled();

@ -181,6 +181,7 @@ set(FDBSERVER_SRCS
workloads/StatusWorkload.actor.cpp
workloads/Storefront.actor.cpp
workloads/StreamingRead.actor.cpp
workloads/TagThrottleApi.actor.cpp
workloads/TargetedKill.actor.cpp
workloads/TaskBucketCorrectness.actor.cpp
workloads/ThreadSafety.actor.cpp

@ -0,0 +1,211 @@
/*
* TagThrottle.actor.cpp
*
* This source file is part of the FoundationDB open source project
*
* Copyright 2013-2020 Apple Inc. and the FoundationDB project authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "fdbclient/NativeAPI.actor.h"
#include "fdbclient/TagThrottle.h"
#include "fdbserver/TesterInterface.actor.h"
#include "fdbserver/workloads/workloads.actor.h"
#include "fdbrpc/simulator.h"
#include "flow/actorcompiler.h" // This must be the last #include.
struct TagThrottleApiWorkload : TestWorkload {
double testDuration;
TagThrottleApiWorkload(WorkloadContext const& wcx) : TestWorkload(wcx) {
testDuration = getOption( options, LiteralStringRef("testDuration"), 10.0 );
}
virtual std::string description() { return "TagThrottleApi"; }
virtual Future<Void> setup(Database const& cx) {
DatabaseContext::debugUseTags = true;
return Void();
}
virtual Future<Void> start(Database const& cx) {
if (this->clientId != 0) return Void();
return timeout(runThrottleApi(this, cx), testDuration, Void());
}
virtual Future<bool> check(Database const& cx) {
return true;
}
virtual void getMetrics(vector<PerfMetric>& m) {}
ACTOR Future<Void> throttleTag(Database cx, std::map<std::pair<TransactionTag, TransactionPriority>, TagThrottleInfo> *manuallyThrottledTags) {
state TransactionTag tag = TransactionTagRef(deterministicRandom()->randomChoice(DatabaseContext::debugTransactionTagChoices));
state TransactionPriority priority = deterministicRandom()->randomChoice(allTransactionPriorities);
state double rate = deterministicRandom()->random01() * 20;
state double duration = 1 + deterministicRandom()->random01() * 19;
TagSet tagSet;
tagSet.addTag(tag);
try {
wait(ThrottleApi::throttleTags(cx, tagSet, rate, duration, false, priority));
}
catch(Error &e) {
state Error err = e;
if(e.code() == error_code_too_many_tag_throttles) {
ASSERT(manuallyThrottledTags->size() >= SERVER_KNOBS->MAX_MANUAL_THROTTLED_TRANSACTION_TAGS);
return Void();
}
throw err;
}
manuallyThrottledTags->insert_or_assign(std::make_pair(tag, priority), TagThrottleInfo(tag, false, priority, rate, now() + duration, duration));
return Void();
}
ACTOR Future<Void> unthrottleTag(Database cx, std::map<std::pair<TransactionTag, TransactionPriority>, TagThrottleInfo> *manuallyThrottledTags) {
state TransactionTag tag = TransactionTagRef(deterministicRandom()->randomChoice(DatabaseContext::debugTransactionTagChoices));
TagSet tagSet;
tagSet.addTag(tag);
state bool autoThrottled = deterministicRandom()->coinflip();
TransactionPriority priority = deterministicRandom()->randomChoice(allTransactionPriorities);
state bool erased = false;
state double expiration = 0;
if(!autoThrottled) {
auto itr = manuallyThrottledTags->find(std::make_pair(tag, priority));
if(itr != manuallyThrottledTags->end()) {
expiration = itr->second.expirationTime;
erased = true;
manuallyThrottledTags->erase(itr);
}
}
bool removed = wait(ThrottleApi::unthrottleTags(cx, tagSet, autoThrottled, priority));
if(removed) {
ASSERT(erased || autoThrottled);
}
else {
ASSERT(expiration < now());
}
return Void();
}
ACTOR Future<Void> getTags(Database cx, std::map<std::pair<TransactionTag, TransactionPriority>, TagThrottleInfo> const* manuallyThrottledTags) {
state double tagLimit = SERVER_KNOBS->MAX_AUTO_THROTTLED_TRANSACTION_TAGS + SERVER_KNOBS->MAX_MANUAL_THROTTLED_TRANSACTION_TAGS + 1;
std::vector<TagThrottleInfo> tags = wait(ThrottleApi::getThrottledTags(cx, tagLimit));
ASSERT(tags.size() < tagLimit);
int manualThrottledTags = 0;
for(auto &tag : tags) {
if(!tag.autoThrottled) {
ASSERT(manuallyThrottledTags->find(std::make_pair(tag.tag, tag.priority)) != manuallyThrottledTags->end());
++manualThrottledTags;
}
}
int minManualThrottledTags = 0;
int maxManualThrottledTags = 0;
for(auto &tag : *manuallyThrottledTags) {
if(tag.second.expirationTime > now()) {
++minManualThrottledTags;
}
++maxManualThrottledTags;
}
ASSERT(manualThrottledTags >= minManualThrottledTags && manualThrottledTags <= maxManualThrottledTags);
return Void();
}
ACTOR Future<Void> unthrottleTagGroup(Database cx, std::map<std::pair<TransactionTag, TransactionPriority>, TagThrottleInfo> *manuallyThrottledTags) {
state int choice = deterministicRandom()->randomInt(0, 3);
if(choice == 0) {
bool unthrottled = wait(ThrottleApi::unthrottleAll(cx));
bool unthrottleExpected = false;
for(auto itr = manuallyThrottledTags->begin(); itr != manuallyThrottledTags->end(); ++itr) {
if(itr->second.expirationTime > now()) {
unthrottleExpected = true;
}
}
ASSERT(!unthrottleExpected || unthrottled);
manuallyThrottledTags->clear();
}
else if(choice == 1) {
bool unthrottled = wait(ThrottleApi::unthrottleManual(cx));
bool unthrottleExpected = false;
for(auto itr = manuallyThrottledTags->begin(); itr != manuallyThrottledTags->end(); ++itr) {
if(itr->second.expirationTime > now()) {
unthrottleExpected = true;
}
}
ASSERT((unthrottled && !manuallyThrottledTags->empty()) || (!unthrottled && !unthrottleExpected));
manuallyThrottledTags->clear();
}
else {
bool unthrottled = wait(ThrottleApi::unthrottleAuto(cx));
}
return Void();
}
ACTOR Future<Void> enableAutoThrottling(Database cx) {
if(deterministicRandom()->coinflip()) {
wait(ThrottleApi::enableAuto(cx, true));
if(deterministicRandom()->coinflip()) {
bool unthrottled = wait(ThrottleApi::unthrottleAuto(cx));
}
}
else {
wait(ThrottleApi::enableAuto(cx, false));
}
return Void();
}
ACTOR Future<Void> runThrottleApi(TagThrottleApiWorkload *self, Database cx) {
state std::map<std::pair<TransactionTag, TransactionPriority>, TagThrottleInfo> manuallyThrottledTags;
loop {
double delayTime = deterministicRandom()->random01() * 5;
wait(delay(delayTime));
state int action = deterministicRandom()->randomInt(0, 5);
if(action == 0) {
wait(self->throttleTag(cx, &manuallyThrottledTags));
}
else if(action == 1) {
wait(self->unthrottleTag(cx, &manuallyThrottledTags));
}
else if(action == 2) {
wait(self->getTags(cx, &manuallyThrottledTags));
}
else if(action == 3) {
wait(self->unthrottleTagGroup(cx, &manuallyThrottledTags));
}
else if(action == 4) {
wait(self->enableAutoThrottling(cx));
}
}
}
};
WorkloadFactory<TagThrottleApiWorkload> TagThrottleApiWorkloadFactory("TagThrottleApi");

@ -155,6 +155,8 @@ if(WITH_PYTHON)
add_fdb_test(TEST_FILES rare/RandomReadWriteTest.txt)
add_fdb_test(TEST_FILES rare/SwizzledLargeApiCorrectness.txt)
add_fdb_test(TEST_FILES rare/RedwoodCorrectnessBTree.txt)
add_fdb_test(TEST_FILES rare/TransactionTagApiCorrectness.txt)
add_fdb_test(TEST_FILES rare/TransactionTagSwizzledApiCorrectness.txt)
add_fdb_test(
TEST_FILES restarting/from_7.0.0/ConfigureTestRestart-1.txt

@ -0,0 +1,25 @@
testTitle=TransactionTagWithApiCorrectness
testName=ApiCorrectness
runSetup=true
clearAfterTest=true
numKeys=5000
onlyLowerCase=true
shortKeysRatio=0.5
minShortKeyLength=1
maxShortKeyLength=3
minLongKeyLength=1
maxLongKeyLength=128
minValueLength=1
maxValueLength=1000
numGets=1000
numGetRanges=100
numGetRangeSelectors=100
numGetKeys=100
numClears=100
numClearRanges=10
maxTransactionBytes=500000
randomTestDuration=120
timeout=2100
testName=TagThrottleApi
testDuration=120

@ -0,0 +1,48 @@
testTitle=TransactionTagWithSwizzledApiCorrectnessTest
testName=ApiCorrectness
runSetup=true
clearAfterTest=true
numKeys=5000
onlyLowerCase=true
shortKeysRatio=0.5
minShortKeyLength=1
maxShortKeyLength=3
minLongKeyLength=1
maxLongKeyLength=128
minValueLength=1
maxValueLength=1000
numGets=1000
numGetRanges=100
numGetRangeSelectors=100
numGetKeys=100
numClears=100
numClearRanges=10
maxTransactionBytes=500000
randomTestDuration=120
timeout=2100
testName=TagThrottleApi
testDuration=120
testName=RandomClogging
testDuration=120.0
swizzle=1
testName=Rollback
testDuration=120.0
meanDelay=10.0
testName=Attrition
testDuration=120.0
testName=Attrition
machinesToKill=10
machinesToLeave=3
reboot=true
testDuration=120.0
testName=Attrition
machinesToKill=10
machinesToLeave=3
reboot=true
testDuration=120.0