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