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