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.Collections.Generic; |
| 9 using System.IO; |
| 10 using System.Reflection; |
| 11 |
| 12 using EnvDTE80; |
| 13 using Microsoft.VisualStudio.TestTools.UnitTesting; |
| 14 |
| 15 using NativeClientVSAddIn; |
| 16 |
| 17 /// <summary> |
| 18 /// This is a test class for PluginDebuggerGDBTest and is intended |
| 19 /// to contain all PluginDebuggerGDB Unit Tests |
| 20 /// </summary> |
| 21 [TestClass] |
| 22 public class PluginDebuggerGDBTest |
| 23 { |
| 24 /// <summary> |
| 25 /// This holds the path to the NaCl solution used in these tests. |
| 26 /// The NaCl 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 static string naclSolution; |
| 32 |
| 33 /// <summary> |
| 34 /// The main visual studio object. |
| 35 /// </summary> |
| 36 private DTE2 dte_; |
| 37 |
| 38 /// <summary> |
| 39 /// Holds the default properties from property pages to use during tests. |
| 40 /// </summary> |
| 41 private MockPropertyManager properties_; |
| 42 |
| 43 /// <summary> |
| 44 /// Gets or sets the test context which provides information about, |
| 45 /// and functionality for the current test run. |
| 46 /// </summary> |
| 47 public TestContext TestContext { get; set; } |
| 48 |
| 49 /// <summary> |
| 50 /// This is run one time before any test methods are called. Here we set-up
a test-copy of a |
| 51 /// new NaCl solution for use in the tests. |
| 52 /// </summary> |
| 53 /// <param name="testContext">Holds information about the current test run</
param> |
| 54 [ClassInitialize] |
| 55 public static void ClassSetup(TestContext testContext) |
| 56 { |
| 57 DTE2 dte = TestUtilities.StartVisualStudioInstance(); |
| 58 try |
| 59 { |
| 60 naclSolution = TestUtilities.CreateBlankValidNaClSolution( |
| 61 dte, |
| 62 "PluginDebuggerGDBTest", |
| 63 NativeClientVSAddIn.Strings.PepperPlatformName, |
| 64 NativeClientVSAddIn.Strings.NaClPlatformName, |
| 65 testContext); |
| 66 } |
| 67 finally |
| 68 { |
| 69 TestUtilities.CleanUpVisualStudioInstance(dte); |
| 70 } |
| 71 } |
| 72 |
| 73 /// <summary> |
| 74 /// This is run before each test to create test resources. |
| 75 /// </summary> |
| 76 [TestInitialize] |
| 77 public void TestSetup() |
| 78 { |
| 79 dte_ = TestUtilities.StartVisualStudioInstance(); |
| 80 try |
| 81 { |
| 82 TestUtilities.AssertAddinLoaded(dte_, NativeClientVSAddIn.Strings.AddInN
ame); |
| 83 } |
| 84 catch |
| 85 { |
| 86 TestUtilities.CleanUpVisualStudioInstance(dte_); |
| 87 throw; |
| 88 } |
| 89 |
| 90 // Set up mock property manager to return the desired property values. |
| 91 properties_ = new MockPropertyManager( |
| 92 PropertyManager.ProjectPlatformType.NaCl, |
| 93 delegate(string page, string name) |
| 94 { |
| 95 switch (page) |
| 96 { |
| 97 case "ConfigurationGeneral": |
| 98 switch (name) |
| 99 { |
| 100 case "VSNaClSDKRoot": return System.Environment.GetEnvironmentVa
riable( |
| 101 NativeClientVSAddIn.Strings.SDKPathEnvironmentVariable); |
| 102 case "NaClIrtPath": return @"fake\Irt\Path"; |
| 103 case "NaClManifestPath": return string.Empty; |
| 104 case "PlatformToolset": return "win_x86_newlib"; |
| 105 } |
| 106 |
| 107 break; |
| 108 case "Property": |
| 109 switch (name) |
| 110 { |
| 111 case "ProjectDirectory": return TestContext.DeploymentDirectory; |
| 112 case "PluginAssembly": return @"fake\Assembly\String"; |
| 113 } |
| 114 |
| 115 break; |
| 116 } |
| 117 |
| 118 return null; |
| 119 }, |
| 120 null); |
| 121 } |
| 122 |
| 123 /// <summary> |
| 124 /// This is run after each test to clean up things created in TestSetup(). |
| 125 /// </summary> |
| 126 [TestCleanup] |
| 127 public void TestCleanup() |
| 128 { |
| 129 TestUtilities.CleanUpVisualStudioInstance(dte_); |
| 130 } |
| 131 |
| 132 /// <summary> |
| 133 /// A test for the constructor. |
| 134 /// </summary> |
| 135 [TestMethod] |
| 136 public void PluginDebuggerGDBConstructorTest() |
| 137 { |
| 138 // Check that a null dte fails. |
| 139 try |
| 140 { |
| 141 PluginDebuggerBase nullDte = new PluginDebuggerGDB(null, properties_); |
| 142 Assert.Fail("Using null DTE instance did not throw exception"); |
| 143 } |
| 144 catch (ArgumentNullException) |
| 145 { |
| 146 // This is expected for a correct implementation. |
| 147 } |
| 148 catch |
| 149 { |
| 150 Assert.Fail("Using null DTE instance threw something other than Argument
NullException"); |
| 151 } |
| 152 |
| 153 // Check that a null PropertyManager fails. |
| 154 try |
| 155 { |
| 156 PluginDebuggerBase nullDte = new PluginDebuggerGDB(dte_, null); |
| 157 Assert.Fail("Using null property manager did not throw exception"); |
| 158 } |
| 159 catch (ArgumentNullException) |
| 160 { |
| 161 // This is expected for a correct implementation. |
| 162 } |
| 163 catch |
| 164 { |
| 165 Assert.Fail("Using null property manager threw something other than Argu
mentNullException"); |
| 166 } |
| 167 } |
| 168 |
| 169 /// <summary> |
| 170 /// Tests that a plugin can be found. |
| 171 /// </summary> |
| 172 [TestMethod] |
| 173 [DeploymentItem("NativeClientVSAddIn.dll")] |
| 174 public void FindAndAttachToNaClPluginTest() |
| 175 { |
| 176 MockProcessSearcher processResults = new MockProcessSearcher(); |
| 177 |
| 178 using (PluginDebuggerGDB target = new PluginDebuggerGDB(dte_, properties_)
) |
| 179 { |
| 180 PluginDebuggerBase_Accessor targetBase = new PluginDebuggerBase_Accessor
( |
| 181 new PrivateObject(target, new PrivateType(typeof(PluginDebuggerBase)
))); |
| 182 targetBase.debuggedChromeMainProcess_ = System.Diagnostics.Process.GetCu
rrentProcess(); |
| 183 |
| 184 uint currentProcId = (uint)targetBase.debuggedChromeMainProcess_.Id; |
| 185 |
| 186 // Target nacl process flag. |
| 187 string naclCommandLine = Strings.NaClLoaderFlag; |
| 188 |
| 189 // Fake the list of processes on the system. |
| 190 processResults.ProcessList.Add( |
| 191 new ProcessInfo( |
| 192 currentProcId, |
| 193 currentProcId, |
| 194 string.Empty, |
| 195 Strings.NaClDebugFlag, |
| 196 Strings.ChromeProcessName)); |
| 197 processResults.ProcessList.Add( |
| 198 new ProcessInfo(1, currentProcId, string.Empty, string.Empty, "MyPar
entProcess")); |
| 199 processResults.ProcessList.Add( |
| 200 new ProcessInfo(11, 1, string.Empty, naclCommandLine, Strings.NaClPr
ocessName)); |
| 201 |
| 202 // This is missing some relevant command line args, should not be attach
ed to. |
| 203 processResults.ProcessList.Add( |
| 204 new ProcessInfo(13, 1, string.Empty, string.Empty, Strings.NaClProce
ssName)); |
| 205 |
| 206 // This doesn't have chrome process as their parent, so they should not
be attached to. |
| 207 processResults.ProcessList.Add( |
| 208 new ProcessInfo(15, 15, string.Empty, naclCommandLine, Strings.NaClP
rocessName)); |
| 209 |
| 210 // Set the private value to the mock object (can't use accessor since no
valid cast). |
| 211 FieldInfo processSearcherField = typeof(PluginDebuggerBase).GetField( |
| 212 "processSearcher_", |
| 213 BindingFlags.NonPublic | BindingFlags.Instance); |
| 214 processSearcherField.SetValue(targetBase.Target, processResults); |
| 215 |
| 216 // Test that the correct processes are attached to. |
| 217 bool goodNaCl = false; |
| 218 var handler = new EventHandler<NativeClientVSAddIn.PluginDebuggerBase.Pl
uginFoundEventArgs>( |
| 219 delegate(object unused, NativeClientVSAddIn.PluginDebuggerBase.PluginF
oundEventArgs args) |
| 220 { |
| 221 switch (args.ProcessID) |
| 222 { |
| 223 case 11: |
| 224 if (goodNaCl) |
| 225 { |
| 226 Assert.Fail("Should not attach twice to same nacl process"); |
| 227 } |
| 228 |
| 229 goodNaCl = true; |
| 230 break; |
| 231 case 13: |
| 232 Assert.Fail("Should not attach to nacl process with bad args"); |
| 233 break; |
| 234 case 15: |
| 235 Assert.Fail("Should not attach to nacl process that is not " |
| 236 + "descendant of Visual Studio"); |
| 237 break; |
| 238 default: |
| 239 Assert.Fail("Should not attach to non-pepper/non-nacl process"); |
| 240 break; |
| 241 } |
| 242 }); |
| 243 |
| 244 target.PluginFoundEvent += handler; |
| 245 target.FindAndAttachToPlugin(null, null); |
| 246 target.PluginFoundEvent -= handler; |
| 247 |
| 248 Assert.IsTrue(goodNaCl, "Failed to attach to NaCl process"); |
| 249 } |
| 250 } |
| 251 |
| 252 /// <summary> |
| 253 /// A test for Attach. Implicitly tests CleanUpGDBProcess(). |
| 254 /// </summary> |
| 255 [TestMethod] |
| 256 [DeploymentItem("NativeClientVSAddIn.dll")] |
| 257 public void AttachNaClGDBTest() |
| 258 { |
| 259 PluginDebuggerGDB_Accessor target = new PluginDebuggerGDB_Accessor(dte_, p
roperties_); |
| 260 |
| 261 string existingGDB = "AttachNaClGDBTest_existingGDB"; |
| 262 try |
| 263 { |
| 264 target.gdbProcess_ = TestUtilities.StartProcessForKilling(existingGDB, 2
0); |
| 265 string existingInitFileName = Path.GetTempFileName(); |
| 266 target.gdbInitFileName_ = existingInitFileName; |
| 267 |
| 268 // Visual studio won't allow adding a breakpoint unless it is associated
with |
| 269 // an existing file and valid line number, so use BlankValidSolution. |
| 270 dte_.Solution.Open(naclSolution); |
| 271 string fileName = "main.cpp"; |
| 272 string functionName = "NaClProjectInstance::HandleMessage"; |
| 273 int lineNumber = 39; |
| 274 dte_.Debugger.Breakpoints.Add(Function: functionName); |
| 275 dte_.Debugger.Breakpoints.Add(Line: lineNumber, File: fileName); |
| 276 |
| 277 target.Attach(null, new PluginDebuggerBase.PluginFoundEventArgs(0)); |
| 278 |
| 279 Assert.IsTrue(File.Exists(target.gdbInitFileName_), "Init file not writt
en"); |
| 280 |
| 281 var gdbCommands = new List<string>(File.ReadAllLines(target.gdbInitFileN
ame_)); |
| 282 |
| 283 // Validate that the commands contain what we specified. |
| 284 // The syntax itself is not validated since this add-in is not responsib
le for |
| 285 // the syntax and it could change. |
| 286 Assert.IsTrue( |
| 287 gdbCommands.Exists(s => s.Contains(fileName) && s.Contains(lineNumbe
r.ToString())), |
| 288 "Line breakpoint not properly set"); |
| 289 Assert.IsTrue( |
| 290 gdbCommands.Exists(s => s.Contains(functionName)), |
| 291 "Function breakpoint not properly set"); |
| 292 |
| 293 // Note fake assembly string should be double escaped when passed to gdb
. |
| 294 Assert.IsTrue( |
| 295 gdbCommands.Exists(s => s.Contains(functionName)), |
| 296 @"fake\\Assembly\\String"); |
| 297 |
| 298 // Check that the pre-existing gdb process was killed and its init file
cleaned up. |
| 299 Assert.IsFalse( |
| 300 TestUtilities.DoesProcessExist("python.exe", existingGDB), |
| 301 "Failed to kill existing GDB process"); |
| 302 Assert.IsFalse( |
| 303 File.Exists(existingInitFileName), |
| 304 "Failed to delete existing temp gdb init file"); |
| 305 } |
| 306 finally |
| 307 { |
| 308 if (dte_.Debugger.Breakpoints != null) |
| 309 { |
| 310 // Remove all breakpoints. |
| 311 foreach (EnvDTE.Breakpoint bp in dte_.Debugger.Breakpoints) |
| 312 { |
| 313 bp.Delete(); |
| 314 } |
| 315 } |
| 316 |
| 317 // Clean up file if not erased. |
| 318 if (!string.IsNullOrEmpty(target.gdbInitFileName_) && File.Exists(target
.gdbInitFileName_)) |
| 319 { |
| 320 File.Delete(target.gdbInitFileName_); |
| 321 } |
| 322 |
| 323 // Kill the gdb process if not killed. |
| 324 if (target.gdbProcess_ != null && !target.gdbProcess_.HasExited) |
| 325 { |
| 326 target.gdbProcess_.Kill(); |
| 327 target.gdbProcess_.Dispose(); |
| 328 } |
| 329 } |
| 330 } |
| 331 |
| 332 /// <summary> |
| 333 /// A test for Dispose. Implicitly tests CleanUpGDBProcess(). |
| 334 /// </summary> |
| 335 [TestMethod] |
| 336 [DeploymentItem("NativeClientVSAddIn.dll")] |
| 337 public void DisposeTest() |
| 338 { |
| 339 PluginDebuggerGDB_Accessor target = new PluginDebuggerGDB_Accessor(dte_, p
roperties_); |
| 340 |
| 341 string existingGDB = "DisposeTest_GDB"; |
| 342 try |
| 343 { |
| 344 target.gdbProcess_ = TestUtilities.StartProcessForKilling(existingGDB, 2
0); |
| 345 string existingInitFileName = Path.GetTempFileName(); |
| 346 target.gdbInitFileName_ = existingInitFileName; |
| 347 |
| 348 target.Dispose(); |
| 349 |
| 350 // Check that the pre-existing gdb process was killed and its init file
cleaned up. |
| 351 Assert.IsFalse( |
| 352 TestUtilities.DoesProcessExist("python.exe", existingGDB), |
| 353 "Failed to kill existing GDB process"); |
| 354 Assert.IsFalse( |
| 355 File.Exists(existingInitFileName), |
| 356 "Failed to delete existing temp gdb init file"); |
| 357 } |
| 358 finally |
| 359 { |
| 360 // Clean up file if not erased. |
| 361 if (!string.IsNullOrEmpty(target.gdbInitFileName_) && File.Exists(target
.gdbInitFileName_)) |
| 362 { |
| 363 File.Delete(target.gdbInitFileName_); |
| 364 } |
| 365 |
| 366 // Kill the gdb process if not killed. |
| 367 if (target.gdbProcess_ != null && !target.gdbProcess_.HasExited) |
| 368 { |
| 369 target.gdbProcess_.Kill(); |
| 370 target.gdbProcess_.Dispose(); |
| 371 } |
| 372 } |
| 373 } |
| 374 |
| 375 /// <summary> |
| 376 /// A test for IsPluginProcess. |
| 377 /// </summary> |
| 378 [TestMethod] |
| 379 [DeploymentItem("NativeClientVSAddIn.dll")] |
| 380 public void IsNaClPluginProcessTest() |
| 381 { |
| 382 PluginDebuggerGDB_Accessor target = new PluginDebuggerGDB_Accessor(dte_, p
roperties_); |
| 383 |
| 384 ProcessInfo badProc = new ProcessInfo( |
| 385 1, 1, string.Empty, Strings.ChromeRendererFlag, Strings.NaClProcessNam
e); |
| 386 ProcessInfo goodProc = new ProcessInfo( |
| 387 1, 1, string.Empty, Strings.NaClLoaderFlag, Strings.NaClProcessName); |
| 388 |
| 389 string goodMainChromeFlags = Strings.NaClDebugFlag; |
| 390 string badMainChromeFlags = string.Format( |
| 391 Strings.PepperProcessPluginFlagFormat, target.pluginAssembly_); |
| 392 |
| 393 Assert.IsTrue(target.IsPluginProcess(goodProc, goodMainChromeFlags)); |
| 394 Assert.IsFalse(target.IsPluginProcess(goodProc, badMainChromeFlags)); |
| 395 Assert.IsFalse(target.IsPluginProcess(badProc, goodMainChromeFlags)); |
| 396 } |
| 397 } |
| 398 } |
OLD | NEW |