blob: 1cdd3e29ca26e57522abd18b32b2e1459ed0b14f [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* 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
*
* http://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.
*/
#include <stdint.h>
#include <unistd.h>
#include <string>
#include <gtest/gtest.h>
#include <android-base/file.h>
#include <memory_trace/MemoryTrace.h>
TEST(MemoryTraceReadTest, malloc_valid) {
std::string line = "1234: malloc 0xabd0000 20";
memory_trace::Entry entry{.start_ns = 1, .end_ns = 1};
std::string error;
ASSERT_TRUE(memory_trace::FillInEntryFromString(line, entry, error)) << error;
EXPECT_EQ(memory_trace::MALLOC, entry.type);
EXPECT_EQ(1234, entry.tid);
EXPECT_EQ(0xabd0000U, entry.ptr);
EXPECT_EQ(20U, entry.size);
EXPECT_EQ(0U, entry.u.align);
EXPECT_EQ(0U, entry.start_ns);
EXPECT_EQ(0U, entry.end_ns);
line += " 1000 1020";
ASSERT_TRUE(memory_trace::FillInEntryFromString(line, entry, error)) << error;
EXPECT_EQ(memory_trace::MALLOC, entry.type);
EXPECT_EQ(1234, entry.tid);
EXPECT_EQ(0xabd0000U, entry.ptr);
EXPECT_EQ(20U, entry.size);
EXPECT_EQ(0U, entry.u.align);
EXPECT_EQ(1000U, entry.start_ns);
EXPECT_EQ(1020U, entry.end_ns);
}
TEST(MemoryTraceReadTest, malloc_invalid) {
// Missing size
std::string line = "1234: malloc 0xabd0000";
memory_trace::Entry entry;
std::string error;
EXPECT_FALSE(memory_trace::FillInEntryFromString(line, entry, error));
EXPECT_EQ("Failed to read malloc data: 1234: malloc 0xabd0000", error);
// Missing pointer and size
line = "1234: malloc";
EXPECT_FALSE(memory_trace::FillInEntryFromString(line, entry, error));
EXPECT_EQ("Failed to process line: 1234: malloc", error);
// Missing end time
line = "1234: malloc 0xabd0000 10 100";
EXPECT_FALSE(memory_trace::FillInEntryFromString(line, entry, error));
EXPECT_EQ("Failed to read timestamps: 1234: malloc 0xabd0000 10 100", error);
}
TEST(MemoryTraceReadTest, free_valid) {
std::string line = "1235: free 0x5000";
memory_trace::Entry entry{.start_ns = 1, .end_ns = 1};
std::string error;
ASSERT_TRUE(memory_trace::FillInEntryFromString(line, entry, error)) << error;
EXPECT_EQ(memory_trace::FREE, entry.type);
EXPECT_EQ(1235, entry.tid);
EXPECT_EQ(0x5000U, entry.ptr);
EXPECT_EQ(0U, entry.size);
EXPECT_EQ(0U, entry.u.align);
EXPECT_EQ(0U, entry.start_ns);
EXPECT_EQ(0U, entry.end_ns);
line += " 540 2000";
ASSERT_TRUE(memory_trace::FillInEntryFromString(line, entry, error)) << error;
EXPECT_EQ(memory_trace::FREE, entry.type);
EXPECT_EQ(1235, entry.tid);
EXPECT_EQ(0x5000U, entry.ptr);
EXPECT_EQ(0U, entry.size);
EXPECT_EQ(0U, entry.u.align);
EXPECT_EQ(540U, entry.start_ns);
EXPECT_EQ(2000U, entry.end_ns);
}
TEST(MemoryTraceReadTest, free_invalid) {
// Missing pointer
std::string line = "1234: free";
memory_trace::Entry entry;
std::string error;
EXPECT_FALSE(memory_trace::FillInEntryFromString(line, entry, error));
EXPECT_EQ("Failed to process line: 1234: free", error);
// Missing end time
line = "1234: free 0x100 100";
EXPECT_FALSE(memory_trace::FillInEntryFromString(line, entry, error));
EXPECT_EQ("Failed to read timestamps: 1234: free 0x100 100", error);
}
TEST(MemoryTraceReadTest, calloc_valid) {
std::string line = "1236: calloc 0x8000 50 30";
memory_trace::Entry entry{.start_ns = 1, .end_ns = 1};
std::string error;
ASSERT_TRUE(memory_trace::FillInEntryFromString(line, entry, error)) << error;
EXPECT_EQ(memory_trace::CALLOC, entry.type);
EXPECT_EQ(1236, entry.tid);
EXPECT_EQ(0x8000U, entry.ptr);
EXPECT_EQ(30U, entry.size);
EXPECT_EQ(50U, entry.u.n_elements);
EXPECT_EQ(0U, entry.start_ns);
EXPECT_EQ(0U, entry.end_ns);
line += " 700 1000";
ASSERT_TRUE(memory_trace::FillInEntryFromString(line, entry, error)) << error;
EXPECT_EQ(memory_trace::CALLOC, entry.type);
EXPECT_EQ(1236, entry.tid);
EXPECT_EQ(0x8000U, entry.ptr);
EXPECT_EQ(30U, entry.size);
EXPECT_EQ(50U, entry.u.n_elements);
EXPECT_EQ(700U, entry.start_ns);
EXPECT_EQ(1000U, entry.end_ns);
}
TEST(MemoryTraceReadTest, calloc_invalid) {
// Missing number of elements
std::string line = "1236: calloc 0x8000 50";
memory_trace::Entry entry;
std::string error;
EXPECT_FALSE(memory_trace::FillInEntryFromString(line, entry, error));
EXPECT_EQ("Failed to read calloc data: 1236: calloc 0x8000 50", error);
// Missing size and number of elements
line = "1236: calloc 0x8000";
EXPECT_FALSE(memory_trace::FillInEntryFromString(line, entry, error));
EXPECT_EQ("Failed to read calloc data: 1236: calloc 0x8000", error);
// Missing pointer, size and number of elements
line = "1236: calloc";
EXPECT_FALSE(memory_trace::FillInEntryFromString(line, entry, error));
EXPECT_EQ("Failed to process line: 1236: calloc", error);
// Missing end time
line = "1236: calloc 0x8000 50 20 100";
EXPECT_FALSE(memory_trace::FillInEntryFromString(line, entry, error));
EXPECT_EQ("Failed to read timestamps: 1236: calloc 0x8000 50 20 100", error);
}
TEST(MemoryTraceReadTest, realloc_valid) {
std::string line = "1237: realloc 0x9000 0x4000 80";
memory_trace::Entry entry{.start_ns = 1, .end_ns = 1};
std::string error;
ASSERT_TRUE(memory_trace::FillInEntryFromString(line, entry, error)) << error;
EXPECT_EQ(memory_trace::REALLOC, entry.type);
EXPECT_EQ(1237, entry.tid);
EXPECT_EQ(0x9000U, entry.ptr);
EXPECT_EQ(80U, entry.size);
EXPECT_EQ(0x4000U, entry.u.old_ptr);
EXPECT_EQ(0U, entry.start_ns);
EXPECT_EQ(0U, entry.end_ns);
line += " 3999 10020";
ASSERT_TRUE(memory_trace::FillInEntryFromString(line, entry, error)) << error;
EXPECT_EQ(memory_trace::REALLOC, entry.type);
EXPECT_EQ(1237, entry.tid);
EXPECT_EQ(0x9000U, entry.ptr);
EXPECT_EQ(80U, entry.size);
EXPECT_EQ(0x4000U, entry.u.old_ptr);
EXPECT_EQ(3999U, entry.start_ns);
EXPECT_EQ(10020U, entry.end_ns);
}
TEST(MemoryTraceReadTest, realloc_invalid) {
// Missing size
std::string line = "1237: realloc 0x9000 0x4000";
memory_trace::Entry entry;
std::string error;
EXPECT_FALSE(memory_trace::FillInEntryFromString(line, entry, error));
EXPECT_EQ("Failed to read realloc data: 1237: realloc 0x9000 0x4000", error);
// Missing size and old pointer
line = "1237: realloc 0x9000";
EXPECT_FALSE(memory_trace::FillInEntryFromString(line, entry, error));
EXPECT_EQ("Failed to read realloc data: 1237: realloc 0x9000", error);
// Missing new pointer, size and old pointer
line = "1237: realloc";
EXPECT_FALSE(memory_trace::FillInEntryFromString(line, entry, error));
EXPECT_EQ("Failed to process line: 1237: realloc", error);
// Missing end time
line = "1237: realloc 0x9000 0x4000 10 500";
EXPECT_FALSE(memory_trace::FillInEntryFromString(line, entry, error));
EXPECT_EQ("Failed to read timestamps: 1237: realloc 0x9000 0x4000 10 500", error);
}
TEST(MemoryTraceReadTest, memalign_valid) {
std::string line = "1238: memalign 0xa000 16 89";
memory_trace::Entry entry{.start_ns = 1, .end_ns = 1};
std::string error;
ASSERT_TRUE(memory_trace::FillInEntryFromString(line, entry, error)) << error;
EXPECT_EQ(memory_trace::MEMALIGN, entry.type);
EXPECT_EQ(1238, entry.tid);
EXPECT_EQ(0xa000U, entry.ptr);
EXPECT_EQ(89U, entry.size);
EXPECT_EQ(16U, entry.u.align);
EXPECT_EQ(0U, entry.start_ns);
EXPECT_EQ(0U, entry.end_ns);
line += " 900 1000";
ASSERT_TRUE(memory_trace::FillInEntryFromString(line, entry, error)) << error;
EXPECT_EQ(memory_trace::MEMALIGN, entry.type);
EXPECT_EQ(1238, entry.tid);
EXPECT_EQ(0xa000U, entry.ptr);
EXPECT_EQ(89U, entry.size);
EXPECT_EQ(16U, entry.u.align);
EXPECT_EQ(900U, entry.start_ns);
EXPECT_EQ(1000U, entry.end_ns);
}
TEST(MemoryTraceReadTest, memalign_invalid) {
// Missing size
std::string line = "1238: memalign 0xa000 16";
memory_trace::Entry entry;
std::string error;
EXPECT_FALSE(memory_trace::FillInEntryFromString(line, entry, error));
EXPECT_EQ("Failed to read memalign data: 1238: memalign 0xa000 16", error);
// Missing alignment and size
line = "1238: memalign 0xa000";
EXPECT_FALSE(memory_trace::FillInEntryFromString(line, entry, error));
EXPECT_EQ("Failed to read memalign data: 1238: memalign 0xa000", error);
// Missing pointer, alignment and size
line = "1238: memalign";
EXPECT_FALSE(memory_trace::FillInEntryFromString(line, entry, error));
EXPECT_EQ("Failed to process line: 1238: memalign", error);
// Missing end time
line = "1238: memalign 0xa000 16 10 800";
EXPECT_FALSE(memory_trace::FillInEntryFromString(line, entry, error));
EXPECT_EQ("Failed to read timestamps: 1238: memalign 0xa000 16 10 800", error);
}
TEST(MemoryTraceReadTest, thread_done_valid) {
std::string line = "1239: thread_done 0x0";
memory_trace::Entry entry{.start_ns = 1, .end_ns = 1};
std::string error;
ASSERT_TRUE(memory_trace::FillInEntryFromString(line, entry, error)) << error;
EXPECT_EQ(memory_trace::THREAD_DONE, entry.type);
EXPECT_EQ(1239, entry.tid);
EXPECT_EQ(0U, entry.ptr);
EXPECT_EQ(0U, entry.size);
EXPECT_EQ(0U, entry.u.old_ptr);
EXPECT_EQ(0U, entry.start_ns);
EXPECT_EQ(0U, entry.end_ns);
line += " 290";
ASSERT_TRUE(memory_trace::FillInEntryFromString(line, entry, error)) << error;
EXPECT_EQ(memory_trace::THREAD_DONE, entry.type);
EXPECT_EQ(1239, entry.tid);
EXPECT_EQ(0U, entry.ptr);
EXPECT_EQ(0U, entry.size);
EXPECT_EQ(0U, entry.u.old_ptr);
EXPECT_EQ(0U, entry.start_ns);
EXPECT_EQ(290U, entry.end_ns);
}
TEST(MemoryTraceReadTest, thread_done_invalid) {
// Missing pointer
std::string line = "1240: thread_done";
memory_trace::Entry entry;
std::string error;
EXPECT_FALSE(memory_trace::FillInEntryFromString(line, entry, error));
EXPECT_EQ("Failed to process line: 1240: thread_done", error);
}
class MemoryTraceOutputTest : public ::testing::Test {
protected:
void SetUp() override {
tmp_file_ = new TemporaryFile();
ASSERT_TRUE(tmp_file_->fd != -1);
}
void TearDown() override { delete tmp_file_; }
void WriteAndReadString(const memory_trace::Entry& entry, std::string& str) {
EXPECT_EQ(lseek(tmp_file_->fd, 0, SEEK_SET), 0);
EXPECT_TRUE(memory_trace::WriteEntryToFd(tmp_file_->fd, entry));
EXPECT_EQ(lseek(tmp_file_->fd, 0, SEEK_SET), 0);
EXPECT_TRUE(android::base::ReadFdToString(tmp_file_->fd, &str));
}
std::string WriteAndGetString(const memory_trace::Entry& entry) {
std::string str;
WriteAndReadString(entry, str);
return str;
}
void VerifyEntry(const memory_trace::Entry& entry, const std::string expected) {
EXPECT_EQ(expected, memory_trace::CreateStringFromEntry(entry));
// The WriteEntryToFd always appends a newline, but string creation doesn't.
EXPECT_EQ(expected + "\n", WriteAndGetString(entry));
}
TemporaryFile* tmp_file_ = nullptr;
};
TEST_F(MemoryTraceOutputTest, malloc_output) {
memory_trace::Entry entry{.tid = 123, .type = memory_trace::MALLOC, .ptr = 0x123, .size = 50};
VerifyEntry(entry, "123: malloc 0x123 50");
entry.start_ns = 10;
entry.end_ns = 200;
VerifyEntry(entry, "123: malloc 0x123 50 10 200");
}
TEST_F(MemoryTraceOutputTest, calloc_output) {
memory_trace::Entry entry{
.tid = 123, .type = memory_trace::CALLOC, .ptr = 0x123, .size = 200, .u.n_elements = 400};
VerifyEntry(entry, "123: calloc 0x123 400 200");
entry.start_ns = 15;
entry.end_ns = 315;
VerifyEntry(entry, "123: calloc 0x123 400 200 15 315");
}
TEST_F(MemoryTraceOutputTest, memalign_output) {
memory_trace::Entry entry{
.tid = 123, .type = memory_trace::MEMALIGN, .ptr = 0x123, .size = 1024, .u.align = 0x10};
VerifyEntry(entry, "123: memalign 0x123 16 1024");
entry.start_ns = 23;
entry.end_ns = 289;
VerifyEntry(entry, "123: memalign 0x123 16 1024 23 289");
}
TEST_F(MemoryTraceOutputTest, realloc_output) {
memory_trace::Entry entry{
.tid = 123, .type = memory_trace::REALLOC, .ptr = 0x123, .size = 300, .u.old_ptr = 0x125};
VerifyEntry(entry, "123: realloc 0x123 0x125 300");
entry.start_ns = 45;
entry.end_ns = 1000;
VerifyEntry(entry, "123: realloc 0x123 0x125 300 45 1000");
}
TEST_F(MemoryTraceOutputTest, free_output) {
memory_trace::Entry entry{.tid = 123, .type = memory_trace::FREE, .ptr = 0x123};
VerifyEntry(entry, "123: free 0x123");
entry.start_ns = 60;
entry.end_ns = 2000;
VerifyEntry(entry, "123: free 0x123 60 2000");
}
TEST_F(MemoryTraceOutputTest, thread_done_output) {
memory_trace::Entry entry{.tid = 123, .type = memory_trace::THREAD_DONE};
VerifyEntry(entry, "123: thread_done 0x0");
entry.start_ns = 0;
entry.end_ns = 2500;
VerifyEntry(entry, "123: thread_done 0x0 2500");
}