/*
- * Copyright 2014 Facebook, Inc.
+ * Copyright 2016 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* limitations under the License.
*/
-#include "DeterministicSchedule.h"
+#include <folly/test/DeterministicSchedule.h>
-#include <gflags/gflags.h>
#include <gtest/gtest.h>
+#include <folly/portability/GFlags.h>
+
using namespace folly::test;
TEST(DeterministicSchedule, uniform) {
}
}
+TEST(DeterministicSchedule, buggyAdd) {
+ for (bool bug : {false, true}) {
+ DeterministicSchedule sched(DeterministicSchedule::uniform(0));
+ if (bug) {
+ FOLLY_TEST_DSCHED_VLOG("Test with race condition");
+ } else {
+ FOLLY_TEST_DSCHED_VLOG("Test without race condition");
+ }
+ DeterministicMutex m;
+ // The use of DeterinisticAtomic is not needed here, but it makes
+ // it easier to understand the sequence of events in logs.
+ DeterministicAtomic<int> test{0};
+ DeterministicAtomic<int> baseline{0};
+ int numThreads = 10;
+ std::vector<std::thread> threads(numThreads);
+ for (int t = 0; t < numThreads; ++t) {
+ threads[t] = DeterministicSchedule::thread([&, t] {
+ baseline.fetch_add(1);
+ // Atomic increment of test protected by mutex m
+ do {
+ // Some threads use lock() others use try_lock()
+ if ((t & 1) == 0) {
+ m.lock();
+ } else {
+ if (!m.try_lock()) {
+ continue;
+ }
+ }
+ int newval = test.load() + 1;
+ if (bug) {
+ // Break the atomicity of the increment operation
+ m.unlock();
+ m.lock();
+ }
+ test.store(newval);
+ m.unlock();
+ break;
+ } while (true);
+ }); // thread lambda
+ } // for t
+ for (auto& t : threads) {
+ DeterministicSchedule::join(t);
+ }
+ if (!bug) {
+ EXPECT_EQ(test.load(), baseline.load());
+ } else {
+ if (test.load() == baseline.load()) {
+ FOLLY_TEST_DSCHED_VLOG("Didn't catch the bug");
+ } else {
+ FOLLY_TEST_DSCHED_VLOG("Caught the bug");
+ }
+ }
+ } // for bug
+} // TEST
+
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
gflags::ParseCommandLineFlags(&argc, &argv, true);