| // 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 <cstddef> | |
| #include <filesystem> // NOLINT | |
| #include <memory> | |
| #include <string> | |
| #include <string_view> | |
| #include <vector> | |
| #include "absl/strings/str_format.h" | |
| #include "./common/blob_file.h" | |
| #include "./common/defs.h" | |
| #include "./common/logging.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<ByteArray>. | |
| // Returns an empty vector if the file cannot be opened. | |
| std::vector<ByteArray> 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<ByteArray> corpus; | |
| ByteSpan blob; | |
| while (reader_->Read(blob).ok()) { | |
| corpus.emplace_back(blob.begin(), blob.end()); | |
| } | |
| FUZZTEST_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<BlobFileReader> reader_ = DefaultBlobFileReaderFactory(); | |
| }; | |
| } // namespace fuzztest::internal | |
| #endif // FUZZTEST_COMMON_TEST_UTIL_H_ |