1 // Copyright 2015 The Chromium 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.
7 #include "base/base_paths.h"
9 #include "base/files/file_path.h"
10 #include "base/files/file_util.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/test/scoped_path_override.h"
13 #include "chromecast/crash/linux/crash_testing_utils.h"
14 #include "chromecast/crash/linux/dump_info.h"
15 #include "chromecast/crash/linux/minidump_generator.h"
16 #include "chromecast/crash/linux/minidump_writer.h"
17 #include "testing/gtest/include/gtest/gtest.h"
19 namespace chromecast
{
22 const char kDumplogFile
[] = "dumplog";
23 const char kLockfileName
[] = "lockfile";
24 const char kMetadataName
[] = "metadata";
25 const char kMinidumpSubdir
[] = "minidumps";
27 class FakeMinidumpGenerator
: public MinidumpGenerator
{
29 FakeMinidumpGenerator() {}
30 ~FakeMinidumpGenerator() override
{}
32 // MinidumpGenerator implementation:
33 bool Generate(const std::string
& minidump_path
) override
{ return true; }
36 int FakeDumpState(const std::string
& minidump_path
) {
42 class MinidumpWriterTest
: public testing::Test
{
44 MinidumpWriterTest() {}
45 ~MinidumpWriterTest() override
{}
47 void SetUp() override
{
48 // Set up a temporary directory which will be used as our fake home dir.
49 base::FilePath fake_home_dir
;
50 ASSERT_TRUE(base::CreateNewTempDirectory("", &fake_home_dir
));
51 home_
.reset(new base::ScopedPathOverride(base::DIR_HOME
, fake_home_dir
));
52 minidump_dir_
= fake_home_dir
.Append(kMinidumpSubdir
);
53 dumplog_file_
= minidump_dir_
.Append(kDumplogFile
);
54 lockfile_path_
= minidump_dir_
.Append(kLockfileName
);
55 metadata_path_
= minidump_dir_
.Append(kMetadataName
);
57 // Create the minidump directory
58 ASSERT_TRUE(base::CreateDirectory(minidump_dir_
));
60 // Lockfile will be automatically created by AppendLockFile
63 bool AppendLockFile(const DumpInfo
& dump
) {
64 return chromecast::AppendLockFile(
65 lockfile_path_
.value(), metadata_path_
.value(), dump
);
68 FakeMinidumpGenerator fake_generator_
;
69 base::FilePath minidump_dir_
;
70 base::FilePath dumplog_file_
;
71 base::FilePath lockfile_path_
;
72 base::FilePath metadata_path_
;
75 scoped_ptr
<base::ScopedPathOverride
> home_
;
77 DISALLOW_COPY_AND_ASSIGN(MinidumpWriterTest
);
80 TEST_F(MinidumpWriterTest
, Write_FailsWithIncorrectMinidumpPath
) {
81 MinidumpWriter
writer(&fake_generator_
,
84 base::Bind(&FakeDumpState
));
86 ASSERT_EQ(-1, writer
.Write());
89 TEST_F(MinidumpWriterTest
, Write_FailsWithMultiLevelRelativeMinidumpPath
) {
90 MinidumpWriter
writer(&fake_generator_
,
93 base::Bind(&FakeDumpState
));
95 ASSERT_EQ(-1, writer
.Write());
98 TEST_F(MinidumpWriterTest
, Write_SucceedsWithSimpleFilename
) {
99 MinidumpWriter
writer(&fake_generator_
,
102 base::Bind(&FakeDumpState
));
104 ASSERT_EQ(0, writer
.Write());
107 TEST_F(MinidumpWriterTest
, Write_SucceedsWithCorrectMinidumpPath
) {
108 MinidumpWriter
writer(&fake_generator_
,
109 dumplog_file_
.value(),
111 base::Bind(&FakeDumpState
));
113 ASSERT_EQ(0, writer
.Write());
116 TEST_F(MinidumpWriterTest
, Write_FailsWithSubdirInCorrectPath
) {
117 MinidumpWriter
writer(&fake_generator_
,
118 dumplog_file_
.Append("subdir/logfile").value(),
120 base::Bind(&FakeDumpState
));
121 ASSERT_EQ(-1, writer
.Write());
124 TEST_F(MinidumpWriterTest
, Write_FailsWhenTooManyDumpsPresent
) {
125 MinidumpWriter
writer(&fake_generator_
,
126 dumplog_file_
.value(),
128 base::Bind(&FakeDumpState
));
130 // Write dump logs to the lockfile.
131 size_t too_many_dumps
= SynchronizedMinidumpManager::kMaxLockfileDumps
+ 1;
132 for (size_t i
= 0; i
< too_many_dumps
; ++i
) {
133 scoped_ptr
<DumpInfo
> info(CreateDumpInfo(
136 "\"dump_time\" : \"2012-01-01 01:02:03\","
137 "\"dump\": \"dump_string\","
138 "\"uptime\": \"123456789\","
139 "\"logfile\": \"logfile.log\""
141 ASSERT_TRUE(info
->valid());
142 ASSERT_TRUE(AppendLockFile(*info
));
145 ASSERT_EQ(-1, writer
.Write());
148 TEST_F(MinidumpWriterTest
, Write_FailsWhenTooManyRecentDumpsPresent
) {
149 MinidumpWriter
writer(&fake_generator_
,
150 dumplog_file_
.value(),
152 base::Bind(&FakeDumpState
));
153 // Multiple iters to make sure period resets work correctly
154 for (int iter
= 0; iter
< 3; ++iter
) {
155 time_t now
= time(nullptr);
157 // Write dump logs to the lockfile.
158 size_t too_many_recent_dumps
=
159 SynchronizedMinidumpManager::kRatelimitPeriodMaxDumps
;
160 for (size_t i
= 0; i
< too_many_recent_dumps
; ++i
) {
161 ASSERT_EQ(0, writer
.Write());
163 // Clear dumps so we don't reach max dumps in lockfile
164 ASSERT_TRUE(ClearDumps(lockfile_path_
.value()));
167 // Should fail with too many dumps
168 ASSERT_EQ(-1, writer
.Write());
170 int64 period
= SynchronizedMinidumpManager::kRatelimitPeriodSeconds
;
172 // Half period shouldn't trigger reset
173 SetRatelimitPeriodStart(metadata_path_
.value(), now
- period
/ 2);
174 ASSERT_EQ(-1, writer
.Write());
176 // Set period starting time to trigger a reset
177 SetRatelimitPeriodStart(metadata_path_
.value(), now
- period
);
180 ASSERT_EQ(0, writer
.Write());
183 TEST_F(MinidumpWriterTest
, Write_SucceedsWhenDumpLimitsNotExceeded
) {
184 MinidumpWriter
writer(&fake_generator_
,
185 dumplog_file_
.value(),
187 base::Bind(&FakeDumpState
));
189 ASSERT_GT(SynchronizedMinidumpManager::kMaxLockfileDumps
, 1);
190 ASSERT_GT(SynchronizedMinidumpManager::kRatelimitPeriodMaxDumps
, 0);
192 // Write an old dump logs to the lockfile.
193 scoped_ptr
<DumpInfo
> info(CreateDumpInfo(
196 "\"dump_time\" : \"2012-01-01 01:02:03\","
197 "\"dump\": \"dump_string\","
198 "\"uptime\": \"123456789\","
199 "\"logfile\": \"logfile.log\""
201 ASSERT_TRUE(info
->valid());
202 ASSERT_TRUE(AppendLockFile(*info
));
203 ASSERT_EQ(0, writer
.Write());
206 } // namespace chromecast