GoogleTest is Google’s C++ testing and mocking framework: https://google.github.io/googletest/. It even includes a Bazel example in their documentation: https://google.github.io/googletest/quickstart-bazel.html
cc_test
is the Bazel rule to execute such a test.
Let’s add a C++ testing file that exercises the magic.c we wrote already. Here’s an example (written by Claude 3.5 Sonnet)
#include <gtest/gtest.h>
#include <unistd.h>
#include <fcntl.h>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <array>
#include <string>
#define MAX_PATH_LENGTH 256
// Test helper function to create a temporary file with content
namespace {
std::string create_test_file(const std::string& content, const std::string& extension) {
std::array<char, MAX_PATH_LENGTH> temp_path = {};
const char* test_tmpdir = getenv("TEST_TMPDIR");
if (test_tmpdir == nullptr) { test_tmpdir = "/tmp"; }
(void)std::snprintf(temp_path.data(), temp_path.size(), "%s/magic_test_XXXXXX%s", test_tmpdir, extension.c_str());
int file_desc = mkstemps(temp_path.data(), static_cast<int>(extension.length()));
if (file_desc == -1) {
perror("Failed to create temp file");
return "";
}
ssize_t bytes_written = write(file_desc, content.c_str(), content.length());
if (bytes_written == -1 || static_cast<size_t>(bytes_written) != content.length()) {
perror("Failed to write to temp file");
close(file_desc);
return "";
}
close(file_desc);
return temp_path.data();
}
}
extern "C" {
#include <magic.h>
}
class MagicTest : public ::testing::Test {
protected:
magic_t magic;
void SetUp() override {
magic = magic_open(MAGIC_MIME_TYPE);
ASSERT_NE(magic, nullptr) << "Failed to initialize libmagic";
ASSERT_EQ(magic_load(magic, NULL), 0) << "Failed to load magic database";
}
void TearDown() override {
if (magic != nullptr) {
magic_close(magic);
}
}
};
TEST_F(MagicTest, DetectMimeType) {
// Create a temporary text file
const std::string content = "Hello, World!";
std::string test_file = create_test_file(content, ".txt");
ASSERT_FALSE(test_file.empty()) << "Failed to create test file";
// Test MIME type detection
const char* mime_type = magic_file(magic, test_file.c_str());
ASSERT_NE(mime_type, nullptr) << "Failed to get MIME type";
EXPECT_STREQ(mime_type, "text/plain") << "Unexpected MIME type";
// Cleanup
EXPECT_EQ(remove(test_file.c_str()), 0) << "Failed to remove test file";
}
int main(int argc, char **argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
Debugging with lldb
In order to use lldb we need to perform some setup. .bazelrc
common:lldb -c dbg --features=oso_prefix_is_pwd
common:lldb --run_under="lldb --local-lldbinit"
.lldbinit
platform settings -w $PWD
settings set target.source-map ./ $PWD
And run the following command to go into lldb view: bazel run :magic --config=lldb