1 : // Copyright 2012 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/trace/client/client_utils.h"
16 :
17 : #include <memory>
18 :
19 : #include "base/environment.h"
20 : #include "base/strings/utf_string_conversions.h"
21 : #include "gtest/gtest.h"
22 : #include "syzygy/core/file_util.h"
23 : #include "syzygy/core/unittest_util.h"
24 : #include "syzygy/trace/client/rpc_session.h"
25 :
26 : // http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx
27 : extern "C" IMAGE_DOS_HEADER __ImageBase;
28 :
29 : namespace trace {
30 : namespace client {
31 :
32 : namespace {
33 :
34 : class GetInstanceIdForModuleTest : public testing::Test {
35 : public:
36 E : GetInstanceIdForModuleTest() : path_(L"C:\\path\\foo.exe") { }
37 :
38 E : virtual void SetUp() override {
39 E : testing::Test::SetUp();
40 E : env_.reset(base::Environment::Create());
41 E : }
42 :
43 E : void SetEnvVar(const base::StringPiece& string) {
44 E : ASSERT_TRUE(env_->SetVar(::kSyzygyRpcInstanceIdEnvVar, string.as_string()));
45 E : }
46 :
47 E : void UnsetEnvVar() {
48 E : ASSERT_TRUE(env_->UnSetVar(::kSyzygyRpcInstanceIdEnvVar));
49 E : }
50 :
51 : base::FilePath path_;
52 : std::unique_ptr<base::Environment> env_;
53 : };
54 :
55 : class IsRpcSessionMandatoryTest : public testing::Test {
56 : public:
57 E : IsRpcSessionMandatoryTest() : path_(L"C:\\path\\foo.exe") { }
58 :
59 E : virtual void SetUp() override {
60 E : testing::Test::SetUp();
61 E : env_.reset(base::Environment::Create());
62 E : }
63 :
64 E : void SetEnvVar(const base::StringPiece& string) {
65 E : ASSERT_TRUE(env_->SetVar(::kSyzygyRpcSessionMandatoryEnvVar,
66 : string.as_string()));
67 E : }
68 :
69 E : void UnsetEnvVar() {
70 E : ASSERT_TRUE(env_->UnSetVar(::kSyzygyRpcSessionMandatoryEnvVar));
71 E : }
72 :
73 : base::FilePath path_;
74 : std::unique_ptr<base::Environment> env_;
75 : };
76 :
77 : } // namespace
78 :
79 E : TEST(GetModuleBaseAddressTest, WorksOnSelf) {
80 E : void* module_base = NULL;
81 E : EXPECT_TRUE(GetModuleBaseAddress(&GetModuleBaseAddress, &module_base));
82 E : EXPECT_EQ(&__ImageBase, module_base);
83 E : }
84 :
85 E : TEST(GetModulePath, WorksOnSelf) {
86 E : void* module_base = NULL;
87 E : ASSERT_TRUE(GetModuleBaseAddress(&GetModuleBaseAddress, &module_base));
88 :
89 E : base::FilePath module_path;
90 E : EXPECT_TRUE(GetModulePath(module_base, &module_path));
91 :
92 : base::FilePath self_path =
93 E : ::testing::GetExeRelativePath(L"rpc_client_lib_unittests.exe");
94 E : EXPECT_SAME_FILE(self_path, module_path);
95 E : }
96 :
97 E : TEST_F(GetInstanceIdForModuleTest, ReturnsEmptyForNoEnvVar) {
98 E : ASSERT_NO_FATAL_FAILURE(UnsetEnvVar());
99 E : EXPECT_EQ(std::string(), GetInstanceIdForModule(path_));
100 E : }
101 :
102 E : TEST_F(GetInstanceIdForModuleTest, ReturnsEmptyForEmptyEnvVar) {
103 E : ASSERT_NO_FATAL_FAILURE(SetEnvVar(""));
104 E : EXPECT_EQ(std::string(), GetInstanceIdForModule(path_));
105 E : }
106 :
107 E : TEST_F(GetInstanceIdForModuleTest, ReturnsEmptyForNoMatch) {
108 E : ASSERT_NO_FATAL_FAILURE(SetEnvVar("bar.exe,1;baz.exe,2"));
109 E : EXPECT_EQ(std::string(""), GetInstanceIdForModule(path_));
110 E : }
111 :
112 E : TEST_F(GetInstanceIdForModuleTest, ReturnsGenericIdWhenNoPathMatches) {
113 E : ASSERT_NO_FATAL_FAILURE(SetEnvVar("1 ;bar.exe,2"));
114 E : EXPECT_EQ(std::string("1"), GetInstanceIdForModule(path_));
115 E : }
116 :
117 E : TEST_F(GetInstanceIdForModuleTest, ReturnsBaseNameId) {
118 E : ASSERT_NO_FATAL_FAILURE(SetEnvVar("1; foo.exe , 2"));
119 E : EXPECT_EQ(std::string("2"), GetInstanceIdForModule(path_));
120 E : }
121 :
122 E : TEST_F(GetInstanceIdForModuleTest, ReturnsExactPathId) {
123 E : ASSERT_NO_FATAL_FAILURE(SetEnvVar("1;foo.exe,2;C:\\path\\foo.exe, 3 "));
124 E : EXPECT_EQ(std::string("3"), GetInstanceIdForModule(path_));
125 E : }
126 :
127 E : TEST(GetInstanceIdForThisModuleTest, WorksAsExpected) {
128 : base::FilePath self_path =
129 E : ::testing::GetExeRelativePath(L"rpc_client_lib_unittests.exe");
130 :
131 E : std::wstring env_var(self_path.value());
132 E : env_var.append(L",1");
133 :
134 E : std::unique_ptr<base::Environment> env;
135 E : env.reset(base::Environment::Create());
136 E : ASSERT_TRUE(env->SetVar(::kSyzygyRpcInstanceIdEnvVar,
137 E : base::WideToUTF8(env_var)));
138 :
139 E : EXPECT_EQ(std::string("1"), GetInstanceIdForThisModule());
140 E : }
141 :
142 E : TEST_F(IsRpcSessionMandatoryTest, ReturnsFalseForNoEnvVar) {
143 E : ASSERT_NO_FATAL_FAILURE(UnsetEnvVar());
144 E : EXPECT_FALSE(IsRpcSessionMandatory(path_));
145 E : }
146 :
147 E : TEST_F(IsRpcSessionMandatoryTest, ReturnsFalseForEmptyEnvVar) {
148 E : ASSERT_NO_FATAL_FAILURE(SetEnvVar(""));
149 E : EXPECT_FALSE(IsRpcSessionMandatory(path_));
150 E : }
151 :
152 E : TEST_F(IsRpcSessionMandatoryTest, ReturnsFalseForNoMatch) {
153 E : ASSERT_NO_FATAL_FAILURE(SetEnvVar("bar.exe,1;baz.exe,1"));
154 E : EXPECT_FALSE(IsRpcSessionMandatory(path_));
155 E : }
156 :
157 E : TEST_F(IsRpcSessionMandatoryTest, ReturnsGlobalValueWhenNoPathMatches) {
158 E : ASSERT_NO_FATAL_FAILURE(SetEnvVar("1 ; bar.exe,0"));
159 E : EXPECT_TRUE(IsRpcSessionMandatory(path_));
160 E : }
161 :
162 E : TEST_F(IsRpcSessionMandatoryTest, ReturnsBaseNameValue) {
163 E : ASSERT_NO_FATAL_FAILURE(SetEnvVar("0; foo.exe , 1"));
164 E : EXPECT_TRUE(IsRpcSessionMandatory(path_));
165 E : }
166 :
167 E : TEST_F(IsRpcSessionMandatoryTest, ReturnsExactPathValue) {
168 E : ASSERT_NO_FATAL_FAILURE(SetEnvVar("0;foo.exe,0;C:\\path\\foo.exe, 1 "));
169 E : EXPECT_TRUE(IsRpcSessionMandatory(path_));
170 E : }
171 :
172 E : TEST_F(IsRpcSessionMandatoryTest, NonNumericIgnored) {
173 E : ASSERT_NO_FATAL_FAILURE(SetEnvVar("foo.exe,baz;C:\\path\\foo.exe,bar"));
174 E : EXPECT_FALSE(IsRpcSessionMandatory(path_));
175 E : }
176 :
177 E : TEST(IsRpcSessionMandatoryThisModuleTest, WorksAsExpected) {
178 : base::FilePath self_path =
179 E : ::testing::GetExeRelativePath(L"rpc_client_lib_unittests.exe");
180 :
181 E : std::wstring env_var(self_path.value());
182 E : env_var.append(L",1");
183 :
184 E : std::unique_ptr<base::Environment> env;
185 E : env.reset(base::Environment::Create());
186 E : ASSERT_TRUE(env->SetVar(::kSyzygyRpcSessionMandatoryEnvVar,
187 E : base::WideToUTF8(env_var)));
188 :
189 E : EXPECT_TRUE(IsRpcSessionMandatoryForThisModule());
190 E : }
191 :
192 E : TEST(InitializeRpcSessionTest, FailureSessionNotMandatory) {
193 : base::FilePath self_path =
194 E : ::testing::GetExeRelativePath(L"rpc_client_lib_unittests.exe");
195 :
196 E : std::unique_ptr<base::Environment> env;
197 E : env.reset(base::Environment::Create());
198 :
199 E : std::wstring env_var(self_path.value());
200 E : env_var.append(L",0");
201 E : ASSERT_TRUE(env->SetVar(::kSyzygyRpcSessionMandatoryEnvVar,
202 E : base::WideToUTF8(env_var)));
203 :
204 E : env_var = self_path.value();
205 E : std::wstring id(L"dummy-id");
206 E : env_var.append(L",");
207 E : env_var.append(id);
208 E : ASSERT_TRUE(env->SetVar(::kSyzygyRpcInstanceIdEnvVar,
209 E : base::WideToUTF8(env_var)));
210 :
211 E : RpcSession session;
212 E : TraceFileSegment segment;
213 E : EXPECT_FALSE(InitializeRpcSession(&session, &segment));
214 :
215 E : EXPECT_EQ(id, session.instance_id());
216 E : }
217 :
218 : // TODO(chrisha): A more involved unittest where we launch a child process
219 : // whose RPC connection is mandatory, but unable to be initialized. Make
220 : // sure that it crashes as expected.
221 :
222 : } // namespace client
223 : } // namespace trace
|