1 : // Copyright 2015 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/poirot/poirot_app.h"
16 :
17 : #include "gtest/gtest.h"
18 : #include "syzygy/common/unittest_util.h"
19 : #include "syzygy/core/unittest_util.h"
20 : #include "syzygy/poirot/unittest_util.h"
21 :
22 : namespace poirot {
23 :
24 : namespace {
25 :
26 : class TestPoirotApp : public PoirotApp {
27 : public:
28 : using PoirotApp::input_minidump_;
29 : using PoirotApp::output_file_;
30 : };
31 :
32 : typedef application::Application<TestPoirotApp> TestApp;
33 :
34 : class PoirotAppTest : public testing::ApplicationTestBase {
35 : public:
36 : typedef testing::ApplicationTestBase Super;
37 :
38 : PoirotAppTest()
39 E : : cmd_line_(base::FilePath(L"poirot.exe")),
40 E : test_impl_(test_app_.implementation()) {}
41 :
42 E : void SetUp() override {
43 E : Super::SetUp();
44 :
45 E : logging::SetMinLogLevel(logging::LOG_ERROR);
46 :
47 : // Setup the IO streams.
48 E : CreateTemporaryDir(&temp_dir_);
49 E : stdin_path_ = temp_dir_.Append(L"NUL");
50 E : stdout_path_ = temp_dir_.Append(L"stdout.txt");
51 E : stderr_path_ = temp_dir_.Append(L"stderr.txt");
52 E : InitStreams(stdin_path_, stdout_path_, stderr_path_);
53 :
54 E : ASSERT_NO_FATAL_FAILURE(ConfigureTestApp(&test_app_));
55 E : }
56 :
57 : // Points the application at the fixture's command-line and IO streams.
58 : template <typename TestAppType>
59 E : void ConfigureTestApp(TestAppType* test_app) {
60 E : test_app->set_command_line(&cmd_line_);
61 E : test_app->set_in(in());
62 E : test_app->set_out(out());
63 E : test_app->set_err(err());
64 E : }
65 :
66 : // Stashes the current log-level before each test instance and restores it
67 : // after each test completes.
68 : testing::ScopedLogLevelSaver log_level_saver;
69 :
70 : // @name The application under test.
71 : // @{
72 : TestApp test_app_;
73 : TestApp::Implementation& test_impl_;
74 : base::FilePath temp_dir_;
75 : base::FilePath stdin_path_;
76 : base::FilePath stdout_path_;
77 : base::FilePath stderr_path_;
78 : // @}
79 :
80 : base::CommandLine cmd_line_;
81 : };
82 :
83 : } // namespace
84 :
85 E : TEST_F(PoirotAppTest, GetHelp) {
86 E : cmd_line_.AppendSwitch("help");
87 E : EXPECT_FALSE(test_impl_.ParseCommandLine(&cmd_line_));
88 E : }
89 :
90 E : TEST_F(PoirotAppTest, ParseEmptyCommandLineFails) {
91 E : EXPECT_FALSE(test_impl_.ParseCommandLine(&cmd_line_));
92 E : }
93 :
94 E : TEST_F(PoirotAppTest, ParseMinimalCommandLineSucceeds) {
95 E : cmd_line_.AppendSwitchPath("input-minidump",
96 : testing::GetSrcRelativePath(testing::kMinidumpUAF));
97 E : EXPECT_TRUE(test_impl_.ParseCommandLine(&cmd_line_));
98 E : EXPECT_SAME_FILE(test_impl_.input_minidump_,
99 E : testing::GetSrcRelativePath(testing::kMinidumpUAF));
100 E : }
101 :
102 E : TEST_F(PoirotAppTest, ParseFullCommandLineSucceeds) {
103 E : cmd_line_.AppendSwitchPath("input-minidump",
104 : testing::GetSrcRelativePath(testing::kMinidumpUAF));
105 E : cmd_line_.AppendSwitchPath("output-file", temp_dir_.Append(L"foo.log"));
106 E : EXPECT_TRUE(test_impl_.ParseCommandLine(&cmd_line_));
107 E : EXPECT_SAME_FILE(testing::GetSrcRelativePath(testing::kMinidumpUAF),
108 E : test_impl_.input_minidump_);
109 E : EXPECT_SAME_FILE(temp_dir_.Append(L"foo.log"), test_impl_.output_file_);
110 E : }
111 :
112 E : TEST_F(PoirotAppTest, ProcessValidFileSucceeds) {
113 E : cmd_line_.AppendSwitchPath("input-minidump",
114 : testing::GetSrcRelativePath(testing::kMinidumpUAF));
115 E : EXPECT_TRUE(test_impl_.ParseCommandLine(&cmd_line_));
116 E : EXPECT_EQ(0, test_impl_.Run());
117 E : }
118 :
119 E : TEST_F(PoirotAppTest, ProcessFileWithNoKaskoStreamFails) {
120 E : cmd_line_.AppendSwitchPath("input-minidump",
121 : testing::GetSrcRelativePath(testing::kMinidumpNoKaskoStream));
122 E : EXPECT_TRUE(test_impl_.ParseCommandLine(&cmd_line_));
123 E : EXPECT_NE(0, test_impl_.Run());
124 E : }
125 :
126 E : TEST_F(PoirotAppTest, ProcessNonExistingFileFails) {
127 E : cmd_line_.AppendSwitchPath("input-minidump",
128 : testing::GetSrcRelativePath(testing::kMinidumpInvalidPath));
129 E : EXPECT_TRUE(test_impl_.ParseCommandLine(&cmd_line_));
130 E : EXPECT_NE(0, test_impl_.Run());
131 E : }
132 :
133 E : TEST_F(PoirotAppTest, WriteJsonOutput) {
134 E : base::FilePath temp_file;
135 E : EXPECT_TRUE(base::CreateTemporaryFileInDir(temp_dir_, &temp_file));
136 E : cmd_line_.AppendSwitchPath("input-minidump",
137 : testing::GetSrcRelativePath(testing::kMinidumpUAF));
138 E : cmd_line_.AppendSwitchPath("output-file", temp_file);
139 E : std::string file_content;
140 E : EXPECT_TRUE(base::ReadFileToString(temp_file, &file_content));
141 E : EXPECT_TRUE(file_content.empty());
142 E : EXPECT_TRUE(test_impl_.ParseCommandLine(&cmd_line_));
143 E : EXPECT_EQ(0, test_impl_.Run());
144 E : EXPECT_TRUE(base::ReadFileToString(temp_file, &file_content));
145 E : EXPECT_FALSE(file_content.empty());
146 E : }
147 :
148 : } // namespace poirot
|