mirror of
https://github.com/chromium/crashpad.git
synced 2024-12-27 15:32:10 +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_misc_info_writer.h',
|
||||||
'minidump_module_writer.cc',
|
'minidump_module_writer.cc',
|
||||||
'minidump_module_writer.h',
|
'minidump_module_writer.h',
|
||||||
|
'minidump_simple_string_dictionary_writer.cc',
|
||||||
|
'minidump_simple_string_dictionary_writer.h',
|
||||||
'minidump_stream_writer.cc',
|
'minidump_stream_writer.cc',
|
||||||
'minidump_stream_writer.h',
|
'minidump_stream_writer.h',
|
||||||
'minidump_string_writer.cc',
|
'minidump_string_writer.cc',
|
||||||
@ -83,6 +85,7 @@
|
|||||||
'minidump_memory_writer_test_util.h',
|
'minidump_memory_writer_test_util.h',
|
||||||
'minidump_misc_info_writer_test.cc',
|
'minidump_misc_info_writer_test.cc',
|
||||||
'minidump_module_writer_test.cc',
|
'minidump_module_writer_test.cc',
|
||||||
|
'minidump_simple_string_dictionary_writer_test.cc',
|
||||||
'minidump_string_writer_test.cc',
|
'minidump_string_writer_test.cc',
|
||||||
'minidump_system_info_writer_test.cc',
|
'minidump_system_info_writer_test.cc',
|
||||||
'minidump_thread_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.
|
//! \note Valid in #kStateMutable.
|
||||||
void set_string(const StringType& string) { string_.assign(string); }
|
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:
|
private:
|
||||||
MinidumpStringType string_base_;
|
MinidumpStringType string_base_;
|
||||||
StringType string_;
|
StringType string_;
|
||||||
@ -113,6 +118,11 @@ class MinidumpUTF8StringWriter final
|
|||||||
//! \note Valid in #kStateMutable.
|
//! \note Valid in #kStateMutable.
|
||||||
void SetUTF8(const std::string& string_utf8) { set_string(string_utf8); }
|
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:
|
private:
|
||||||
DISALLOW_COPY_AND_ASSIGN(MinidumpUTF8StringWriter);
|
DISALLOW_COPY_AND_ASSIGN(MinidumpUTF8StringWriter);
|
||||||
};
|
};
|
||||||
|
@ -181,8 +181,9 @@ TEST(MinidumpStringWriter, MinidumpUTF8StringWriter) {
|
|||||||
|
|
||||||
file_writer.Reset();
|
file_writer.Reset();
|
||||||
crashpad::internal::MinidumpUTF8StringWriter string_writer;
|
crashpad::internal::MinidumpUTF8StringWriter string_writer;
|
||||||
string_writer.SetUTF8(
|
std::string test_string(kTestData[index].string, kTestData[index].length);
|
||||||
std::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));
|
EXPECT_TRUE(string_writer.WriteEverything(&file_writer));
|
||||||
|
|
||||||
const size_t expected_utf8_bytes_with_nul = kTestData[index].length + 1;
|
const size_t expected_utf8_bytes_with_nul = kTestData[index].length + 1;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user