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/instrument/instrumenter_with_agent.h"
16 :
17 : #include "base/command_line.h"
18 : #include "base/compiler_specific.h"
19 : #include "gmock/gmock.h"
20 : #include "gtest/gtest.h"
21 : #include "syzygy/core/unittest_util.h"
22 : #include "syzygy/pe/unittest_util.h"
23 :
24 : namespace instrument {
25 :
26 : namespace {
27 :
28 : using testing::StrictMock;
29 : using testing::Return;
30 : using testing::_;
31 :
32 : class MockRelinker : public pe::PERelinker {
33 : public:
34 E : MOCK_METHOD0(Init, bool());
35 E : MOCK_METHOD0(Relink, bool());
36 : };
37 :
38 : class TestInstrumenterWithAgent : public InstrumenterWithAgent {
39 : public:
40 : using InstrumenterWithAgent::input_dll_path_;
41 : using InstrumenterWithAgent::input_pdb_path_;
42 : using InstrumenterWithAgent::output_dll_path_;
43 : using InstrumenterWithAgent::output_pdb_path_;
44 : using InstrumenterWithAgent::allow_overwrite_;
45 : using InstrumenterWithAgent::new_decomposer_;
46 : using InstrumenterWithAgent::no_augment_pdb_;
47 : using InstrumenterWithAgent::no_parse_debug_info_;
48 : using InstrumenterWithAgent::no_strip_strings_;
49 :
50 E : MOCK_METHOD0(InstrumentImpl, bool());
51 :
52 E : pe::PERelinker* GetRelinker() OVERRIDE {
53 E : return &mock_relinker_;
54 E : }
55 :
56 : StrictMock<MockRelinker> mock_relinker_;
57 : };
58 :
59 : class InstrumenterWithAgentTest : public testing::PELibUnitTest {
60 : public:
61 : typedef testing::PELibUnitTest Super;
62 :
63 E : InstrumenterWithAgentTest()
64 : : cmd_line_(base::FilePath(L"instrument.exe")) {
65 E : }
66 :
67 E : virtual void SetUp() OVERRIDE {
68 E : testing::Test::SetUp();
69 :
70 : // Several of the tests generate progress and (deliberate) error messages
71 : // that would otherwise clutter the unittest output.
72 E : logging::SetMinLogLevel(logging::LOG_FATAL);
73 :
74 : // Setup the IO streams.
75 E : CreateTemporaryDir(&temp_dir_);
76 E : stdin_path_ = temp_dir_.Append(L"NUL");
77 E : stdout_path_ = temp_dir_.Append(L"stdout.txt");
78 E : stderr_path_ = temp_dir_.Append(L"stderr.txt");
79 E : InitStreams(stdin_path_, stdout_path_, stderr_path_);
80 :
81 : // Initialize the (potential) input and output path values.
82 E : abs_input_dll_path_ = testing::GetExeRelativePath(testing::kTestDllName);
83 E : input_dll_path_ = testing::GetRelativePath(abs_input_dll_path_);
84 E : abs_input_pdb_path_ = testing::GetExeRelativePath(testing::kTestDllPdbName);
85 E : input_pdb_path_ = testing::GetRelativePath(abs_input_pdb_path_);
86 E : output_dll_path_ = temp_dir_.Append(input_dll_path_.BaseName());
87 E : output_pdb_path_ = temp_dir_.Append(input_pdb_path_.BaseName());
88 E : }
89 :
90 E : void SetUpValidCommandLine() {
91 E : cmd_line_.AppendSwitchPath("input-dll", input_dll_path_);
92 E : cmd_line_.AppendSwitchPath("output-dll", output_dll_path_);
93 E : }
94 :
95 : protected:
96 : base::FilePath temp_dir_;
97 :
98 : // @name The redirected streams paths.
99 : // @{
100 : base::FilePath stdin_path_;
101 : base::FilePath stdout_path_;
102 : base::FilePath stderr_path_;
103 : // @}
104 :
105 : // @name Command-line and parameters.
106 : // @{
107 : CommandLine cmd_line_;
108 : base::FilePath input_dll_path_;
109 : base::FilePath input_pdb_path_;
110 : base::FilePath output_dll_path_;
111 : base::FilePath output_pdb_path_;
112 : base::FilePath test_dll_filter_path_;
113 : base::FilePath dummy_filter_path_;
114 : // @}
115 :
116 : // @name Expected final values of input parameters.
117 : // @{
118 : base::FilePath abs_input_dll_path_;
119 : base::FilePath abs_input_pdb_path_;
120 : // @}
121 :
122 : // The fake instrumenter we delegate to.
123 : TestInstrumenterWithAgent instrumenter_;
124 : };
125 :
126 : } // namespace
127 :
128 E : TEST_F(InstrumenterWithAgentTest, EmptyCommandLineFails) {
129 E : ASSERT_FALSE(instrumenter_.ParseCommandLine(&cmd_line_));
130 E : }
131 :
132 E : TEST_F(InstrumenterWithAgentTest, ParseWithNoInputImageFails) {
133 E : cmd_line_.AppendSwitchPath("output-image", output_dll_path_);
134 :
135 E : ASSERT_FALSE(instrumenter_.ParseCommandLine(&cmd_line_));
136 E : }
137 :
138 E : TEST_F(InstrumenterWithAgentTest, ParseWithNoOutputImageFails) {
139 E : cmd_line_.AppendSwitchPath("input-image", input_dll_path_);
140 :
141 E : ASSERT_FALSE(instrumenter_.ParseCommandLine(&cmd_line_));
142 E : }
143 :
144 E : TEST_F(InstrumenterWithAgentTest, DeprecatedParseNoModeSpecifyDlls) {
145 E : cmd_line_.AppendSwitchPath("input-dll", input_dll_path_);
146 E : cmd_line_.AppendSwitchPath("output-dll", output_dll_path_);
147 :
148 E : EXPECT_TRUE(instrumenter_.ParseCommandLine(&cmd_line_));
149 E : EXPECT_EQ(abs_input_dll_path_, instrumenter_.input_dll_path_);
150 E : EXPECT_EQ(output_dll_path_, instrumenter_.output_dll_path_);
151 :
152 E : EXPECT_FALSE(instrumenter_.allow_overwrite_);
153 E : EXPECT_FALSE(instrumenter_.new_decomposer_);
154 E : EXPECT_FALSE(instrumenter_.no_augment_pdb_);
155 E : EXPECT_FALSE(instrumenter_.no_parse_debug_info_);
156 E : EXPECT_FALSE(instrumenter_.no_strip_strings_);
157 E : }
158 :
159 E : TEST_F(InstrumenterWithAgentTest, agent_dll) {
160 E : EXPECT_EQ(0U, instrumenter_.agent_dll().size());
161 E : }
162 :
163 E : TEST_F(InstrumenterWithAgentTest, Instrument) {
164 E : SetUpValidCommandLine();
165 :
166 E : EXPECT_TRUE(instrumenter_.ParseCommandLine(&cmd_line_));
167 E : EXPECT_CALL(instrumenter_.mock_relinker_, Init()).WillOnce(Return(true));
168 E : EXPECT_CALL(instrumenter_.mock_relinker_, Relink()).WillOnce(Return(true));
169 E : EXPECT_CALL(instrumenter_, InstrumentImpl()).WillOnce(Return(true));
170 :
171 E : EXPECT_TRUE(instrumenter_.Instrument());
172 E : }
173 :
174 E : TEST_F(InstrumenterWithAgentTest, InstrumentFailsInit) {
175 E : SetUpValidCommandLine();
176 :
177 E : EXPECT_CALL(instrumenter_.mock_relinker_, Init()).WillOnce(Return(false));
178 :
179 E : EXPECT_FALSE(instrumenter_.Instrument());
180 E : }
181 :
182 E : TEST_F(InstrumenterWithAgentTest, InstrumentFailsRelink) {
183 E : SetUpValidCommandLine();
184 :
185 E : EXPECT_CALL(instrumenter_.mock_relinker_, Init()).WillOnce(Return(true));
186 E : EXPECT_CALL(instrumenter_.mock_relinker_, Relink()).WillOnce(Return(false));
187 E : EXPECT_CALL(instrumenter_, InstrumentImpl()).WillOnce(Return(true));
188 :
189 E : EXPECT_FALSE(instrumenter_.Instrument());
190 E : }
191 :
192 : } // namespace instrument
|