This is an automated email from the ASF dual-hosted git repository.

masaori pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new e084750c69 Convert CacheDir regression tests into unit tests (#10635)
e084750c69 is described below

commit e084750c6943920cae0fe611d9ebf416c09d2c97
Author: Masaori Koshiba <[email protected]>
AuthorDate: Thu Oct 19 10:11:20 2023 +0900

    Convert CacheDir regression tests into unit tests (#10635)
    
    * Convert CacheDir regression tests into unit tests
    
    * Fix clang-format
    
    * Fix LOOP_CHECK_MODE
---
 src/iocore/cache/CacheDir.cc           | 217 +--------------------------
 src/iocore/cache/Makefile.am           |   8 +
 src/iocore/cache/P_CacheDir.h          |   6 +
 src/iocore/cache/test/test_CacheDir.cc | 262 +++++++++++++++++++++++++++++++++
 src/tests/CMakeLists.txt               |   1 +
 5 files changed, 278 insertions(+), 216 deletions(-)

diff --git a/src/iocore/cache/CacheDir.cc b/src/iocore/cache/CacheDir.cc
index 97e309b810..ea7ea0d732 100644
--- a/src/iocore/cache/CacheDir.cc
+++ b/src/iocore/cache/CacheDir.cc
@@ -22,12 +22,11 @@
  */
 
 #include "P_Cache.h"
+#include "P_CacheDir.h"
 
 #include "tscore/hugepages.h"
-#include "tscore/Regression.h"
 #include "tscore/Random.h"
 
-// #define LOOP_CHECK_MODE 1
 #ifdef LOOP_CHECK_MODE
 #define DIR_LOOP_THRESHOLD 1000
 #endif
@@ -1241,217 +1240,3 @@ const uint8_t CacheKey_prev_table[256] = {
   209, 247, 189, 72,  69,  238, 133, 13,  167, 31,  235, 116, 201, 190, 213, 
203, 104, 115, 12,  212, 52,  63,  149, 135, 183, 84,
   147, 163, 249, 65,  217, 174, 70,  6,   64,  90,  155, 177, 185, 182, 108, 
121, 164, 136, 58,  220, 241, 4,
 };
-
-//
-// Regression
-//
-unsigned int regress_rand_seed = 0;
-void
-regress_rand_init(unsigned int i)
-{
-  regress_rand_seed = i;
-}
-
-static void
-regress_rand_CacheKey(const CacheKey *key)
-{
-  unsigned int *x = (unsigned int *)key;
-  for (int i = 0; i < 4; i++) {
-    x[i] = next_rand(&regress_rand_seed);
-  }
-}
-
-void
-dir_corrupt_bucket(Dir *b, int s, Vol *vol)
-{
-  int l    = (static_cast<int>(dir_bucket_length(b, s, vol) * 
ts::Random::drandom()));
-  Dir *e   = b;
-  Dir *seg = vol->dir_segment(s);
-  for (int i = 0; i < l; i++) {
-    ink_release_assert(e);
-    e = next_dir(e, seg);
-  }
-  ink_release_assert(e);
-  dir_set_next(e, dir_to_offset(e, seg));
-}
-
-EXCLUSIVE_REGRESSION_TEST(Cache_dir)(RegressionTest *t, int /* atype 
ATS_UNUSED */, int *status)
-{
-  ink_hrtime ttime;
-  int ret = REGRESSION_TEST_PASSED;
-
-  if ((CacheProcessor::IsCacheEnabled() != CACHE_INITIALIZED) || gnvol < 1) {
-    rprintf(t, "cache not ready/configured");
-    *status = REGRESSION_TEST_FAILED;
-    return;
-  }
-  Vol *vol        = gvol[0];
-  EThread *thread = this_ethread();
-  MUTEX_TRY_LOCK(lock, vol->mutex, thread);
-  ink_release_assert(lock.is_locked());
-  rprintf(t, "clearing vol 0\n", free);
-  vol_dir_clear(vol);
-
-  // coverity[var_decl]
-  Dir dir;
-  dir_clear(&dir);
-  dir_set_phase(&dir, 0);
-  dir_set_head(&dir, true);
-  dir_set_offset(&dir, 1);
-
-  vol->header->agg_pos = vol->header->write_pos += 1024;
-
-  CacheKey key;
-  rand_CacheKey(&key, thread->mutex);
-
-  int s    = key.slice32(0) % vol->segments, i, j;
-  Dir *seg = vol->dir_segment(s);
-
-  // test insert
-  rprintf(t, "insert test\n", free);
-  int inserted = 0;
-  int free     = dir_freelist_length(vol, s);
-  int n        = free;
-  rprintf(t, "free: %d\n", free);
-  while (n--) {
-    if (!dir_insert(&key, vol, &dir)) {
-      break;
-    }
-    inserted++;
-  }
-  rprintf(t, "inserted: %d\n", inserted);
-  if (static_cast<unsigned int>(inserted - free) > 1) {
-    ret = REGRESSION_TEST_FAILED;
-  }
-
-  // test delete
-  rprintf(t, "delete test\n");
-  for (i = 0; i < vol->buckets; i++) {
-    for (j = 0; j < DIR_DEPTH; j++) {
-      dir_set_offset(dir_bucket_row(dir_bucket(i, seg), j), 0); // delete
-    }
-  }
-  dir_clean_segment(s, vol);
-  int newfree = dir_freelist_length(vol, s);
-  rprintf(t, "newfree: %d\n", newfree);
-  if (static_cast<unsigned int>(newfree - free) > 1) {
-    ret = REGRESSION_TEST_FAILED;
-  }
-
-  // test insert-delete
-  rprintf(t, "insert-delete test\n");
-  regress_rand_init(13);
-  ttime = ink_get_hrtime();
-  for (i = 0; i < newfree; i++) {
-    regress_rand_CacheKey(&key);
-    dir_insert(&key, vol, &dir);
-  }
-  uint64_t us = (ink_get_hrtime() - ttime) / HRTIME_USECOND;
-  // On windows us is sometimes 0. I don't know why.
-  // printout the insert rate only if its not 0
-  if (us) {
-    rprintf(t, "insert rate = %d / second\n", static_cast<int>((newfree * 
static_cast<uint64_t>(1000000)) / us));
-  }
-  regress_rand_init(13);
-  ttime = ink_get_hrtime();
-  for (i = 0; i < newfree; i++) {
-    Dir *last_collision = nullptr;
-    regress_rand_CacheKey(&key);
-    if (!dir_probe(&key, vol, &dir, &last_collision)) {
-      ret = REGRESSION_TEST_FAILED;
-    }
-  }
-  us = (ink_get_hrtime() - ttime) / HRTIME_USECOND;
-  // On windows us is sometimes 0. I don't know why.
-  // printout the probe rate only if its not 0
-  if (us) {
-    rprintf(t, "probe rate = %d / second\n", static_cast<int>((newfree * 
static_cast<uint64_t>(1000000)) / us));
-  }
-
-  for (int c = 0; c < vol->direntries() * 0.75; c++) {
-    regress_rand_CacheKey(&key);
-    dir_insert(&key, vol, &dir);
-  }
-
-  Dir dir1;
-  memset(static_cast<void *>(&dir1), 0, sizeof(dir1));
-  int s1, b1;
-
-  rprintf(t, "corrupt_bucket test\n");
-  for (int ntimes = 0; ntimes < 10; ntimes++) {
-#ifdef LOOP_CHECK_MODE
-    // dir_probe in bucket with loop
-    rand_CacheKey(&key, thread->mutex);
-    s1 = key.slice32(0) % vol->segments;
-    b1 = key.slice32(1) % vol->buckets;
-    dir_corrupt_bucket(dir_bucket(b1, vol->dir_segment(s1)), s1, vol);
-    dir_insert(&key, vol, &dir);
-    Dir *last_collision = 0;
-    dir_probe(&key, vol, &dir, &last_collision);
-
-    rand_CacheKey(&key, thread->mutex);
-    s1 = key.slice32(0) % vol->segments;
-    b1 = key.slice32(1) % vol->buckets;
-    dir_corrupt_bucket(dir_bucket(b1, vol->dir_segment(s1)), s1, vol);
-
-    last_collision = 0;
-    dir_probe(&key, vol, &dir, &last_collision);
-
-    // dir_overwrite in bucket with loop
-    rand_CacheKey(&key, thread->mutex);
-    s1 = key.slice32(0) % vol->segments;
-    b1 = key.slice32(1) % vol->buckets;
-    CacheKey key1;
-    key1.b[1] = 127;
-    dir1      = dir;
-    dir_set_offset(&dir1, 23);
-    dir_insert(&key1, vol, &dir1);
-    dir_insert(&key, vol, &dir);
-    key1.b[1] = 80;
-    dir_insert(&key1, vol, &dir1);
-    dir_corrupt_bucket(dir_bucket(b1, vol->dir_segment(s1)), s1, vol);
-    dir_overwrite(&key, vol, &dir, &dir, 1);
-
-    rand_CacheKey(&key, thread->mutex);
-    s1       = key.slice32(0) % vol->segments;
-    b1       = key.slice32(1) % vol->buckets;
-    key.b[1] = 23;
-    dir_insert(&key, vol, &dir1);
-    dir_corrupt_bucket(dir_bucket(b1, vol->dir_segment(s1)), s1, vol);
-    dir_overwrite(&key, vol, &dir, &dir, 0);
-
-    rand_CacheKey(&key, thread->mutex);
-    s1        = key.slice32(0) % vol->segments;
-    Dir *seg1 = vol->dir_segment(s1);
-    // dir_freelist_length in freelist with loop
-    dir_corrupt_bucket(dir_from_offset(vol->header->freelist[s], seg1), s1, 
vol);
-    dir_freelist_length(vol, s1);
-
-    rand_CacheKey(&key, thread->mutex);
-    s1 = key.slice32(0) % vol->segments;
-    b1 = key.slice32(1) % vol->buckets;
-    // dir_bucket_length in bucket with loop
-    dir_corrupt_bucket(dir_bucket(b1, vol->dir_segment(s1)), s1, vol);
-    dir_bucket_length(dir_bucket(b1, vol->dir_segment(s1)), s1, vol);
-    if (!check_dir(vol))
-      ret = REGRESSION_TEST_FAILED;
-#else
-    // test corruption detection
-    rand_CacheKey(&key, thread->mutex);
-    s1 = key.slice32(0) % vol->segments;
-    b1 = key.slice32(1) % vol->buckets;
-
-    dir_insert(&key, vol, &dir1);
-    dir_insert(&key, vol, &dir1);
-    dir_insert(&key, vol, &dir1);
-    dir_insert(&key, vol, &dir1);
-    dir_insert(&key, vol, &dir1);
-    dir_corrupt_bucket(dir_bucket(b1, vol->dir_segment(s1)), s1, vol);
-    if (check_dir(vol)) {
-      ret = REGRESSION_TEST_FAILED;
-    }
-#endif
-  }
-  vol_dir_clear(vol);
-  *status = ret;
-}
diff --git a/src/iocore/cache/Makefile.am b/src/iocore/cache/Makefile.am
index 99c9e8fcd6..ac8190f883 100644
--- a/src/iocore/cache/Makefile.am
+++ b/src/iocore/cache/Makefile.am
@@ -131,6 +131,7 @@ endif
 
 check_PROGRAMS = \
   test_Cache \
+  test_CacheDir \
   test_RWW \
   test_Alternate_L_to_S \
   test_Alternate_S_to_L \
@@ -311,6 +312,13 @@ test_Cache_SOURCES = \
   $(test_main_SOURCES) \
   ./test/test_Cache.cc
 
+test_CacheDir_CPPFLAGS = $(test_CPPFLAGS)
+test_CacheDir_LDFLAGS = @AM_LDFLAGS@
+test_CacheDir_LDADD = $(test_LDADD)
+test_CacheDir_SOURCES = \
+  $(test_main_SOURCES) \
+  ./test/test_CacheDir.cc
+
 test_RWW_CPPFLAGS = $(test_CPPFLAGS)
 test_RWW_LDFLAGS = @AM_LDFLAGS@
 test_RWW_LDADD = $(test_LDADD)
diff --git a/src/iocore/cache/P_CacheDir.h b/src/iocore/cache/P_CacheDir.h
index ef717eba4e..27b5068728 100644
--- a/src/iocore/cache/P_CacheDir.h
+++ b/src/iocore/cache/P_CacheDir.h
@@ -36,6 +36,8 @@ struct InterimCacheVol;
 struct CacheVC;
 class CacheEvacuateDocVC;
 
+// #define LOOP_CHECK_MODE 1
+
 /*
   Directory layout
 */
@@ -282,6 +284,10 @@ uint64_t dir_entries_used(Vol *vol);
 void sync_cache_dir_on_shutdown();
 int dir_freelist_length(Vol *vol, int s);
 
+int dir_bucket_length(Dir *b, int s, Vol *vol);
+int dir_freelist_length(Vol *vol, int s);
+void dir_clean_segment(int s, Vol *vol);
+
 // Inline Functions
 
 #define dir_in_seg(_s, _i) ((Dir *)(((char *)(_s)) + (SIZEOF_DIR * (_i))))
diff --git a/src/iocore/cache/test/test_CacheDir.cc 
b/src/iocore/cache/test/test_CacheDir.cc
new file mode 100644
index 0000000000..a6d29140c8
--- /dev/null
+++ b/src/iocore/cache/test/test_CacheDir.cc
@@ -0,0 +1,262 @@
+/** @file
+
+  A brief file description
+
+  @section license License
+
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you 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 "main.h"
+
+#include "P_CacheDir.h"
+
+#include "tscore/Random.h"
+
+// Required by main.h
+int cache_vols            = 1;
+bool reuse_existing_cache = false;
+
+namespace
+{
+DbgCtl dbg_ctl_cache_dir_test{"cache_dir_test"};
+
+unsigned int regress_rand_seed = 0;
+
+void
+regress_rand_init(unsigned int i)
+{
+  regress_rand_seed = i;
+}
+
+static void
+regress_rand_CacheKey(const CacheKey *key)
+{
+  unsigned int *x = (unsigned int *)key;
+  for (int i = 0; i < 4; i++) {
+    x[i] = next_rand(&regress_rand_seed);
+  }
+}
+
+void
+dir_corrupt_bucket(Dir *b, int s, Vol *vol)
+{
+  int l    = (static_cast<int>(dir_bucket_length(b, s, vol) * 
ts::Random::drandom()));
+  Dir *e   = b;
+  Dir *seg = vol->dir_segment(s);
+  for (int i = 0; i < l; i++) {
+    ink_release_assert(e);
+    e = next_dir(e, seg);
+  }
+  ink_release_assert(e);
+  dir_set_next(e, dir_to_offset(e, seg));
+}
+
+} // namespace
+
+class CacheDirTest : public CacheInit
+{
+public:
+  int
+  cache_init_success_callback(int event, void *e) override
+  {
+    // Test
+    _run();
+
+    // Teardown
+    TerminalTest *tt = new TerminalTest;
+    this_ethread()->schedule_imm(tt);
+    delete this;
+
+    return 0;
+  }
+
+private:
+  void
+  _run()
+  {
+    ink_hrtime ttime;
+
+    REQUIRE(CacheProcessor::IsCacheEnabled() == CACHE_INITIALIZED);
+    REQUIRE(gnvol >= 1);
+
+    Vol *vol        = gvol[0];
+    EThread *thread = this_ethread();
+    MUTEX_TRY_LOCK(lock, vol->mutex, thread);
+    ink_release_assert(lock.is_locked());
+    vol_dir_clear(vol);
+
+    // coverity[var_decl]
+    Dir dir;
+    dir_clear(&dir);
+    dir_set_phase(&dir, 0);
+    dir_set_head(&dir, true);
+    dir_set_offset(&dir, 1);
+
+    vol->header->agg_pos = vol->header->write_pos += 1024;
+
+    CacheKey key;
+    rand_CacheKey(&key, thread->mutex);
+
+    int s    = key.slice32(0) % vol->segments, i, j;
+    Dir *seg = vol->dir_segment(s);
+
+    // test insert
+    int inserted = 0;
+    int free     = dir_freelist_length(vol, s);
+    int n        = free;
+    while (n--) {
+      if (!dir_insert(&key, vol, &dir)) {
+        break;
+      }
+      inserted++;
+    }
+    CHECK(static_cast<unsigned int>(inserted - free) <= 1);
+
+    // test delete
+    for (i = 0; i < vol->buckets; i++) {
+      for (j = 0; j < DIR_DEPTH; j++) {
+        dir_set_offset(dir_bucket_row(dir_bucket(i, seg), j), 0); // delete
+      }
+    }
+    dir_clean_segment(s, vol);
+    int newfree = dir_freelist_length(vol, s);
+    CHECK(static_cast<unsigned int>(newfree - free) <= 1);
+
+    // test insert-delete
+    regress_rand_init(13);
+    ttime = ink_get_hrtime();
+    for (i = 0; i < newfree; i++) {
+      regress_rand_CacheKey(&key);
+      dir_insert(&key, vol, &dir);
+    }
+    uint64_t us = (ink_get_hrtime() - ttime) / HRTIME_USECOND;
+    // On windows us is sometimes 0. I don't know why.
+    // printout the insert rate only if its not 0
+    if (us) {
+      Dbg(dbg_ctl_cache_dir_test, "insert rate = %d / second", 
static_cast<int>((newfree * static_cast<uint64_t>(1000000)) / us));
+    }
+    regress_rand_init(13);
+    ttime = ink_get_hrtime();
+    for (i = 0; i < newfree; i++) {
+      Dir *last_collision = nullptr;
+      regress_rand_CacheKey(&key);
+      CHECK(dir_probe(&key, vol, &dir, &last_collision));
+    }
+    us = (ink_get_hrtime() - ttime) / HRTIME_USECOND;
+    // On windows us is sometimes 0. I don't know why.
+    // printout the probe rate only if its not 0
+    if (us) {
+      Dbg(dbg_ctl_cache_dir_test, "probe rate = %d / second", 
static_cast<int>((newfree * static_cast<uint64_t>(1000000)) / us));
+    }
+
+    for (int c = 0; c < vol->direntries() * 0.75; c++) {
+      regress_rand_CacheKey(&key);
+      dir_insert(&key, vol, &dir);
+    }
+
+    Dir dir1;
+    memset(static_cast<void *>(&dir1), 0, sizeof(dir1));
+    int s1, b1;
+
+    Dbg(dbg_ctl_cache_dir_test, "corrupt_bucket test");
+    for (int ntimes = 0; ntimes < 10; ntimes++) {
+#ifdef LOOP_CHECK_MODE
+      // dir_probe in bucket with loop
+      rand_CacheKey(&key, thread->mutex);
+      s1 = key.slice32(0) % vol->segments;
+      b1 = key.slice32(1) % vol->buckets;
+      dir_corrupt_bucket(dir_bucket(b1, vol->dir_segment(s1)), s1, vol);
+      dir_insert(&key, vol, &dir);
+      Dir *last_collision = 0;
+      dir_probe(&key, vol, &dir, &last_collision);
+
+      rand_CacheKey(&key, thread->mutex);
+      s1 = key.slice32(0) % vol->segments;
+      b1 = key.slice32(1) % vol->buckets;
+      dir_corrupt_bucket(dir_bucket(b1, vol->dir_segment(s1)), s1, vol);
+
+      last_collision = 0;
+      dir_probe(&key, vol, &dir, &last_collision);
+
+      // dir_overwrite in bucket with loop
+      rand_CacheKey(&key, thread->mutex);
+      s1 = key.slice32(0) % vol->segments;
+      b1 = key.slice32(1) % vol->buckets;
+      CacheKey key1;
+      key1.b[1] = 127;
+      dir1      = dir;
+      dir_set_offset(&dir1, 23);
+      dir_insert(&key1, vol, &dir1);
+      dir_insert(&key, vol, &dir);
+      key1.b[1] = 80;
+      dir_insert(&key1, vol, &dir1);
+      dir_corrupt_bucket(dir_bucket(b1, vol->dir_segment(s1)), s1, vol);
+      dir_overwrite(&key, vol, &dir, &dir, 1);
+
+      rand_CacheKey(&key, thread->mutex);
+      s1       = key.slice32(0) % vol->segments;
+      b1       = key.slice32(1) % vol->buckets;
+      key.b[1] = 23;
+      dir_insert(&key, vol, &dir1);
+      dir_corrupt_bucket(dir_bucket(b1, vol->dir_segment(s1)), s1, vol);
+      dir_overwrite(&key, vol, &dir, &dir, 0);
+
+      rand_CacheKey(&key, thread->mutex);
+      s1        = key.slice32(0) % vol->segments;
+      Dir *seg1 = vol->dir_segment(s1);
+      // dir_freelist_length in freelist with loop
+      dir_corrupt_bucket(dir_from_offset(vol->header->freelist[s], seg1), s1, 
vol);
+      dir_freelist_length(vol, s1);
+
+      rand_CacheKey(&key, thread->mutex);
+      s1 = key.slice32(0) % vol->segments;
+      b1 = key.slice32(1) % vol->buckets;
+      // dir_bucket_length in bucket with loop
+      dir_corrupt_bucket(dir_bucket(b1, vol->dir_segment(s1)), s1, vol);
+      dir_bucket_length(dir_bucket(b1, vol->dir_segment(s1)), s1, vol);
+      CHECK(check_dir(vol));
+#else
+      // test corruption detection
+      rand_CacheKey(&key, thread->mutex);
+      s1 = key.slice32(0) % vol->segments;
+      b1 = key.slice32(1) % vol->buckets;
+
+      dir_insert(&key, vol, &dir1);
+      dir_insert(&key, vol, &dir1);
+      dir_insert(&key, vol, &dir1);
+      dir_insert(&key, vol, &dir1);
+      dir_insert(&key, vol, &dir1);
+      dir_corrupt_bucket(dir_bucket(b1, vol->dir_segment(s1)), s1, vol);
+      CHECK(!check_dir(vol));
+#endif
+    }
+    vol_dir_clear(vol);
+  }
+};
+
+TEST_CASE("CacheDir")
+{
+  init_cache(0);
+
+  CacheDirTest *init = new CacheDirTest;
+
+  this_ethread()->schedule_imm(init);
+  this_thread()->execute();
+
+  return;
+}
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
index 4627281dd5..d6c2e672ae 100644
--- a/src/tests/CMakeLists.txt
+++ b/src/tests/CMakeLists.txt
@@ -102,6 +102,7 @@ if(ENABLE_DISK_FAILURE_TESTS)
     Populated_Cache_Disk_Failure 
${CMAKE_SOURCE_DIR}/src/iocore/cache/test/test_Populated_Cache_Disk_Failure.cc
   )
 endif()
+add_cache_test(CacheDir 
${CMAKE_SOURCE_DIR}/src/iocore/cache/test/test_CacheDir.cc)
 add_cache_test(RWW ${CMAKE_SOURCE_DIR}/src/iocore/cache/test/test_RWW.cc)
 add_cache_test(Alternate_L_to_S 
${CMAKE_SOURCE_DIR}/src/iocore/cache/test/test_Alternate_L_to_S.cc)
 add_cache_test(Alternate_S_to_L 
${CMAKE_SOURCE_DIR}/src/iocore/cache/test/test_Alternate_S_to_L.cc)

Reply via email to