1 : // Copyright 2013 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/optimize/optimize_app.h"
16 :
17 : #include "base/stringprintf.h"
18 : #include "gmock/gmock.h"
19 : #include "gtest/gtest.h"
20 : #include "syzygy/common/unittest_util.h"
21 : #include "syzygy/core/unittest_util.h"
22 : #include "syzygy/pe/pe_utils.h"
23 : #include "syzygy/pe/unittest_util.h"
24 :
25 : namespace optimize {
26 :
27 : using common::Application;
28 : using ::testing::ScopedLogLevelSaver;
29 :
30 : namespace {
31 :
32 : class TestOptimizeApp : public OptimizeApp {
33 : public:
34 : using OptimizeApp::input_image_path_;
35 : using OptimizeApp::input_pdb_path_;
36 : using OptimizeApp::output_image_path_;
37 : using OptimizeApp::output_pdb_path_;
38 : using OptimizeApp::branch_file_path_;
39 : using OptimizeApp::basic_block_reorder_;
40 : using OptimizeApp::block_alignment_;
41 : using OptimizeApp::fuzz_;
42 : using OptimizeApp::inlining_;
43 : using OptimizeApp::peephole_;
44 : using OptimizeApp::overwrite_;
45 : };
46 :
47 : typedef common::Application<TestOptimizeApp> TestApp;
48 :
49 : class OptimizeAppTest : public testing::PELibUnitTest {
50 : public:
51 : typedef testing::PELibUnitTest Super;
52 :
53 : OptimizeAppTest()
54 : : cmd_line_(base::FilePath(L"optimize.exe")),
55 E : test_impl_(test_app_.implementation()) {
56 E : }
57 :
58 E : void SetUp() {
59 E : Super::SetUp();
60 :
61 : // Several of the tests generate progress and (deliberate) error messages
62 : // that would otherwise clutter the unittest output.
63 E : logging::SetMinLogLevel(logging::LOG_FATAL);
64 :
65 : // Setup the IO streams.
66 E : CreateTemporaryDir(&temp_dir_);
67 E : stdin_path_ = temp_dir_.Append(L"NUL");
68 E : stdout_path_ = temp_dir_.Append(L"stdout.txt");
69 E : stderr_path_ = temp_dir_.Append(L"stderr.txt");
70 E : InitStreams(stdin_path_, stdout_path_, stderr_path_);
71 :
72 : // Initialize the (potential) input and output path values.
73 E : abs_input_image_path_ = testing::GetExeRelativePath(testing::kTestDllName);
74 E : input_image_path_ = testing::GetRelativePath(abs_input_image_path_);
75 E : abs_input_pdb_path_ = testing::GetExeRelativePath(testing::kTestDllPdbName);
76 E : input_pdb_path_ = testing::GetRelativePath(abs_input_pdb_path_);
77 E : output_image_path_ = temp_dir_.Append(input_image_path_.BaseName());
78 E : output_pdb_path_ = temp_dir_.Append(input_pdb_path_.BaseName());
79 E : branch_file_path_ = temp_dir_.Append(L"branch.json");
80 :
81 : // Point the application at the test's command-line and IO streams.
82 E : test_app_.set_command_line(&cmd_line_);
83 E : test_app_.set_in(in());
84 E : test_app_.set_out(out());
85 E : test_app_.set_err(err());
86 E : }
87 :
88 : // Stashes the current log-level before each test instance and restores it
89 : // after each test completes.
90 : ScopedLogLevelSaver log_level_saver;
91 :
92 : // @name The application under test.
93 : // @{
94 : TestApp test_app_;
95 : TestApp::Implementation& test_impl_;
96 : base::FilePath temp_dir_;
97 : base::FilePath stdin_path_;
98 : base::FilePath stdout_path_;
99 : base::FilePath stderr_path_;
100 : // @}
101 :
102 : // @name Command-line and parameters.
103 : // @{
104 : CommandLine cmd_line_;
105 : base::FilePath input_image_path_;
106 : base::FilePath input_pdb_path_;
107 : base::FilePath output_image_path_;
108 : base::FilePath output_pdb_path_;
109 : base::FilePath branch_file_path_;
110 : // @}
111 :
112 : // @name Expected final values of input parameters.
113 : // @{
114 : base::FilePath abs_input_image_path_;
115 : base::FilePath abs_input_pdb_path_;
116 : // @}
117 : };
118 :
119 : } // namespace
120 :
121 E : TEST_F(OptimizeAppTest, GetHelp) {
122 E : cmd_line_.AppendSwitch("help");
123 E : ASSERT_FALSE(test_impl_.ParseCommandLine(&cmd_line_));
124 E : }
125 :
126 E : TEST_F(OptimizeAppTest, EmptyCommandLineFails) {
127 E : ASSERT_FALSE(test_impl_.ParseCommandLine(&cmd_line_));
128 E : }
129 :
130 E : TEST_F(OptimizeAppTest, ParseWithNoInputFails) {
131 E : cmd_line_.AppendSwitchPath("output-image", output_image_path_);
132 :
133 E : ASSERT_FALSE(test_impl_.ParseCommandLine(&cmd_line_));
134 E : }
135 :
136 E : TEST_F(OptimizeAppTest, ParseWithNoOutputFails) {
137 E : cmd_line_.AppendSwitchPath("input-image", output_image_path_);
138 :
139 E : ASSERT_FALSE(test_impl_.ParseCommandLine(&cmd_line_));
140 E : }
141 :
142 E : TEST_F(OptimizeAppTest, ParseMinimalCommandLineWithInputAndOutput) {
143 E : cmd_line_.AppendSwitchPath("input-image", input_image_path_);
144 E : cmd_line_.AppendSwitchPath("output-image", output_image_path_);
145 :
146 E : EXPECT_TRUE(test_impl_.ParseCommandLine(&cmd_line_));
147 E : EXPECT_TRUE(test_impl_.SetUp());
148 E : }
149 :
150 E : TEST_F(OptimizeAppTest, ParseMinimalCommandLineWithBranchFile) {
151 E : cmd_line_.AppendSwitchPath("branch-file", branch_file_path_);
152 E : cmd_line_.AppendSwitchPath("input-image", input_image_path_);
153 E : cmd_line_.AppendSwitchPath("output-image", output_image_path_);
154 E : EXPECT_FALSE(test_impl_.overwrite_);
155 E : EXPECT_FALSE(test_impl_.inlining_);
156 E : EXPECT_FALSE(test_impl_.block_alignment_);
157 E : EXPECT_FALSE(test_impl_.basic_block_reorder_);
158 E : EXPECT_FALSE(test_impl_.peephole_);
159 E : EXPECT_FALSE(test_impl_.fuzz_);
160 :
161 E : EXPECT_TRUE(test_impl_.ParseCommandLine(&cmd_line_));
162 E : EXPECT_TRUE(test_impl_.SetUp());
163 E : }
164 :
165 E : TEST_F(OptimizeAppTest, ParseFullCommandLineWithBranchFile) {
166 E : cmd_line_.AppendSwitchPath("input-image", input_image_path_);
167 E : cmd_line_.AppendSwitchPath("output-image", output_image_path_);
168 E : cmd_line_.AppendSwitchPath("output-pdb", output_pdb_path_);
169 E : cmd_line_.AppendSwitchPath("branch-file", branch_file_path_);
170 E : cmd_line_.AppendSwitch("overwrite");
171 :
172 E : EXPECT_TRUE(test_impl_.ParseCommandLine(&cmd_line_));
173 E : EXPECT_FALSE(test_impl_.input_image_path_.empty());
174 E : EXPECT_TRUE(test_impl_.input_pdb_path_.empty());
175 E : EXPECT_EQ(output_image_path_, test_impl_.output_image_path_);
176 E : EXPECT_EQ(output_pdb_path_, test_impl_.output_pdb_path_);
177 E : EXPECT_EQ(branch_file_path_, test_impl_.branch_file_path_);
178 E : EXPECT_TRUE(test_impl_.overwrite_);
179 :
180 E : EXPECT_TRUE(test_impl_.SetUp());
181 E : }
182 :
183 E : TEST_F(OptimizeAppTest, ParseFullCommandLineWithInputAndOutputPdb) {
184 E : cmd_line_.AppendSwitchPath("input-image", input_image_path_);
185 E : cmd_line_.AppendSwitchPath("input-pdb", input_pdb_path_);
186 E : cmd_line_.AppendSwitchPath("output-image", output_image_path_);
187 E : cmd_line_.AppendSwitchPath("output-pdb", output_pdb_path_);
188 E : cmd_line_.AppendSwitch("overwrite");
189 E : cmd_line_.AppendSwitch("inlining");
190 E : cmd_line_.AppendSwitch("block-alignment");
191 E : cmd_line_.AppendSwitch("basic-block-reorder");
192 E : cmd_line_.AppendSwitch("peephole");
193 E : cmd_line_.AppendSwitch("fuzz");
194 :
195 E : EXPECT_TRUE(test_impl_.ParseCommandLine(&cmd_line_));
196 E : EXPECT_EQ(abs_input_image_path_, test_impl_.input_image_path_);
197 E : EXPECT_EQ(abs_input_pdb_path_, test_impl_.input_pdb_path_);
198 E : EXPECT_EQ(output_image_path_, test_impl_.output_image_path_);
199 E : EXPECT_EQ(output_pdb_path_, test_impl_.output_pdb_path_);
200 E : EXPECT_TRUE(test_impl_.overwrite_);
201 E : EXPECT_TRUE(test_impl_.inlining_);
202 E : EXPECT_TRUE(test_impl_.block_alignment_);
203 E : EXPECT_TRUE(test_impl_.basic_block_reorder_);
204 E : EXPECT_TRUE(test_impl_.peephole_);
205 E : EXPECT_TRUE(test_impl_.fuzz_);
206 :
207 E : EXPECT_TRUE(test_impl_.SetUp());
208 E : }
209 :
210 E : TEST_F(OptimizeAppTest, ParseAllCommandLineWithInputAndOutputPdb) {
211 E : cmd_line_.AppendSwitchPath("input-image", input_image_path_);
212 E : cmd_line_.AppendSwitchPath("input-pdb", input_pdb_path_);
213 E : cmd_line_.AppendSwitchPath("output-image", output_image_path_);
214 E : cmd_line_.AppendSwitchPath("output-pdb", output_pdb_path_);
215 E : cmd_line_.AppendSwitch("overwrite");
216 E : cmd_line_.AppendSwitch("all");
217 :
218 E : EXPECT_TRUE(test_impl_.ParseCommandLine(&cmd_line_));
219 E : EXPECT_EQ(abs_input_image_path_, test_impl_.input_image_path_);
220 E : EXPECT_EQ(abs_input_pdb_path_, test_impl_.input_pdb_path_);
221 E : EXPECT_EQ(output_image_path_, test_impl_.output_image_path_);
222 E : EXPECT_EQ(output_pdb_path_, test_impl_.output_pdb_path_);
223 E : EXPECT_TRUE(test_impl_.overwrite_);
224 E : EXPECT_TRUE(test_impl_.inlining_);
225 E : EXPECT_TRUE(test_impl_.block_alignment_);
226 E : EXPECT_TRUE(test_impl_.basic_block_reorder_);
227 E : EXPECT_TRUE(test_impl_.block_alignment_);
228 E : EXPECT_TRUE(test_impl_.peephole_);
229 E : EXPECT_FALSE(test_impl_.fuzz_);
230 :
231 E : EXPECT_TRUE(test_impl_.SetUp());
232 E : }
233 :
234 E : TEST_F(OptimizeAppTest, RelinkDecompose) {
235 E : cmd_line_.AppendSwitchPath("input-image", input_image_path_);
236 E : cmd_line_.AppendSwitchPath("output-image", output_image_path_);
237 E : cmd_line_.AppendSwitch("overwrite");
238 :
239 E : ASSERT_EQ(0, test_app_.Run());
240 E : ASSERT_NO_FATAL_FAILURE(CheckTestDll(output_image_path_));
241 E : }
242 :
243 : } // namespace optimize
|