mirror of
https://github.com/chromium/crashpad.git
synced 2024-12-26 23:01:05 +08:00
Add MinidumpSimpleStringDictionaryWriter and its test.
TEST=minidump_test MinidumpSimpleStringDictionaryWriter.* R=rsesek@chromium.org Review URL: https://codereview.chromium.org/656173003
This commit is contained in:
parent
6c1a46f2bb
commit
c9db1b1d19
@ -44,6 +44,8 @@
|
||||
'minidump_misc_info_writer.h',
|
||||
'minidump_module_writer.cc',
|
||||
'minidump_module_writer.h',
|
||||
'minidump_simple_string_dictionary_writer.cc',
|
||||
'minidump_simple_string_dictionary_writer.h',
|
||||
'minidump_stream_writer.cc',
|
||||
'minidump_stream_writer.h',
|
||||
'minidump_string_writer.cc',
|
||||
@ -83,6 +85,7 @@
|
||||
'minidump_memory_writer_test_util.h',
|
||||
'minidump_misc_info_writer_test.cc',
|
||||
'minidump_module_writer_test.cc',
|
||||
'minidump_simple_string_dictionary_writer_test.cc',
|
||||
'minidump_string_writer_test.cc',
|
||||
'minidump_system_info_writer_test.cc',
|
||||
'minidump_thread_writer_test.cc',
|
||||
|
158
minidump/minidump_simple_string_dictionary_writer.cc
Normal file
158
minidump/minidump_simple_string_dictionary_writer.cc
Normal file
@ -0,0 +1,158 @@
|
||||
// Copyright 2014 The Crashpad Authors. All rights reserved.
|
||||
//
|
||||
// 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 "minidump/minidump_simple_string_dictionary_writer.h"
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "util/numeric/safe_assignment.h"
|
||||
|
||||
namespace crashpad {
|
||||
|
||||
MinidumpSimpleStringDictionaryEntryWriter::
|
||||
MinidumpSimpleStringDictionaryEntryWriter()
|
||||
: MinidumpWritable(), entry_(), key_(), value_() {
|
||||
}
|
||||
|
||||
MinidumpSimpleStringDictionaryEntryWriter::
|
||||
~MinidumpSimpleStringDictionaryEntryWriter() {
|
||||
}
|
||||
|
||||
const MinidumpSimpleStringDictionaryEntry*
|
||||
MinidumpSimpleStringDictionaryEntryWriter::MinidumpSimpleStringDictionaryEntry()
|
||||
const {
|
||||
DCHECK_EQ(state(), kStateWritable);
|
||||
|
||||
return &entry_;
|
||||
}
|
||||
|
||||
void MinidumpSimpleStringDictionaryEntryWriter::SetKeyValue(
|
||||
const std::string& key,
|
||||
const std::string& value) {
|
||||
key_.SetUTF8(key);
|
||||
value_.SetUTF8(value);
|
||||
}
|
||||
|
||||
bool MinidumpSimpleStringDictionaryEntryWriter::Freeze() {
|
||||
DCHECK_EQ(state(), kStateMutable);
|
||||
|
||||
if (!MinidumpWritable::Freeze()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
key_.RegisterRVA(&entry_.key);
|
||||
value_.RegisterRVA(&entry_.value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t MinidumpSimpleStringDictionaryEntryWriter::SizeOfObject() {
|
||||
DCHECK_GE(state(), kStateFrozen);
|
||||
|
||||
// This object doesn’t directly write anything itself. Its
|
||||
// MinidumpSimpleStringDictionaryEntry is written by its parent as part of a
|
||||
// MinidumpSimpleStringDictionary, and its children are responsible for
|
||||
// writing themselves.
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<internal::MinidumpWritable*>
|
||||
MinidumpSimpleStringDictionaryEntryWriter::Children() {
|
||||
DCHECK_GE(state(), kStateFrozen);
|
||||
|
||||
std::vector<MinidumpWritable*> children(1, &key_);
|
||||
children.push_back(&value_);
|
||||
return children;
|
||||
}
|
||||
|
||||
bool MinidumpSimpleStringDictionaryEntryWriter::WriteObject(
|
||||
FileWriterInterface* file_writer) {
|
||||
DCHECK_EQ(state(), kStateWritable);
|
||||
|
||||
// This object doesn’t directly write anything itself. Its
|
||||
// MinidumpSimpleStringDictionaryEntry is written by its parent as part of a
|
||||
// MinidumpSimpleStringDictionary, and its children are responsible for
|
||||
// writing themselves.
|
||||
return true;
|
||||
}
|
||||
|
||||
MinidumpSimpleStringDictionaryWriter::MinidumpSimpleStringDictionaryWriter()
|
||||
: MinidumpWritable(), simple_string_dictionary_base_(), entries_() {
|
||||
}
|
||||
|
||||
MinidumpSimpleStringDictionaryWriter::~MinidumpSimpleStringDictionaryWriter() {
|
||||
}
|
||||
|
||||
void MinidumpSimpleStringDictionaryWriter::AddEntry(
|
||||
MinidumpSimpleStringDictionaryEntryWriter* entry) {
|
||||
DCHECK_GE(state(), kStateMutable);
|
||||
|
||||
entries_[entry->Key()] = entry;
|
||||
}
|
||||
|
||||
bool MinidumpSimpleStringDictionaryWriter::Freeze() {
|
||||
DCHECK_EQ(state(), kStateMutable);
|
||||
|
||||
if (!MinidumpWritable::Freeze()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t entry_count = entries_.size();
|
||||
if (!AssignIfInRange(&simple_string_dictionary_base_.count, entry_count)) {
|
||||
LOG(ERROR) << "entry_count " << entry_count << " out of range";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t MinidumpSimpleStringDictionaryWriter::SizeOfObject() {
|
||||
DCHECK_GE(state(), kStateFrozen);
|
||||
|
||||
return sizeof(simple_string_dictionary_base_) +
|
||||
entries_.size() * sizeof(MinidumpSimpleStringDictionaryEntry);
|
||||
}
|
||||
|
||||
std::vector<internal::MinidumpWritable*>
|
||||
MinidumpSimpleStringDictionaryWriter::Children() {
|
||||
DCHECK_GE(state(), kStateMutable);
|
||||
|
||||
std::vector<MinidumpWritable*> children;
|
||||
for (const auto& key_entry : entries_) {
|
||||
children.push_back(key_entry.second);
|
||||
}
|
||||
|
||||
return children;
|
||||
}
|
||||
|
||||
bool MinidumpSimpleStringDictionaryWriter::WriteObject(
|
||||
FileWriterInterface* file_writer) {
|
||||
DCHECK_GE(state(), kStateWritable);
|
||||
|
||||
WritableIoVec iov;
|
||||
iov.iov_base = &simple_string_dictionary_base_;
|
||||
iov.iov_len = sizeof(simple_string_dictionary_base_);
|
||||
std::vector<WritableIoVec> iovecs(1, iov);
|
||||
|
||||
if (!entries_.empty()) {
|
||||
iov.iov_len = sizeof(MinidumpSimpleStringDictionaryEntry);
|
||||
for (const auto& key_entry : entries_) {
|
||||
iov.iov_base = key_entry.second->MinidumpSimpleStringDictionaryEntry();
|
||||
iovecs.push_back(iov);
|
||||
}
|
||||
}
|
||||
|
||||
return file_writer->WriteIoVec(&iovecs);
|
||||
}
|
||||
|
||||
} // namespace crashpad
|
125
minidump/minidump_simple_string_dictionary_writer.h
Normal file
125
minidump/minidump_simple_string_dictionary_writer.h
Normal file
@ -0,0 +1,125 @@
|
||||
// Copyright 2014 The Crashpad Authors. All rights reserved.
|
||||
//
|
||||
// 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.
|
||||
|
||||
#ifndef CRASHPAD_MINIDUMP_MINIDUMP_SIMPLE_STRING_DICTIONARY_WRITER_H_
|
||||
#define CRASHPAD_MINIDUMP_MINIDUMP_SIMPLE_STRING_DICTIONARY_WRITER_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "minidump/minidump_extensions.h"
|
||||
#include "minidump/minidump_string_writer.h"
|
||||
#include "minidump/minidump_writable.h"
|
||||
#include "util/file/file_writer.h"
|
||||
|
||||
namespace crashpad {
|
||||
|
||||
//! \brief The writer for a MinidumpSimpleStringDictionaryEntry object in a
|
||||
//! minidump file.
|
||||
//!
|
||||
//! Because MinidumpSimpleStringDictionaryEntry objects only appear as elements
|
||||
//! of MinidumpSimpleStringDictionary objects, this class does not write any
|
||||
//! data on its own. It makes its MinidumpSimpleStringDictionaryEntry data
|
||||
//! available to its MinidumpSimpleStringDictionaryWriter parent, which writes
|
||||
//! it as part of a MinidumpSimpleStringDictionary.
|
||||
class MinidumpSimpleStringDictionaryEntryWriter final
|
||||
: public internal::MinidumpWritable {
|
||||
public:
|
||||
MinidumpSimpleStringDictionaryEntryWriter();
|
||||
~MinidumpSimpleStringDictionaryEntryWriter();
|
||||
|
||||
//! \brief Returns a MinidumpSimpleStringDictionaryEntry referencing this
|
||||
//! object’s data.
|
||||
//!
|
||||
//! This method is expected to be called by a
|
||||
//! MinidumpSimpleStringDictionaryWriter in order to obtain a
|
||||
//! MinidumpSimpleStringDictionaryEntry to include in its list.
|
||||
//!
|
||||
//! \note Valid in #kStateWritable.
|
||||
const MinidumpSimpleStringDictionaryEntry*
|
||||
MinidumpSimpleStringDictionaryEntry() const;
|
||||
|
||||
//! \brief Sets the strings to be written as the entry object’s key and value.
|
||||
//!
|
||||
//! \note Valid in #kStateMutable.
|
||||
void SetKeyValue(const std::string& key, const std::string& value);
|
||||
|
||||
//! \brief Retrieves the key to be written.
|
||||
//!
|
||||
//! \note Valid in any state.
|
||||
const std::string& Key() const { return key_.UTF8(); }
|
||||
|
||||
protected:
|
||||
// MinidumpWritable:
|
||||
|
||||
bool Freeze() override;
|
||||
size_t SizeOfObject() override;
|
||||
std::vector<MinidumpWritable*> Children() override;
|
||||
bool WriteObject(FileWriterInterface* file_writer) override;
|
||||
|
||||
private:
|
||||
struct MinidumpSimpleStringDictionaryEntry entry_;
|
||||
internal::MinidumpUTF8StringWriter key_;
|
||||
internal::MinidumpUTF8StringWriter value_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(MinidumpSimpleStringDictionaryEntryWriter);
|
||||
};
|
||||
|
||||
//! \brief The writer for a MinidumpSimpleStringDictionary object in a minidump
|
||||
//! file, containing a list of MinidumpSimpleStringDictionaryEntry objects.
|
||||
//!
|
||||
//! Because this class writes a representatin of a dictionary, the order of
|
||||
//! entries is insignificant. Entries may be written in any order.
|
||||
class MinidumpSimpleStringDictionaryWriter final
|
||||
: public internal::MinidumpWritable {
|
||||
public:
|
||||
MinidumpSimpleStringDictionaryWriter();
|
||||
~MinidumpSimpleStringDictionaryWriter();
|
||||
|
||||
//! \brief Adds a MinidumpSimpleStringDictionaryEntryWriter to the
|
||||
//! MinidumpSimpleStringDictionary.
|
||||
//!
|
||||
//! \a entry will become a child of this object in the overall tree of
|
||||
//! internal::MinidumpWritable objects.
|
||||
//!
|
||||
//! If the key contained in \a entry duplicates the key of an entry already
|
||||
//! present in the MinidumpSimpleStringDictionary, the new \a entry will
|
||||
//! replace the previous one.
|
||||
//!
|
||||
//! \note Valid in #kStateMutable.
|
||||
void AddEntry(MinidumpSimpleStringDictionaryEntryWriter* entry);
|
||||
|
||||
protected:
|
||||
// MinidumpWritable:
|
||||
|
||||
bool Freeze() override;
|
||||
size_t SizeOfObject() override;
|
||||
std::vector<MinidumpWritable*> Children() override;
|
||||
bool WriteObject(FileWriterInterface* file_writer) override;
|
||||
|
||||
private:
|
||||
MinidumpSimpleStringDictionary simple_string_dictionary_base_;
|
||||
std::map<std::string, MinidumpSimpleStringDictionaryEntryWriter*>
|
||||
entries_; // weak
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(MinidumpSimpleStringDictionaryWriter);
|
||||
};
|
||||
|
||||
} // namespace crashpad
|
||||
|
||||
#endif // CRASHPAD_MINIDUMP_MINIDUMP_SIMPLE_STRING_DICTIONARY_WRITER_H_
|
224
minidump/minidump_simple_string_dictionary_writer_test.cc
Normal file
224
minidump/minidump_simple_string_dictionary_writer_test.cc
Normal file
@ -0,0 +1,224 @@
|
||||
// Copyright 2014 The Crashpad Authors. All rights reserved.
|
||||
//
|
||||
// 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 "minidump/minidump_simple_string_dictionary_writer.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "minidump/minidump_extensions.h"
|
||||
#include "util/file/string_file_writer.h"
|
||||
|
||||
namespace crashpad {
|
||||
namespace test {
|
||||
namespace {
|
||||
|
||||
const MinidumpSimpleStringDictionary* MinidumpSimpleStringDictionaryCast(
|
||||
const StringFileWriter& file_writer) {
|
||||
return reinterpret_cast<const MinidumpSimpleStringDictionary*>(
|
||||
&file_writer.string()[0]);
|
||||
}
|
||||
|
||||
TEST(MinidumpSimpleStringDictionaryWriter, EmptySimpleStringDictionary) {
|
||||
StringFileWriter file_writer;
|
||||
|
||||
MinidumpSimpleStringDictionaryWriter dictionary_writer;
|
||||
|
||||
EXPECT_TRUE(dictionary_writer.WriteEverything(&file_writer));
|
||||
ASSERT_EQ(sizeof(MinidumpSimpleStringDictionary),
|
||||
file_writer.string().size());
|
||||
|
||||
const MinidumpSimpleStringDictionary* dictionary =
|
||||
MinidumpSimpleStringDictionaryCast(file_writer);
|
||||
EXPECT_EQ(0u, dictionary->count);
|
||||
}
|
||||
|
||||
std::string MinidumpUTF8StringAtRVA(const StringFileWriter& file_writer,
|
||||
RVA rva) {
|
||||
const std::string& contents = file_writer.string();
|
||||
if (rva == 0) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
if (rva + sizeof(MinidumpUTF8String) > contents.size()) {
|
||||
ADD_FAILURE()
|
||||
<< "rva " << rva << " too large for contents " << contents.size();
|
||||
return std::string();
|
||||
}
|
||||
|
||||
const MinidumpUTF8String* minidump_string =
|
||||
reinterpret_cast<const MinidumpUTF8String*>(&contents[rva]);
|
||||
|
||||
// Verify that the file has enough data for the string’s stated length plus
|
||||
// its required NUL terminator.
|
||||
if (rva + sizeof(MinidumpUTF8String) + minidump_string->Length + 1 >
|
||||
contents.size()) {
|
||||
ADD_FAILURE()
|
||||
<< "rva " << rva << ", length " << minidump_string->Length
|
||||
<< " too large for contents " << contents.size();
|
||||
return std::string();
|
||||
}
|
||||
|
||||
std::string minidump_string_data(
|
||||
reinterpret_cast<const char*>(&minidump_string->Buffer[0]),
|
||||
minidump_string->Length);
|
||||
return minidump_string_data;
|
||||
}
|
||||
|
||||
TEST(MinidumpSimpleStringDictionaryWriter, EmptyKeyValue) {
|
||||
StringFileWriter file_writer;
|
||||
|
||||
MinidumpSimpleStringDictionaryWriter dictionary_writer;
|
||||
MinidumpSimpleStringDictionaryEntryWriter entry_writer;
|
||||
dictionary_writer.AddEntry(&entry_writer);
|
||||
|
||||
EXPECT_TRUE(dictionary_writer.WriteEverything(&file_writer));
|
||||
ASSERT_EQ(sizeof(MinidumpSimpleStringDictionary) +
|
||||
sizeof(MinidumpSimpleStringDictionaryEntry) +
|
||||
2 * sizeof(MinidumpUTF8String) + 1 + 3 + 1, // 3 for padding
|
||||
file_writer.string().size());
|
||||
|
||||
const MinidumpSimpleStringDictionary* dictionary =
|
||||
MinidumpSimpleStringDictionaryCast(file_writer);
|
||||
EXPECT_EQ(1u, dictionary->count);
|
||||
EXPECT_EQ(12u, dictionary->entries[0].key);
|
||||
EXPECT_EQ(20u, dictionary->entries[0].value);
|
||||
EXPECT_EQ("",
|
||||
MinidumpUTF8StringAtRVA(file_writer, dictionary->entries[0].key));
|
||||
EXPECT_EQ("",
|
||||
MinidumpUTF8StringAtRVA(file_writer, dictionary->entries[0].value));
|
||||
}
|
||||
|
||||
TEST(MinidumpSimpleStringDictionaryWriter, OneKeyValue) {
|
||||
StringFileWriter file_writer;
|
||||
|
||||
char kKey[] = "key";
|
||||
char kValue[] = "value";
|
||||
|
||||
MinidumpSimpleStringDictionaryWriter dictionary_writer;
|
||||
MinidumpSimpleStringDictionaryEntryWriter entry_writer;
|
||||
entry_writer.SetKeyValue(kKey, kValue);
|
||||
dictionary_writer.AddEntry(&entry_writer);
|
||||
|
||||
EXPECT_TRUE(dictionary_writer.WriteEverything(&file_writer));
|
||||
ASSERT_EQ(sizeof(MinidumpSimpleStringDictionary) +
|
||||
sizeof(MinidumpSimpleStringDictionaryEntry) +
|
||||
2 * sizeof(MinidumpUTF8String) + sizeof(kKey) + sizeof(kValue),
|
||||
file_writer.string().size());
|
||||
|
||||
const MinidumpSimpleStringDictionary* dictionary =
|
||||
MinidumpSimpleStringDictionaryCast(file_writer);
|
||||
EXPECT_EQ(1u, dictionary->count);
|
||||
EXPECT_EQ(12u, dictionary->entries[0].key);
|
||||
EXPECT_EQ(20u, dictionary->entries[0].value);
|
||||
EXPECT_EQ(kKey,
|
||||
MinidumpUTF8StringAtRVA(file_writer, dictionary->entries[0].key));
|
||||
EXPECT_EQ(kValue,
|
||||
MinidumpUTF8StringAtRVA(file_writer, dictionary->entries[0].value));
|
||||
}
|
||||
|
||||
TEST(MinidumpSimpleStringDictionaryWriter, ThreeKeysValues) {
|
||||
StringFileWriter file_writer;
|
||||
|
||||
char kKey0[] = "m0";
|
||||
char kValue0[] = "value0";
|
||||
char kKey1[] = "zzz1";
|
||||
char kValue1[] = "v1";
|
||||
char kKey2[] = "aa2";
|
||||
char kValue2[] = "val2";
|
||||
|
||||
MinidumpSimpleStringDictionaryWriter dictionary_writer;
|
||||
MinidumpSimpleStringDictionaryEntryWriter entry_writer_0;
|
||||
entry_writer_0.SetKeyValue(kKey0, kValue0);
|
||||
dictionary_writer.AddEntry(&entry_writer_0);
|
||||
MinidumpSimpleStringDictionaryEntryWriter entry_writer_1;
|
||||
entry_writer_1.SetKeyValue(kKey1, kValue1);
|
||||
dictionary_writer.AddEntry(&entry_writer_1);
|
||||
MinidumpSimpleStringDictionaryEntryWriter entry_writer_2;
|
||||
entry_writer_2.SetKeyValue(kKey2, kValue2);
|
||||
dictionary_writer.AddEntry(&entry_writer_2);
|
||||
|
||||
EXPECT_TRUE(dictionary_writer.WriteEverything(&file_writer));
|
||||
ASSERT_EQ(sizeof(MinidumpSimpleStringDictionary) +
|
||||
3 * sizeof(MinidumpSimpleStringDictionaryEntry) +
|
||||
6 * sizeof(MinidumpUTF8String) + sizeof(kKey2) +
|
||||
sizeof(kValue2) + 3 + sizeof(kKey0) + 1 + sizeof(kValue0) + 1 +
|
||||
sizeof(kKey1) + 3 + sizeof(kValue1),
|
||||
file_writer.string().size());
|
||||
|
||||
const MinidumpSimpleStringDictionary* dictionary =
|
||||
MinidumpSimpleStringDictionaryCast(file_writer);
|
||||
EXPECT_EQ(3u, dictionary->count);
|
||||
EXPECT_EQ(28u, dictionary->entries[0].key);
|
||||
EXPECT_EQ(36u, dictionary->entries[0].value);
|
||||
EXPECT_EQ(48u, dictionary->entries[1].key);
|
||||
EXPECT_EQ(56u, dictionary->entries[1].value);
|
||||
EXPECT_EQ(68u, dictionary->entries[2].key);
|
||||
EXPECT_EQ(80u, dictionary->entries[2].value);
|
||||
|
||||
// The entries don’t appear in the order they were added. The current
|
||||
// implementation uses a std::map and sorts keys, so the entires appear in
|
||||
// alphabetical order. However, this is an implementation detail, and it’s OK
|
||||
// if the writer stops sorting in this order. Testing for a specific order is
|
||||
// just the easiest way to write this test while the writer will output things
|
||||
// in a known order.
|
||||
EXPECT_EQ(kKey2,
|
||||
MinidumpUTF8StringAtRVA(file_writer, dictionary->entries[0].key));
|
||||
EXPECT_EQ(kValue2,
|
||||
MinidumpUTF8StringAtRVA(file_writer, dictionary->entries[0].value));
|
||||
EXPECT_EQ(kKey0,
|
||||
MinidumpUTF8StringAtRVA(file_writer, dictionary->entries[1].key));
|
||||
EXPECT_EQ(kValue0,
|
||||
MinidumpUTF8StringAtRVA(file_writer, dictionary->entries[1].value));
|
||||
EXPECT_EQ(kKey1,
|
||||
MinidumpUTF8StringAtRVA(file_writer, dictionary->entries[2].key));
|
||||
EXPECT_EQ(kValue1,
|
||||
MinidumpUTF8StringAtRVA(file_writer, dictionary->entries[2].value));
|
||||
}
|
||||
|
||||
TEST(MinidumpSimpleStringDictionaryWriter, DuplicateKeyValue) {
|
||||
StringFileWriter file_writer;
|
||||
|
||||
char kKey[] = "key";
|
||||
char kValue0[] = "fake_value";
|
||||
char kValue1[] = "value";
|
||||
|
||||
MinidumpSimpleStringDictionaryWriter dictionary_writer;
|
||||
MinidumpSimpleStringDictionaryEntryWriter entry_writer_0;
|
||||
entry_writer_0.SetKeyValue(kKey, kValue0);
|
||||
dictionary_writer.AddEntry(&entry_writer_0);
|
||||
MinidumpSimpleStringDictionaryEntryWriter entry_writer_1;
|
||||
entry_writer_1.SetKeyValue(kKey, kValue1);
|
||||
dictionary_writer.AddEntry(&entry_writer_1);
|
||||
|
||||
EXPECT_TRUE(dictionary_writer.WriteEverything(&file_writer));
|
||||
ASSERT_EQ(sizeof(MinidumpSimpleStringDictionary) +
|
||||
sizeof(MinidumpSimpleStringDictionaryEntry) +
|
||||
2 * sizeof(MinidumpUTF8String) + sizeof(kKey) + sizeof(kValue1),
|
||||
file_writer.string().size());
|
||||
|
||||
const MinidumpSimpleStringDictionary* dictionary =
|
||||
MinidumpSimpleStringDictionaryCast(file_writer);
|
||||
EXPECT_EQ(1u, dictionary->count);
|
||||
EXPECT_EQ(12u, dictionary->entries[0].key);
|
||||
EXPECT_EQ(20u, dictionary->entries[0].value);
|
||||
EXPECT_EQ(kKey,
|
||||
MinidumpUTF8StringAtRVA(file_writer, dictionary->entries[0].key));
|
||||
EXPECT_EQ(kValue1,
|
||||
MinidumpUTF8StringAtRVA(file_writer, dictionary->entries[0].value));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace test
|
||||
} // namespace crashpad
|
@ -69,6 +69,11 @@ class MinidumpStringWriter : public MinidumpWritable {
|
||||
//! \note Valid in #kStateMutable.
|
||||
void set_string(const StringType& string) { string_.assign(string); }
|
||||
|
||||
//! \brief Retrieves the string to be written.
|
||||
//!
|
||||
//! \note Valid in any state.
|
||||
const StringType& string() const { return string_; }
|
||||
|
||||
private:
|
||||
MinidumpStringType string_base_;
|
||||
StringType string_;
|
||||
@ -113,6 +118,11 @@ class MinidumpUTF8StringWriter final
|
||||
//! \note Valid in #kStateMutable.
|
||||
void SetUTF8(const std::string& string_utf8) { set_string(string_utf8); }
|
||||
|
||||
//! \brief Retrieves the string to be written.
|
||||
//!
|
||||
//! \note Valid in any state.
|
||||
const std::string& UTF8() const { return string(); }
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(MinidumpUTF8StringWriter);
|
||||
};
|
||||
|
@ -181,8 +181,9 @@ TEST(MinidumpStringWriter, MinidumpUTF8StringWriter) {
|
||||
|
||||
file_writer.Reset();
|
||||
crashpad::internal::MinidumpUTF8StringWriter string_writer;
|
||||
string_writer.SetUTF8(
|
||||
std::string(kTestData[index].string, kTestData[index].length));
|
||||
std::string test_string(kTestData[index].string, kTestData[index].length);
|
||||
string_writer.SetUTF8(test_string);
|
||||
EXPECT_EQ(test_string, string_writer.UTF8());
|
||||
EXPECT_TRUE(string_writer.WriteEverything(&file_writer));
|
||||
|
||||
const size_t expected_utf8_bytes_with_nul = kTestData[index].length + 1;
|
||||
|
Loading…
x
Reference in New Issue
Block a user