blob: 71a226836f47408075b152b03f98cc87ec00d16d [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#include <lib/crashlog.h>
#include <lib/crashlog/panic_buffer.h>
#include <lib/unittest/unittest.h>
#include <ktl/string_view.h>
#include <ktl/unique_ptr.h>
namespace {
constexpr size_t kLargeBufferSize = 64 * 1024;
constexpr size_t kTooSmallBufferSize = 64;
bool BasicTest() {
BEGIN_TEST;
fbl::AllocChecker ac;
auto buffer = ktl::make_unique<char[]>(&ac, kLargeBufferSize);
ASSERT_TRUE(ac.check());
size_t len = crashlog_to_string(buffer.get(), kLargeBufferSize, ZirconCrashReason::NoCrash);
EXPECT_LE(len, kLargeBufferSize);
EXPECT_GT(len, 0u);
ktl::string_view text{buffer.get(), len};
EXPECT_TRUE(text.ends_with('\n'));
EXPECT_TRUE(text.find("BACKTRACE"sv) != ktl::string_view::npos);
END_TEST;
}
bool OomTest() {
BEGIN_TEST;
fbl::AllocChecker ac;
auto buffer = ktl::make_unique<char[]>(&ac, kLargeBufferSize);
ASSERT_TRUE(ac.check());
size_t len = crashlog_to_string(buffer.get(), kLargeBufferSize, ZirconCrashReason::Oom);
EXPECT_LE(len, kLargeBufferSize);
EXPECT_GT(len, 0u);
// OOM case should not include the full dump.
ktl::string_view text{buffer.get(), len};
EXPECT_TRUE(text.ends_with('\n'));
EXPECT_TRUE(text.find("BACKTRACE"sv) == ktl::string_view::npos);
END_TEST;
}
bool TruncationTest() {
BEGIN_TEST;
constexpr char kCanaryValue = '\xa5';
char buffer[kTooSmallBufferSize + 1];
buffer[sizeof(buffer) - 1] = kCanaryValue;
size_t len = crashlog_to_string(buffer, sizeof(buffer) - 1, ZirconCrashReason::NoCrash);
EXPECT_LT(len, sizeof(buffer));
EXPECT_GT(len, 0u);
EXPECT_EQ(buffer[sizeof(buffer) - 1], kCanaryValue);
END_TEST;
}
bool PanicBufferTest() {
BEGIN_TEST;
PanicBuffer b;
ASSERT_EQ(0u, strlen(b.c_str()));
const char kMsg[] = "hello";
b.Append(kMsg);
ASSERT_FALSE(strcmp(b.c_str(), kMsg));
// Grossly over append.
for (unsigned i = 0; i < PanicBuffer::kMaxSize; ++i) {
b.Append(kMsg);
}
ASSERT_EQ(PanicBuffer::kMaxSize - 1, strlen(b.c_str()));
END_TEST;
}
} // namespace
UNITTEST_START_TESTCASE(crashlog_tests)
UNITTEST("basic", BasicTest)
UNITTEST("oom", OomTest)
UNITTEST("truncation", TruncationTest)
UNITTEST("panic_buffer", PanicBufferTest)
UNITTEST_END_TESTCASE(crashlog_tests, "crashlog", "crashlog tests")