| OLD | NEW |
| (Empty) |
| 1 // Copyright 2007-2009 Google Inc. | |
| 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 | |
| 16 // | |
| 17 // Process unit tests. | |
| 18 | |
| 19 #include <vector> | |
| 20 | |
| 21 #include "omaha/base/app_util.h" | |
| 22 #include "omaha/base/path.h" | |
| 23 #include "omaha/base/process.h" | |
| 24 #include "omaha/base/user_info.h" | |
| 25 #include "omaha/testing/unit_test.h" | |
| 26 | |
| 27 namespace omaha { | |
| 28 | |
| 29 const int kWaitUntilDeadMs = 10000; | |
| 30 | |
| 31 // Process class that terminates the associated process when deleted. | |
| 32 class ScopedProcess : public Process { | |
| 33 public: | |
| 34 explicit ScopedProcess(const TCHAR* name) : Process(name, NULL) {} | |
| 35 virtual ~ScopedProcess() { | |
| 36 Terminate(0); | |
| 37 EXPECT_TRUE(WaitUntilDead(kWaitUntilDeadMs)); | |
| 38 } | |
| 39 }; | |
| 40 | |
| 41 TEST(ProcessTest, StartOneProcess) { | |
| 42 const TCHAR kExecutableName[] = _T("cmd.exe"); | |
| 43 const TCHAR kExecutableArguments[] = _T("/c exit 702"); | |
| 44 const int kExpectedExitCode = 702; | |
| 45 | |
| 46 CString path = ConcatenatePath(app_util::GetSystemDir(), kExecutableName); | |
| 47 ScopedProcess process(path); | |
| 48 | |
| 49 ASSERT_HRESULT_SUCCEEDED(process.Start(kExecutableArguments, NULL)); | |
| 50 EXPECT_TRUE(process.WaitUntilDead(kWaitUntilDeadMs)); | |
| 51 | |
| 52 // Check the exit code to get some assurance that the process actually ran. | |
| 53 uint32 exit_code = 0; | |
| 54 EXPECT_TRUE(process.GetExitCode(&exit_code)); | |
| 55 EXPECT_EQ(kExpectedExitCode, exit_code); | |
| 56 } | |
| 57 | |
| 58 // Dummy process to spin off and then find. The numeric argument will make | |
| 59 // netstat run until it's killed by the ScopedProcess destructor. | |
| 60 const TCHAR kTestExecutable[] = _T("netstat.exe"); | |
| 61 const TCHAR kTestArguments[] = _T("10"); | |
| 62 const TCHAR kTestExcludeArguments[] = _T("-o 20"); | |
| 63 const TCHAR kTestExcludeString[] = _T("20"); | |
| 64 const TCHAR kTestIncludeArguments[] = _T("-o 30"); | |
| 65 const TCHAR kTestIncludeString[] = _T("30"); | |
| 66 const int kWaitForProcessStartMs = 500; | |
| 67 const int kMaxWaitIterations = 10; | |
| 68 | |
| 69 TEST(ProcessTest, FindOneProcess) { | |
| 70 CString path = ConcatenatePath(app_util::GetSystemDir(), kTestExecutable); | |
| 71 ScopedProcess process(path); | |
| 72 ASSERT_HRESULT_SUCCEEDED(process.Start(kTestArguments, NULL)); | |
| 73 for (int i = 0; i < kMaxWaitIterations; ++i) { | |
| 74 ::Sleep(kWaitForProcessStartMs); | |
| 75 if (process.Running()) | |
| 76 break; | |
| 77 } | |
| 78 EXPECT_TRUE(process.Running()); | |
| 79 | |
| 80 // Try to find the test process. | |
| 81 uint32 exclude_mask = INCLUDE_ONLY_PROCESS_OWNED_BY_USER; | |
| 82 CString user_sid; | |
| 83 std::vector<CString> command_lines; | |
| 84 std::vector<uint32> process_ids; | |
| 85 | |
| 86 ASSERT_SUCCEEDED(omaha::user_info::GetProcessUser(NULL, NULL, &user_sid)); | |
| 87 | |
| 88 // This test intermittently fails to find the process when run on Pulse. | |
| 89 // This code attempts to ensure that the process is further along in the | |
| 90 // initialization process by waiting until Process::GetCommandLine succeeds. | |
| 91 // This test case does not result in FindProcesses using GetCommandLine, but | |
| 92 // waiting until this point may be enough to address the intermitent failures. | |
| 93 HRESULT hr = E_FAIL; | |
| 94 CString process_cmd; | |
| 95 for (int tries = 0; tries < 100 && FAILED(hr); ++tries) { | |
| 96 ::Sleep(50); | |
| 97 hr = Process::GetCommandLine(process.GetId(), &process_cmd); | |
| 98 } | |
| 99 EXPECT_SUCCEEDED(hr); | |
| 100 | |
| 101 ASSERT_SUCCEEDED(Process::FindProcesses(exclude_mask, | |
| 102 kTestExecutable, | |
| 103 true, | |
| 104 user_sid, | |
| 105 command_lines, | |
| 106 &process_ids)); | |
| 107 ASSERT_EQ(1, process_ids.size()); // Exit before accessing invalid element. | |
| 108 EXPECT_EQ(process.GetId(), process_ids[0]); | |
| 109 } | |
| 110 | |
| 111 TEST(ProcessTest, ExcludeProcess) { | |
| 112 // Make sure the test process is not already running. | |
| 113 uint32 exclude_mask = INCLUDE_ONLY_PROCESS_OWNED_BY_USER; | |
| 114 CString user_sid; | |
| 115 std::vector<CString> command_lines; | |
| 116 std::vector<uint32> process_ids; | |
| 117 | |
| 118 ASSERT_SUCCEEDED(omaha::user_info::GetProcessUser(NULL, NULL, &user_sid)); | |
| 119 ASSERT_SUCCEEDED(Process::FindProcesses(exclude_mask, | |
| 120 kTestExecutable, | |
| 121 true, | |
| 122 user_sid, | |
| 123 command_lines, | |
| 124 &process_ids)); | |
| 125 ASSERT_EQ(0, process_ids.size()); | |
| 126 | |
| 127 // Ok, test process not running. Let's continue running the test. | |
| 128 CString path = ConcatenatePath(app_util::GetSystemDir(), kTestExecutable); | |
| 129 ScopedProcess process(path); | |
| 130 ScopedProcess exclude_process(path); | |
| 131 | |
| 132 ASSERT_HRESULT_SUCCEEDED(process.Start(kTestArguments, NULL)); | |
| 133 ASSERT_HRESULT_SUCCEEDED(exclude_process.Start(kTestExcludeArguments, NULL)); | |
| 134 for (int i = 0; i < kMaxWaitIterations; ++i) { | |
| 135 ::Sleep(kWaitForProcessStartMs); | |
| 136 if (process.Running() && exclude_process.Running()) | |
| 137 break; | |
| 138 } | |
| 139 EXPECT_TRUE(process.Running()); | |
| 140 EXPECT_TRUE(exclude_process.Running()); | |
| 141 | |
| 142 // Try to find just the first process, excluding the other. | |
| 143 exclude_mask = INCLUDE_ONLY_PROCESS_OWNED_BY_USER | | |
| 144 EXCLUDE_CURRENT_PROCESS | | |
| 145 EXCLUDE_PROCESS_COMMAND_LINE_CONTAINING_STRING; | |
| 146 | |
| 147 command_lines.push_back(kTestExcludeString); | |
| 148 ASSERT_SUCCEEDED(Process::FindProcesses(exclude_mask, | |
| 149 kTestExecutable, | |
| 150 true, | |
| 151 user_sid, | |
| 152 command_lines, | |
| 153 &process_ids)); | |
| 154 ASSERT_EQ(1, process_ids.size()); | |
| 155 EXPECT_EQ(process.GetId(), process_ids[0]); | |
| 156 } | |
| 157 | |
| 158 TEST(ProcessTest, IncludeProcess) { | |
| 159 CString path = ConcatenatePath(app_util::GetSystemDir(), kTestExecutable); | |
| 160 ScopedProcess process(path); | |
| 161 ScopedProcess include_process(path); | |
| 162 | |
| 163 ASSERT_HRESULT_SUCCEEDED(process.Start(kTestArguments, NULL)); | |
| 164 ASSERT_HRESULT_SUCCEEDED(include_process.Start(kTestIncludeArguments, NULL)); | |
| 165 for (int i = 0; i < kMaxWaitIterations; ++i) { | |
| 166 ::Sleep(kWaitForProcessStartMs); | |
| 167 if (process.Running() && include_process.Running()) | |
| 168 break; | |
| 169 } | |
| 170 EXPECT_TRUE(process.Running()); | |
| 171 EXPECT_TRUE(include_process.Running()); | |
| 172 | |
| 173 // Try to find just the first process, excluding the other. | |
| 174 uint32 exclude_mask = INCLUDE_ONLY_PROCESS_OWNED_BY_USER | | |
| 175 EXCLUDE_CURRENT_PROCESS | | |
| 176 INCLUDE_PROCESS_COMMAND_LINE_CONTAINING_STRING; | |
| 177 CString user_sid; | |
| 178 std::vector<CString> command_lines; | |
| 179 std::vector<uint32> process_ids; | |
| 180 | |
| 181 command_lines.push_back(kTestIncludeString); | |
| 182 ASSERT_SUCCEEDED(omaha::user_info::GetProcessUser(NULL, NULL, &user_sid)); | |
| 183 ASSERT_SUCCEEDED(Process::FindProcesses(exclude_mask, | |
| 184 kTestExecutable, | |
| 185 true, | |
| 186 user_sid, | |
| 187 command_lines, | |
| 188 &process_ids)); | |
| 189 ASSERT_EQ(1, process_ids.size()); | |
| 190 EXPECT_EQ(include_process.GetId(), process_ids[0]); | |
| 191 } | |
| 192 | |
| 193 TEST(ProcessTest, GetImagePath) { | |
| 194 // Get this module's path. | |
| 195 HMODULE handle = ::GetModuleHandle(NULL); | |
| 196 ASSERT_TRUE(handle != NULL); | |
| 197 | |
| 198 TCHAR file_name[MAX_PATH] = {0}; | |
| 199 ASSERT_NE(::GetModuleFileName(handle, file_name, MAX_PATH), 0); | |
| 200 ASSERT_NE(0, wcslen(file_name)); | |
| 201 | |
| 202 CString exe = GetFileFromPath(file_name); | |
| 203 ASSERT_FALSE(exe.IsEmpty()); | |
| 204 | |
| 205 CString user_sid; | |
| 206 ASSERT_SUCCEEDED(omaha::user_info::GetProcessUser(NULL, NULL, &user_sid)); | |
| 207 | |
| 208 // Test the method. | |
| 209 CString path; | |
| 210 ASSERT_SUCCEEDED(Process::GetImagePath(exe, user_sid, &path)); | |
| 211 | |
| 212 // Compare the result. | |
| 213 ASSERT_STREQ(file_name, path); | |
| 214 } | |
| 215 | |
| 216 TEST(ProcessTest, GetParentProcessId_CurrentProcess) { | |
| 217 Process process(::GetCurrentProcessId()); | |
| 218 uint32 parent_pid = 0; | |
| 219 EXPECT_SUCCEEDED(process.GetParentProcessId(&parent_pid)); | |
| 220 EXPECT_NE(0, parent_pid); | |
| 221 } | |
| 222 | |
| 223 TEST(ProcessTest, GetParentProcessId_ChildProcess) { | |
| 224 CString path = ConcatenatePath(app_util::GetSystemDir(), kTestExecutable); | |
| 225 ScopedProcess process(path); | |
| 226 | |
| 227 EXPECT_HRESULT_SUCCEEDED(process.Start(kTestArguments, NULL)); | |
| 228 for (int i = 0; i < kMaxWaitIterations; ++i) { | |
| 229 ::Sleep(kWaitForProcessStartMs); | |
| 230 if (process.Running()) { | |
| 231 break; | |
| 232 } | |
| 233 } | |
| 234 | |
| 235 EXPECT_TRUE(process.Running()); | |
| 236 | |
| 237 uint32 parent_pid = 0; | |
| 238 EXPECT_SUCCEEDED(process.GetParentProcessId(&parent_pid)); | |
| 239 EXPECT_EQ(::GetCurrentProcessId(), parent_pid); | |
| 240 } | |
| 241 | |
| 242 } // namespace omaha | |
| 243 | |
| OLD | NEW |