mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-09-20 16:50:48 +00:00
Add more tests for RWLock.
This commit is contained in:
parent
d74f72d310
commit
fc00569db6
@ -24,6 +24,39 @@ namespace DB
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
class Events
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Events() : start_time(std::chrono::steady_clock::now()) {}
|
||||||
|
|
||||||
|
void add(String && event)
|
||||||
|
{
|
||||||
|
String timepoint = std::to_string(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start_time).count());
|
||||||
|
if (timepoint.length() < 5)
|
||||||
|
timepoint.insert(0, 5 - timepoint.length(), ' ');
|
||||||
|
std::lock_guard lock{mutex};
|
||||||
|
std::cout << timepoint << " : " << event << std::endl;
|
||||||
|
events.emplace_back(std::move(event));
|
||||||
|
}
|
||||||
|
|
||||||
|
void check(const Strings & expected_events)
|
||||||
|
{
|
||||||
|
std::lock_guard lock{mutex};
|
||||||
|
EXPECT_EQ(events.size(), expected_events.size());
|
||||||
|
for (size_t i = 0; i != events.size(); ++i)
|
||||||
|
EXPECT_EQ(events[i], (i < expected_events.size() ? expected_events[i] : ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::chrono::time_point<std::chrono::steady_clock> start_time;
|
||||||
|
Strings events TSA_GUARDED_BY(mutex);
|
||||||
|
mutable std::mutex mutex;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST(Common, RWLock1)
|
TEST(Common, RWLock1)
|
||||||
{
|
{
|
||||||
/// Tests with threads require this, because otherwise
|
/// Tests with threads require this, because otherwise
|
||||||
@ -287,3 +320,200 @@ TEST(Common, RWLockNotUpgradeableWithNoQuery)
|
|||||||
|
|
||||||
read_thread.join();
|
read_thread.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(Common, RWLockWriteLockTimeoutDuringRead)
|
||||||
|
{
|
||||||
|
static auto rw_lock = RWLockImpl::create();
|
||||||
|
Events events;
|
||||||
|
|
||||||
|
std::thread ra_thread([&] ()
|
||||||
|
{
|
||||||
|
events.add("Locking ra");
|
||||||
|
auto ra = rw_lock->getLock(RWLockImpl::Read, "ra");
|
||||||
|
events.add(ra ? "Locked ra" : "Failed to lock ra");
|
||||||
|
EXPECT_NE(ra, nullptr);
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(std::chrono::duration<int, std::milli>(400));
|
||||||
|
|
||||||
|
events.add("Unlocking ra");
|
||||||
|
ra.reset();
|
||||||
|
events.add("Unlocked ra");
|
||||||
|
});
|
||||||
|
|
||||||
|
std::thread wc_thread([&] ()
|
||||||
|
{
|
||||||
|
std::this_thread::sleep_for(std::chrono::duration<int, std::milli>(100));
|
||||||
|
events.add("Locking wc");
|
||||||
|
auto wc = rw_lock->getLock(RWLockImpl::Write, "wc", std::chrono::milliseconds(200));
|
||||||
|
events.add(wc ? "Locked wc" : "Failed to lock wc");
|
||||||
|
EXPECT_EQ(wc, nullptr);
|
||||||
|
});
|
||||||
|
|
||||||
|
ra_thread.join();
|
||||||
|
wc_thread.join();
|
||||||
|
|
||||||
|
{
|
||||||
|
events.add("Locking wd");
|
||||||
|
auto wd = rw_lock->getLock(RWLockImpl::Write, "wd", std::chrono::milliseconds(1000));
|
||||||
|
events.add(wd ? "Locked wd" : "Failed to lock wd");
|
||||||
|
EXPECT_NE(wd, nullptr);
|
||||||
|
events.add("Unlocking wd");
|
||||||
|
wd.reset();
|
||||||
|
events.add("Unlocked wd");
|
||||||
|
}
|
||||||
|
|
||||||
|
events.check(
|
||||||
|
{"Locking ra",
|
||||||
|
"Locked ra",
|
||||||
|
"Locking wc",
|
||||||
|
"Failed to lock wc",
|
||||||
|
"Unlocking ra",
|
||||||
|
"Unlocked ra",
|
||||||
|
"Locking wd",
|
||||||
|
"Locked wd",
|
||||||
|
"Unlocking wd",
|
||||||
|
"Unlocked wd"});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(Common, RWLockWriteLockTimeoutDuringTwoReads)
|
||||||
|
{
|
||||||
|
static auto rw_lock = RWLockImpl::create();
|
||||||
|
Events events;
|
||||||
|
|
||||||
|
std::thread ra_thread([&] ()
|
||||||
|
{
|
||||||
|
events.add("Locking ra");
|
||||||
|
auto ra = rw_lock->getLock(RWLockImpl::Read, "ra");
|
||||||
|
events.add(ra ? "Locked ra" : "Failed to lock ra");
|
||||||
|
EXPECT_NE(ra, nullptr);
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(std::chrono::duration<int, std::milli>(400));
|
||||||
|
|
||||||
|
events.add("Unlocking ra");
|
||||||
|
ra.reset();
|
||||||
|
events.add("Unlocked ra");
|
||||||
|
});
|
||||||
|
|
||||||
|
std::thread rb_thread([&] ()
|
||||||
|
{
|
||||||
|
std::this_thread::sleep_for(std::chrono::duration<int, std::milli>(200));
|
||||||
|
events.add("Locking rb");
|
||||||
|
|
||||||
|
auto rb = rw_lock->getLock(RWLockImpl::Read, "rb");
|
||||||
|
events.add(rb ? "Locked rb" : "Failed to lock rb");
|
||||||
|
EXPECT_NE(rb, nullptr);
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(std::chrono::duration<int, std::milli>(200));
|
||||||
|
events.add("Unlocking rb");
|
||||||
|
rb.reset();
|
||||||
|
events.add("Unlocked rb");
|
||||||
|
});
|
||||||
|
|
||||||
|
std::thread wc_thread([&] ()
|
||||||
|
{
|
||||||
|
std::this_thread::sleep_for(std::chrono::duration<int, std::milli>(100));
|
||||||
|
events.add("Locking wc");
|
||||||
|
auto wc = rw_lock->getLock(RWLockImpl::Write, "wc", std::chrono::milliseconds(200));
|
||||||
|
events.add(wc ? "Locked wc" : "Failed to lock wc");
|
||||||
|
EXPECT_EQ(wc, nullptr);
|
||||||
|
});
|
||||||
|
|
||||||
|
ra_thread.join();
|
||||||
|
rb_thread.join();
|
||||||
|
wc_thread.join();
|
||||||
|
|
||||||
|
{
|
||||||
|
events.add("Locking wd");
|
||||||
|
auto wd = rw_lock->getLock(RWLockImpl::Write, "wd", std::chrono::milliseconds(1000));
|
||||||
|
events.add(wd ? "Locked wd" : "Failed to lock wd");
|
||||||
|
EXPECT_NE(wd, nullptr);
|
||||||
|
events.add("Unlocking wd");
|
||||||
|
wd.reset();
|
||||||
|
events.add("Unlocked wd");
|
||||||
|
}
|
||||||
|
|
||||||
|
events.check(
|
||||||
|
{"Locking ra",
|
||||||
|
"Locked ra",
|
||||||
|
"Locking wc",
|
||||||
|
"Locking rb",
|
||||||
|
"Failed to lock wc",
|
||||||
|
"Locked rb",
|
||||||
|
"Unlocking ra",
|
||||||
|
"Unlocked ra",
|
||||||
|
"Unlocking rb",
|
||||||
|
"Unlocked rb",
|
||||||
|
"Locking wd",
|
||||||
|
"Locked wd",
|
||||||
|
"Unlocking wd",
|
||||||
|
"Unlocked wd"});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(Common, RWLockWriteLockTimeoutDuringWriteWithWaitingRead)
|
||||||
|
{
|
||||||
|
static auto rw_lock = RWLockImpl::create();
|
||||||
|
Events events;
|
||||||
|
|
||||||
|
std::thread wa_thread([&] ()
|
||||||
|
{
|
||||||
|
events.add("Locking wa");
|
||||||
|
auto wa = rw_lock->getLock(RWLockImpl::Write, "wa");
|
||||||
|
events.add(wa ? "Locked wa" : "Failed to lock wa");
|
||||||
|
EXPECT_NE(wa, nullptr);
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(std::chrono::duration<int, std::milli>(500));
|
||||||
|
|
||||||
|
events.add("Unlocking wa");
|
||||||
|
wa.reset();
|
||||||
|
events.add("Unlocked wa");
|
||||||
|
});
|
||||||
|
|
||||||
|
std::thread wb_thread([&] ()
|
||||||
|
{
|
||||||
|
std::this_thread::sleep_for(std::chrono::duration<int, std::milli>(100));
|
||||||
|
events.add("Locking wb");
|
||||||
|
auto wc = rw_lock->getLock(RWLockImpl::Write, "wc", std::chrono::milliseconds(200));
|
||||||
|
events.add(wc ? "Locked wb" : "Failed to lock wb");
|
||||||
|
EXPECT_EQ(wc, nullptr);
|
||||||
|
});
|
||||||
|
|
||||||
|
std::thread rc_thread([&] ()
|
||||||
|
{
|
||||||
|
std::this_thread::sleep_for(std::chrono::duration<int, std::milli>(200));
|
||||||
|
events.add("Locking rc");
|
||||||
|
auto rc = rw_lock->getLock(RWLockImpl::Read, "rc", std::chrono::milliseconds(200));
|
||||||
|
events.add(rc ? "Locked rc" : "Failed to lock rc");
|
||||||
|
EXPECT_EQ(rc, nullptr);
|
||||||
|
});
|
||||||
|
|
||||||
|
wa_thread.join();
|
||||||
|
wb_thread.join();
|
||||||
|
rc_thread.join();
|
||||||
|
|
||||||
|
{
|
||||||
|
events.add("Locking wd");
|
||||||
|
auto wd = rw_lock->getLock(RWLockImpl::Write, "wd", std::chrono::milliseconds(1000));
|
||||||
|
events.add(wd ? "Locked wd" : "Failed to lock wd");
|
||||||
|
EXPECT_NE(wd, nullptr);
|
||||||
|
events.add("Unlocking wd");
|
||||||
|
wd.reset();
|
||||||
|
events.add("Unlocked wd");
|
||||||
|
}
|
||||||
|
|
||||||
|
events.check(
|
||||||
|
{"Locking wa",
|
||||||
|
"Locked wa",
|
||||||
|
"Locking wb",
|
||||||
|
"Locking rc",
|
||||||
|
"Failed to lock wb",
|
||||||
|
"Failed to lock rc",
|
||||||
|
"Unlocking wa",
|
||||||
|
"Unlocked wa",
|
||||||
|
"Locking wd",
|
||||||
|
"Locked wd",
|
||||||
|
"Unlocking wd",
|
||||||
|
"Unlocked wd"});
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user