aboutsummaryrefslogtreecommitdiff
path: root/src/processor
diff options
context:
space:
mode:
authorted.mielczarek <ted.mielczarek@4c0a9323-5329-0410-9bdc-e9ce6186880e>2009-12-09 01:24:37 +0000
committerted.mielczarek <ted.mielczarek@4c0a9323-5329-0410-9bdc-e9ce6186880e>2009-12-09 01:24:37 +0000
commit0cbd50c975c1680a6cd0f1ce2760e157e2bfd46f (patch)
tree087407aaa36763ad53ad94ddbbf94517a99a0655 /src/processor
parentremove trailing comma from enum definition to make it compile with -pedantic (diff)
downloadbreakpad-0cbd50c975c1680a6cd0f1ce2760e157e2bfd46f.tar.xz
Allow Minidump class to be instantiated with stream instead of file. r=mark at http://breakpad.appspot.com/46001
git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@438 4c0a9323-5329-0410-9bdc-e9ce6186880e
Diffstat (limited to 'src/processor')
-rw-r--r--src/processor/minidump.cc76
-rw-r--r--src/processor/minidump_unittest.cc103
2 files changed, 151 insertions, 28 deletions
diff --git a/src/processor/minidump.cc b/src/processor/minidump.cc
index ab4e4286..49118589 100644
--- a/src/processor/minidump.cc
+++ b/src/processor/minidump.cc
@@ -50,6 +50,8 @@ typedef SSIZE_T ssize_t;
#endif // _WIN32
#include <cassert>
+#include <fstream>
+#include <iostream>
#include <limits>
#include <map>
#include <vector>
@@ -66,6 +68,8 @@ typedef SSIZE_T ssize_t;
namespace google_breakpad {
+using std::istream;
+using std::ifstream;
using std::numeric_limits;
using std::vector;
@@ -3331,35 +3335,44 @@ Minidump::Minidump(const string& path)
directory_(NULL),
stream_map_(new MinidumpStreamMap()),
path_(path),
- fd_(-1),
+ stream_(NULL),
swap_(false),
valid_(false) {
}
+Minidump::Minidump(istream& stream)
+ : header_(),
+ directory_(NULL),
+ stream_map_(new MinidumpStreamMap()),
+ path_(),
+ stream_(&stream),
+ swap_(false),
+ valid_(false) {
+}
Minidump::~Minidump() {
+ if (stream_) {
+ BPLOG(INFO) << "Minidump closing minidump";
+ }
+ if (!path_.empty()) {
+ delete stream_;
+ }
delete directory_;
delete stream_map_;
- if (fd_ != -1) {
- BPLOG(INFO) << "Minidump closing minidump on fd " << fd_;
- close(fd_);
- }
}
bool Minidump::Open() {
- if (fd_ != -1) {
- BPLOG(INFO) << "Minidump reopening minidump " << path_ << " on fd " << fd_;
+ if (stream_ != NULL) {
+ BPLOG(INFO) << "Minidump reopening minidump " << path_;
// The file is already open. Seek to the beginning, which is the position
// the file would be at if it were opened anew.
return SeekSet(0);
}
- // O_BINARY is useful (and defined) on Windows. On other platforms, it's
- // useless, and because it's defined as 0 above, harmless.
- fd_ = open(path_.c_str(), O_RDONLY | O_BINARY);
- if (fd_ == -1) {
+ stream_ = new ifstream(path_.c_str(), std::ios::in | std::ios::binary);
+ if (!stream_ || !stream_->good()) {
string error_string;
int error_code = ErrnoString(&error_string);
BPLOG(ERROR) << "Minidump could not open minidump " << path_ <<
@@ -3367,7 +3380,7 @@ bool Minidump::Open() {
return false;
}
- BPLOG(INFO) << "Minidump opened minidump " << path_ << " on fd " << fd_;
+ BPLOG(INFO) << "Minidump opened minidump " << path_;
return true;
}
@@ -3617,10 +3630,12 @@ const MDRawDirectory* Minidump::GetDirectoryEntryAtIndex(unsigned int index)
bool Minidump::ReadBytes(void* bytes, size_t count) {
// Can't check valid_ because Read needs to call this method before
- // validity can be determined. The only member that this method
- // depends on is mFD, and an unset or invalid fd may generate an
- // error but should not cause a crash.
- ssize_t bytes_read = read(fd_, bytes, count);
+ // validity can be determined.
+ if (!stream_) {
+ return false;
+ }
+ stream_->read(static_cast<char*>(bytes), count);
+ size_t bytes_read = stream_->gcount();
if (static_cast<size_t>(bytes_read) != count) {
if (bytes_read == -1) {
string error_string;
@@ -3637,23 +3652,28 @@ bool Minidump::ReadBytes(void* bytes, size_t count) {
bool Minidump::SeekSet(off_t offset) {
// Can't check valid_ because Read needs to call this method before
- // validity can be determined. The only member that this method
- // depends on is mFD, and an unset or invalid fd may generate an
- // error but should not cause a crash.
- off_t sought = lseek(fd_, offset, SEEK_SET);
- if (sought != offset) {
- if (sought == -1) {
- string error_string;
- int error_code = ErrnoString(&error_string);
- BPLOG(ERROR) << "SeekSet: error " << error_code << ": " << error_string;
- } else {
- BPLOG(ERROR) << "SeekSet: sought " << sought << "/" << offset;
- }
+ // validity can be determined.
+ if (!stream_) {
+ return false;
+ }
+ stream_->seekg(offset, std::ios_base::beg);
+ if (!stream_->good()) {
+ string error_string;
+ int error_code = ErrnoString(&error_string);
+ BPLOG(ERROR) << "SeekSet: error " << error_code << ": " << error_string;
return false;
}
return true;
}
+off_t Minidump::Tell() {
+ if (!valid_ || !stream_) {
+ return (off_t)-1;
+ }
+
+ return stream_->tellg();
+}
+
string* Minidump::ReadString(off_t offset) {
if (!valid_) {
diff --git a/src/processor/minidump_unittest.cc b/src/processor/minidump_unittest.cc
new file mode 100644
index 00000000..3a83235e
--- /dev/null
+++ b/src/processor/minidump_unittest.cc
@@ -0,0 +1,103 @@
+// Copyright (c) 2009, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Unit test for Minidump. Uses a pre-generated minidump and
+// verifies that certain streams are correct.
+
+#include <cstdlib>
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <string>
+#include <vector>
+#include "breakpad_googletest_includes.h"
+#include "google_breakpad/common/minidump_format.h"
+#include "google_breakpad/processor/minidump.h"
+#include "processor/logging.h"
+
+namespace {
+
+using google_breakpad::Minidump;
+using std::ifstream;
+using std::istringstream;
+using std::string;
+using std::vector;
+using ::testing::Return;
+
+class MinidumpTest : public ::testing::Test {
+public:
+ void SetUp() {
+ minidump_file_ = string(getenv("srcdir") ? getenv("srcdir") : ".") +
+ "/src/processor/testdata/minidump2.dmp";
+ }
+ string minidump_file_;
+};
+
+TEST_F(MinidumpTest, TestMinidumpFromFile) {
+ Minidump minidump(minidump_file_);
+ ASSERT_EQ(minidump.path(), minidump_file_);
+ ASSERT_TRUE(minidump.Read());
+ const MDRawHeader* header = minidump.header();
+ ASSERT_NE(header, (MDRawHeader*)NULL);
+ ASSERT_EQ(header->signature, MD_HEADER_SIGNATURE);
+ //TODO: add more checks here
+}
+
+TEST_F(MinidumpTest, TestMinidumpFromStream) {
+ // read minidump contents into memory, construct a stringstream around them
+ ifstream file_stream(minidump_file_.c_str(), std::ios::in);
+ ASSERT_TRUE(file_stream.good());
+ vector<char> bytes;
+ file_stream.seekg(0, std::ios_base::end);
+ ASSERT_TRUE(file_stream.good());
+ bytes.resize(file_stream.tellg());
+ file_stream.seekg(0, std::ios_base::beg);
+ ASSERT_TRUE(file_stream.good());
+ file_stream.read(&bytes[0], bytes.size());
+ ASSERT_TRUE(file_stream.good());
+ string str(&bytes[0], bytes.size());
+ istringstream stream(str);
+ ASSERT_TRUE(stream.good());
+
+ // now read minidump from stringstream
+ Minidump minidump(stream);
+ ASSERT_EQ(minidump.path(), "");
+ ASSERT_TRUE(minidump.Read());
+ const MDRawHeader* header = minidump.header();
+ ASSERT_NE(header, (MDRawHeader*)NULL);
+ ASSERT_EQ(header->signature, MD_HEADER_SIGNATURE);
+ //TODO: add more checks here
+}
+
+} // namespace
+
+int main(int argc, char* argv[]) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}