blob: bd45e90f293db194dc69d1f3e12532e7852aff4a [file] [log] [blame]
Satoru Takabayashie7f6d2a2018-08-08 17:06:29 +09001// Copyright 2018 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/util.h"
6
Satoru Takabayashi9a587522018-10-29 09:36:27 +09007#include <stdlib.h>
8
Kansho Nishida630cc7a2019-10-23 17:37:41 +09009#include <fcntl.h>
Miriam Zimmerman36042862019-11-14 20:01:29 -080010#include <limits>
Satoru Takabayashi9a587522018-10-29 09:36:27 +090011#include <memory>
Tim Zheng11a665e2019-06-26 17:44:01 -070012#include <sys/mman.h>
Satoru Takabayashi9a587522018-10-29 09:36:27 +090013
Miriam Zimmermana23f18f2020-11-12 11:09:27 -080014#include <base/command_line.h>
Satoru Takabayashie7f6d2a2018-08-08 17:06:29 +090015#include <base/files/file_util.h>
16#include <base/files/scoped_temp_dir.h>
Jeffrey Kardatzke437fa922019-05-09 11:34:32 -070017#include <base/rand_util.h>
Ian Barkley-Yeungc377b092019-10-09 19:23:53 -070018#include <base/test/simple_test_clock.h>
Kansho Nishida630cc7a2019-10-23 17:37:41 +090019#include <base/time/time.h>
Simon Glass2b1da092020-05-21 12:24:16 -060020#include <brillo/process/process.h>
Jeffrey Kardatzke437fa922019-05-09 11:34:32 -070021#include <brillo/streams/memory_stream.h>
Satoru Takabayashie7f6d2a2018-08-08 17:06:29 +090022#include <gtest/gtest.h>
23
24#include "crash-reporter/crash_sender_paths.h"
25#include "crash-reporter/paths.h"
26#include "crash-reporter/test_util.h"
Miriam Zimmermana23f18f2020-11-12 11:09:27 -080027#include "metrics/metrics_library_mock.h"
Satoru Takabayashie7f6d2a2018-08-08 17:06:29 +090028
Tim Zheng11a665e2019-06-26 17:44:01 -070029// The QEMU emulator we use to run unit tests on simulated ARM boards does not
30// support memfd_create. (https://bugs.launchpad.net/qemu/+bug/1734792) Skip
31// tests that rely on memfd_create on ARM boards.
32#if defined(ARCH_CPU_ARM_FAMILY)
33#define DISABLED_ON_QEMU_FOR_MEMFD_CREATE(test_name) DISABLED_##test_name
34#else
35#define DISABLED_ON_QEMU_FOR_MEMFD_CREATE(test_name) test_name
36#endif
37
Satoru Takabayashie7f6d2a2018-08-08 17:06:29 +090038namespace util {
Satoru Takabayashib2ca40d2018-08-09 14:02:04 +090039namespace {
40
Jeffrey Kardatzke437fa922019-05-09 11:34:32 -070041constexpr char kLsbReleaseContents[] =
Satoru Takabayashib2ca40d2018-08-09 14:02:04 +090042 "CHROMEOS_RELEASE_BOARD=bob\n"
43 "CHROMEOS_RELEASE_NAME=Chromium OS\n"
44 "CHROMEOS_RELEASE_VERSION=10964.0.2018_08_13_1405\n";
45
Jeffrey Kardatzkeea333932019-04-12 10:17:51 -070046constexpr char kHwClassContents[] = "fake_hwclass";
47
Jeffrey Kardatzke437fa922019-05-09 11:34:32 -070048constexpr char kGzipPath[] = "/bin/gzip";
49
50constexpr char kSemiRandomData[] =
51 "ABJCI239AJSDLKJ;kalkjkjsd98723;KJHASD87;kqw3p088ad;lKJASDP823;KJ";
52constexpr int kRandomDataMinLength = 32768; // 32kB
53constexpr int kRandomDataMaxLength = 262144; // 256kB
54
Kansho Nishida630cc7a2019-10-23 17:37:41 +090055constexpr char kReadFdToStreamContents[] = "1234567890";
56
Jeffrey Kardatzke437fa922019-05-09 11:34:32 -070057// Verifies that |raw_file| corresponds to the gzip'd version of
58// |compressed_file| by decompressing it and comparing the contents. Returns
59// true if they match, false otherwise. This will overwrite the contents of
60// |compressed_file| in the process of doing this.
61bool VerifyCompression(const base::FilePath& raw_file,
62 const base::FilePath& compressed_file) {
63 if (!base::PathExists(raw_file)) {
64 LOG(ERROR) << "raw_file doesn't exist for verifying compression: "
65 << raw_file.value();
66 return false;
67 }
68 if (!base::PathExists(compressed_file)) {
69 LOG(ERROR) << "compressed_file doesn't exist for verifying compression: "
70 << compressed_file.value();
71 return false;
72 }
73 brillo::ProcessImpl proc;
74 proc.AddArg(kGzipPath);
75 proc.AddArg("-d"); // decompress
76 proc.AddArg(compressed_file.value());
77 std::string error;
78 const int res = util::RunAndCaptureOutput(&proc, STDERR_FILENO, &error);
79 if (res < 0) {
80 PLOG(ERROR) << "Failed to execute gzip";
81 return false;
82 }
83 if (res != 0) {
84 LOG(ERROR) << "Failed to un-gzip " << compressed_file.value();
85 util::LogMultilineError(error);
86 return false;
87 }
88 base::FilePath uncompressed_file = compressed_file.RemoveFinalExtension();
89 std::string raw_contents;
90 std::string uncompressed_contents;
91 if (!base::ReadFileToString(raw_file, &raw_contents)) {
92 LOG(ERROR) << "Failed reading in raw_file " << raw_file.value();
93 return false;
94 }
95 if (!base::ReadFileToString(uncompressed_file, &uncompressed_contents)) {
96 LOG(ERROR) << "Failed reading in uncompressed_file "
97 << uncompressed_file.value();
98 return false;
99 }
100 return raw_contents == uncompressed_contents;
101}
102
103// We use a somewhat random string of ASCII data to better reflect the data we
104// would be compressing for real. We also shouldn't use something like
105// base::RandBytesAsString() because that will generate uniformly random data
106// which does not compress.
107std::string CreateSemiRandomString(size_t size) {
108 std::string result;
109 result.reserve(size);
110 while (result.length() < size) {
111 int rem = size - result.length();
112 if (rem > sizeof(kSemiRandomData) - 1)
113 rem = sizeof(kSemiRandomData) - 1;
114 int rand_start = base::RandInt(0, rem - 1);
115 int rand_end = base::RandInt(rand_start + 1, rem);
116 result.append(&kSemiRandomData[rand_start], rand_end - rand_start);
117 }
118 return result;
119}
120
Satoru Takabayashib2ca40d2018-08-09 14:02:04 +0900121} // namespace
Satoru Takabayashie7f6d2a2018-08-08 17:06:29 +0900122
123class CrashCommonUtilTest : public testing::Test {
Jeffrey Kardatzke437fa922019-05-09 11:34:32 -0700124 protected:
Satoru Takabayashie7f6d2a2018-08-08 17:06:29 +0900125 void SetUp() override {
126 ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir());
127 test_dir_ = scoped_temp_dir_.GetPath();
128 paths::SetPrefixForTesting(test_dir_);
Kansho Nishida630cc7a2019-10-23 17:37:41 +0900129 base::FilePath file = scoped_temp_dir_.GetPath().Append("tmpfile");
130 ASSERT_TRUE(test_util::CreateFile(file, kReadFdToStreamContents));
131 fd_ = open(file.value().c_str(), O_RDONLY);
Miriam Zimmermana23f18f2020-11-12 11:09:27 -0800132
133 // We need to properly init the CommandLine object for the metrics tests,
134 // which log it.
135 base::CommandLine::Init(0, nullptr);
Satoru Takabayashie7f6d2a2018-08-08 17:06:29 +0900136 }
137
138 void TearDown() override { paths::SetPrefixForTesting(base::FilePath()); }
139
140 base::FilePath test_dir_;
141 base::ScopedTempDir scoped_temp_dir_;
Kansho Nishida630cc7a2019-10-23 17:37:41 +0900142 unsigned int fd_;
Satoru Takabayashie7f6d2a2018-08-08 17:06:29 +0900143};
144
145TEST_F(CrashCommonUtilTest, IsCrashTestInProgress) {
146 EXPECT_FALSE(IsCrashTestInProgress());
147 ASSERT_TRUE(
148 test_util::CreateFile(paths::GetAt(paths::kSystemRunStateDirectory,
149 paths::kCrashTestInProgress),
150 ""));
151 EXPECT_TRUE(IsCrashTestInProgress());
152}
153
Satoru Takabayashi2d728042018-12-10 09:19:00 +0900154TEST_F(CrashCommonUtilTest, IsDeviceCoredumpUploadAllowed) {
155 EXPECT_FALSE(IsDeviceCoredumpUploadAllowed());
156 ASSERT_TRUE(
157 test_util::CreateFile(paths::GetAt(paths::kCrashReporterStateDirectory,
158 paths::kDeviceCoredumpUploadAllowed),
159 ""));
160 EXPECT_TRUE(IsDeviceCoredumpUploadAllowed());
161}
162
Satoru Takabayashie7f6d2a2018-08-08 17:06:29 +0900163TEST_F(CrashCommonUtilTest, IsDeveloperImage) {
164 EXPECT_FALSE(IsDeveloperImage());
165
166 ASSERT_TRUE(test_util::CreateFile(paths::Get(paths::kLeaveCoreFile), ""));
167 EXPECT_TRUE(IsDeveloperImage());
168
169 ASSERT_TRUE(
170 test_util::CreateFile(paths::GetAt(paths::kSystemRunStateDirectory,
171 paths::kCrashTestInProgress),
172 ""));
173 EXPECT_FALSE(IsDeveloperImage());
174}
175
Satoru Takabayashif6a36802018-08-14 16:23:05 +0900176TEST_F(CrashCommonUtilTest, IsTestImage) {
177 EXPECT_FALSE(IsTestImage());
178
179 // Should return false because the channel is stable.
180 ASSERT_TRUE(test_util::CreateFile(
181 paths::GetAt(paths::kEtcDirectory, paths::kLsbRelease),
182 "CHROMEOS_RELEASE_TRACK=stable-channel"));
183 EXPECT_FALSE(IsTestImage());
184
185 // Should return true because the channel is testimage.
186 ASSERT_TRUE(test_util::CreateFile(
187 paths::GetAt(paths::kEtcDirectory, paths::kLsbRelease),
188 "CHROMEOS_RELEASE_TRACK=testimage-channel"));
189 EXPECT_TRUE(IsTestImage());
190
191 // Should return false if kCrashTestInProgress is present.
192 ASSERT_TRUE(
193 test_util::CreateFile(paths::GetAt(paths::kSystemRunStateDirectory,
194 paths::kCrashTestInProgress),
195 ""));
196 EXPECT_FALSE(IsTestImage());
197}
198
Satoru Takabayashi9a587522018-10-29 09:36:27 +0900199TEST_F(CrashCommonUtilTest, IsOfficialImage) {
200 EXPECT_FALSE(IsOfficialImage());
201
Satoru Takabayashi9a587522018-10-29 09:36:27 +0900202 // Check if lsb-release is handled correctly.
203 ASSERT_TRUE(test_util::CreateFile(
204 paths::Get("/etc/lsb-release"),
205 "CHROMEOS_RELEASE_DESCRIPTION=10964.0 (Test Build) developer-build"));
206 EXPECT_FALSE(IsOfficialImage());
207
208 ASSERT_TRUE(test_util::CreateFile(
209 paths::Get("/etc/lsb-release"),
210 "CHROMEOS_RELEASE_DESCRIPTION=10964.0 (Official Build) canary-channel"));
211 EXPECT_TRUE(IsOfficialImage());
212}
213
Ian Barkley-Yeungb12d6cc2020-02-12 14:00:54 -0800214TEST_F(CrashCommonUtilTest, HasMockConsent) {
Miriam Zimmerman3c951162020-03-18 09:39:21 -0700215 ASSERT_TRUE(test_util::CreateFile(paths::Get("/etc/lsb-release"),
216 "CHROMEOS_RELEASE_TRACK=testimage-channel\n"
217 "CHROMEOS_RELEASE_DESCRIPTION=12985.0.0 "
218 "(Official Build) dev-channel asuka test"));
Ian Barkley-Yeungb12d6cc2020-02-12 14:00:54 -0800219 EXPECT_FALSE(HasMockConsent());
220 ASSERT_TRUE(test_util::CreateFile(
221 paths::GetAt(paths::kSystemRunStateDirectory, paths::kMockConsent), ""));
222 EXPECT_TRUE(HasMockConsent());
223}
224
Miriam Zimmermana23f18f2020-11-12 11:09:27 -0800225TEST_F(CrashCommonUtilTest, IgnoresMockConsentNonTest) {
226 ASSERT_TRUE(test_util::CreateFile(paths::Get("/etc/lsb-release"),
227 "CHROMEOS_RELEASE_TRACK=dev-channel\n"
228 "CHROMEOS_RELEASE_DESCRIPTION=12985.0.0 "
229 "(Official Build) dev-channel asuka"));
230 EXPECT_FALSE(HasMockConsent());
231 ASSERT_TRUE(test_util::CreateFile(
232 paths::GetAt(paths::kSystemRunStateDirectory, paths::kMockConsent), ""));
233 EXPECT_FALSE(HasMockConsent());
234}
235
Jeffrey Kardatzkee3fb8fb2019-05-13 13:59:12 -0700236TEST_F(CrashCommonUtilTest, GetOsTimestamp) {
237 // If we can't read /etc/lsb-release then we should be returning the null
238 // time.
239 EXPECT_TRUE(util::GetOsTimestamp().is_null());
240
241 base::FilePath lsb_file_path = paths::Get("/etc/lsb-release");
242 ASSERT_TRUE(test_util::CreateFile(lsb_file_path, "foo=bar"));
243 base::Time old_time = base::Time::Now() - base::TimeDelta::FromDays(366);
244 ASSERT_TRUE(base::TouchFile(lsb_file_path, old_time, old_time));
245 // ext2/ext3 seem to have a timestamp granularity of 1s.
246 EXPECT_EQ(util::GetOsTimestamp().ToTimeVal().tv_sec,
247 old_time.ToTimeVal().tv_sec);
248}
249
250TEST_F(CrashCommonUtilTest, IsOsTimestampTooOldForUploads) {
Ian Barkley-Yeungc377b092019-10-09 19:23:53 -0700251 base::SimpleTestClock clock;
252 const base::Time now = test_util::GetDefaultTime();
253 clock.SetNow(now);
254
255 EXPECT_FALSE(util::IsOsTimestampTooOldForUploads(base::Time(), &clock));
Jeffrey Kardatzkee3fb8fb2019-05-13 13:59:12 -0700256 EXPECT_FALSE(util::IsOsTimestampTooOldForUploads(
Ian Barkley-Yeungc377b092019-10-09 19:23:53 -0700257 now - base::TimeDelta::FromDays(179), &clock));
Jeffrey Kardatzkee3fb8fb2019-05-13 13:59:12 -0700258 EXPECT_TRUE(util::IsOsTimestampTooOldForUploads(
Ian Barkley-Yeungc377b092019-10-09 19:23:53 -0700259 now - base::TimeDelta::FromDays(181), &clock));
Miriam Zimmerman36042862019-11-14 20:01:29 -0800260
261 // Crashes with invalid timestamps should upload.
262 EXPECT_FALSE(util::IsOsTimestampTooOldForUploads(
263 now + base::TimeDelta::FromDays(1), &clock));
264 EXPECT_FALSE(util::IsOsTimestampTooOldForUploads(
265 base::Time::FromTimeT(std::numeric_limits<time_t>::min()), &clock));
Jeffrey Kardatzkee3fb8fb2019-05-13 13:59:12 -0700266}
267
Jeffrey Kardatzkeea333932019-04-12 10:17:51 -0700268TEST_F(CrashCommonUtilTest, GetHardwareClass) {
269 EXPECT_EQ("undefined", GetHardwareClass());
270
271 ASSERT_TRUE(test_util::CreateFile(
272 paths::Get("/sys/devices/platform/chromeos_acpi/HWID"),
273 kHwClassContents));
274 EXPECT_EQ(kHwClassContents, GetHardwareClass());
275}
276
277TEST_F(CrashCommonUtilTest, GetBootModeString) {
278 EXPECT_EQ("missing-crossystem", GetBootModeString());
279
Jeffrey Kardatzkeea333932019-04-12 10:17:51 -0700280 ASSERT_TRUE(
281 test_util::CreateFile(paths::GetAt(paths::kSystemRunStateDirectory,
282 paths::kCrashTestInProgress),
283 ""));
284 EXPECT_EQ("", GetBootModeString());
285}
286
Satoru Takabayashib2ca40d2018-08-09 14:02:04 +0900287TEST_F(CrashCommonUtilTest, GetCachedKeyValue) {
288 ASSERT_TRUE(test_util::CreateFile(paths::Get("/etc/lsb-release"),
289 kLsbReleaseContents));
290 ASSERT_TRUE(test_util::CreateFile(paths::Get("/empty/lsb-release"), ""));
291
292 std::string value;
293 // No directories are specified.
294 EXPECT_FALSE(GetCachedKeyValue(base::FilePath("lsb-release"),
295 "CHROMEOS_RELEASE_VERSION", {}, &value));
296 // A non-existent directory is specified.
297 EXPECT_FALSE(GetCachedKeyValue(base::FilePath("lsb-release"),
298 "CHROMEOS_RELEASE_VERSION",
299 {paths::Get("/non-existent")}, &value));
300
301 // A non-existent base name is specified.
302 EXPECT_FALSE(GetCachedKeyValue(base::FilePath("non-existent"),
303 "CHROMEOS_RELEASE_VERSION",
304 {paths::Get("/etc")}, &value));
305
306 // A wrong key is specified.
307 EXPECT_FALSE(GetCachedKeyValue(base::FilePath("lsb-release"), "WRONG_KEY",
308 {paths::Get("/etc")}, &value));
309
310 // This should succeed.
311 EXPECT_TRUE(GetCachedKeyValue(base::FilePath("lsb-release"),
312 "CHROMEOS_RELEASE_VERSION",
313 {paths::Get("/etc")}, &value));
314 EXPECT_EQ("10964.0.2018_08_13_1405", value);
315
316 // A non-existent directory is included, but this should still succeed.
317 EXPECT_TRUE(GetCachedKeyValue(
318 base::FilePath("lsb-release"), "CHROMEOS_RELEASE_VERSION",
319 {paths::Get("/non-existent"), paths::Get("/etc")}, &value));
320 EXPECT_EQ("10964.0.2018_08_13_1405", value);
321
322 // A empty file is included, but this should still succeed.
323 EXPECT_TRUE(GetCachedKeyValue(
324 base::FilePath("lsb-release"), "CHROMEOS_RELEASE_VERSION",
325 {paths::Get("/empty"), paths::Get("/etc")}, &value));
326 EXPECT_EQ("10964.0.2018_08_13_1405", value);
327}
328
329TEST_F(CrashCommonUtilTest, GetCachedKeyValueDefault) {
330 std::string value;
331 EXPECT_FALSE(
332 GetCachedKeyValueDefault(base::FilePath("test.txt"), "FOO", &value));
333
Jeffrey Kardatzke8ed15d12019-03-21 16:57:20 -0700334 // kEtcDirectory is the second candidate directory.
Satoru Takabayashib2ca40d2018-08-09 14:02:04 +0900335 ASSERT_TRUE(test_util::CreateFile(
Jeffrey Kardatzke8ed15d12019-03-21 16:57:20 -0700336 paths::GetAt(paths::kEtcDirectory, "test.txt"), "FOO=2\n"));
Satoru Takabayashib2ca40d2018-08-09 14:02:04 +0900337 EXPECT_TRUE(
338 GetCachedKeyValueDefault(base::FilePath("test.txt"), "FOO", &value));
339 EXPECT_EQ("2", value);
340
341 // kCrashReporterStateDirectory is the first candidate directory.
342 ASSERT_TRUE(test_util::CreateFile(
Jeffrey Kardatzke8ed15d12019-03-21 16:57:20 -0700343 paths::GetAt(paths::kCrashReporterStateDirectory, "test.txt"),
344 "FOO=1\n"));
Satoru Takabayashib2ca40d2018-08-09 14:02:04 +0900345 EXPECT_TRUE(
346 GetCachedKeyValueDefault(base::FilePath("test.txt"), "FOO", &value));
347 EXPECT_EQ("1", value);
348}
349
Satoru Takabayashi8ce6db82018-08-17 15:18:41 +0900350TEST_F(CrashCommonUtilTest, GetUserCrashDirectories) {
351 auto mock =
352 std::make_unique<org::chromium::SessionManagerInterfaceProxyMock>();
353
354 std::vector<base::FilePath> directories;
355
356 test_util::SetActiveSessions(mock.get(), {});
357 EXPECT_TRUE(GetUserCrashDirectories(mock.get(), &directories));
358 EXPECT_TRUE(directories.empty());
359
360 test_util::SetActiveSessions(mock.get(),
361 {{"user1", "hash1"}, {"user2", "hash2"}});
362 EXPECT_TRUE(GetUserCrashDirectories(mock.get(), &directories));
363 EXPECT_EQ(2, directories.size());
Satoru Takabayashib09f7052018-10-01 15:26:29 +0900364 EXPECT_EQ(paths::Get("/home/user/hash1/crash").value(),
365 directories[0].value());
366 EXPECT_EQ(paths::Get("/home/user/hash2/crash").value(),
367 directories[1].value());
Satoru Takabayashi8ce6db82018-08-17 15:18:41 +0900368}
369
Jeffrey Kardatzke437fa922019-05-09 11:34:32 -0700370TEST_F(CrashCommonUtilTest, GzipStream) {
371 std::string content = CreateSemiRandomString(
372 base::RandInt(kRandomDataMinLength, kRandomDataMaxLength));
Ian Barkley-Yeunge87b4f42019-05-22 15:05:13 -0700373 std::vector<unsigned char> compressed_content =
Jeffrey Kardatzke437fa922019-05-09 11:34:32 -0700374 util::GzipStream(brillo::MemoryStream::OpenCopyOf(
375 content.c_str(), content.length(), nullptr));
376 EXPECT_FALSE(compressed_content.empty());
Ian Barkley-Yeunge87b4f42019-05-22 15:05:13 -0700377 EXPECT_LT(compressed_content.size(), content.size())
378 << "Didn't actually compress";
Jeffrey Kardatzke437fa922019-05-09 11:34:32 -0700379 base::FilePath raw_file;
380 ASSERT_TRUE(base::CreateTemporaryFileInDir(test_dir_, &raw_file));
Ian Barkley-Yeunge87b4f42019-05-22 15:05:13 -0700381 base::FilePath compressed_file_name;
382 ASSERT_TRUE(base::CreateTemporaryFileInDir(test_dir_, &compressed_file_name));
Jeffrey Kardatzke437fa922019-05-09 11:34:32 -0700383 // Remove the file we will decompress to or gzip will fail on decompression.
Ian Barkley-Yeunge87b4f42019-05-22 15:05:13 -0700384 ASSERT_TRUE(base::DeleteFile(compressed_file_name, false));
385 compressed_file_name = compressed_file_name.AddExtension(".gz");
Jeffrey Kardatzke437fa922019-05-09 11:34:32 -0700386 ASSERT_EQ(base::WriteFile(raw_file, content.c_str(), content.length()),
387 content.length());
Ian Barkley-Yeunge87b4f42019-05-22 15:05:13 -0700388 {
389 base::File compressed_file(
390 compressed_file_name, base::File::FLAG_WRITE | base::File::FLAG_CREATE);
391 ASSERT_TRUE(compressed_file.IsValid());
392 ssize_t write_result = HANDLE_EINTR(write(compressed_file.GetPlatformFile(),
393 compressed_content.data(),
394 compressed_content.size()));
395 ASSERT_EQ(write_result, compressed_content.size());
396 }
397 EXPECT_TRUE(VerifyCompression(raw_file, compressed_file_name))
Jeffrey Kardatzke437fa922019-05-09 11:34:32 -0700398 << "Random input data: " << content;
399}
400
Tim Zheng11a665e2019-06-26 17:44:01 -0700401TEST_F(CrashCommonUtilTest,
402 DISABLED_ON_QEMU_FOR_MEMFD_CREATE(ReadMemfdToStringEmpty)) {
403 int memfd = memfd_create("test_memfd", 0);
404 std::string read_outs;
405 EXPECT_FALSE(ReadMemfdToString(memfd, &read_outs));
406}
407
408TEST_F(CrashCommonUtilTest,
409 DISABLED_ON_QEMU_FOR_MEMFD_CREATE(ReadMemfdToStringSuccess)) {
410 int memfd = memfd_create("test_memfd", 0);
411 const std::string write_ins = "Test data to write into memfd";
412 ASSERT_EQ(write(memfd, write_ins.c_str(), strlen(write_ins.c_str())),
413 strlen(write_ins.c_str()));
414 std::string read_outs;
415 EXPECT_TRUE(ReadMemfdToString(memfd, &read_outs));
416 EXPECT_EQ(read_outs, write_ins);
417}
418
Kansho Nishida630cc7a2019-10-23 17:37:41 +0900419TEST_F(CrashCommonUtilTest, ReadFdToStream) {
420 std::stringstream stream;
421 EXPECT_TRUE(ReadFdToStream(fd_, &stream));
422 EXPECT_EQ(kReadFdToStreamContents, stream.str());
423}
424
Miriam Zimmermana23f18f2020-11-12 11:09:27 -0800425TEST_F(CrashCommonUtilTest, IsFeedbackAllowedMock) {
426 MetricsLibraryMock mock_metrics;
427 mock_metrics.set_metrics_enabled(false);
428
429 ASSERT_TRUE(test_util::CreateFile(paths::Get("/etc/lsb-release"),
430 "CHROMEOS_RELEASE_TRACK=testimage-channel\n"
431 "CHROMEOS_RELEASE_DESCRIPTION=12985.0.0 "
432 "(Official Build) dev-channel asuka test"));
433
434 EXPECT_FALSE(IsFeedbackAllowed(&mock_metrics));
435 ASSERT_TRUE(test_util::CreateFile(
436 paths::GetAt(paths::kSystemRunStateDirectory, paths::kMockConsent), ""));
437 EXPECT_TRUE(HasMockConsent());
438
439 EXPECT_TRUE(IsFeedbackAllowed(&mock_metrics));
440}
441
442TEST_F(CrashCommonUtilTest, IsFeedbackAllowedDev) {
443 MetricsLibraryMock mock_metrics;
444 mock_metrics.set_metrics_enabled(false);
445
446 EXPECT_FALSE(IsFeedbackAllowed(&mock_metrics));
447
448 ASSERT_TRUE(test_util::CreateFile(paths::Get(paths::kLeaveCoreFile), ""));
449
450 EXPECT_TRUE(IsFeedbackAllowed(&mock_metrics));
451}
452
453// Disable this test when in a VM because there's no easy way to mock the
454// VmSupport class.
455// TODO(https://crbug.com/1150011): When that class can be replaced for tests,
456// use a fake implementation here to set metrics consent appropriately.
457#if !USE_KVM_GUEST
458TEST_F(CrashCommonUtilTest, IsFeedbackAllowedRespectsMetricsLib) {
459 MetricsLibraryMock mock_metrics;
460 mock_metrics.set_metrics_enabled(false);
461
462 EXPECT_FALSE(IsFeedbackAllowed(&mock_metrics));
463
464 mock_metrics.set_metrics_enabled(true);
465 EXPECT_TRUE(IsFeedbackAllowed(&mock_metrics));
466}
467#endif // USE_KVM_GUEST
468
Satoru Takabayashie7f6d2a2018-08-08 17:06:29 +0900469} // namespace util