Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 namespace UnitTests | |
| 6 { | |
| 7 using System; | |
| 8 using System.Diagnostics; | |
| 9 using System.IO; | |
| 10 using System.Reflection; | |
| 11 using System.Threading; | |
| 12 | |
| 13 using EnvDTE80; | |
| 14 using Microsoft.VisualStudio.TestTools.UnitTesting; | |
| 15 | |
| 16 using NativeClientVSAddIn; | |
| 17 | |
| 18 /// <summary> | |
| 19 /// This is a test class for PluginDebuggerHelperTest and is intended | |
| 20 /// to contain all PluginDebuggerHelperTest Unit Tests. | |
| 21 /// </summary> | |
| 22 [TestClass] | |
| 23 public class PluginDebuggerHelperTest | |
| 24 { | |
| 25 /// <summary> | |
| 26 /// The dummy loop solution is a valid nacl/pepper plug-in VS solution. | |
| 27 /// It is copied into the testing deployment directory and opened in some te sts. | |
| 28 /// Because unit-tests run in any order, the solution should not be written to | |
| 29 /// in any tests. | |
| 30 /// </summary> | |
| 31 private const string DummyLoopSolution = @"\DummyLoop\DummyLoop.sln"; | |
| 32 | |
| 33 /// <summary> | |
| 34 /// The main visual studio object. | |
| 35 /// </summary> | |
| 36 private DTE2 dte_ = null; | |
| 37 | |
| 38 /// <summary> | |
| 39 /// Gets or sets the test context which provides information about, | |
| 40 /// and functionality for the current test run. | |
| 41 /// </summary> | |
| 42 public TestContext TestContext { get; set; } | |
| 43 | |
| 44 /// <summary> | |
| 45 /// This is run before each test to create test resources. | |
| 46 /// </summary> | |
| 47 [TestInitialize] | |
| 48 public void TestSetup() | |
| 49 { | |
| 50 dte_ = TestUtilities.StartVisualStudioInstance(); | |
| 51 } | |
| 52 | |
| 53 /// <summary> | |
| 54 /// This is run after each test to clean up things created in TestSetup(). | |
| 55 /// </summary> | |
| 56 [TestCleanup] | |
| 57 public void TestCleanup() | |
| 58 { | |
| 59 TestUtilities.CleanUpVisualStudioInstance(dte_); | |
| 60 } | |
| 61 | |
| 62 /// <summary> | |
| 63 /// A test for PluginDebuggerHelper Constructor. | |
| 64 /// </summary> | |
| 65 [TestMethod] | |
| 66 public void PluginDebuggerHelperConstructorTest() | |
| 67 { | |
| 68 // Check that a null dte fails. | |
| 69 try | |
| 70 { | |
| 71 PluginDebuggerHelper nullDte = new PluginDebuggerHelper(null); | |
| 72 Assert.Fail("Using null DTE instance did not throw exception"); | |
| 73 } | |
| 74 catch (ArgumentNullException) | |
| 75 { | |
| 76 // This is expected for a correct implementation. | |
| 77 } | |
| 78 catch | |
| 79 { | |
| 80 Assert.Fail("Using null DTE instance threw something other than Argument NullException"); | |
| 81 } | |
| 82 | |
| 83 PluginDebuggerHelper_Accessor target = new PluginDebuggerHelper_Accessor(d te_); | |
| 84 Assert.AreEqual(dte_, target.dte_); | |
| 85 Assert.IsNull(target.webServerOutputPane_); | |
| 86 Assert.IsFalse(target.isProperlyInitialized_); | |
| 87 } | |
| 88 | |
| 89 /// <summary> | |
| 90 /// This unit test verifies that the gdb init file is written correctly, | |
| 91 /// and old-existing GDB processes are cleaned up. | |
| 92 /// Verification of actual attachment is the responsibility of integration | |
| 93 /// tests and NaCl-GDB itself. | |
| 94 /// </summary> | |
| 95 [TestMethod] | |
| 96 [DeploymentItem("NativeClientVSAddIn.dll")] | |
| 97 public void AttachNaClGDBTest() | |
| 98 { | |
| 99 PluginDebuggerHelper_Accessor target = new PluginDebuggerHelper_Accessor(d te_); | |
| 100 string existingGDB = "AttachNaClGDBTest_existingGDB"; | |
| 101 try | |
| 102 { | |
| 103 target.pluginProjectDirectory_ = TestContext.DeploymentDirectory; | |
| 104 target.pluginAssembly_ = "fakeAssemblyString"; | |
| 105 target.irtPath_ = "fakeIrtPath"; | |
| 106 target.gdbPath_ = "python.exe"; | |
| 107 target.gdbProcess_ = TestUtilities.StartProcessForKilling(existingGDB, 2 0); | |
| 108 string existingInitFileName = Path.GetTempFileName(); | |
| 109 target.gdbInitFileName_ = existingInitFileName; | |
| 110 target.isProperlyInitialized_ = true; | |
| 111 | |
| 112 // Visual studio won't allow adding a breakpoint unless it is associated with | |
| 113 // an existing file and valid line number, so use DummyLoopSolution. | |
| 114 dte_.Solution.Open(TestContext.DeploymentDirectory + DummyLoopSolution); | |
| 115 string fileName = "main.cpp"; | |
| 116 string functionName = "DummyInstance::HandleMessage"; | |
| 117 int lineNumber = 35; | |
| 118 dte_.Debugger.Breakpoints.Add(Function: functionName); | |
| 119 dte_.Debugger.Breakpoints.Add(Line: lineNumber, File: fileName); | |
| 120 | |
| 121 target.AttachNaClGDB(null, new PluginDebuggerHelper.PluginFoundEventArgs (0)); | |
| 122 | |
| 123 Assert.IsTrue(File.Exists(target.gdbInitFileName_), "Init file not writt en"); | |
| 124 | |
| 125 string[] gdbCommands = File.ReadAllLines(target.gdbInitFileName_); | |
| 126 bool functionBP = false; | |
| 127 bool lineBP = false; | |
| 128 | |
| 129 // Validate that the commands contain what we specified. | |
| 130 // The syntax itself is not validated since this add-in is not responsib le for | |
| 131 // the syntax and it could change. | |
| 132 foreach (string command in gdbCommands) | |
| 133 { | |
| 134 if (command.Contains(fileName) && command.Contains(lineNumber.ToString ())) | |
| 135 { | |
| 136 lineBP = true; | |
| 137 } | |
| 138 | |
| 139 if (command.Contains(functionName)) | |
| 140 { | |
| 141 functionBP = true; | |
| 142 } | |
| 143 } | |
| 144 | |
| 145 Assert.IsFalse( | |
| 146 TestUtilities.DoesProcessExist("python.exe", existingGDB), | |
| 147 "Failed to kill existing GDB process"); | |
| 148 Assert.IsFalse( | |
| 149 File.Exists(existingInitFileName), | |
| 150 "Failed to delete existing temp gdb init file"); | |
| 151 Assert.IsTrue(lineBP, "Line breakpoint not properly set"); | |
| 152 Assert.IsTrue(functionBP, "Function breakpoint not properly set"); | |
| 153 } | |
| 154 finally | |
| 155 { | |
| 156 if (dte_.Debugger.Breakpoints != null) | |
| 157 { | |
| 158 // Remove all breakpoints. | |
| 159 foreach (EnvDTE.Breakpoint bp in dte_.Debugger.Breakpoints) | |
| 160 { | |
| 161 bp.Delete(); | |
| 162 } | |
| 163 } | |
| 164 | |
| 165 if (!string.IsNullOrEmpty(target.gdbInitFileName_) && File.Exists(target .gdbInitFileName_)) | |
|
binji
2012/07/20 00:24:53
This seems like duplication of the responsibilitie
tysand
2012/08/07 23:01:54
Yes, but if the test fails then we're leaking file
| |
| 166 { | |
| 167 File.Delete(target.gdbInitFileName_); | |
| 168 } | |
| 169 | |
| 170 if (target.gdbProcess_ != null && !target.gdbProcess_.HasExited) | |
|
binji
2012/07/20 00:24:53
same here
tysand
2012/08/07 23:01:54
Done.
| |
| 171 { | |
| 172 target.gdbProcess_.Kill(); | |
| 173 target.gdbProcess_.Dispose(); | |
| 174 } | |
| 175 } | |
| 176 } | |
| 177 | |
| 178 /// <summary> | |
| 179 /// A test for FindAndAttachToPlugin. | |
| 180 /// </summary> | |
| 181 [TestMethod] | |
| 182 [DeploymentItem("NativeClientVSAddIn.dll")] | |
| 183 public void FindAndAttachToPluginTest() | |
| 184 { | |
| 185 PluginDebuggerHelper_Accessor target = new PluginDebuggerHelper_Accessor(d te_); | |
| 186 target.isProperlyInitialized_ = true; | |
| 187 | |
| 188 MockProcessSearcher processResults = new MockProcessSearcher(); | |
| 189 uint currentProcId = (uint)System.Diagnostics.Process.GetCurrentProcess(). Id; | |
| 190 string naclCommandLine = Strings.NaClProcessTypeFlag + " " + Strings.NaClD ebugFlag; | |
| 191 target.pluginAssembly_ = "testAssemblyPath"; | |
| 192 string pluginLoadFlag = string.Format( | |
| 193 Strings.PepperProcessPluginFlagFormat, target.pluginAssembly_); | |
| 194 string pepperCommandLine = string.Concat( | |
| 195 pluginLoadFlag, " ", Strings.PepperProcessTypeFlag); | |
| 196 string pluginFlagCommandLine = | |
| 197 string.Format(Strings.PepperProcessPluginFlagFormat, target.pluginAsse mbly_); | |
| 198 | |
| 199 // Fake the list of processes on the system. | |
| 200 processResults.ProcessList.Add( | |
| 201 new ProcessInfo(currentProcId, currentProcId, string.Empty, string.Emp ty, "devenv.exe")); | |
| 202 processResults.ProcessList.Add( | |
| 203 new ProcessInfo(1, currentProcId, string.Empty, string.Empty, "MyParen tProcess")); | |
| 204 processResults.ProcessList.Add( | |
| 205 new ProcessInfo(10, 1, string.Empty, pepperCommandLine, Strings.Pepper ProcessName)); | |
| 206 processResults.ProcessList.Add( | |
| 207 new ProcessInfo(11, 1, string.Empty, naclCommandLine, Strings.NaClProc essName)); | |
| 208 processResults.ProcessList.Add( | |
| 209 new ProcessInfo(12, 1, string.Empty, pluginFlagCommandLine, Strings.Pe pperProcessName)); | |
| 210 processResults.ProcessList.Add( | |
| 211 new ProcessInfo(13, 1, string.Empty, Strings.NaClDebugFlag, Strings.Na ClProcessName)); | |
| 212 | |
| 213 // These two don't have this process as their parent, so they should not b e attached to. | |
| 214 processResults.ProcessList.Add( | |
| 215 new ProcessInfo(14, 14, string.Empty, pepperCommandLine, Strings.Peppe rProcessName)); | |
| 216 processResults.ProcessList.Add( | |
| 217 new ProcessInfo(15, 15, string.Empty, naclCommandLine, Strings.NaClPro cessName)); | |
| 218 | |
| 219 // Set the private value to the mock object (can't use accessor since no v alid cast). | |
| 220 typeof(PluginDebuggerHelper).GetField( | |
| 221 "processSearcher_", | |
| 222 BindingFlags.NonPublic | BindingFlags.Instance).SetValue(target.Target , processResults); | |
| 223 | |
| 224 // Test that the correct processes are attached to. | |
| 225 bool goodNaCl = false; | |
| 226 bool goodPepper = false; | |
| 227 var handler = new EventHandler<NativeClientVSAddIn.PluginDebuggerHelper.Pl uginFoundEventArgs>( | |
| 228 delegate(object unused, NativeClientVSAddIn.PluginDebuggerHelper.PluginF oundEventArgs args) | |
| 229 { | |
| 230 switch (args.ProcessID) | |
| 231 { | |
| 232 case 10: | |
| 233 if (goodPepper) | |
| 234 { | |
| 235 Assert.Fail("Should not attach twice to same pepper process"); | |
| 236 } | |
| 237 | |
| 238 if (target.projectPlatformType_ == | |
| 239 PluginDebuggerHelper_Accessor.ProjectPlatformType.NaCl) | |
| 240 { | |
| 241 Assert.Fail("Attached to pepper process when NaCl was the target "); | |
| 242 } | |
| 243 | |
| 244 goodPepper = true; | |
| 245 break; | |
| 246 case 11: | |
| 247 if (goodNaCl) | |
| 248 { | |
| 249 Assert.Fail("Should not attach twice to same nacl process"); | |
| 250 } | |
| 251 | |
| 252 if (target.projectPlatformType_ == | |
| 253 PluginDebuggerHelper_Accessor.ProjectPlatformType.Pepper) | |
| 254 { | |
| 255 Assert.Fail("Attached to nacl process when pepper was the target "); | |
| 256 } | |
| 257 | |
| 258 goodNaCl = true; | |
| 259 break; | |
| 260 case 12: | |
| 261 Assert.Fail("Should not attach to pepper process with bad args"); | |
| 262 break; | |
| 263 case 13: | |
| 264 Assert.Fail("Should not attach to nacl process with bad args"); | |
| 265 break; | |
| 266 case 14: | |
| 267 Assert.Fail("Should not attach to pepper process that is not " | |
| 268 + "descendant of Visual Studio"); | |
| 269 break; | |
| 270 case 15: | |
| 271 Assert.Fail("Should not attach to nacl process that is not " | |
| 272 + "descendant of Visual Studio"); | |
| 273 break; | |
| 274 default: | |
| 275 Assert.Fail("Should not attach to non-pepper/non-nacl process"); | |
| 276 break; | |
| 277 } | |
| 278 }); | |
| 279 | |
| 280 target.add_PluginFoundEvent(handler); | |
| 281 target.projectPlatformType_ = PluginDebuggerHelper_Accessor.ProjectPlatfor mType.Pepper; | |
| 282 target.FindAndAttachToPlugin(null, null); | |
| 283 target.projectPlatformType_ = PluginDebuggerHelper_Accessor.ProjectPlatfor mType.NaCl; | |
| 284 target.FindAndAttachToPlugin(null, null); | |
| 285 target.remove_PluginFoundEvent(handler); | |
| 286 Assert.IsTrue(goodPepper, "Failed to attach to pepper process"); | |
| 287 Assert.IsTrue(goodNaCl, "Failed to attach to NaCl process"); | |
| 288 } | |
| 289 | |
| 290 /// <summary> | |
| 291 /// A test for LoadProjectSettings. | |
| 292 /// </summary> | |
| 293 [TestMethod] | |
| 294 public void LoadProjectSettingsTest() | |
| 295 { | |
| 296 string expectedSDKRootDir = | |
| 297 Environment.GetEnvironmentVariable(Strings.SDKPathEnvironmentVariable) ; | |
| 298 Assert.IsNotNull(expectedSDKRootDir, "SDK Path environment variable not se t!"); | |
| 299 | |
| 300 PluginDebuggerHelper_Accessor target = new PluginDebuggerHelper_Accessor(d te_); | |
| 301 target.isProperlyInitialized_ = false; | |
| 302 try | |
| 303 { | |
| 304 target.LoadProjectSettings(); | |
| 305 Assert.Fail("Initializing with no loaded solution shouldn't succeed"); | |
| 306 } | |
| 307 catch (ArgumentOutOfRangeException) | |
| 308 { | |
| 309 // This is expected for a correct implementation. | |
| 310 } | |
| 311 | |
| 312 dte_.Solution.Open(TestContext.DeploymentDirectory + DummyLoopSolution); | |
| 313 | |
| 314 // Setting the start-up project to a non-cpp project should make loading f ail. | |
| 315 string badProjectUniqueName = @"NotNaCl\NotNaCl.csproj"; | |
| 316 object[] badStartupProj = { badProjectUniqueName }; | |
| 317 dte_.Solution.SolutionBuild.StartupProjects = badStartupProj; | |
| 318 Assert.IsFalse(target.LoadProjectSettings()); | |
| 319 Assert.IsFalse(target.isProperlyInitialized_); | |
| 320 | |
| 321 // Setting the start-up project to correct C++ project, but also setting t he platform | |
| 322 // to non-nacl/pepper should make loading fail. | |
| 323 string projectUniqueName = @"DummyLoop\DummyLoop.vcxproj"; | |
| 324 object[] startupProj = { projectUniqueName }; | |
| 325 dte_.Solution.SolutionBuild.StartupProjects = startupProj; | |
| 326 TestUtilities.SetSolutionConfiguration(dte_, projectUniqueName, "Debug", " Win32"); | |
| 327 Assert.IsFalse(target.LoadProjectSettings()); | |
| 328 Assert.IsFalse(target.isProperlyInitialized_); | |
| 329 | |
| 330 // Setting the platform to NaCl should make loading succeed. | |
| 331 TestUtilities.SetSolutionConfiguration( | |
| 332 dte_, projectUniqueName, "Debug", Strings.NaClPlatformName); | |
| 333 Assert.IsTrue(target.LoadProjectSettings()); | |
| 334 Assert.IsTrue(target.isProperlyInitialized_); | |
| 335 Assert.AreEqual( | |
| 336 target.projectPlatformType_, | |
| 337 PluginDebuggerHelper_Accessor.ProjectPlatformType.NaCl); | |
| 338 Assert.AreEqual( | |
| 339 target.pluginProjectDirectory_, | |
| 340 TestContext.DeploymentDirectory + @"\DummyLoop\DummyLoop\"); | |
| 341 Assert.AreEqual( | |
| 342 target.pluginAssembly_, | |
| 343 TestContext.DeploymentDirectory + @"\DummyLoop\DummyLoop\NaCl\Debug\Du mmyLoop.nexe"); | |
| 344 Assert.AreEqual( | |
| 345 target.pluginOutputDirectory_, | |
| 346 TestContext.DeploymentDirectory + @"\DummyLoop\DummyLoop\NaCl\Debug\") ; | |
| 347 Assert.AreEqual(target.sdkRootDirectory_, expectedSDKRootDir); | |
| 348 Assert.AreEqual(target.webServerExecutable_, "python.exe"); | |
| 349 ////Assert.AreEqual(target._webServerArguments, ""); | |
|
binji
2012/07/20 00:24:53
Remove commented code.
tysand
2012/08/07 23:01:54
Done.
| |
| 350 ////Assert.AreEqual(target._gdbPath, ""); | |
| 351 | |
| 352 // Setting platform to Pepper should make succeed. | |
| 353 TestUtilities.SetSolutionConfiguration( | |
| 354 dte_, projectUniqueName, "Debug", Strings.PepperPlatformName); | |
| 355 Assert.IsTrue(target.LoadProjectSettings()); | |
| 356 Assert.IsTrue(target.isProperlyInitialized_); | |
| 357 Assert.AreEqual( | |
| 358 target.projectPlatformType_, | |
| 359 PluginDebuggerHelper_Accessor.ProjectPlatformType.Pepper); | |
| 360 Assert.AreEqual( | |
| 361 target.pluginProjectDirectory_, | |
| 362 TestContext.DeploymentDirectory + @"\DummyLoop\DummyLoop\"); | |
| 363 Assert.AreEqual( | |
| 364 target.pluginAssembly_, | |
| 365 TestContext.DeploymentDirectory + @"\DummyLoop\Debug\PPAPI\DummyLoop.d ll"); | |
| 366 Assert.AreEqual( | |
| 367 target.pluginOutputDirectory_, | |
| 368 TestContext.DeploymentDirectory + @"\DummyLoop\Debug\PPAPI\"); | |
| 369 Assert.AreEqual(target.sdkRootDirectory_, expectedSDKRootDir); | |
| 370 Assert.AreEqual(target.webServerExecutable_, "python.exe"); | |
| 371 ////Assert.AreEqual(target._webServerArguments, ""); | |
| 372 ////Assert.AreEqual(target._gdbPath, ""); | |
| 373 } | |
| 374 | |
| 375 /// <summary> | |
| 376 /// Checks that VS properly attaches debugger. | |
| 377 /// </summary> | |
| 378 [TestMethod] | |
| 379 [DeploymentItem("NativeClientVSAddIn.dll")] | |
| 380 public void AttachVSDebuggerTest() | |
| 381 { | |
| 382 using (Process dummyProc = TestUtilities.StartProcessForKilling("DummyProc ", 20)) | |
| 383 { | |
| 384 try | |
| 385 { | |
| 386 PluginDebuggerHelper_Accessor target = new PluginDebuggerHelper_Access or(dte_); | |
| 387 target.projectPlatformType_ = PluginDebuggerHelper_Accessor.ProjectPla tformType.Pepper; | |
| 388 target.isProperlyInitialized_ = true; | |
| 389 | |
| 390 target.AttachVSDebugger( | |
| 391 null, | |
| 392 new NativeClientVSAddIn.PluginDebuggerHelper.PluginFoundEventArgs( (uint)dummyProc.Id)); | |
|
binji
2012/07/20 00:24:53
nit: wrap at 100 chars
tysand
2012/08/07 23:01:54
Done.
| |
| 393 | |
| 394 bool isBeingDebugged = false; | |
| 395 foreach (EnvDTE.Process proc in dte_.Debugger.DebuggedProcesses) | |
| 396 { | |
| 397 if (proc.ProcessID == dummyProc.Id) | |
| 398 { | |
| 399 isBeingDebugged = true; | |
| 400 } | |
| 401 } | |
| 402 | |
| 403 Assert.IsTrue(isBeingDebugged, "Visual Studio debugger did not attach" ); | |
| 404 } | |
| 405 finally | |
| 406 { | |
| 407 if (dummyProc != null && !dummyProc.HasExited) | |
| 408 { | |
| 409 dummyProc.Kill(); | |
| 410 dummyProc.Dispose(); | |
|
binji
2012/07/20 00:24:53
dispose is unnecessary because of using above, rig
tysand
2012/08/07 23:01:54
Done.
| |
| 411 } | |
| 412 } | |
| 413 } | |
| 414 } | |
| 415 | |
| 416 /// <summary> | |
| 417 /// A test for StartDebugging. | |
| 418 /// </summary> | |
| 419 [TestMethod] | |
| 420 public void StartDebuggingTest() | |
|
binji
2012/07/20 00:24:53
I don't understand what this is testing. It looks
tysand
2012/08/07 23:01:54
Done.
| |
| 421 { | |
| 422 PluginDebuggerHelper_Accessor target = new PluginDebuggerHelper_Accessor(d te_); | |
| 423 | |
| 424 // Neutralize StartWebServer by providing dummy executable settings. | |
| 425 target.webServerExecutable_ = "python.exe"; | |
| 426 target.webServerArguments_ = "-c \"print 'test'\""; | |
| 427 target.pluginProjectDirectory_ = TestContext.DeploymentDirectory; | |
| 428 | |
| 429 // Have the timer call a function to set success to true. | |
| 430 ManualResetEvent finderSuccess = new ManualResetEvent(false); | |
| 431 target.pluginFinderTimer_ = new System.Windows.Forms.Timer(); | |
| 432 target.pluginFinderTimer_.Tick += (a, b) => { finderSuccess.Set(); }; | |
| 433 | |
| 434 // Check that an exception is thrown if not initialized properly. | |
| 435 target.isProperlyInitialized_ = false; | |
| 436 try | |
| 437 { | |
| 438 target.StartDebugging(); | |
| 439 Assert.Fail("Debugging started when not initialized"); | |
| 440 } | |
| 441 catch (Exception) | |
| 442 { | |
| 443 // Expected in a proper implementation. | |
| 444 } | |
| 445 | |
| 446 // Properly start debugging and wait for event signal. | |
| 447 target.isProperlyInitialized_ = true; | |
| 448 target.StartDebugging(); | |
| 449 | |
| 450 // Pump events waiting for signal, time-out after 10 seconds. | |
| 451 bool success = false; | |
| 452 for (int i = 0; i < 20; i++) | |
| 453 { | |
| 454 System.Windows.Forms.Application.DoEvents(); | |
| 455 if (finderSuccess.WaitOne(500)) | |
| 456 { | |
| 457 success = true; | |
| 458 break; | |
| 459 } | |
| 460 } | |
| 461 | |
| 462 Assert.IsTrue(success, "Plug-in finder timer did not fire"); | |
| 463 } | |
| 464 | |
| 465 /// <summary> | |
| 466 /// This tests that StartWebServer executes webServerExecutable_ with webSer verArguments_ | |
| 467 /// as arguments, sets the working directory to the project directory, and h ooks | |
| 468 /// up stdout and stderr from the web server to the Web Server output panel in VS. | |
| 469 /// This test implicitly covers WebServerMessageReceive. | |
| 470 /// </summary> | |
| 471 [TestMethod] | |
| 472 [DeploymentItem("NativeClientVSAddIn.dll")] | |
| 473 public void StartWebServerTest() | |
| 474 { | |
| 475 PluginDebuggerHelper_Accessor target = new PluginDebuggerHelper_Accessor(d te_); | |
| 476 try | |
| 477 { | |
| 478 string successMessage = "successful test!"; | |
| 479 string stderrMessage = "stderr test"; | |
| 480 target.webServerExecutable_ = "python.exe"; | |
| 481 | |
| 482 // To save pain, if modifying this in the future avoid special character s, | |
| 483 // or make sure to double escape them. Ex: \n --> \\n. | |
| 484 string program = | |
| 485 "import os;" + | |
| 486 "import sys;" + | |
| 487 string.Format("sys.stdout.write('{0}');", successMessage) + | |
| 488 string.Format("sys.stderr.write('{0}');", stderrMessage) + | |
| 489 "sys.stdout.write(os.getcwd());" + | |
| 490 "sys.stdout.flush();" + | |
| 491 "sys.stderr.flush()"; | |
| 492 target.webServerArguments_ = string.Format("-c \"{0}\"", program); | |
| 493 target.pluginProjectDirectory_ = TestContext.DeploymentDirectory; | |
| 494 target.isProperlyInitialized_ = true; | |
| 495 target.StartWebServer(); | |
| 496 | |
| 497 // Check that the output pane exists. | |
| 498 EnvDTE.OutputWindowPane window = dte_.ToolWindows.OutputWindow.OutputWin dowPanes.Item( | |
| 499 Strings.WebServerOutputWindowTitle); | |
| 500 Assert.IsNotNull(window, "Web server output pane failed to create"); | |
| 501 | |
| 502 // Wait for results to arrive for up to 10 seconds, checking every 0.5 s econds. | |
| 503 string result = TestUtilities.GetPaneText(target.webServerOutputPane_); | |
|
binji
2012/07/20 00:24:53
move this inside the for loop, remove the duplicat
tysand
2012/08/07 23:01:54
Done.
| |
| 504 for (int repeat = 0; repeat < 20; repeat++) | |
| 505 { | |
| 506 if (result != null && | |
| 507 result.Contains(successMessage) && | |
| 508 result.Contains(stderrMessage) && | |
| 509 result.Contains(TestContext.DeploymentDirectory)) | |
| 510 { | |
| 511 break; | |
| 512 } | |
| 513 | |
| 514 Thread.Sleep(500); | |
| 515 result = TestUtilities.GetPaneText(target.webServerOutputPane_); | |
| 516 } | |
| 517 | |
| 518 Assert.IsFalse(string.IsNullOrEmpty(result), "Nothing printed to output pane"); | |
| 519 StringAssert.Contains( | |
| 520 result, | |
| 521 successMessage, | |
| 522 "Executable did not successfully run given arguments"); | |
| 523 StringAssert.Contains( | |
| 524 result, | |
| 525 TestContext.DeploymentDirectory, | |
| 526 "Web server working directory was not set to project directory"); | |
| 527 StringAssert.Contains(result, stderrMessage, "Standard error message was not captured"); | |
| 528 } | |
| 529 finally | |
| 530 { | |
| 531 if (!target.webServer_.WaitForExit(1000)) | |
| 532 { | |
| 533 target.webServer_.Kill(); | |
| 534 target.webServer_.Dispose(); | |
| 535 } | |
| 536 } | |
| 537 } | |
| 538 | |
| 539 /// <summary> | |
| 540 /// Ensures that StopDebugging() kills GDB and the web server, and resets th e state of | |
| 541 /// PluginDebuggerHelper to before debugging started. | |
| 542 /// Implicitly tests KillGDBProcess(). | |
| 543 /// </summary> | |
| 544 [TestMethod] | |
| 545 public void StopDebuggingTest() | |
| 546 { | |
| 547 PluginDebuggerHelper_Accessor target = new PluginDebuggerHelper_Accessor(d te_); | |
| 548 string webServerIdentifier = "StartVisualStudioInstance_TestWebServer"; | |
| 549 string gdbIdentifier = "StartVisualStudioInstance_TestGDB"; | |
| 550 | |
| 551 // Set up items that should exist given a successful calling of StartDebug ging(). | |
| 552 target.gdbInitFileName_ = Path.GetTempFileName(); | |
| 553 target.pluginFinderForbiddenPids_.Add(123); | |
|
binji
2012/07/20 00:24:53
what is 123?
tysand
2012/08/07 23:01:54
Done.
| |
| 554 target.webServer_ = TestUtilities.StartProcessForKilling(webServerIdentifi er, 20); | |
| 555 target.gdbProcess_ = TestUtilities.StartProcessForKilling(gdbIdentifier, 2 0); | |
| 556 target.isProperlyInitialized_ = true; | |
| 557 | |
| 558 target.StopDebugging(); | |
| 559 | |
| 560 Assert.IsFalse(target.isProperlyInitialized_, "Failed to set initialized s tate to false"); | |
| 561 Assert.IsFalse(target.pluginFinderTimer_.Enabled, "Plug-in finder timer no t stopped"); | |
| 562 Assert.IsFalse( | |
| 563 TestUtilities.DoesProcessExist("python.exe", webServerIdentifier), | |
| 564 "Failed to kill web server process"); | |
| 565 Assert.IsFalse( | |
| 566 TestUtilities.DoesProcessExist("python.exe", gdbIdentifier), | |
| 567 "Failed to kill gdb process"); | |
| 568 Assert.IsFalse( | |
| 569 File.Exists(target.gdbInitFileName_), | |
| 570 "Failed to delete temp gdb init file"); | |
| 571 Assert.IsTrue( | |
| 572 target.pluginFinderForbiddenPids_.Count == 0, | |
| 573 "Plugin finder Process IDs not cleared"); | |
| 574 } | |
| 575 | |
| 576 /// <summary> | |
| 577 /// A test for WebServerWriteLine. | |
| 578 /// </summary> | |
| 579 [TestMethod] | |
| 580 [DeploymentItem("NativeClientVSAddIn.dll")] | |
| 581 public void WebServerWriteLineTest() | |
| 582 { | |
| 583 PluginDebuggerHelper_Accessor target = new PluginDebuggerHelper_Accessor(d te_); | |
| 584 string successMessage = "successful test!"; | |
| 585 target.webServerOutputPane_ = dte_.ToolWindows.OutputWindow.OutputWindowPa nes.Add( | |
| 586 Strings.WebServerOutputWindowTitle); | |
| 587 target.isProperlyInitialized_ = true; | |
| 588 target.WebServerWriteLine(successMessage); | |
| 589 string result = TestUtilities.GetPaneText(target.webServerOutputPane_); | |
|
binji
2012/07/20 00:24:53
same as above, move inside loop, etc.
tysand
2012/08/07 23:01:54
Done.
| |
| 590 | |
| 591 // Wait for results to arrive for up to 10 seconds, checking every 0.5 sec onds. | |
| 592 for (int repeat = 0; repeat < 20; repeat++) | |
| 593 { | |
| 594 if (result != null && | |
| 595 result.Contains(successMessage)) | |
|
binji
2012/07/20 00:24:53
nit: looks like this should fit on the previous li
tysand
2012/08/07 23:01:54
Done.
| |
| 596 { | |
| 597 break; | |
| 598 } | |
| 599 | |
| 600 Thread.Sleep(500); | |
| 601 result = TestUtilities.GetPaneText(target.webServerOutputPane_); | |
| 602 } | |
| 603 | |
| 604 StringAssert.Contains(result, successMessage, "Message failed to print"); | |
| 605 } | |
| 606 } | |
| 607 } | |
| OLD | NEW |