OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <fstream> | 5 #include <fstream> |
6 | 6 |
7 #include "base/base_paths.h" | 7 #include "base/base_paths.h" |
8 #include "base/bind.h" | 8 #include "base/bind.h" |
9 #include "base/files/file.h" | 9 #include "base/files/file.h" |
10 #include "base/files/file_util.h" | 10 #include "base/files/file_util.h" |
11 #include "base/memory/scoped_vector.h" | 11 #include "base/memory/scoped_vector.h" |
12 #include "base/test/scoped_path_override.h" | 12 #include "base/test/scoped_path_override.h" |
13 #include "base/threading/thread_restrictions.h" | |
14 #include "chromecast/app/linux/cast_crash_reporter_client.h" | 13 #include "chromecast/app/linux/cast_crash_reporter_client.h" |
15 #include "chromecast/crash/app_state_tracker.h" | 14 #include "chromecast/crash/app_state_tracker.h" |
16 #include "chromecast/crash/linux/crash_util.h" | 15 #include "chromecast/crash/linux/crash_util.h" |
17 #include "chromecast/crash/linux/dump_info.h" | 16 #include "chromecast/crash/linux/dump_info.h" |
18 #include "testing/gtest/include/gtest/gtest.h" | 17 #include "testing/gtest/include/gtest/gtest.h" |
19 | 18 |
20 namespace chromecast { | 19 namespace chromecast { |
21 namespace { | 20 namespace { |
22 | 21 |
23 const char kFakeDumpstateContents[] = "Dumpstate Contents\nDumpdumpdumpdump\n"; | 22 const char kFakeDumpstateContents[] = "Dumpstate Contents\nDumpdumpdumpdump\n"; |
(...skipping 16 matching lines...) Expand all Loading... |
40 DCHECK(in.is_open()); | 39 DCHECK(in.is_open()); |
41 while (std::getline(in, entry)) { | 40 while (std::getline(in, entry)) { |
42 scoped_ptr<DumpInfo> info(new DumpInfo(entry)); | 41 scoped_ptr<DumpInfo> info(new DumpInfo(entry)); |
43 dumps.push_back(info.Pass()); | 42 dumps.push_back(info.Pass()); |
44 } | 43 } |
45 return dumps.Pass(); | 44 return dumps.Pass(); |
46 } | 45 } |
47 | 46 |
48 } // namespace | 47 } // namespace |
49 | 48 |
50 class CastCrashReporterClientTest : public testing::Test { | 49 TEST(CastCrashReporterClientTest, EndToEnd) { |
51 protected: | 50 // Set up a temporary directory which will be used as our fake home dir. |
52 CastCrashReporterClientTest() {} | 51 base::FilePath fake_home_dir; |
53 ~CastCrashReporterClientTest() override {} | 52 ASSERT_TRUE(base::CreateNewTempDirectory("", &fake_home_dir)); |
| 53 base::ScopedPathOverride home(base::DIR_HOME, fake_home_dir); |
54 | 54 |
55 static void SetUpTestCase() { | 55 // Set a callback to be used in place of the |dumpstate| executable. |
56 // Set a callback to be used in place of the |dumpstate| executable. | 56 CrashUtil::SetDumpStateCbForTest(base::Bind(&WriteFakeDumpStateFile)); |
57 CrashUtil::SetDumpStateCbForTest(base::Bind(&WriteFakeDumpStateFile)); | |
58 } | |
59 | 57 |
60 // testing::Test implementation: | 58 // "Launch" YouTube. |
61 void SetUp() override { | 59 AppStateTracker::SetLastLaunchedApp("youtube"); |
62 // Set up a temporary directory which will be used as our fake home dir. | 60 AppStateTracker::SetCurrentApp("youtube"); |
63 ASSERT_TRUE(base::CreateNewTempDirectory("", &fake_home_dir_)); | |
64 home_override_.reset( | |
65 new base::ScopedPathOverride(base::DIR_HOME, fake_home_dir_)); | |
66 | 61 |
67 // "Launch" YouTube. | 62 // "Launch" and switch to Pandora. |
68 AppStateTracker::SetLastLaunchedApp("youtube"); | 63 AppStateTracker::SetLastLaunchedApp("pandora"); |
69 AppStateTracker::SetCurrentApp("youtube"); | 64 AppStateTracker::SetCurrentApp("pandora"); |
70 | 65 |
71 // "Launch" and switch to Pandora. | 66 // "Launch" Netflix. |
72 AppStateTracker::SetLastLaunchedApp("pandora"); | 67 AppStateTracker::SetLastLaunchedApp("netflix"); |
73 AppStateTracker::SetCurrentApp("pandora"); | 68 // Netflix crashed. |
74 | 69 |
75 // "Launch" Netflix. | 70 // A minidump file is created. |
76 AppStateTracker::SetLastLaunchedApp("netflix"); | 71 base::FilePath minidump_path; |
77 // Netflix crashed. | 72 base::CreateTemporaryFile(&minidump_path); |
| 73 base::File minidump(minidump_path, |
| 74 base::File::FLAG_OPEN | base::File::FLAG_APPEND); |
| 75 minidump.Write(0, kFakeMinidumpContents, sizeof(kFakeMinidumpContents) - 1); |
| 76 minidump.Close(); |
78 | 77 |
79 // A minidump file is created. | 78 // Handle the crash. |
80 base::CreateTemporaryFile(&minidump_path_); | 79 CastCrashReporterClient client; |
81 base::File minidump(minidump_path_, | 80 ASSERT_TRUE(client.HandleCrashDump(minidump_path.value().c_str())); |
82 base::File::FLAG_OPEN | base::File::FLAG_APPEND); | |
83 minidump.Write(0, kFakeMinidumpContents, sizeof(kFakeMinidumpContents) - 1); | |
84 minidump.Close(); | |
85 } | |
86 | 81 |
87 void TearDown() override { | 82 // Assert that the original file has been moved. |
88 // Remove IO restrictions in order to examine the state of the filesystem. | 83 ASSERT_FALSE(base::PathExists(minidump_path)); |
89 base::ThreadRestrictions::SetIOAllowed(true); | |
90 | 84 |
91 // Assert that the original file has been moved. | 85 // Assert that the file has been moved to "minidumps", with the expected |
92 ASSERT_FALSE(base::PathExists(minidump_path_)); | 86 // contents. |
| 87 std::string contents; |
| 88 base::FilePath new_minidump = |
| 89 fake_home_dir.Append("minidumps").Append(minidump_path.BaseName()); |
| 90 ASSERT_TRUE(base::PathExists(new_minidump)); |
| 91 ASSERT_TRUE(base::ReadFileToString(new_minidump, &contents)); |
| 92 ASSERT_EQ(kFakeMinidumpContents, contents); |
93 | 93 |
94 // Assert that the file has been moved to "minidumps", with the expected | 94 // Assert that the dumpstate file has been written with the expected contents. |
95 // contents. | 95 base::FilePath dumpstate = new_minidump.AddExtension(".txt.gz"); |
96 std::string contents; | 96 ASSERT_TRUE(base::PathExists(dumpstate)); |
97 base::FilePath new_minidump = | 97 ASSERT_TRUE(base::ReadFileToString(dumpstate, &contents)); |
98 fake_home_dir_.Append("minidumps").Append(minidump_path_.BaseName()); | 98 ASSERT_EQ(kFakeDumpstateContents, contents); |
99 ASSERT_TRUE(base::PathExists(new_minidump)); | |
100 ASSERT_TRUE(base::ReadFileToString(new_minidump, &contents)); | |
101 ASSERT_EQ(kFakeMinidumpContents, contents); | |
102 | 99 |
103 // Assert that the dumpstate file has been written with the expected | 100 // Assert that the lockfile has logged the correct information. |
104 // contents. | 101 base::FilePath lockfile = |
105 base::FilePath dumpstate = new_minidump.AddExtension(".txt.gz"); | 102 fake_home_dir.Append("minidumps").Append("lockfile"); |
106 ASSERT_TRUE(base::PathExists(dumpstate)); | 103 ASSERT_TRUE(base::PathExists(lockfile)); |
107 ASSERT_TRUE(base::ReadFileToString(dumpstate, &contents)); | 104 ScopedVector<DumpInfo> dumps = GetCurrentDumps(lockfile.value()); |
108 ASSERT_EQ(kFakeDumpstateContents, contents); | 105 ASSERT_EQ(1u, dumps.size()); |
109 | 106 |
110 // Assert that the lockfile has logged the correct information. | 107 const DumpInfo& dump_info = *(dumps[0]); |
111 base::FilePath lockfile = | 108 ASSERT_TRUE(dump_info.valid()); |
112 fake_home_dir_.Append("minidumps").Append("lockfile"); | 109 EXPECT_EQ(new_minidump.value(), dump_info.crashed_process_dump()); |
113 ASSERT_TRUE(base::PathExists(lockfile)); | 110 EXPECT_EQ(dumpstate.value(), dump_info.logfile()); |
114 ScopedVector<DumpInfo> dumps = GetCurrentDumps(lockfile.value()); | 111 EXPECT_EQ("youtube", dump_info.params().previous_app_name); |
115 ASSERT_EQ(1u, dumps.size()); | 112 EXPECT_EQ("pandora", dump_info.params().current_app_name); |
116 | 113 EXPECT_EQ("netflix", dump_info.params().last_app_name); |
117 const DumpInfo& dump_info = *(dumps[0]); | |
118 ASSERT_TRUE(dump_info.valid()); | |
119 EXPECT_EQ(new_minidump.value(), dump_info.crashed_process_dump()); | |
120 EXPECT_EQ(dumpstate.value(), dump_info.logfile()); | |
121 EXPECT_EQ("youtube", dump_info.params().previous_app_name); | |
122 EXPECT_EQ("pandora", dump_info.params().current_app_name); | |
123 EXPECT_EQ("netflix", dump_info.params().last_app_name); | |
124 } | |
125 | |
126 const base::FilePath& minidump_path() { return minidump_path_; } | |
127 | |
128 private: | |
129 base::FilePath fake_home_dir_; | |
130 base::FilePath minidump_path_; | |
131 scoped_ptr<base::ScopedPathOverride> home_override_; | |
132 }; | |
133 | |
134 TEST_F(CastCrashReporterClientTest, EndToEndTestOnIORestrictedThread) { | |
135 // Handle a "crash" on an IO restricted thread. | |
136 base::ThreadRestrictions::SetIOAllowed(false); | |
137 CastCrashReporterClient client; | |
138 ASSERT_TRUE(client.HandleCrashDump(minidump_path().value().c_str())); | |
139 | |
140 // Assert that the thread is IO restricted when the function exits. | |
141 // Note that SetIOAllowed returns the previous value. | |
142 ASSERT_FALSE(base::ThreadRestrictions::SetIOAllowed(true)); | |
143 } | 114 } |
144 | 115 |
145 TEST_F(CastCrashReporterClientTest, EndToEndTestOnNonIORestrictedThread) { | 116 } // namespace chromecast |
146 // Handle a crash on a non-IO restricted thread. | |
147 base::ThreadRestrictions::SetIOAllowed(true); | |
148 CastCrashReporterClient client; | |
149 ASSERT_TRUE(client.HandleCrashDump(minidump_path().value().c_str())); | |
150 | |
151 // Assert that the thread is not IO restricted when the function exits. | |
152 // Note that SetIOAllowed returns the previous value. | |
153 ASSERT_TRUE(base::ThreadRestrictions::SetIOAllowed(true)); | |
154 } | |
155 | |
156 } // namespace chromecast | |
OLD | NEW |