#include "base/debug/asan_service.h"
#if defined(ADDRESS_SANITIZER)
#include <map>
#include <memory>
#include <sstream>
#include "base/debug/asan_invalid_access.h"
#include "base/memory/raw_ref.h"
#include "base/run_loop.h"
#include "base/test/bind.h"
#include "base/test/task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#if defined(GTEST_HAS_DEATH_TEST)
namespace base {
namespace debug {
class AsanServiceTest : public ::testing::Test {
protected:
void SetUp() override { AsanService::GetInstance()->Initialize(); }
};
bool ExitedCleanly(int exit_status) {
return exit_status == 0;
}
#if BUILDFLAG(IS_FUCHSIA)
#define MAYBE_ErrorCallback …
#define MAYBE_CrashInErrorCallback …
#define MAYBE_ShouldExitCleanly …
#define MAYBE_TaskTraceCallback …
#else
#define MAYBE_ErrorCallback …
#define MAYBE_CrashInErrorCallback …
#define MAYBE_ShouldExitCleanly …
#define MAYBE_TaskTraceCallback …
#endif
TEST_F(AsanServiceTest, MAYBE_ErrorCallback) {
AsanService::GetInstance()->AddErrorCallback([](const char*, bool*) {
AsanService::GetInstance()->Log("\nErrorCallback1");
});
EXPECT_DEATH(AsanHeapUseAfterFree(), "ErrorCallback1");
AsanService::GetInstance()->AddErrorCallback([](const char*, bool*) {
AsanService::GetInstance()->Log("\nErrorCallback2");
});
EXPECT_DEATH(AsanHeapUseAfterFree(), "ErrorCallback1");
EXPECT_DEATH(AsanHeapUseAfterFree(), "ErrorCallback2");
}
TEST_F(AsanServiceTest, MAYBE_CrashInErrorCallback) {
AsanService::GetInstance()->AddErrorCallback([](const char*, bool*) {
AsanService::GetInstance()->Log("\nErrorCallback1");
AsanHeapUseAfterFree();
});
EXPECT_DEATH(AsanHeapUseAfterFree(),
"AddressSanitizer: nested bug in the same thread");
}
TEST_F(AsanServiceTest, MAYBE_ShouldExitCleanly) {
AsanService::GetInstance()->AddErrorCallback([](const char*, bool*) {
AsanService::GetInstance()->Log("\nErrorCallback1");
});
EXPECT_DEATH(AsanHeapUseAfterFree(), "ErrorCallback1");
EXPECT_DEATH(AsanHeapUseAfterFree(), "ABORTING");
AsanService::GetInstance()->AddErrorCallback(
[](const char* reason, bool* should_exit_cleanly) {
AsanService::GetInstance()->Log("\nShouldExitCleanly");
*should_exit_cleanly = true;
});
EXPECT_EXIT(AsanHeapUseAfterFree(), ExitedCleanly, "ErrorCallback1");
EXPECT_EXIT(AsanHeapUseAfterFree(), ExitedCleanly, "ShouldExitCleanly");
EXPECT_EXIT(AsanHeapUseAfterFree(), ExitedCleanly, "EXITING");
}
class AsanTaskTraceTest {
public:
AsanTaskTraceTest() {}
void Run() {
task_runner_->PostTask(
FROM_HERE, BindOnce(&AsanTaskTraceTest::PostingTask, Unretained(this)));
task_environment_.RunUntilIdle();
}
private:
void PostingTask() {
task_runner_->PostTask(FROM_HERE, BindOnce(&AsanHeapUseAfterFree));
}
test::TaskEnvironment task_environment_;
const raw_ref<SingleThreadTaskRunner> task_runner_{
*task_environment_.GetMainThreadTaskRunner()};
};
TEST_F(AsanServiceTest, MAYBE_TaskTraceCallback) {
AsanTaskTraceTest test;
EXPECT_DEATH(test.Run(), "#0 0x.* .*\\n\\s+#1 0x.*");
}
}
}
#endif
#endif