about summary refs log tree commit diff homepage
path: root/unittests
diff options
context:
space:
mode:
authorDaniel Schemmel <daniel@schemmel.net>2023-03-22 22:21:41 +0000
committerCristian Cadar <c.cadar@imperial.ac.uk>2023-03-23 14:20:37 +0000
commit91468cf16fb158cd6be5eb9d9c5259f7f88bdf9a (patch)
tree97d74a5784e711754c1277b215ae8e68845ba3b8 /unittests
parent94376216f09802dd1d402b317dd703071e9a7099 (diff)
downloadklee-91468cf16fb158cd6be5eb9d9c5259f7f88bdf9a.tar.gz
Run KDAlloc/rusage unittest a few times to allow for swapfile interference
Diffstat (limited to 'unittests')
-rw-r--r--unittests/KDAlloc/rusage.cpp43
1 files changed, 25 insertions, 18 deletions
diff --git a/unittests/KDAlloc/rusage.cpp b/unittests/KDAlloc/rusage.cpp
index fa755b73..453c5e5d 100644
--- a/unittests/KDAlloc/rusage.cpp
+++ b/unittests/KDAlloc/rusage.cpp
@@ -11,7 +11,7 @@
 
 #include "gtest/gtest.h"
 
-#include <deque>
+#include <vector>
 
 #include <sys/resource.h>
 
@@ -20,7 +20,7 @@
 #if !defined(__has_feature) ||                                                 \
     (!__has_feature(memory_sanitizer) && !__has_feature(address_sanitizer))
 
-std::size_t write_to_allocations(std::deque<void *> &allocations) {
+std::size_t write_to_allocations(std::vector<void *> &allocations) {
   struct rusage ru;
   getrusage(RUSAGE_SELF, &ru);
   auto initial = ru.ru_minflt;
@@ -41,26 +41,33 @@ TEST(KDAllocTest, Rusage) {
                                           0); // 1 GB
   klee::kdalloc::Allocator allocator = factory.makeAllocator();
 
-  std::deque<void *> allocations;
+  std::vector<void *> allocations;
   for (std::size_t i = 0; i < 1000; ++i) {
-    auto p = allocator.allocate(16);
-    allocations.emplace_back(p);
+    allocations.emplace_back(allocator.allocate(16));
   }
 
-  auto pageFaults = write_to_allocations(allocations);
-
-  ASSERT_GT(pageFaults, static_cast<std::size_t>(0))
-      << "No page faults happened";
-  ASSERT_EQ(pageFaults, allocations.size())
-      << "Number of (minor) page faults and objects differs";
-
-  factory.getMapping().clear();
-
-  // try again: this should (again) trigger a minor page fault for every object
-  auto pageFaultsSecondTry = write_to_allocations(allocations);
+  // When writing to allocations we should have at least one page fault per
+  // object, but may have more due to unrelated behavior (e.g., swapping). In
+  // the hopes that such interference is relatively rare, we try a few times to
+  // encounter a perfect run, where the number of page faults matches the number
+  // of allocated objects exactly.
+  constexpr std::size_t tries = 100;
+  for (std::size_t i = 0; i < tries; ++i) {
+    auto pageFaults = write_to_allocations(allocations);
+    if (pageFaults == allocations.size()) {
+      // we have a perfect match
+      return;
+    }
+
+    ASSERT_GE(pageFaults, allocations.size())
+        << "There should be at least as many page faults as allocated objects";
+
+    factory.getMapping().clear();
+  }
 
-  ASSERT_EQ(pageFaults, pageFaultsSecondTry)
-      << "Number of minor page faults in second try differs";
+  FAIL()
+      << "No single try out of " << tries
+      << " yielded a perfect match between page faults and allocated objects";
 }
 
 #endif