blob: dd1cbb682d0871f5f8be168c3a6da2aad07ba15b [file] [log] [blame]
Miriam Zimmerman18f8d622020-10-02 11:06:32 -07001// Copyright 2020 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "crash-reporter/crash_serializer.h"
6
7#include <string>
8#include <tuple>
9#include <utility>
10#include <vector>
11
12#include <base/files/file_util.h>
13#include <base/files/scoped_temp_dir.h>
14#include <gmock/gmock.h>
15#include <gtest/gtest.h>
16
17#include "crash-reporter/crash_sender_base.h"
18#include "crash-reporter/crash_sender_paths.h"
19#include "crash-reporter/crash_serializer.pb.h"
20#include "crash-reporter/paths.h"
21#include "crash-reporter/test_util.h"
22
23namespace crash_serializer {
24namespace {
25
26constexpr char kFakeClientId[] = "00112233445566778899aabbccddeeff";
27
28} // namespace
29
30class CrashSerializerTest : public testing::Test {
31 protected:
32 void SetUp() override {
33 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
34 test_dir_ = temp_dir_.GetPath();
35 paths::SetPrefixForTesting(test_dir_);
36
37 // Make sure the directory for the lock file exists.
38 const base::FilePath lock_file_path =
39 paths::Get(paths::kCrashSenderLockFile);
40 const base::FilePath lock_file_directory = lock_file_path.DirName();
41 ASSERT_TRUE(base::CreateDirectory(lock_file_directory));
42 }
43
44 void TearDown() override { paths::SetPrefixForTesting(base::FilePath()); }
45
46 base::ScopedTempDir temp_dir_;
47 base::FilePath test_dir_;
48};
49
50enum MissingFile {
51 kNone,
52 kPayloadFile,
53 kLogFile,
54 kTextFile,
55 kBinFile,
56 kCoreFile,
57};
58
59class CrashSerializerParameterizedTest
60 : public CrashSerializerTest,
61 public ::testing::WithParamInterface<
62 std::tuple<bool, bool, MissingFile>> {
63 protected:
64 void SetUp() override {
65 std::tie(absolute_paths_, fetch_core_, missing_file_) = GetParam();
66 CrashSerializerTest::SetUp();
67 }
68 bool absolute_paths_;
69 bool fetch_core_;
70 MissingFile missing_file_;
71};
72
73TEST_P(CrashSerializerParameterizedTest, TestSerializeCrash) {
74 const base::FilePath system_dir = paths::Get(paths::kSystemCrashDirectory);
75 ASSERT_TRUE(base::CreateDirectory(system_dir));
76
77 const base::FilePath payload_file_relative("0.0.0.0.payload");
78 const base::FilePath payload_file_absolute =
79 system_dir.Append(payload_file_relative);
80 const std::string payload_contents = "foobar_payload";
81 if (missing_file_ != kPayloadFile) {
82 ASSERT_TRUE(test_util::CreateFile(payload_file_absolute, payload_contents));
83 }
84 const base::FilePath& payload_file =
85 absolute_paths_ ? payload_file_absolute : payload_file_relative;
86
87 const base::FilePath log_file_relative("0.0.0.0.log");
88 const base::FilePath log_file_absolute = system_dir.Append(log_file_relative);
89 const std::string log_contents = "foobar_log";
90 if (missing_file_ != kLogFile) {
91 ASSERT_TRUE(test_util::CreateFile(log_file_absolute, log_contents));
92 }
93 const base::FilePath& log_file =
94 absolute_paths_ ? log_file_absolute : log_file_relative;
95
96 const base::FilePath text_var_file_relative("data.txt");
97 const base::FilePath text_var_file_absolute =
98 system_dir.Append(text_var_file_relative);
99 const std::string text_var_contents = "upload_text_contents";
100 if (missing_file_ != kTextFile) {
101 ASSERT_TRUE(
102 test_util::CreateFile(text_var_file_absolute, text_var_contents));
103 }
104 const base::FilePath& text_var_file =
105 absolute_paths_ ? text_var_file_absolute : text_var_file_relative;
106
107 const base::FilePath file_var_file_relative("data.bin");
108 const base::FilePath file_var_file_absolute =
109 system_dir.Append(file_var_file_relative);
110 const std::string file_var_contents = "upload_file_contents";
111 if (missing_file_ != kBinFile) {
112 ASSERT_TRUE(
113 test_util::CreateFile(file_var_file_absolute, file_var_contents));
114 }
115 const base::FilePath& file_var_file =
116 absolute_paths_ ? file_var_file_absolute : file_var_file_relative;
117
118 const base::FilePath core_file_relative("0.0.0.0.core");
119 const base::FilePath core_file_absolute =
120 system_dir.Append(core_file_relative);
121 const std::string core_contents = "corey_mccoreface";
122 if (missing_file_ != kCoreFile) {
123 ASSERT_TRUE(test_util::CreateFile(core_file_absolute, core_contents));
124 }
125
126 brillo::KeyValueStore metadata;
127 metadata.SetString("exec_name", "fake_exec_name");
128 metadata.SetString("ver", "fake_chromeos_ver");
129 metadata.SetString("upload_var_prod", "fake_product");
130 metadata.SetString("upload_var_ver", "fake_version");
131 metadata.SetString("sig", "fake_sig");
132 metadata.SetString("upload_var_guid", "SHOULD_NOT_BE_USED");
133 metadata.SetString("upload_var_foovar", "bar");
134 metadata.SetString("upload_var_in_progress_integration_test", "test.Test");
135 metadata.SetString("upload_var_collector", "fake_collector");
136 metadata.SetString("upload_text_footext", text_var_file.value());
137 metadata.SetString("upload_file_log", log_file.value());
138 metadata.SetString("upload_file_foofile", file_var_file.value());
139 metadata.SetString("error_type", "fake_error");
140
141 util::CrashDetails details = {
142 .meta_file = base::FilePath(system_dir).Append("0.0.0.0.meta"),
143 .payload_file = payload_file,
144 .payload_kind = "fake_payload",
145 .client_id = kFakeClientId,
146 .metadata = metadata,
147 };
148
149 Serializer::Options options;
150 options.fetch_coredumps = fetch_core_;
151
152 Serializer serializer(std::make_unique<test_util::AdvancingClock>(), options);
153
154 crash::CrashInfo info;
155 std::vector<crash::CrashBlob> blobs;
156 base::FilePath core_path;
157 EXPECT_EQ(serializer.SerializeCrash(details, &info, &blobs, &core_path),
158 missing_file_ != kPayloadFile);
159
160 if (missing_file_ == kPayloadFile) {
161 return;
162 }
163
164 // We'd really like to set up a proto with the expected values and
165 // EXPECT_THAT(info, EqualsProto(expected_info)), but EqualsProto is
166 // unavailable in chromium OS, so do it one field at a time instead.
167 EXPECT_EQ(info.exec_name(), "fake_exec_name");
168 EXPECT_EQ(info.prod(), "fake_product");
169 EXPECT_EQ(info.ver(), "fake_version");
170 EXPECT_EQ(info.sig(), "fake_sig");
171 EXPECT_EQ(info.in_progress_integration_test(), "test.Test");
172 EXPECT_EQ(info.collector(), "fake_collector");
173
174 int num_fields = 8;
175 if (missing_file_ != kTextFile) {
176 num_fields++;
177 }
178
179 ASSERT_EQ(info.fields_size(), num_fields);
180
181 int field_idx = 0;
182 EXPECT_EQ(info.fields(field_idx).key(), "board");
183 EXPECT_EQ(info.fields(field_idx).text(), "undefined");
184 field_idx++;
185
186 EXPECT_EQ(info.fields(field_idx).key(), "hwclass");
187 EXPECT_EQ(info.fields(field_idx).text(), "undefined");
188 field_idx++;
189
190 EXPECT_EQ(info.fields(field_idx).key(), "sig2");
191 EXPECT_EQ(info.fields(field_idx).text(), "fake_sig");
192 field_idx++;
193
194 EXPECT_EQ(info.fields(field_idx).key(), "image_type");
195 EXPECT_EQ(info.fields(field_idx).text(), "");
196 field_idx++;
197
198 EXPECT_EQ(info.fields(field_idx).key(), "boot_mode");
199 EXPECT_EQ(info.fields(field_idx).text(), "missing-crossystem");
200 field_idx++;
201
202 EXPECT_EQ(info.fields(field_idx).key(), "error_type");
203 EXPECT_EQ(info.fields(field_idx).text(), "fake_error");
204 field_idx++;
205
206 EXPECT_EQ(info.fields(field_idx).key(), "guid");
207 EXPECT_EQ(info.fields(field_idx).text(), "00112233445566778899aabbccddeeff");
208 field_idx++;
209
210 if (missing_file_ != kTextFile) {
211 EXPECT_EQ(info.fields(field_idx).key(), "footext");
212 EXPECT_EQ(info.fields(field_idx).text(), "upload_text_contents");
213 field_idx++;
214 }
215
216 EXPECT_EQ(info.fields(field_idx).key(), "foovar");
217 EXPECT_EQ(info.fields(field_idx).text(), "bar");
218 field_idx++;
219
220 int num_blobs = 1;
221 if (missing_file_ != kBinFile) {
222 num_blobs++;
223 }
224 if (missing_file_ != kLogFile) {
225 num_blobs++;
226 }
227
228 ASSERT_EQ(blobs.size(), num_blobs);
229
230 int blob_idx = 0;
231 EXPECT_EQ(blobs[blob_idx].key(), "upload_file_fake_payload");
232 EXPECT_EQ(blobs[blob_idx].blob(), "foobar_payload");
233 EXPECT_EQ(blobs[blob_idx].filename(), payload_file_relative.value());
234 blob_idx++;
235
236 if (missing_file_ != kBinFile) {
237 EXPECT_EQ(blobs[blob_idx].key(), "foofile");
238 EXPECT_EQ(blobs[blob_idx].blob(), "upload_file_contents");
239 EXPECT_EQ(blobs[blob_idx].filename(), file_var_file_relative.value());
240 blob_idx++;
241 }
242
243 if (missing_file_ != kLogFile) {
244 EXPECT_EQ(blobs[blob_idx].key(), "log");
245 EXPECT_EQ(blobs[blob_idx].blob(), "foobar_log");
246 EXPECT_EQ(blobs[blob_idx].filename(), log_file_relative.value());
247 blob_idx++;
248 }
249
250 if (missing_file_ != kCoreFile && fetch_core_) {
251 EXPECT_EQ(core_path, core_file_absolute);
252 } else {
253 EXPECT_EQ(core_path, base::FilePath());
254 }
255}
256
257INSTANTIATE_TEST_SUITE_P(CrashSerializerParameterizedTestInstantiation,
258 CrashSerializerParameterizedTest,
259 testing::Combine(testing::Bool(),
260 testing::Bool(),
261 testing::Values(kNone,
262 kPayloadFile,
263 kLogFile,
264 kTextFile,
265 kBinFile,
266 kCoreFile)));
267
268} // namespace crash_serializer