2024-02-09 12:21:45 -08:00
|
|
|
// Copyright 2024 The Crashpad 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
|
|
|
|
//
|
|
|
|
// 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 "client/crashpad_info.h"
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
|
|
|
|
#include "gtest/gtest.h"
|
|
|
|
|
|
|
|
namespace crashpad {
|
|
|
|
namespace test {
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
constexpr uint32_t kTestStreamType = 0x33333;
|
|
|
|
|
|
|
|
class CrashpadInfoTest : public testing::Test {
|
|
|
|
protected:
|
|
|
|
CrashpadInfo& crashpad_info() { return crashpad_info_; }
|
|
|
|
|
|
|
|
// Returns the current head of the list of streams in `crashpad_info_`. Note
|
|
|
|
// that the returned pointer is invalidated if a stream is added or updated.
|
|
|
|
internal::UserDataMinidumpStreamListEntry* GetCurrentHead() {
|
|
|
|
return crashpad_info().GetUserDataMinidumpStreamHeadForTesting();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Returns a pointer to the next node in the list after the given `node`.
|
|
|
|
internal::UserDataMinidumpStreamListEntry* GetNext(
|
|
|
|
internal::UserDataMinidumpStreamListEntry* node) {
|
|
|
|
return reinterpret_cast<internal::UserDataMinidumpStreamListEntry*>(
|
|
|
|
node->next);
|
|
|
|
}
|
|
|
|
|
|
|
|
internal::UserDataMinidumpStreamListEntry* initial_head() {
|
|
|
|
return initial_head_;
|
|
|
|
}
|
|
|
|
|
|
|
|
internal::UserDataMinidumpStreamListEntry* initial_tail() {
|
|
|
|
return initial_tail_;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
void SetUp() override {
|
|
|
|
ASSERT_EQ(nullptr, GetCurrentHead());
|
|
|
|
|
|
|
|
// Create a simple test list with the structure
|
|
|
|
// `initial_head_` -> `initial_tail_`.
|
|
|
|
initial_tail_ = AddStream(0x11111, kInitialTailData);
|
|
|
|
initial_head_ = AddStream(0x22222, kInitialHeadData);
|
|
|
|
|
|
|
|
// Validate the list's contents.
|
|
|
|
auto current = GetCurrentHead();
|
|
|
|
ASSERT_EQ(initial_head_, current);
|
|
|
|
ASSERT_EQ(kInitialHeadData, reinterpret_cast<char*>(current->base_address));
|
|
|
|
current = GetNext(current);
|
|
|
|
ASSERT_EQ(initial_tail_, current);
|
|
|
|
ASSERT_EQ(nullptr, GetNext(current));
|
|
|
|
}
|
|
|
|
|
2024-02-13 10:08:20 -08:00
|
|
|
void TearDown() override {
|
|
|
|
// Free the list. The list lives until process exit in production, but must
|
|
|
|
// be freed in tests as multiple tests run in the same process.
|
|
|
|
auto current = GetCurrentHead();
|
|
|
|
while (current) {
|
|
|
|
auto next = GetNext(current);
|
|
|
|
delete current;
|
|
|
|
current = next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-09 12:21:45 -08:00
|
|
|
internal::UserDataMinidumpStreamListEntry* AddStream(uint32_t stream_type,
|
|
|
|
const char* data) {
|
|
|
|
return reinterpret_cast<internal::UserDataMinidumpStreamListEntry*>(
|
|
|
|
crashpad_info().AddUserDataMinidumpStream(
|
|
|
|
stream_type, data, strlen(data)));
|
|
|
|
}
|
|
|
|
|
|
|
|
CrashpadInfo crashpad_info_;
|
|
|
|
|
|
|
|
static constexpr char kInitialHeadData[] = "head";
|
|
|
|
static constexpr char kInitialTailData[] = "tail";
|
|
|
|
|
|
|
|
internal::UserDataMinidumpStreamListEntry* initial_head_ = nullptr;
|
|
|
|
internal::UserDataMinidumpStreamListEntry* initial_tail_ = nullptr;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Tests that updating the head of the list updates the head pointer, the new
|
|
|
|
// head contains the updated data, and the updated node points to the next node.
|
|
|
|
TEST_F(CrashpadInfoTest, UpdateUserDataMinidumpStreamHead) {
|
|
|
|
const std::string new_data = "this is a new string";
|
|
|
|
const auto new_entry = crashpad_info().UpdateUserDataMinidumpStream(
|
|
|
|
initial_head(), kTestStreamType, new_data.data(), new_data.size());
|
|
|
|
const auto head = GetCurrentHead();
|
|
|
|
EXPECT_EQ(new_entry, head);
|
|
|
|
EXPECT_EQ(new_data.data(), reinterpret_cast<char*>(head->base_address));
|
|
|
|
EXPECT_EQ(new_data.size(), head->size);
|
|
|
|
EXPECT_EQ(kTestStreamType, head->stream_type);
|
|
|
|
EXPECT_EQ(initial_tail(), GetNext(head));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Tests that updating the tail of the list results in a tail pointing to
|
|
|
|
// nullptr, and that the node before the updated node points to it.
|
|
|
|
TEST_F(CrashpadInfoTest, UpdateUserDataMinidumpStreamTail) {
|
|
|
|
const std::string new_data = "new";
|
|
|
|
const auto new_entry = crashpad_info().UpdateUserDataMinidumpStream(
|
|
|
|
initial_tail(), kTestStreamType, new_data.data(), new_data.size());
|
|
|
|
const auto tail = GetNext(GetCurrentHead());
|
|
|
|
EXPECT_EQ(new_entry, tail);
|
|
|
|
EXPECT_EQ(nullptr, GetNext(tail));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Tests that the handle returned from updating an entry is usable for updating
|
|
|
|
// the entry again.
|
|
|
|
TEST_F(CrashpadInfoTest, UpdateUserDataMinidumpStreamMultipleTimes) {
|
|
|
|
// Update the entry at the head; the updated entry should become the new head.
|
|
|
|
const std::string new_data = "new";
|
|
|
|
const auto new_entry_1 = crashpad_info().UpdateUserDataMinidumpStream(
|
|
|
|
initial_head(), kTestStreamType, new_data.data(), new_data.size());
|
|
|
|
EXPECT_EQ(new_entry_1, GetCurrentHead());
|
|
|
|
|
|
|
|
// Update the updated entry again; another new entry should replace it as
|
|
|
|
// head.
|
|
|
|
const auto new_entry_2 = crashpad_info().UpdateUserDataMinidumpStream(
|
|
|
|
new_entry_1, kTestStreamType, new_data.data(), new_data.size());
|
|
|
|
EXPECT_NE(new_entry_1, new_entry_2);
|
|
|
|
EXPECT_EQ(new_entry_2, GetCurrentHead());
|
|
|
|
EXPECT_EQ(initial_tail(), GetNext(GetCurrentHead()));
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
} // namespace test
|
|
|
|
} // namespace crashpad
|