1 : // Copyright 2016 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : #include "syzygy/kasko/kasko_upload_app.h"
16 :
17 : #include "base/files/file_util.h"
18 : #include "base/strings/stringprintf.h"
19 : #include "gtest/gtest.h"
20 : #include "syzygy/common/unittest_util.h"
21 : #include "syzygy/core/unittest_util.h"
22 : #include "syzygy/kasko/crash_keys_serialization.h"
23 : #include "syzygy/kasko/testing/test_server.h"
24 :
25 m : namespace kasko {
26 :
27 : // A server that is unlikely to exist. Even if it does exist, the path is very
28 : // unlikely to exist, so this should fail most anywhere.
29 m : static const base::string16 kDummyServer(
30 m : L"http:/bla.bar.baz.google.com:65001/unlikely/to/exist");
31 :
32 m : class KaskoUploadAppTest : public ::testing::ApplicationTestBase {
33 m : public:
34 m : typedef ::testing::ApplicationTestBase Super;
35 m : typedef application::Application<KaskoUploadApp> TestApplication;
36 :
37 m : KaskoUploadAppTest()
38 m : : cmd_line_(base::FilePath(L"kasko_upload.exe")),
39 m : impl_(app_.implementation()) {
40 m : }
41 :
42 m : void SetUp() override {
43 m : Super::SetUp();
44 :
45 : // Setup the IO streams.
46 m : ASSERT_NO_FATAL_FAILURE(CreateTemporaryDir(&temp_dir_));
47 m : stdin_path_ = temp_dir_.Append(L"NUL");
48 m : stdout_path_ = temp_dir_.Append(L"stdout.txt");
49 m : stderr_path_ = temp_dir_.Append(L"stderr.txt");
50 m : ASSERT_NO_FATAL_FAILURE(InitStreams(
51 m : stdin_path_, stdout_path_, stderr_path_));
52 :
53 : // Point the application at the test's command-line and IO streams.
54 m : app_.set_command_line(&cmd_line_);
55 m : app_.set_in(in());
56 m : app_.set_out(out());
57 m : app_.set_err(err());
58 m : }
59 :
60 m : base::FilePath ValidMinidumpPath() const {
61 m : return ::testing::GetSrcRelativePath(
62 m : L"syzygy/poirot/test_data/use-after-free.dmp");
63 m : }
64 :
65 m : base::FilePath InvalidMinidumpPath() const {
66 m : return base::FilePath(L"Z:\\this\\does\\not\\exist.dmp");
67 m : }
68 :
69 m : base::FilePath ValidCrashKeysPath() const {
70 m : base::FilePath path = temp_dir_.Append(L"valid-crash-keys.kys");
71 m : if (!base::PathExists(path)) {
72 m : std::map<base::string16, base::string16> crash_keys;
73 m : crash_keys[L"channel"] = L"canary";
74 m : crash_keys[L"guid"] = L"aa2f3148-3a99-4b92-b53b-8ce5ee0ab6ec";
75 m : crash_keys[L"platform"] = L"win32";
76 m : crash_keys[L"prod"] = L"Chrome";
77 m : crash_keys[L"ptype"] = L"browser";
78 m : crash_keys[L"ver"] = L"49.0.2619.1";
79 m : crash_keys[L"metrics_client_id"] = L"BDB9F5962B1F43E18C530B0BA1B80040";
80 m : EXPECT_TRUE(WriteCrashKeysToFile(path, crash_keys));
81 m : }
82 m : return path;
83 m : }
84 :
85 m : base::FilePath IncompleteCrashKeysPath() const {
86 m : base::FilePath path = temp_dir_.Append(L"incomplete-crash-keys.kys");
87 m : if (!base::PathExists(path)) {
88 m : std::map<base::string16, base::string16> crash_keys;
89 m : crash_keys[L"foo"] = L"bar";
90 m : EXPECT_TRUE(WriteCrashKeysToFile(path, crash_keys));
91 m : }
92 m : return path;
93 m : }
94 :
95 m : base::FilePath MalformedCrashKeysPath() const {
96 m : static const char kBadData[] = "this is \"no good as a } JSON dictionary";
97 m : base::FilePath path = temp_dir_.Append(L"malformed-crash-keys.kys");
98 m : if (!base::PathExists(path))
99 m : base::WriteFile(path, kBadData, sizeof(kBadData));
100 m : return path;
101 m : }
102 :
103 m : base::FilePath InvalidCrashKeysPath() const {
104 m : return base::FilePath(L"Z:\\not\\a\\valid\\path.kys");
105 m : }
106 :
107 : // The command line to be given to the application under test.
108 m : base::CommandLine cmd_line_;
109 :
110 : // The application object under test.
111 m : TestApplication app_;
112 :
113 : // A reference to the underlying application implementation for convenience.
114 m : KaskoUploadApp& impl_;
115 :
116 : // A temporary folder where all IO will be stored.
117 m : base::FilePath temp_dir_;
118 :
119 : // @name File paths used for the standard IO streams.
120 : // @{
121 m : base::FilePath stdin_path_;
122 m : base::FilePath stdout_path_;
123 m : base::FilePath stderr_path_;
124 : // @}
125 m : };
126 :
127 m : TEST_F(KaskoUploadAppTest, FailedParseMissingMinidump) {
128 m : ASSERT_FALSE(impl_.ParseCommandLine(&cmd_line_));
129 m : }
130 :
131 m : TEST_F(KaskoUploadAppTest, SuccessfulParseMinimal) {
132 m : cmd_line_.AppendSwitchPath(KaskoUploadApp::kMinidumpSwitch,
133 m : InvalidMinidumpPath());
134 m : ASSERT_TRUE(impl_.ParseCommandLine(&cmd_line_));
135 m : EXPECT_EQ(InvalidMinidumpPath(), impl_.minidump_path());
136 :
137 m : base::FilePath expected_crash_keys_path =
138 m : impl_.minidump_path().ReplaceExtension(L".kys");
139 m : EXPECT_EQ(expected_crash_keys_path, impl_.crash_keys_path());
140 :
141 m : EXPECT_EQ(impl_.kDefaultUploadUrl, impl_.upload_url());
142 m : }
143 :
144 m : TEST_F(KaskoUploadAppTest, SuccessfulParseFull) {
145 m : cmd_line_.AppendSwitchPath(KaskoUploadApp::kMinidumpSwitch,
146 m : InvalidMinidumpPath());
147 m : cmd_line_.AppendSwitchPath(KaskoUploadApp::kCrashKeysSwitch,
148 m : InvalidCrashKeysPath());
149 m : cmd_line_.AppendSwitchNative(KaskoUploadApp::kUploadUrlSwitch, kDummyServer);
150 m : ASSERT_TRUE(impl_.ParseCommandLine(&cmd_line_));
151 :
152 m : EXPECT_EQ(InvalidMinidumpPath(), impl_.minidump_path());
153 m : EXPECT_EQ(InvalidCrashKeysPath(), impl_.crash_keys_path());
154 m : EXPECT_EQ(kDummyServer, impl_.upload_url());
155 m : }
156 :
157 m : TEST_F(KaskoUploadAppTest, CrashKeysFileMissing) {
158 m : cmd_line_.AppendSwitchPath(KaskoUploadApp::kMinidumpSwitch,
159 m : ValidMinidumpPath());
160 m : cmd_line_.AppendSwitchPath(KaskoUploadApp::kCrashKeysSwitch,
161 m : InvalidCrashKeysPath());
162 m : EXPECT_EQ(KaskoUploadApp::kReturnCodeCrashKeysFileMissing, app_.Run());
163 m : }
164 :
165 m : TEST_F(KaskoUploadAppTest, CrashKeysFileMalformed) {
166 m : cmd_line_.AppendSwitchPath(KaskoUploadApp::kMinidumpSwitch,
167 m : ValidMinidumpPath());
168 m : cmd_line_.AppendSwitchPath(KaskoUploadApp::kCrashKeysSwitch,
169 m : MalformedCrashKeysPath());
170 m : EXPECT_EQ(KaskoUploadApp::kReturnCodeCrashKeysFileMalformed, app_.Run());
171 m : }
172 :
173 m : TEST_F(KaskoUploadAppTest, CrashKeysAbsent) {
174 m : cmd_line_.AppendSwitchPath(KaskoUploadApp::kMinidumpSwitch,
175 m : ValidMinidumpPath());
176 m : cmd_line_.AppendSwitchPath(KaskoUploadApp::kCrashKeysSwitch,
177 m : IncompleteCrashKeysPath());
178 m : EXPECT_EQ(KaskoUploadApp::kReturnCodeCrashKeysAbsent, app_.Run());
179 m : }
180 :
181 m : TEST_F(KaskoUploadAppTest, MinidumpFileMissing) {
182 m : cmd_line_.AppendSwitchPath(KaskoUploadApp::kMinidumpSwitch,
183 m : InvalidMinidumpPath());
184 m : cmd_line_.AppendSwitchPath(KaskoUploadApp::kCrashKeysSwitch,
185 m : ValidCrashKeysPath());
186 m : EXPECT_EQ(KaskoUploadApp::kReturnCodeMinidumpFileMissing, app_.Run());
187 m : }
188 :
189 m : TEST_F(KaskoUploadAppTest, UploadFailed) {
190 m : cmd_line_.AppendSwitchPath(KaskoUploadApp::kMinidumpSwitch,
191 m : ValidMinidumpPath());
192 m : cmd_line_.AppendSwitchPath(KaskoUploadApp::kCrashKeysSwitch,
193 m : ValidCrashKeysPath());
194 m : cmd_line_.AppendSwitchNative(KaskoUploadApp::kUploadUrlSwitch, kDummyServer);
195 m : EXPECT_EQ(KaskoUploadApp::kReturnCodeUploadFailed, app_.Run());
196 m : }
197 :
198 m : TEST_F(KaskoUploadAppTest, UploadSucceeds) {
199 m : kasko::testing::TestServer test_server;
200 m : ASSERT_TRUE(test_server.Start());
201 m : base::string16 upload_url = base::StringPrintf(L"http://localhost:%d/crash",
202 m : test_server.port());
203 :
204 m : cmd_line_.AppendSwitchPath(KaskoUploadApp::kMinidumpSwitch,
205 m : ValidMinidumpPath());
206 m : cmd_line_.AppendSwitchPath(KaskoUploadApp::kCrashKeysSwitch,
207 m : ValidCrashKeysPath());
208 m : cmd_line_.AppendSwitchNative(KaskoUploadApp::kUploadUrlSwitch, upload_url);
209 :
210 m : EXPECT_EQ(KaskoUploadApp::kReturnCodeSuccess, app_.Run());
211 m : }
212 :
213 m : } // namespace kasko
|