Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 using NativeClientVSAddIn; | |
| 2 using Microsoft.VisualStudio.TestTools.UnitTesting; | |
| 3 using EnvDTE80; | |
| 4 using System; | |
| 5 using System.Collections.Generic; | |
| 6 using System.Diagnostics; | |
| 7 using System.IO; | |
| 8 using System.Reflection; | |
| 9 using System.Threading; | |
| 10 | |
| 11 namespace UnitTests | |
| 12 { | |
| 13 /// <summary> | |
| 14 ///This is a test class for PluginDebuggerHelperTest and is intended | |
| 15 ///to contain all PluginDebuggerHelperTest Unit Tests | |
| 16 ///</summary> | |
| 17 [TestClass()] | |
| 18 public class PluginDebuggerHelperTest | |
| 19 { | |
| 20 /// <summary> | |
| 21 /// The dummy loop solution is a valid nacl/pepper plug-in VS solution | |
| 22 /// It is copied into the testing deployment directory and opened in som e tests | |
| 23 /// Because unit-tests run in any order, the solution should not be writ ten to | |
| 24 /// in any tests. | |
| 25 /// </summary> | |
| 26 private const string DummyLoopSolution = "\\DummyLoop\\DummyLoop.sln"; | |
|
Petr Hosek
2012/07/10 05:37:21
You can use non-interpreted string to avoid those
tysand
2012/07/11 05:23:46
Done.
| |
| 27 private TestContext _testContextInstance; | |
| 28 | |
| 29 /// <summary> | |
| 30 ///Gets or sets the test context which provides | |
| 31 ///information about and functionality for the current test run. | |
| 32 ///</summary> | |
| 33 public TestContext TestContext | |
| 34 { | |
| 35 get | |
| 36 { | |
| 37 return _testContextInstance; | |
| 38 } | |
| 39 set | |
| 40 { | |
| 41 _testContextInstance = value; | |
| 42 } | |
| 43 } | |
| 44 | |
| 45 /// <summary> | |
| 46 ///A test for PluginDebuggerHelper Constructor | |
| 47 ///</summary> | |
| 48 [TestMethod()] | |
| 49 public void PluginDebuggerHelperConstructorTest() | |
| 50 { | |
| 51 // Check null dte fails | |
| 52 try | |
| 53 { | |
| 54 PluginDebuggerHelper nullDte = new PluginDebuggerHelper(null); | |
| 55 Assert.Fail("Using null DTE instance did not throw exception"); | |
| 56 } | |
| 57 catch (ArgumentNullException) | |
| 58 { | |
| 59 } | |
| 60 catch | |
| 61 { | |
| 62 Assert.Fail("Using null DTE instance threw something other than ArgumentNullException"); | |
| 63 } | |
| 64 | |
| 65 DTE2 dte = TestUtilities.StartVisualStudioInstance(); | |
|
Petr Hosek
2012/07/10 05:37:21
Since you are using this in every single test meth
tysand
2012/07/11 05:23:46
Done.
| |
| 66 try | |
| 67 { | |
| 68 PluginDebuggerHelper_Accessor target = new PluginDebuggerHelper_ Accessor(dte); | |
| 69 Assert.AreEqual(dte, target._dte); | |
| 70 Assert.IsNull(target._webServerOutputPane); | |
| 71 Assert.IsFalse(target._isDebuggingNow); | |
| 72 Assert.IsFalse(target._isProperlyInitialized); | |
| 73 } | |
| 74 finally | |
| 75 { | |
| 76 TestUtilities.CleanUpVisualStudioInstance(dte); | |
|
Petr Hosek
2012/07/10 05:37:21
The same here, could you move this to a shared cle
tysand
2012/07/11 05:23:46
Done.
| |
| 77 } | |
| 78 } | |
| 79 | |
| 80 /// <summary> | |
| 81 /// This unit test verifies that the gdb init file is written correctly, | |
| 82 /// and old-existing GDB processes are cleaned up | |
| 83 /// Verification of actual attachment is the responsibility of integrati on | |
| 84 /// tests and NaCl-GDB itself | |
| 85 ///</summary> | |
| 86 [TestMethod()] | |
| 87 [DeploymentItem("NativeClientVSAddIn.dll")] | |
| 88 public void AttachNaClGDBTest() | |
| 89 { | |
| 90 DTE2 dte = TestUtilities.StartVisualStudioInstance(); | |
| 91 PluginDebuggerHelper_Accessor target = new PluginDebuggerHelper_Acce ssor(dte); | |
| 92 string existingGDB = "AttachNaClGDBTest_existingGDB"; | |
| 93 try | |
| 94 { | |
| 95 target._pluginProjectDirectory = TestContext.DeploymentDirectory ; | |
|
Petr Hosek
2012/07/10 05:37:21
I would turn these into properties, accessing clas
tysand
2012/07/11 05:23:46
Most methods being tested are private and don't ha
| |
| 96 target._pluginAssembly = "fakeAssemblyString"; | |
| 97 target._irtPath = "fakeIrtPath"; | |
| 98 target._gdbPath = "python.exe"; | |
| 99 target._gdbProcess = TestUtilities.StartProcessForKilling(existi ngGDB, 20); | |
| 100 string existingInitFileName = Path.GetTempFileName(); | |
| 101 target._gdbInitFileName = existingInitFileName; | |
| 102 target._isDebuggingNow = true; | |
| 103 target._isProperlyInitialized = true; | |
| 104 | |
| 105 // Visual studio won't allow adding a breakpoint unless it is as sociated with | |
| 106 // an existing file and valid line number | |
| 107 dte.Solution.Open(TestContext.DeploymentDirectory + DummyLoopSol ution); | |
| 108 string fileName = "main.cpp"; | |
| 109 string functionName = "DummyInstance::HandleMessage"; | |
| 110 int lineNumber = 35; | |
| 111 dte.Debugger.Breakpoints.Add(Function: functionName); | |
| 112 dte.Debugger.Breakpoints.Add(Line: lineNumber, File: fileName); | |
| 113 | |
| 114 target.AttachNaClGDB(null, new PluginFoundEventArgs(0)); | |
| 115 | |
| 116 Assert.IsTrue(File.Exists(target._gdbInitFileName), "Init file n ot written"); | |
| 117 | |
| 118 string[] gdbCommands = File.ReadAllLines(target._gdbInitFileName ); | |
| 119 bool functionBP = false; | |
| 120 bool lineBP = false; | |
| 121 | |
| 122 // Validate that commands contain what we specified | |
| 123 // Syntax itself is not validated since this add-in is not respo nsible for | |
| 124 // the syntax and it could change | |
| 125 foreach (string command in gdbCommands) | |
| 126 { | |
| 127 if (command.Contains(fileName) && command.Contains(lineNumbe r.ToString())) | |
| 128 lineBP = true; | |
| 129 if (command.Contains(functionName)) | |
| 130 functionBP = true; | |
| 131 } | |
| 132 | |
| 133 Assert.IsFalse(TestUtilities.DoesProcessExist(existingGDB, "pyth on.exe"), "Failed to kill existing GDB process"); | |
| 134 Assert.IsFalse(File.Exists(existingInitFileName), "Failed to del ete existing temp gdb init file"); | |
| 135 Assert.IsTrue(lineBP, "Line breakpoint not properly set"); | |
| 136 Assert.IsTrue(functionBP, "Function breakpoint not properly set" ); | |
| 137 } | |
| 138 finally | |
| 139 { | |
| 140 if (dte.Debugger.Breakpoints != null) | |
| 141 { | |
| 142 // Remove all breakpoints | |
| 143 foreach(EnvDTE.Breakpoint bp in dte.Debugger.Breakpoints) | |
| 144 bp.Delete(); | |
| 145 } | |
| 146 if (!String.IsNullOrEmpty(target._gdbInitFileName) && File.Exist s(target._gdbInitFileName)) | |
| 147 File.Delete(target._gdbInitFileName); | |
| 148 if (target._gdbProcess != null && !target._gdbProcess.HasExited) | |
| 149 target._gdbProcess.Kill(); | |
| 150 TestUtilities.CleanUpVisualStudioInstance(dte); | |
| 151 } | |
| 152 } | |
| 153 | |
| 154 /// <summary> | |
| 155 ///A test for FindAndAttachToPlugin | |
| 156 ///</summary> | |
| 157 [TestMethod()] | |
| 158 [DeploymentItem("NativeClientVSAddIn.dll")] | |
| 159 public void FindAndAttachToPluginTest() | |
| 160 { | |
| 161 DTE2 dte = TestUtilities.StartVisualStudioInstance(); | |
| 162 try | |
| 163 { | |
| 164 PluginDebuggerHelper_Accessor target = new PluginDebuggerHelper_ Accessor(dte); | |
| 165 target._isDebuggingNow = true; | |
| 166 target._isProperlyInitialized = true; | |
| 167 | |
| 168 MockProcessSearcher processResults = new MockProcessSearcher(); | |
| 169 uint currentProcId = (uint)System.Diagnostics.Process.GetCurrent Process().Id; | |
| 170 string naclCommandLine = Strings.NaClProcessTypeFlag + " " + Str ings.NaClDebugFlag; | |
| 171 target._pluginAssembly = "testAssemblyPath"; | |
| 172 string pepperCommandLine = String.Format(Strings.PepperProcessPl uginFlagFormat, target._pluginAssembly) + | |
| 173 " " + Strings.PepperProcessTypeFlag; | |
| 174 | |
| 175 // Fake the list of processes on the system | |
| 176 processResults.Results.Add(new ProcessInfo(currentProcId, curren tProcId, "", "", "devenv.exe")); | |
| 177 processResults.Results.Add(new ProcessInfo(1, currentProcId, "", "", "MyParentProcess")); | |
| 178 processResults.Results.Add(new ProcessInfo(10, 1, "", pepperComm andLine, Strings.PepperProcessName)); | |
| 179 processResults.Results.Add(new ProcessInfo(11, 1, "", naclComman dLine, Strings.NaClProcessName)); | |
| 180 processResults.Results.Add(new ProcessInfo(12, 1, "", | |
| 181 String.Format(Strings.PepperProcessPluginFlagFormat, target. _pluginAssembly), | |
| 182 Strings.PepperProcessName)); | |
| 183 processResults.Results.Add(new ProcessInfo(13, 1, "", Strings.Na ClDebugFlag, Strings.NaClProcessName)); | |
| 184 | |
| 185 // These two don't have this process as their parent, so they sh ould not be attached to | |
| 186 processResults.Results.Add(new ProcessInfo(14, 14, "", pepperCom mandLine, Strings.PepperProcessName)); | |
| 187 processResults.Results.Add(new ProcessInfo(15, 15, "", naclComma ndLine, Strings.NaClProcessName)); | |
| 188 | |
| 189 // Set the private value to the mock object (can't use accessor since no valid cast) | |
| 190 typeof(PluginDebuggerHelper).GetField("_processSearcher", Bindin gFlags.NonPublic | BindingFlags.Instance). | |
| 191 SetValue(target.Target, processResults); | |
| 192 | |
| 193 // Test that the correct processes are attached to | |
| 194 bool goodNaCl = false; | |
| 195 bool goodPepper = false; | |
| 196 EventHandler<PluginFoundEventArgs> handler = new EventHandler<Pl uginFoundEventArgs>( | |
| 197 delegate(object unused, PluginFoundEventArgs args) | |
|
Petr Hosek
2012/07/10 05:37:21
I would use lambda instead of delegate, i.e. `(unu
tysand
2012/07/11 05:23:46
Delegate seems more readable to me in this context
| |
| 198 { | |
| 199 switch (args.ProcessID) | |
| 200 { | |
| 201 case 10: | |
| 202 if (goodPepper) | |
| 203 Assert.Fail("Should not attach twice to same pepper process"); | |
| 204 if (target._projectPlatformType == PluginDebugge rHelper_Accessor.ProjectPlatformType.NaCl) | |
| 205 Assert.Fail("Attached to pepper process when NaCl was the target"); | |
| 206 goodPepper = true; | |
| 207 break; | |
| 208 case 11: | |
| 209 if (goodNaCl) | |
| 210 Assert.Fail("Should not attach twice to same nacl process"); | |
| 211 if (target._projectPlatformType == PluginDebugge rHelper_Accessor.ProjectPlatformType.Pepper) | |
| 212 Assert.Fail("Attached to nacl process when p epper was the target"); | |
| 213 goodNaCl = true; | |
| 214 break; | |
| 215 case 12: | |
| 216 Assert.Fail("Should not attach to pepper process with bad args"); | |
| 217 break; | |
| 218 case 13: | |
| 219 Assert.Fail("Should not attach to nacl process w ith bad args"); | |
| 220 break; | |
| 221 case 14: | |
| 222 Assert.Fail("Should not attach to pepper process that is not descendant of Visual Studio"); | |
| 223 break; | |
| 224 case 15: | |
| 225 Assert.Fail("Should not attach to nacl process t hat is not descendant of Visual Studio"); | |
| 226 break; | |
| 227 default: | |
| 228 Assert.Fail("Should not attach to non-pepper/nac l process"); | |
| 229 break; | |
| 230 } | |
| 231 }); | |
| 232 | |
| 233 target.add_PluginFoundEvent(handler); | |
| 234 target._projectPlatformType = PluginDebuggerHelper_Accessor.Proj ectPlatformType.Pepper; | |
| 235 target.FindAndAttachToPlugin(null, null); | |
| 236 target._projectPlatformType = PluginDebuggerHelper_Accessor.Proj ectPlatformType.NaCl; | |
| 237 target.FindAndAttachToPlugin(null, null); | |
| 238 target.remove_PluginFoundEvent(handler); | |
| 239 Assert.IsTrue(goodPepper, "Failed to attach to pepper process"); | |
| 240 Assert.IsTrue(goodNaCl, "Failed to attach to NaCl process"); | |
| 241 } | |
| 242 finally | |
| 243 { | |
| 244 TestUtilities.CleanUpVisualStudioInstance(dte); | |
| 245 } | |
| 246 } | |
| 247 | |
| 248 /// <summary> | |
| 249 ///A test for InitializeFromProjectSettings | |
| 250 ///</summary> | |
| 251 [TestMethod()] | |
| 252 public void InitializeFromProjectSettingsTest() | |
| 253 { | |
| 254 DTE2 dte = TestUtilities.StartVisualStudioInstance(); | |
| 255 try | |
| 256 { | |
| 257 string expectedSDKRootDir = Environment.GetEnvironmentVariable(S trings.SDKPathEnvironmentVariable); | |
| 258 Assert.IsNotNull(expectedSDKRootDir, "SDK Path environment varia ble not set!"); | |
| 259 | |
| 260 PluginDebuggerHelper_Accessor target = new PluginDebuggerHelper_ Accessor(dte); | |
| 261 target._isDebuggingNow = false; | |
| 262 target._isProperlyInitialized = false; | |
| 263 try | |
| 264 { | |
| 265 target.InitializeFromProjectSettings(); | |
| 266 Assert.Fail("Initializing with no loaded solution shouldn't succeed"); | |
| 267 } | |
| 268 catch (ArgumentOutOfRangeException e) | |
| 269 { | |
| 270 } | |
| 271 | |
| 272 dte.Solution.Open(TestContext.DeploymentDirectory + DummyLoopSol ution); | |
| 273 | |
| 274 // Set start-up project to a non-cpp project, should not initial ize | |
| 275 string badProjectUniqueName = "NotNaCl\\NotNaCl.csproj"; | |
| 276 object[] badStartupProj = { badProjectUniqueName }; | |
| 277 dte.Solution.SolutionBuild.StartupProjects = badStartupProj; | |
| 278 Assert.IsFalse(target.InitializeFromProjectSettings()); | |
| 279 Assert.IsFalse(target._isProperlyInitialized); | |
| 280 | |
| 281 // Set start-up project to correct C++ project, but set platform to non-nacl/pepper | |
| 282 // Initialization should fail | |
| 283 string projectUniqueName = "DummyLoop\\DummyLoop.vcxproj"; | |
| 284 object[] startupProj = { projectUniqueName }; | |
| 285 dte.Solution.SolutionBuild.StartupProjects = startupProj; | |
| 286 TestUtilities.SetSolutionConfiguration(dte, projectUniqueName, " Debug", "Win32"); | |
| 287 Assert.IsFalse(target.InitializeFromProjectSettings()); | |
| 288 Assert.IsFalse(target._isProperlyInitialized); | |
| 289 | |
| 290 // Set platform to NaCl, should succeed | |
| 291 TestUtilities.SetSolutionConfiguration(dte, projectUniqueName, " Debug", Strings.NaClPlatformName); | |
| 292 Assert.IsTrue(target.InitializeFromProjectSettings()); | |
| 293 Assert.IsTrue(target._isProperlyInitialized); | |
| 294 Assert.AreEqual(target._projectPlatformType, PluginDebuggerHelpe r_Accessor.ProjectPlatformType.NaCl); | |
| 295 Assert.AreEqual(target._debuggerType, PluginDebuggerHelper_Acces sor.DebuggerType.GDB); | |
| 296 Assert.AreEqual(target._pluginProjectDirectory, TestContext.Depl oymentDirectory + "\\DummyLoop\\DummyLoop\\"); | |
| 297 Assert.AreEqual(target._pluginAssembly, TestContext.DeploymentDi rectory + "\\DummyLoop\\DummyLoop\\NaCl\\Debug\\DummyLoop.nexe"); | |
| 298 Assert.AreEqual(target._pluginOutputDirectory, TestContext.Deplo ymentDirectory + "\\DummyLoop\\DummyLoop\\NaCl\\Debug\\"); | |
| 299 Assert.AreEqual(target._sdkRootDirectory, expectedSDKRootDir); | |
| 300 Assert.AreEqual(target._webServerExecutable, "python.exe"); | |
| 301 //Assert.AreEqual(target._webServerArguments, ""); | |
| 302 //Assert.AreEqual(target._gdbPath, ""); | |
| 303 | |
| 304 // Set platform to Pepper, should succeed | |
| 305 TestUtilities.SetSolutionConfiguration(dte, projectUniqueName, " Debug", Strings.PepperPlatformName); | |
| 306 Assert.IsTrue(target.InitializeFromProjectSettings()); | |
| 307 Assert.IsTrue(target._isProperlyInitialized); | |
| 308 Assert.AreEqual(target._projectPlatformType, PluginDebuggerHelpe r_Accessor.ProjectPlatformType.Pepper); | |
| 309 Assert.AreEqual(target._debuggerType, PluginDebuggerHelper_Acces sor.DebuggerType.VS); | |
| 310 Assert.AreEqual(target._pluginProjectDirectory, TestContext.Depl oymentDirectory + "\\DummyLoop\\DummyLoop\\"); | |
| 311 Assert.AreEqual(target._pluginAssembly, TestContext.DeploymentDi rectory + "\\DummyLoop\\Debug\\PPAPI\\DummyLoop.dll"); | |
| 312 Assert.AreEqual(target._pluginOutputDirectory, TestContext.Deplo ymentDirectory + "\\DummyLoop\\Debug\\PPAPI\\"); | |
| 313 Assert.AreEqual(target._sdkRootDirectory, expectedSDKRootDir); | |
| 314 Assert.AreEqual(target._webServerExecutable, "python.exe"); | |
| 315 //Assert.AreEqual(target._webServerArguments, ""); | |
| 316 //Assert.AreEqual(target._gdbPath, ""); | |
| 317 } | |
| 318 finally | |
| 319 { | |
| 320 TestUtilities.CleanUpVisualStudioInstance(dte); | |
| 321 } | |
| 322 } | |
| 323 | |
| 324 /// <summary> | |
| 325 /// Checks that VS properly attaches debugger | |
| 326 ///</summary> | |
| 327 [TestMethod()] | |
| 328 [DeploymentItem("NativeClientVSAddIn.dll")] | |
| 329 public void AttachVSDebuggerTest() | |
| 330 { | |
| 331 Process dummyProc = null; | |
|
Petr Hosek
2012/07/10 05:37:21
You might consider wrapping the Process into using
tysand
2012/07/11 05:23:46
Done.
| |
| 332 DTE2 dte = TestUtilities.StartVisualStudioInstance(); | |
| 333 try | |
| 334 { | |
| 335 PluginDebuggerHelper_Accessor target = new PluginDebuggerHelper_ Accessor(dte); | |
| 336 target._debuggerType = PluginDebuggerHelper_Accessor.DebuggerTyp e.VS; | |
| 337 target._projectPlatformType = PluginDebuggerHelper_Accessor.Proj ectPlatformType.Pepper; | |
| 338 target._isDebuggingNow = true; | |
| 339 target._isProperlyInitialized = true; | |
| 340 | |
| 341 dummyProc = TestUtilities.StartProcessForKilling("DummyProc", 20 ); | |
| 342 target.AttachVSDebugger(null, new PluginFoundEventArgs(((uint)du mmyProc.Id))); | |
| 343 | |
| 344 bool isBeingDebugged = false; | |
| 345 foreach (EnvDTE.Process proc in dte.Debugger.DebuggedProcesses) | |
| 346 { | |
| 347 if (proc.ProcessID == dummyProc.Id) | |
| 348 isBeingDebugged = true; | |
| 349 } | |
| 350 Assert.IsTrue(isBeingDebugged, "Visual Studio debugger did not a ttach"); | |
| 351 } | |
| 352 finally | |
| 353 { | |
| 354 if (dummyProc != null && !dummyProc.HasExited) | |
| 355 dummyProc.Kill(); | |
| 356 | |
| 357 TestUtilities.CleanUpVisualStudioInstance(dte); | |
| 358 } | |
| 359 } | |
| 360 | |
| 361 /// <summary> | |
| 362 ///A test for StartDebugging | |
| 363 ///Also implicitly tests IsDebuggerRunningTest | |
| 364 ///</summary> | |
| 365 [TestMethod()] | |
| 366 public void StartDebuggingTest() | |
| 367 { | |
| 368 DTE2 dte = TestUtilities.StartVisualStudioInstance(); | |
| 369 try | |
| 370 { | |
| 371 PluginDebuggerHelper_Accessor target = new PluginDebuggerHelper_ Accessor(dte); | |
| 372 | |
| 373 // Neutralize StartWebServer by providing dummy executable setti ngs: | |
| 374 target._webServerExecutable = "python.exe"; | |
| 375 target._webServerArguments = "-c \"print 'test'\""; | |
| 376 target._pluginProjectDirectory = TestContext.DeploymentDirectory ; | |
| 377 | |
| 378 // Have the timer call a function to set success to true | |
| 379 ManualResetEvent finderSuccess = new ManualResetEvent(false); | |
| 380 target._pluginFinderTimer = new System.Windows.Forms.Timer(); | |
| 381 target._pluginFinderTimer.Tick += new EventHandler(delegate(obje ct a, EventArgs b) { finderSuccess.Set(); }); | |
|
Petr Hosek
2012/07/10 05:37:21
I would use lambda here.
tysand
2012/07/11 05:23:46
Done.
| |
| 382 | |
| 383 // Check that nothing happens when not initialized | |
| 384 target._isDebuggingNow = false; | |
| 385 target._isProperlyInitialized = false; | |
| 386 target.StartDebugging(); | |
| 387 Assert.IsFalse(target.IsDebuggerRunning, "Debugging started when not properly initialized"); | |
| 388 | |
| 389 // Properly start debugging and wait for event signal | |
| 390 target._isProperlyInitialized = true; | |
| 391 target.StartDebugging(); | |
| 392 | |
| 393 // Pump events waiting for signal, time-out after 10 seconds | |
| 394 bool success = false; | |
| 395 for (int i = 0; i < 20; i++) | |
| 396 { | |
| 397 System.Windows.Forms.Application.DoEvents(); | |
| 398 if (finderSuccess.WaitOne(500)) | |
| 399 { | |
| 400 success = true; | |
| 401 break; | |
| 402 } | |
| 403 } | |
|
Petr Hosek
2012/07/10 05:37:21
When handling events, you might consider using Rea
tysand
2012/07/11 05:23:46
Would require an external install in order to use
| |
| 404 | |
| 405 Assert.IsTrue(success, "Plug-in finder timer did not fire"); | |
| 406 Assert.IsTrue(target.IsDebuggerRunning, "IsDebuggerRunning not t rue after debugging started"); | |
| 407 } | |
| 408 finally | |
| 409 { | |
| 410 TestUtilities.CleanUpVisualStudioInstance(dte); | |
| 411 } | |
| 412 } | |
| 413 | |
| 414 /// <summary> | |
| 415 /// Tests that StartWebServer executes _webServerExecutable with _webSer verArguments | |
| 416 /// as arguments, sets the working directory to the project directory, a nd hooks | |
| 417 /// up stdout and stderr from the web server to the Web Server output pa nel in VS. | |
| 418 /// This test implicitly covers WebServerMessageReceive | |
| 419 ///</summary> | |
| 420 [TestMethod()] | |
| 421 [DeploymentItem("NativeClientVSAddIn.dll")] | |
| 422 public void StartWebServerTest() | |
| 423 { | |
| 424 DTE2 dte = TestUtilities.StartVisualStudioInstance(); | |
| 425 PluginDebuggerHelper_Accessor target = new PluginDebuggerHelper_Acce ssor(dte); | |
| 426 try | |
| 427 { | |
| 428 string successMessage = "successful test!"; | |
| 429 string stderrMessage = "stderr test"; | |
| 430 target._webServerExecutable = "python.exe"; | |
| 431 | |
| 432 // To save pain, if modifying this in the future avoid special c haracters, | |
| 433 // or make sure to double escape them. Ex: \n --> \\n | |
| 434 string program = | |
| 435 "import os;" + | |
| 436 "import sys;" + | |
| 437 String.Format("sys.stdout.write('{0}');", successMessage) + | |
| 438 String.Format("sys.stderr.write('{0}');", stderrMessage) + | |
| 439 "sys.stdout.write(os.getcwd());" + | |
| 440 "sys.stdout.flush();" + | |
| 441 "sys.stderr.flush()"; | |
| 442 target._webServerArguments = String.Format("-c \"{0}\"", program ); | |
| 443 target._pluginProjectDirectory = TestContext.DeploymentDirectory ; | |
| 444 target._isDebuggingNow = false; | |
| 445 target._isProperlyInitialized = true; | |
| 446 target.StartWebServer(); | |
| 447 | |
| 448 // Check that the output pane exists | |
| 449 EnvDTE.OutputWindowPane window = dte.ToolWindows.OutputWindow.Ou tputWindowPanes.Item( | |
| 450 Strings.WebServerOutputWindowTitle); | |
| 451 Assert.IsNotNull(window, "Web server output pane failed to creat e"); | |
| 452 | |
| 453 // Wait for results to arrive for up to 10 seconds, checking eve ry 0.5 seconds | |
| 454 string result = TestUtilities.GetPaneText(target._webServerOutpu tPane); | |
| 455 for (int repeat = 0; repeat < 20; repeat++) | |
| 456 { | |
| 457 if (result != null && | |
| 458 result.Contains(successMessage) && | |
| 459 result.Contains(stderrMessage) && | |
| 460 result.Contains(TestContext.DeploymentDirectory)) | |
| 461 break; | |
| 462 Thread.Sleep(500); | |
| 463 result = TestUtilities.GetPaneText(target._webServerOutputPa ne); | |
| 464 } | |
| 465 | |
| 466 Assert.IsFalse(String.IsNullOrEmpty(result), "Nothing printed to output pane"); | |
| 467 StringAssert.Contains(result, successMessage, "Executable did no t successfully run given arguments"); | |
| 468 StringAssert.Contains(result, stderrMessage, "Standard error mes sage was not captured"); | |
| 469 StringAssert.Contains(result, TestContext.DeploymentDirectory, " Web server working directory was not set to project directory"); | |
| 470 } | |
| 471 finally | |
| 472 { | |
| 473 if (!target._webServer.WaitForExit(1000)) | |
| 474 target._webServer.Kill(); | |
| 475 TestUtilities.CleanUpVisualStudioInstance(dte); | |
| 476 } | |
| 477 } | |
| 478 | |
| 479 /// <summary> | |
| 480 /// Ensures that StopDebugging() kills GDB and the web server, and reset s the state of | |
| 481 /// PluginDebuggerHelper to before debugging started | |
| 482 /// Implicitly tests KillGDBProcess() | |
| 483 ///</summary> | |
| 484 [TestMethod()] | |
| 485 public void StopDebuggingTest() | |
| 486 { | |
| 487 DTE2 dte = TestUtilities.StartVisualStudioInstance(); | |
| 488 try | |
| 489 { | |
| 490 PluginDebuggerHelper_Accessor target = new PluginDebuggerHelper_ Accessor(dte); | |
| 491 string webServerIdentifier = "StartVisualStudioInstance_TestWebS erver"; | |
| 492 string gdbIdentifier = "StartVisualStudioInstance_TestGDB"; | |
| 493 | |
| 494 // Setup up items that should exist given a successful calling o f StartDebugging() | |
| 495 target._gdbInitFileName = Path.GetTempFileName(); | |
| 496 target._isDebuggingNow = true; | |
| 497 target._pluginFinderForbiddenPids.Add(123); | |
| 498 target._webServer = TestUtilities.StartProcessForKilling(webServ erIdentifier, 20); | |
| 499 target._gdbProcess = TestUtilities.StartProcessForKilling(gdbIde ntifier, 20); | |
| 500 target._isProperlyInitialized = true; | |
| 501 | |
| 502 target.StopDebugging(); | |
| 503 | |
| 504 Assert.IsFalse(TestUtilities.DoesProcessExist(webServerIdentifie r, "python.exe"), "Failed to kill web server process"); | |
| 505 Assert.IsFalse(TestUtilities.DoesProcessExist(gdbIdentifier, "py thon.exe"), "Failed to kill gdb process"); | |
| 506 Assert.IsFalse(target.IsDebuggerRunning, "Failed to set debug ru nning state to false"); | |
| 507 Assert.IsFalse(File.Exists(target._gdbInitFileName), "Failed to delete temp gdb init file"); | |
| 508 Assert.IsFalse(target._isProperlyInitialized, "Failed to set ini tialized state to false"); | |
| 509 Assert.IsTrue(target._pluginFinderForbiddenPids.Count == 0, "Plu gin finder Process IDs not cleared"); | |
| 510 Assert.IsFalse(target._pluginFinderTimer.Enabled, "Plug-in finde r timer not stopped"); | |
| 511 } | |
| 512 finally | |
| 513 { | |
| 514 TestUtilities.CleanUpVisualStudioInstance(dte); | |
| 515 } | |
| 516 } | |
| 517 | |
| 518 /// <summary> | |
| 519 ///A test for WebServerWriteLine | |
| 520 ///</summary> | |
| 521 [TestMethod()] | |
| 522 [DeploymentItem("NativeClientVSAddIn.dll")] | |
| 523 public void WebServerWriteLineTest() | |
| 524 { | |
| 525 DTE2 dte = TestUtilities.StartVisualStudioInstance(); | |
| 526 try | |
| 527 { | |
| 528 PluginDebuggerHelper_Accessor target = new PluginDebuggerHelper_ Accessor(dte); | |
| 529 string successMessage = "successful test!"; | |
| 530 target._webServerOutputPane = dte.ToolWindows.OutputWindow.Outpu tWindowPanes.Add( | |
| 531 Strings.WebServerOutputWindowTitle); | |
| 532 target._isDebuggingNow = true; | |
| 533 target._isProperlyInitialized = true; | |
| 534 target.WebServerWriteLine(successMessage); | |
| 535 string result = TestUtilities.GetPaneText(target._webServerOutpu tPane); | |
| 536 | |
| 537 // Wait for results to arrive for up to 10 seconds, checking eve ry 0.5 seconds | |
| 538 for (int repeat = 0; repeat < 20; repeat++) | |
| 539 { | |
| 540 if (result != null && | |
| 541 result.Contains(successMessage)) | |
| 542 break; | |
| 543 Thread.Sleep(500); | |
| 544 result = TestUtilities.GetPaneText(target._webServerOutputPa ne); | |
| 545 } | |
| 546 StringAssert.Contains(result, successMessage, "Message failed to print"); | |
| 547 } | |
| 548 finally | |
| 549 { | |
| 550 TestUtilities.CleanUpVisualStudioInstance(dte); | |
| 551 } | |
| 552 } | |
| 553 } | |
| 554 } | |
| OLD | NEW |