// Copyright 2022 The Centipede Authors. // // Licensed 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 // // https://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. #ifndef FUZZTEST_COMMON_TEST_UTIL_H_ #define FUZZTEST_COMMON_TEST_UTIL_H_ #include #include // NOLINT #include #include #include #include #include "absl/log/check.h" #include "absl/strings/str_format.h" #include "./common/blob_file.h" #include "./common/defs.h" #include "./common/logging.h" #define EXPECT_OK(status) EXPECT_TRUE((status).ok()) << VV(status) #define ASSERT_OK(status) ASSERT_TRUE((status).ok()) << VV(status) namespace fuzztest::internal { // Returns a temp dir for use inside tests. The base dir is chosen in the // following order of precedence: // - $TEST_TMPDIR (highest) // - $TMPDIR // - /tmp // // An optional `subdir` can be appended to the base dir chosen as above. One // useful value always available inside a TEST macro (and its variations) is // `test_into_->name()`, which returns the name of the test case. // // If the final dir doesn't exist, it gets created. std::filesystem::path GetTestTempDir(std::string_view subdir); // Returns a path for i-th temporary file. std::string GetTempFilePath(std::string_view subdir, size_t i); // Returns the root directory filepath for a test's "runfiles". std::filesystem::path GetTestRunfilesDir(); // Returns the filepath of a test's data dependency file. std::filesystem::path GetDataDependencyFilepath(std::string_view rel_path); // Returns a path to `llvm-symbolizer` binary. std::string GetLLVMSymbolizerPath(); // Returns a path to `objdump` binary. std::string GetObjDumpPath(); // Resets the PATH envvar to "`dir`:$PATH". void PrependDirToPathEnvvar(std::string_view dir); // Creates or clears a tmp dir in CTOR. The dir will end with `leaf` subdir. // // TODO(b/393384208): Merge this with TempDir in temp_dir.h. class TempDir { public: explicit TempDir(std::string_view leaf1, std::string_view leaf2 = "") : path_{GetTestTempDir(leaf1) / leaf2} { std::filesystem::remove_all(path_); std::filesystem::create_directories(path_); } const std::filesystem::path& path() const { return path_; } std::string GetFilePath(std::string_view file_name) const { return path_ / file_name; } std::string CreateSubdir(std::string_view name) const { std::string path = GetFilePath(name); std::filesystem::remove_all(path); std::filesystem::create_directories(path); return path; } private: std::filesystem::path path_; }; class TempCorpusDir : public TempDir { public: // Reuse the parent's ctor. using TempDir::TempDir; // Loads the corpus from the file `name_prefix``shard_index` // and returns it as a vector. // Returns an empty vector if the file cannot be opened. std::vector GetCorpus(size_t shard_index, std::string_view name_prefix = "corpus.") { // NOTE: The "6" in the "%06d" comes from kDigitsInShardIndex in // environment.cc. if (!reader_ ->Open(GetFilePath( absl::StrFormat("%s%06d", name_prefix, shard_index))) .ok()) { return {}; } std::vector corpus; ByteSpan blob; while (reader_->Read(blob).ok()) { corpus.emplace_back(blob.begin(), blob.end()); } CHECK_OK(reader_->Close()); return corpus; } // Returns the count of elements in the corpus file `path`/`file_name`. size_t CountElementsInCorpusFile(size_t shard_index, std::string_view name_prefix = "corpus.") { return GetCorpus(shard_index, name_prefix).size(); } private: std::unique_ptr reader_ = DefaultBlobFileReaderFactory(); }; } // namespace fuzztest::internal #endif // FUZZTEST_COMMON_TEST_UTIL_H_