1 // Copyright 2006 Google LLC
2 //
3 // Redistribution and use in source and binary forms, with or without
4 // modification, are permitted provided that the following conditions are
5 // met:
6 //
7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 // * Redistributions in binary form must reproduce the above
10 // copyright notice, this list of conditions and the following disclaimer
11 // in the documentation and/or other materials provided with the
12 // distribution.
13 // * Neither the name of Google LLC nor the names of its
14 // contributors may be used to endorse or promote products derived from
15 // this software without specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29 // Author: [email protected] (Dan Waylonis)
30
31 /*
32 g++ -I../ ../common/convert_UTF.cc \
33 ../common/string_conversion.cc \
34 minidump_file_writer.cc \
35 minidump_file_writer_unittest.cc \
36 -o minidump_file_writer_unittest
37 */
38
39 #ifdef HAVE_CONFIG_H
40 #include <config.h> // Must come first
41 #endif
42
43 #include <fcntl.h>
44 #include <unistd.h>
45
46 #include "minidump_file_writer-inl.h"
47
48 using google_breakpad::MinidumpFileWriter;
49
50 #define ASSERT_TRUE(cond) \
51 if (!(cond)) { \
52 fprintf(stderr, "FAILED: %s at %s:%d\n", #cond, __FILE__, __LINE__); \
53 return false; \
54 }
55
56 #define ASSERT_EQ(e1, e2) ASSERT_TRUE((e1) == (e2))
57 #define ASSERT_NE(e1, e2) ASSERT_TRUE((e1) != (e2))
58
59 struct StringStructure {
60 unsigned long integer_value;
61 MDLocationDescriptor first_string;
62 MDLocationDescriptor second_string;
63 };
64
65 struct ArrayStructure {
66 unsigned char char_value;
67 unsigned short short_value;
68 unsigned long long_value;
69 };
70
71 typedef struct {
72 unsigned long count;
73 ArrayStructure array[0];
74 } ObjectAndArrayStructure;
75
WriteFile(const char * path)76 static bool WriteFile(const char* path) {
77 MinidumpFileWriter writer;
78 if (writer.Open(path)) {
79 // Test a single structure
80 google_breakpad::TypedMDRVA<StringStructure> strings(&writer);
81 ASSERT_TRUE(strings.Allocate());
82 strings.get()->integer_value = 0xBEEF;
83 const char* first = "First String";
84 ASSERT_TRUE(writer.WriteString(first, 0, &strings.get()->first_string));
85 const wchar_t* second = L"Second String";
86 ASSERT_TRUE(writer.WriteString(second, 0, &strings.get()->second_string));
87
88 // Test an array structure
89 google_breakpad::TypedMDRVA<ArrayStructure> array(&writer);
90 unsigned int count = 10;
91 ASSERT_TRUE(array.AllocateArray(count));
92 for (unsigned char i = 0; i < count; ++i) {
93 ArrayStructure local;
94 local.char_value = i;
95 local.short_value = i + 1;
96 local.long_value = i + 2;
97 ASSERT_TRUE(array.CopyIndex(i, &local));
98 }
99
100 // Test an object followed by an array
101 google_breakpad::TypedMDRVA<ObjectAndArrayStructure> obj_array(&writer);
102 ASSERT_TRUE(obj_array.AllocateObjectAndArray(count,
103 sizeof(ArrayStructure)));
104 obj_array.get()->count = count;
105 for (unsigned char i = 0; i < count; ++i) {
106 ArrayStructure local;
107 local.char_value = i;
108 local.short_value = i + 1;
109 local.long_value = i + 2;
110 ASSERT_TRUE(obj_array.CopyIndexAfterObject(i, &local, sizeof(local)));
111 }
112 }
113
114 return writer.Close();
115 }
116
CompareFile(const char * path)117 static bool CompareFile(const char* path) {
118 unsigned long expected[] = {
119 #if defined(__BIG_ENDIAN__)
120 0x0000beef, 0x0000001e, 0x00000018, 0x00000020, 0x00000038, 0x00000000,
121 0x00000018, 0x00460069, 0x00720073, 0x00740020, 0x00530074, 0x00720069,
122 0x006e0067, 0x00000000, 0x0000001a, 0x00530065, 0x0063006f, 0x006e0064,
123 0x00200053, 0x00740072, 0x0069006e, 0x00670000, 0x00000001, 0x00000002,
124 0x01000002, 0x00000003, 0x02000003, 0x00000004, 0x03000004, 0x00000005,
125 0x04000005, 0x00000006, 0x05000006, 0x00000007, 0x06000007, 0x00000008,
126 0x07000008, 0x00000009, 0x08000009, 0x0000000a, 0x0900000a, 0x0000000b,
127 0x0000000a, 0x00000001, 0x00000002, 0x01000002, 0x00000003, 0x02000003,
128 0x00000004, 0x03000004, 0x00000005, 0x04000005, 0x00000006, 0x05000006,
129 0x00000007, 0x06000007, 0x00000008, 0x07000008, 0x00000009, 0x08000009,
130 0x0000000a, 0x0900000a, 0x0000000b, 0x00000000
131 #else
132 0x0000beef, 0x0000001e, 0x00000018, 0x00000020,
133 0x00000038, 0x00000000, 0x00000018, 0x00690046,
134 0x00730072, 0x00200074, 0x00740053, 0x00690072,
135 0x0067006e, 0x00000000, 0x0000001a, 0x00650053,
136 0x006f0063, 0x0064006e, 0x00530020, 0x00720074,
137 0x006e0069, 0x00000067, 0x00011e00, 0x00000002,
138 0x00021e01, 0x00000003, 0x00031e02, 0x00000004,
139 0x00041e03, 0x00000005, 0x00051e04, 0x00000006,
140 0x00061e05, 0x00000007, 0x00071e06, 0x00000008,
141 0x00081e07, 0x00000009, 0x00091e08, 0x0000000a,
142 0x000a1e09, 0x0000000b, 0x0000000a, 0x00011c00,
143 0x00000002, 0x00021c01, 0x00000003, 0x00031c02,
144 0x00000004, 0x00041c03, 0x00000005, 0x00051c04,
145 0x00000006, 0x00061c05, 0x00000007, 0x00071c06,
146 0x00000008, 0x00081c07, 0x00000009, 0x00091c08,
147 0x0000000a, 0x000a1c09, 0x0000000b, 0x00000000,
148 #endif
149 };
150 size_t expected_byte_count = sizeof(expected);
151 int fd = open(path, O_RDONLY, 0600);
152 void* buffer = malloc(expected_byte_count);
153 ASSERT_NE(fd, -1);
154 ASSERT_TRUE(buffer);
155 ASSERT_EQ(read(fd, buffer, expected_byte_count),
156 static_cast<ssize_t>(expected_byte_count));
157
158 char* b1;
159 char* b2;
160 b1 = reinterpret_cast<char*>(buffer);
161 b2 = reinterpret_cast<char*>(expected);
162 while (*b1 == *b2) {
163 b1++;
164 b2++;
165 }
166
167 printf("%p\n", reinterpret_cast<void*>(b1 - (char*)buffer));
168
169 ASSERT_EQ(memcmp(buffer, expected, expected_byte_count), 0);
170 return true;
171 }
172
RunTests()173 static bool RunTests() {
174 const char* path = "/tmp/minidump_file_writer_unittest.dmp";
175 ASSERT_TRUE(WriteFile(path));
176 ASSERT_TRUE(CompareFile(path));
177 unlink(path);
178 return true;
179 }
180
main(int argc,const char * argv[])181 extern "C" int main(int argc, const char* argv[]) {
182 return RunTests() ? 0 : 1;
183 }
184