github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/c-deps/libroach/testutils.cc (about)

     1  // Copyright 2017 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  #include "testutils.h"
    12  #include <err.h>
    13  #include <ftw.h>
    14  #include <google/protobuf/stubs/stringprintf.h>
    15  #include <gtest/gtest.h>
    16  #include <regex>
    17  #include <rocksdb/status.h>
    18  #include <stdlib.h>
    19  #include <string>
    20  #include "fmt.h"
    21  
    22  extern "C" {
    23  // Tests are run in plain C++, we need a symbol for rocksDBLog, normally
    24  // implemented on the Go side.
    25  void __attribute__((weak)) rocksDBLog(bool, int, char*, int) {}
    26  }  // extern "C"
    27  
    28  namespace testutils {
    29  
    30  static int nftw_unlink_cb(const char* name, const struct stat*, int type, struct FTW*) {
    31    if (type == FTW_DP) {
    32      return rmdir(name);
    33    } else if (type == FTW_F || type == FTW_SL) {
    34      return unlink(name);
    35    }
    36    return 0;
    37  }
    38  
    39  TempDirHandler::TempDirHandler() {
    40    const char* ostmpdir = getenv("TEMPDIR");
    41    if (ostmpdir == NULL) {
    42      ostmpdir = "/tmp";
    43    }
    44    size_t len = strlen(ostmpdir);
    45    if (ostmpdir[len - 1] == '/') {
    46      len--;
    47    }
    48  
    49    // mkdtemp needs a []char to modify.
    50    const char* dirname = "/roachccl.XXXXXX";
    51    char* tmpl = new char[len + strlen(dirname) + 1];
    52    strncpy(tmpl, ostmpdir, len);
    53    strcpy(&tmpl[len], dirname);
    54  
    55    if (mkdtemp(tmpl) == NULL) {
    56      err(1, "creating temporary directory %s", tmpl);
    57    }
    58    tmp_dir_ = tmpl;
    59    delete[] tmpl;
    60  }
    61  
    62  TempDirHandler::~TempDirHandler() {
    63    if (tmp_dir_ == "") {
    64      return;
    65    }
    66    const int fd_limit = 16;
    67    if (nftw(tmp_dir_.c_str(), nftw_unlink_cb, fd_limit, FTW_DEPTH | FTW_PHYS) != 0) {
    68      err(1, "removing temporary directory %s", tmp_dir_.c_str());
    69    }
    70  }
    71  
    72  std::string TempDirHandler::Path(const std::string& subpath) { return tmp_dir_ + "/" + subpath; }
    73  
    74  rocksdb::Status compareErrorMessage(rocksdb::Status status, const char* err_msg, bool partial) {
    75    if (strcmp("", err_msg) == 0) {
    76      // Expected success.
    77      if (status.ok()) {
    78        return rocksdb::Status::OK();
    79      }
    80      return rocksdb::Status::InvalidArgument(
    81          fmt::StringPrintf("expected success, got error \"%s\"", status.getState()));
    82    }
    83  
    84    // Expected failure.
    85    if (status.ok()) {
    86      return rocksdb::Status::InvalidArgument(
    87          fmt::StringPrintf("expected error \"%s\", got success", err_msg));
    88    }
    89    std::regex re(err_msg);
    90    if (partial) {
    91      // Partial regexp match.
    92      std::cmatch cm;
    93      if (std::regex_search(status.getState(), cm, re)) {
    94        return rocksdb::Status::OK();
    95      }
    96    } else {
    97      // Full regexp match.
    98      if (std::regex_match(status.getState(), re)) {
    99        return rocksdb::Status::OK();
   100      }
   101    }
   102  
   103    return rocksdb::Status::InvalidArgument(
   104        fmt::StringPrintf("expected error \"%s\", got \"%s\"", err_msg, status.getState()));
   105  }
   106  
   107  rocksdb::Status compareErrorMessage(rocksdb::Status status, std::string err_msg, bool partial) {
   108    return compareErrorMessage(status, err_msg.c_str(), partial);
   109  }
   110  
   111  }  // namespace testutils