Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(226)

Unified Diff: minidump/minidump_writable_test.cc

Issue 432003005: Introduce MinidumpWritable, its dependencies, and their tests (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: Address review comments Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « minidump/minidump_writable.cc ('k') | util/file/fd_io.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: minidump/minidump_writable_test.cc
diff --git a/minidump/minidump_writable_test.cc b/minidump/minidump_writable_test.cc
new file mode 100644
index 0000000000000000000000000000000000000000..6adad96806cbd13c1037f9aaef729a7a9ae8862e
--- /dev/null
+++ b/minidump/minidump_writable_test.cc
@@ -0,0 +1,835 @@
+// 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_writable.h"
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "gtest/gtest.h"
+#include "util/file/string_file_writer.h"
+
+namespace {
+
+using namespace crashpad;
+using namespace testing;
+
+class BaseTestMinidumpWritable : public crashpad::internal::MinidumpWritable {
+ public:
+ BaseTestMinidumpWritable()
+ : MinidumpWritable(),
+ children_(),
+ expected_offset_(-1),
+ alignment_(0),
+ phase_(kPhaseEarly),
+ has_alignment_(false),
+ has_phase_(false),
+ verified_(false) {}
+
+ ~BaseTestMinidumpWritable() { EXPECT_TRUE(verified_); }
+
+ void SetAlignment(size_t alignment) {
+ alignment_ = alignment;
+ has_alignment_ = true;
+ }
+
+ void AddChild(BaseTestMinidumpWritable* child) { children_.push_back(child); }
+
+ void SetPhaseLate() {
+ phase_ = kPhaseLate;
+ has_phase_ = true;
+ }
+
+ void Verify() {
+ verified_ = true;
+ EXPECT_EQ(kStateWritten, state());
+ for (BaseTestMinidumpWritable* child : children_) {
+ child->Verify();
+ }
+ }
+
+ protected:
+ virtual bool Freeze() override {
+ EXPECT_EQ(kStateMutable, state());
+ bool rv = MinidumpWritable::Freeze();
+ EXPECT_TRUE(rv);
+ EXPECT_EQ(kStateFrozen, state());
+ return rv;
+ }
+
+ virtual size_t Alignment() override {
+ EXPECT_GE(state(), kStateFrozen);
+ return has_alignment_ ? alignment_ : MinidumpWritable::Alignment();
+ }
+
+ virtual std::vector<MinidumpWritable*> Children() override {
+ EXPECT_GE(state(), kStateFrozen);
+ if (!children_.empty()) {
+ std::vector<MinidumpWritable*> children;
+ for (BaseTestMinidumpWritable* child : children_) {
+ children.push_back(child);
+ }
+ return children;
+ }
+ return MinidumpWritable::Children();
+ }
+
+ virtual Phase WritePhase() override {
+ return has_phase_ ? phase_ : MinidumpWritable::Phase();
+ }
+
+ virtual bool WillWriteAtOffsetImpl(off_t offset) override {
+ EXPECT_EQ(state(), kStateFrozen);
+ expected_offset_ = offset;
+ bool rv = MinidumpWritable::WillWriteAtOffsetImpl(offset);
+ EXPECT_TRUE(rv);
+ return rv;
+ }
+
+ virtual bool WriteObject(FileWriterInterface* file_writer) override {
+ EXPECT_EQ(state(), kStateWritable);
+ EXPECT_EQ(expected_offset_, file_writer->Seek(0, SEEK_CUR));
+
+ // Subclasses must override this.
+ return false;
+ }
+
+ private:
+ std::vector<BaseTestMinidumpWritable*> children_;
+ off_t expected_offset_;
+ size_t alignment_;
+ Phase phase_;
+ bool has_alignment_;
+ bool has_phase_;
+ bool verified_;
+
+ DISALLOW_COPY_AND_ASSIGN(BaseTestMinidumpWritable);
+};
+
+class TestStringMinidumpWritable final : public BaseTestMinidumpWritable {
+ public:
+ TestStringMinidumpWritable() : BaseTestMinidumpWritable(), data_() {}
+
+ ~TestStringMinidumpWritable() {}
+
+ void SetData(const std::string& string) { data_ = string; }
+
+ protected:
+ virtual size_t SizeOfObject() override {
+ EXPECT_GE(state(), kStateFrozen);
+ return data_.size();
+ }
+
+ virtual bool WriteObject(FileWriterInterface* file_writer) override {
+ BaseTestMinidumpWritable::WriteObject(file_writer);
+ EXPECT_TRUE(file_writer->Write(&data_[0], data_.size()));
+ return true;
+ }
+
+ private:
+ std::string data_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestStringMinidumpWritable);
+};
+
+TEST(MinidumpWritable, MinidumpWritable) {
+ StringFileWriter writer;
+
+ {
+ SCOPED_TRACE("empty");
+ writer.Reset();
+ TestStringMinidumpWritable string_writable;
+ EXPECT_TRUE(string_writable.WriteEverything(&writer));
+ EXPECT_TRUE(writer.string().empty());
+ string_writable.Verify();
+ }
+
+ {
+ SCOPED_TRACE("childless");
+ writer.Reset();
+ TestStringMinidumpWritable string_writable;
+ string_writable.SetData("a");
+ EXPECT_TRUE(string_writable.WriteEverything(&writer));
+ EXPECT_EQ(1u, writer.string().size());
+ EXPECT_EQ("a", writer.string());
+ string_writable.Verify();
+ }
+
+ {
+ SCOPED_TRACE("parent-child");
+ writer.Reset();
+ TestStringMinidumpWritable parent;
+ parent.SetData("b");
+ TestStringMinidumpWritable child;
+ child.SetData("c");
+ parent.AddChild(&child);
+ EXPECT_TRUE(parent.WriteEverything(&writer));
+ EXPECT_EQ(5u, writer.string().size());
+ EXPECT_EQ(std::string("b\0\0\0c", 5), writer.string());
+ parent.Verify();
+ }
+
+ {
+ SCOPED_TRACE("base alignment 2");
+ writer.Reset();
+ TestStringMinidumpWritable parent;
+ parent.SetData("de");
+ TestStringMinidumpWritable child;
+ child.SetData("f");
+ parent.AddChild(&child);
+ EXPECT_TRUE(parent.WriteEverything(&writer));
+ EXPECT_EQ(5u, writer.string().size());
+ EXPECT_EQ(std::string("de\0\0f", 5), writer.string());
+ parent.Verify();
+ }
+
+ {
+ SCOPED_TRACE("base alignment 3");
+ writer.Reset();
+ TestStringMinidumpWritable parent;
+ parent.SetData("ghi");
+ TestStringMinidumpWritable child;
+ child.SetData("j");
+ parent.AddChild(&child);
+ EXPECT_TRUE(parent.WriteEverything(&writer));
+ EXPECT_EQ(5u, writer.string().size());
+ EXPECT_EQ(std::string("ghi\0j", 5), writer.string());
+ parent.Verify();
+ }
+
+ {
+ SCOPED_TRACE("base alignment 4");
+ writer.Reset();
+ TestStringMinidumpWritable parent;
+ parent.SetData("klmn");
+ TestStringMinidumpWritable child;
+ child.SetData("o");
+ parent.AddChild(&child);
+ EXPECT_TRUE(parent.WriteEverything(&writer));
+ EXPECT_EQ(5u, writer.string().size());
+ EXPECT_EQ("klmno", writer.string());
+ parent.Verify();
+ }
+
+ {
+ SCOPED_TRACE("base alignment 5");
+ writer.Reset();
+ TestStringMinidumpWritable parent;
+ parent.SetData("pqrst");
+ TestStringMinidumpWritable child;
+ child.SetData("u");
+ parent.AddChild(&child);
+ EXPECT_TRUE(parent.WriteEverything(&writer));
+ EXPECT_EQ(9u, writer.string().size());
+ EXPECT_EQ(std::string("pqrst\0\0\0u", 9), writer.string());
+ parent.Verify();
+ }
+
+ {
+ SCOPED_TRACE("two children");
+ writer.Reset();
+ TestStringMinidumpWritable parent;
+ parent.SetData("parent");
+ TestStringMinidumpWritable child_0;
+ child_0.SetData("child_0");
+ parent.AddChild(&child_0);
+ TestStringMinidumpWritable child_1;
+ child_1.SetData("child_1");
+ parent.AddChild(&child_1);
+ EXPECT_TRUE(parent.WriteEverything(&writer));
+ EXPECT_EQ(23u, writer.string().size());
+ EXPECT_EQ(std::string("parent\0\0child_0\0child_1", 23), writer.string());
+ parent.Verify();
+ }
+
+ {
+ SCOPED_TRACE("grandchild");
+ writer.Reset();
+ TestStringMinidumpWritable parent;
+ parent.SetData("parent");
+ TestStringMinidumpWritable child;
+ child.SetData("child");
+ parent.AddChild(&child);
+ TestStringMinidumpWritable grandchild;
+ grandchild.SetData("grandchild");
+ child.AddChild(&grandchild);
+ EXPECT_TRUE(parent.WriteEverything(&writer));
+ EXPECT_EQ(26u, writer.string().size());
+ EXPECT_EQ(std::string("parent\0\0child\0\0\0grandchild", 26),
+ writer.string());
+ parent.Verify();
+ }
+
+ {
+ SCOPED_TRACE("grandchild with empty parent");
+ writer.Reset();
+ TestStringMinidumpWritable parent;
+ TestStringMinidumpWritable child;
+ child.SetData("child");
+ parent.AddChild(&child);
+ TestStringMinidumpWritable grandchild;
+ grandchild.SetData("grandchild");
+ child.AddChild(&grandchild);
+ EXPECT_TRUE(parent.WriteEverything(&writer));
+ EXPECT_EQ(18u, writer.string().size());
+ EXPECT_EQ(std::string("child\0\0\0grandchild", 18), writer.string());
+ parent.Verify();
+ }
+
+ {
+ SCOPED_TRACE("grandchild with empty child");
+ writer.Reset();
+ TestStringMinidumpWritable parent;
+ parent.SetData("parent");
+ TestStringMinidumpWritable child;
+ parent.AddChild(&child);
+ TestStringMinidumpWritable grandchild;
+ grandchild.SetData("grandchild");
+ child.AddChild(&grandchild);
+ EXPECT_TRUE(parent.WriteEverything(&writer));
+ EXPECT_EQ(18u, writer.string().size());
+ EXPECT_EQ(std::string("parent\0\0grandchild", 18), writer.string());
+ parent.Verify();
+ }
+
+ {
+ SCOPED_TRACE("grandchild with empty grandchild");
+ writer.Reset();
+ TestStringMinidumpWritable parent;
+ parent.SetData("parent");
+ TestStringMinidumpWritable child;
+ child.SetData("child");
+ parent.AddChild(&child);
+ TestStringMinidumpWritable grandchild;
+ child.AddChild(&grandchild);
+ EXPECT_TRUE(parent.WriteEverything(&writer));
+ EXPECT_EQ(13u, writer.string().size());
+ EXPECT_EQ(std::string("parent\0\0child", 13), writer.string());
+ parent.Verify();
+ }
+
+ {
+ SCOPED_TRACE("grandchild with late-phase grandchild");
+ writer.Reset();
+ TestStringMinidumpWritable parent;
+ parent.SetData("parent");
+ TestStringMinidumpWritable child;
+ child.SetData("child");
+ parent.AddChild(&child);
+ TestStringMinidumpWritable grandchild;
+ grandchild.SetData("grandchild");
+ grandchild.SetPhaseLate();
+ child.AddChild(&grandchild);
+ EXPECT_TRUE(parent.WriteEverything(&writer));
+ EXPECT_EQ(26u, writer.string().size());
+ EXPECT_EQ(std::string("parent\0\0child\0\0\0grandchild", 26),
+ writer.string());
+ parent.Verify();
+ }
+
+ {
+ SCOPED_TRACE("grandchild with late-phase child");
+ writer.Reset();
+ TestStringMinidumpWritable parent;
+ parent.SetData("parent");
+ TestStringMinidumpWritable child;
+ child.SetData("child");
+ child.SetPhaseLate();
+ parent.AddChild(&child);
+ TestStringMinidumpWritable grandchild;
+ grandchild.SetData("grandchild");
+ child.AddChild(&grandchild);
+ EXPECT_TRUE(parent.WriteEverything(&writer));
+ EXPECT_EQ(25u, writer.string().size());
+ EXPECT_EQ(std::string("parent\0\0grandchild\0\0child", 25),
+ writer.string());
+ parent.Verify();
+ }
+
+ {
+ SCOPED_TRACE("family tree");
+ writer.Reset();
+ TestStringMinidumpWritable parent;
+ parent.SetData("P..");
+ TestStringMinidumpWritable child_0;
+ child_0.SetData("C0.");
+ parent.AddChild(&child_0);
+ TestStringMinidumpWritable child_1;
+ child_1.SetData("C1.");
+ parent.AddChild(&child_1);
+ TestStringMinidumpWritable grandchild_00;
+ grandchild_00.SetData("G00");
+ child_0.AddChild(&grandchild_00);
+ TestStringMinidumpWritable grandchild_01;
+ grandchild_01.SetData("G01");
+ child_0.AddChild(&grandchild_01);
+ TestStringMinidumpWritable grandchild_10;
+ grandchild_10.SetData("G10");
+ child_1.AddChild(&grandchild_10);
+ TestStringMinidumpWritable grandchild_11;
+ grandchild_11.SetData("G11");
+ child_1.AddChild(&grandchild_11);
+ EXPECT_TRUE(parent.WriteEverything(&writer));
+ EXPECT_EQ(27u, writer.string().size());
+ EXPECT_EQ(std::string("P..\0C0.\0G00\0G01\0C1.\0G10\0G11", 27),
+ writer.string());
+ parent.Verify();
+ }
+
+ {
+ SCOPED_TRACE("family tree with C0 late");
+ writer.Reset();
+ TestStringMinidumpWritable parent;
+ parent.SetData("P..");
+ TestStringMinidumpWritable child_0;
+ child_0.SetData("C0.");
+ child_0.SetPhaseLate();
+ parent.AddChild(&child_0);
+ TestStringMinidumpWritable child_1;
+ child_1.SetData("C1.");
+ parent.AddChild(&child_1);
+ TestStringMinidumpWritable grandchild_00;
+ grandchild_00.SetData("G00");
+ child_0.AddChild(&grandchild_00);
+ TestStringMinidumpWritable grandchild_01;
+ grandchild_01.SetData("G01");
+ child_0.AddChild(&grandchild_01);
+ TestStringMinidumpWritable grandchild_10;
+ grandchild_10.SetData("G10");
+ child_1.AddChild(&grandchild_10);
+ TestStringMinidumpWritable grandchild_11;
+ grandchild_11.SetData("G11");
+ child_1.AddChild(&grandchild_11);
+ EXPECT_TRUE(parent.WriteEverything(&writer));
+ EXPECT_EQ(27u, writer.string().size());
+ EXPECT_EQ(std::string("P..\0G00\0G01\0C1.\0G10\0G11\0C0.", 27),
+ writer.string());
+ parent.Verify();
+ }
+
+ {
+ SCOPED_TRACE("family tree with G0 late");
+ writer.Reset();
+ TestStringMinidumpWritable parent;
+ parent.SetData("P..");
+ TestStringMinidumpWritable child_0;
+ child_0.SetData("C0.");
+ parent.AddChild(&child_0);
+ TestStringMinidumpWritable child_1;
+ child_1.SetData("C1.");
+ parent.AddChild(&child_1);
+ TestStringMinidumpWritable grandchild_00;
+ grandchild_00.SetData("G00");
+ grandchild_00.SetPhaseLate();
+ child_0.AddChild(&grandchild_00);
+ TestStringMinidumpWritable grandchild_01;
+ grandchild_01.SetData("G01");
+ grandchild_01.SetPhaseLate();
+ child_0.AddChild(&grandchild_01);
+ TestStringMinidumpWritable grandchild_10;
+ grandchild_10.SetData("G10");
+ child_1.AddChild(&grandchild_10);
+ TestStringMinidumpWritable grandchild_11;
+ grandchild_11.SetData("G11");
+ child_1.AddChild(&grandchild_11);
+ EXPECT_TRUE(parent.WriteEverything(&writer));
+ EXPECT_EQ(27u, writer.string().size());
+ EXPECT_EQ(std::string("P..\0C0.\0C1.\0G10\0G11\0G00\0G01", 27),
+ writer.string());
+ parent.Verify();
+ }
+
+ {
+ SCOPED_TRACE("align 1");
+ writer.Reset();
+ TestStringMinidumpWritable parent;
+ parent.SetData("p");
+ TestStringMinidumpWritable child;
+ child.SetData("c");
+ child.SetAlignment(1);
+ parent.AddChild(&child);
+ EXPECT_TRUE(parent.WriteEverything(&writer));
+ EXPECT_EQ(2u, writer.string().size());
+ EXPECT_EQ("pc", writer.string());
+ parent.Verify();
+ }
+
+ {
+ SCOPED_TRACE("align 2");
+ writer.Reset();
+ TestStringMinidumpWritable parent;
+ parent.SetData("p");
+ TestStringMinidumpWritable child;
+ child.SetData("c");
+ child.SetAlignment(2);
+ parent.AddChild(&child);
+ EXPECT_TRUE(parent.WriteEverything(&writer));
+ EXPECT_EQ(3u, writer.string().size());
+ EXPECT_EQ(std::string("p\0c", 3), writer.string());
+ parent.Verify();
+ }
+}
+
+class TestRVAMinidumpWritable final : public BaseTestMinidumpWritable {
+ public:
+ TestRVAMinidumpWritable() : BaseTestMinidumpWritable(), rva_() {}
+
+ ~TestRVAMinidumpWritable() {}
+
+ void SetRVA(MinidumpWritable* other) { other->RegisterRVA(&rva_); }
+
+ protected:
+ virtual size_t SizeOfObject() override {
+ EXPECT_GE(state(), kStateFrozen);
+ return sizeof(rva_);
+ }
+
+ virtual bool WriteObject(FileWriterInterface* file_writer) override {
+ BaseTestMinidumpWritable::WriteObject(file_writer);
+ EXPECT_TRUE(file_writer->Write(&rva_, sizeof(rva_)));
+ return true;
+ }
+
+ private:
+ RVA rva_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestRVAMinidumpWritable);
+};
+
+RVA RVAAtIndex(const std::string& string, size_t index) {
+ return *reinterpret_cast<const RVA*>(&string[index * sizeof(RVA)]);
+}
+
+TEST(MinidumpWritable, RVA) {
+ StringFileWriter writer;
+
+ {
+ SCOPED_TRACE("unset");
+ writer.Reset();
+ TestRVAMinidumpWritable rva_writable;
+ EXPECT_TRUE(rva_writable.WriteEverything(&writer));
+
+ ASSERT_EQ(sizeof(RVA), writer.string().size());
+ EXPECT_EQ(0 * sizeof(RVA), RVAAtIndex(writer.string(), 0));
+ rva_writable.Verify();
+ }
+
+ {
+ SCOPED_TRACE("self");
+ writer.Reset();
+ TestRVAMinidumpWritable rva_writable;
+ rva_writable.SetRVA(&rva_writable);
+ EXPECT_TRUE(rva_writable.WriteEverything(&writer));
+
+ ASSERT_EQ(sizeof(RVA), writer.string().size());
+ EXPECT_EQ(0 * sizeof(RVA), RVAAtIndex(writer.string(), 0));
+ rva_writable.Verify();
+ }
+
+ {
+ SCOPED_TRACE("parent-child self");
+ writer.Reset();
+ TestRVAMinidumpWritable parent;
+ parent.SetRVA(&parent);
+ TestRVAMinidumpWritable child;
+ child.SetRVA(&child);
+ parent.AddChild(&child);
+ EXPECT_TRUE(parent.WriteEverything(&writer));
+
+ ASSERT_EQ(2 * sizeof(RVA), writer.string().size());
+ EXPECT_EQ(0 * sizeof(RVA), RVAAtIndex(writer.string(), 0));
+ EXPECT_EQ(1 * sizeof(RVA), RVAAtIndex(writer.string(), 1));
+ parent.Verify();
+ }
+
+ {
+ SCOPED_TRACE("parent-child only");
+ writer.Reset();
+ TestRVAMinidumpWritable parent;
+ TestRVAMinidumpWritable child;
+ parent.SetRVA(&child);
+ parent.AddChild(&child);
+ EXPECT_TRUE(parent.WriteEverything(&writer));
+
+ ASSERT_EQ(2 * sizeof(RVA), writer.string().size());
+ EXPECT_EQ(1 * sizeof(RVA), RVAAtIndex(writer.string(), 0));
+ EXPECT_EQ(0 * sizeof(RVA), RVAAtIndex(writer.string(), 1));
+ parent.Verify();
+ }
+
+ {
+ SCOPED_TRACE("parent-child circular");
+ writer.Reset();
+ TestRVAMinidumpWritable parent;
+ TestRVAMinidumpWritable child;
+ parent.SetRVA(&child);
+ child.SetRVA(&parent);
+ parent.AddChild(&child);
+ EXPECT_TRUE(parent.WriteEverything(&writer));
+
+ ASSERT_EQ(2 * sizeof(RVA), writer.string().size());
+ EXPECT_EQ(1 * sizeof(RVA), RVAAtIndex(writer.string(), 0));
+ EXPECT_EQ(0 * sizeof(RVA), RVAAtIndex(writer.string(), 1));
+ parent.Verify();
+ }
+
+ {
+ SCOPED_TRACE("grandchildren");
+ writer.Reset();
+ TestRVAMinidumpWritable parent;
+ TestRVAMinidumpWritable child;
+ parent.SetRVA(&child);
+ parent.AddChild(&child);
+ TestRVAMinidumpWritable grandchild_0;
+ grandchild_0.SetRVA(&child);
+ child.AddChild(&grandchild_0);
+ TestRVAMinidumpWritable grandchild_1;
+ grandchild_1.SetRVA(&child);
+ child.AddChild(&grandchild_1);
+ TestRVAMinidumpWritable grandchild_2;
+ grandchild_2.SetRVA(&child);
+ child.AddChild(&grandchild_2);
+ EXPECT_TRUE(parent.WriteEverything(&writer));
+
+ ASSERT_EQ(5 * sizeof(RVA), writer.string().size());
+ EXPECT_EQ(1 * sizeof(RVA), RVAAtIndex(writer.string(), 0));
+ EXPECT_EQ(0 * sizeof(RVA), RVAAtIndex(writer.string(), 1));
+ EXPECT_EQ(1 * sizeof(RVA), RVAAtIndex(writer.string(), 2));
+ EXPECT_EQ(1 * sizeof(RVA), RVAAtIndex(writer.string(), 3));
+ EXPECT_EQ(1 * sizeof(RVA), RVAAtIndex(writer.string(), 4));
+ parent.Verify();
+ }
+}
+
+class TestLocationDescriptorMinidumpWritable final
+ : public BaseTestMinidumpWritable {
+ public:
+ TestLocationDescriptorMinidumpWritable()
+ : BaseTestMinidumpWritable(), location_descriptor_(), string_() {}
+
+ ~TestLocationDescriptorMinidumpWritable() {}
+
+ void SetLocationDescriptor(MinidumpWritable* other) {
+ other->RegisterLocationDescriptor(&location_descriptor_);
+ }
+
+ void SetString(const std::string& string) { string_ = string; }
+
+ protected:
+ virtual size_t SizeOfObject() override {
+ EXPECT_GE(state(), kStateFrozen);
+ // NUL-terminate.
+ return sizeof(location_descriptor_) + string_.size() + 1;
+ }
+
+ virtual bool WriteObject(FileWriterInterface* file_writer) override {
+ BaseTestMinidumpWritable::WriteObject(file_writer);
+ WritableIoVec iov;
+ iov.iov_base = &location_descriptor_;
+ iov.iov_len = sizeof(location_descriptor_);
+ std::vector<WritableIoVec> iovecs(1, iov);
+ // NUL-terminate.
+ iov.iov_base = &string_[0];
+ iov.iov_len = string_.size() + 1;
+ iovecs.push_back(iov);
+ EXPECT_TRUE(file_writer->WriteIoVec(&iovecs));
+ return true;
+ }
+
+ private:
+ MINIDUMP_LOCATION_DESCRIPTOR location_descriptor_;
+ std::string string_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestLocationDescriptorMinidumpWritable);
+};
+
+struct LocationDescriptorAndData {
+ MINIDUMP_LOCATION_DESCRIPTOR location_descriptor;
+ char string[1];
+};
+
+const LocationDescriptorAndData* LDDAtIndex(const std::string& string,
+ size_t index) {
+ return reinterpret_cast<const LocationDescriptorAndData*>(&string[index]);
+}
+
+TEST(MinidumpWritable, LocationDescriptor) {
+ StringFileWriter writer;
+
+ {
+ SCOPED_TRACE("unset");
+ writer.Reset();
+ TestLocationDescriptorMinidumpWritable location_descriptor_writable;
+ EXPECT_TRUE(location_descriptor_writable.WriteEverything(&writer));
+
+ ASSERT_EQ(9u, writer.string().size());
+ const LocationDescriptorAndData* ldd = LDDAtIndex(writer.string(), 0);
+ EXPECT_EQ(0u, ldd->location_descriptor.DataSize);
+ EXPECT_EQ(0u, ldd->location_descriptor.Rva);
+ location_descriptor_writable.Verify();
+ }
+
+ {
+ SCOPED_TRACE("self");
+ writer.Reset();
+ TestLocationDescriptorMinidumpWritable location_descriptor_writable;
+ location_descriptor_writable.SetLocationDescriptor(
+ &location_descriptor_writable);
+ EXPECT_TRUE(location_descriptor_writable.WriteEverything(&writer));
+
+ ASSERT_EQ(9u, writer.string().size());
+ const LocationDescriptorAndData* ldd = LDDAtIndex(writer.string(), 0);
+ EXPECT_EQ(9u, ldd->location_descriptor.DataSize);
+ EXPECT_EQ(0u, ldd->location_descriptor.Rva);
+ location_descriptor_writable.Verify();
+ }
+
+ {
+ SCOPED_TRACE("self with data");
+ writer.Reset();
+ TestLocationDescriptorMinidumpWritable location_descriptor_writable;
+ location_descriptor_writable.SetLocationDescriptor(
+ &location_descriptor_writable);
+ location_descriptor_writable.SetString("zz");
+ EXPECT_TRUE(location_descriptor_writable.WriteEverything(&writer));
+
+ ASSERT_EQ(11u, writer.string().size());
+ const LocationDescriptorAndData* ldd = LDDAtIndex(writer.string(), 0);
+ EXPECT_EQ(11u, ldd->location_descriptor.DataSize);
+ EXPECT_EQ(0u, ldd->location_descriptor.Rva);
+ EXPECT_STREQ("zz", ldd->string);
+ location_descriptor_writable.Verify();
+ }
+
+ {
+ SCOPED_TRACE("parent-child self");
+ writer.Reset();
+ TestLocationDescriptorMinidumpWritable parent;
+ parent.SetLocationDescriptor(&parent);
+ parent.SetString("yy");
+ TestLocationDescriptorMinidumpWritable child;
+ child.SetLocationDescriptor(&child);
+ child.SetString("x");
+ parent.AddChild(&child);
+ EXPECT_TRUE(parent.WriteEverything(&writer));
+
+ ASSERT_EQ(22u, writer.string().size());
+ const LocationDescriptorAndData* ldd = LDDAtIndex(writer.string(), 0);
+ EXPECT_EQ(11u, ldd->location_descriptor.DataSize);
+ EXPECT_EQ(0u, ldd->location_descriptor.Rva);
+ EXPECT_STREQ("yy", ldd->string);
+ ldd = LDDAtIndex(writer.string(), 12);
+ EXPECT_EQ(10u, ldd->location_descriptor.DataSize);
+ EXPECT_EQ(12u, ldd->location_descriptor.Rva);
+ EXPECT_STREQ("x", ldd->string);
+ parent.Verify();
+ }
+
+ {
+ SCOPED_TRACE("parent-child only");
+ writer.Reset();
+ TestLocationDescriptorMinidumpWritable parent;
+ TestLocationDescriptorMinidumpWritable child;
+ parent.SetLocationDescriptor(&child);
+ parent.SetString("www");
+ child.SetString("vv");
+ parent.AddChild(&child);
+ EXPECT_TRUE(parent.WriteEverything(&writer));
+
+ ASSERT_EQ(23u, writer.string().size());
+ const LocationDescriptorAndData* ldd = LDDAtIndex(writer.string(), 0);
+ EXPECT_EQ(11u, ldd->location_descriptor.DataSize);
+ EXPECT_EQ(12u, ldd->location_descriptor.Rva);
+ EXPECT_STREQ("www", ldd->string);
+ ldd = LDDAtIndex(writer.string(), 12);
+ EXPECT_EQ(0u, ldd->location_descriptor.DataSize);
+ EXPECT_EQ(0u, ldd->location_descriptor.Rva);
+ EXPECT_STREQ("vv", ldd->string);
+ parent.Verify();
+ }
+
+ {
+ SCOPED_TRACE("parent-child circular");
+ writer.Reset();
+ TestLocationDescriptorMinidumpWritable parent;
+ TestLocationDescriptorMinidumpWritable child;
+ parent.SetLocationDescriptor(&child);
+ parent.SetString("uuuu");
+ child.SetLocationDescriptor(&parent);
+ child.SetString("tttt");
+ parent.AddChild(&child);
+ EXPECT_TRUE(parent.WriteEverything(&writer));
+
+ ASSERT_EQ(29u, writer.string().size());
+ const LocationDescriptorAndData* ldd = LDDAtIndex(writer.string(), 0);
+ EXPECT_EQ(13u, ldd->location_descriptor.DataSize);
+ EXPECT_EQ(16u, ldd->location_descriptor.Rva);
+ EXPECT_STREQ("uuuu", ldd->string);
+ ldd = LDDAtIndex(writer.string(), 16);
+ EXPECT_EQ(13u, ldd->location_descriptor.DataSize);
+ EXPECT_EQ(0u, ldd->location_descriptor.Rva);
+ EXPECT_STREQ("tttt", ldd->string);
+ parent.Verify();
+ }
+
+ {
+ SCOPED_TRACE("grandchildren");
+ writer.Reset();
+ TestLocationDescriptorMinidumpWritable parent;
+ TestLocationDescriptorMinidumpWritable child;
+ parent.SetLocationDescriptor(&child);
+ parent.SetString("s");
+ parent.AddChild(&child);
+ child.SetString("r");
+ TestLocationDescriptorMinidumpWritable grandchild_0;
+ grandchild_0.SetLocationDescriptor(&child);
+ grandchild_0.SetString("q");
+ child.AddChild(&grandchild_0);
+ TestLocationDescriptorMinidumpWritable grandchild_1;
+ grandchild_1.SetLocationDescriptor(&child);
+ grandchild_1.SetString("p");
+ child.AddChild(&grandchild_1);
+ TestLocationDescriptorMinidumpWritable grandchild_2;
+ grandchild_2.SetLocationDescriptor(&child);
+ grandchild_2.SetString("o");
+ child.AddChild(&grandchild_2);
+ EXPECT_TRUE(parent.WriteEverything(&writer));
+
+ ASSERT_EQ(58u, writer.string().size());
+ const LocationDescriptorAndData* ldd = LDDAtIndex(writer.string(), 0);
+ EXPECT_EQ(10u, ldd->location_descriptor.DataSize);
+ EXPECT_EQ(12u, ldd->location_descriptor.Rva);
+ EXPECT_STREQ("s", ldd->string);
+ ldd = LDDAtIndex(writer.string(), 12);
+ EXPECT_EQ(0u, ldd->location_descriptor.DataSize);
+ EXPECT_EQ(0u, ldd->location_descriptor.Rva);
+ EXPECT_STREQ("r", ldd->string);
+ ldd = LDDAtIndex(writer.string(), 24);
+ EXPECT_EQ(10u, ldd->location_descriptor.DataSize);
+ EXPECT_EQ(12u, ldd->location_descriptor.Rva);
+ EXPECT_STREQ("q", ldd->string);
+ ldd = LDDAtIndex(writer.string(), 36);
+ EXPECT_EQ(10u, ldd->location_descriptor.DataSize);
+ EXPECT_EQ(12u, ldd->location_descriptor.Rva);
+ EXPECT_STREQ("p", ldd->string);
+ ldd = LDDAtIndex(writer.string(), 48);
+ EXPECT_EQ(10u, ldd->location_descriptor.DataSize);
+ EXPECT_EQ(12u, ldd->location_descriptor.Rva);
+ EXPECT_STREQ("o", ldd->string);
+ parent.Verify();
+ }
+}
+
+} // namespace
« no previous file with comments | « minidump/minidump_writable.cc ('k') | util/file/fd_io.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698