OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 The Native Client 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 #region | |
6 | |
7 using System.Collections.Generic; | |
8 using System.Linq; | |
9 using Google.MsAd7.BaseImpl; | |
10 using Google.NaClVsx.DebugSupport; | |
11 using Google.NaClVsx.DebugSupport.DWARF; | |
12 using Microsoft.VisualStudio; | |
13 using Microsoft.VisualStudio.Debugger.Interop; | |
14 using Microsoft.VisualStudio.TestTools.UnitTesting; | |
15 | |
16 #endregion | |
17 | |
18 namespace NaClVsx.Package_UnitTestProject { | |
19 ///<summary> | |
20 /// This is a test class for BreakpointInfoTest and is intended | |
21 /// to contain all BreakpointInfoTest Unit Tests | |
22 ///</summary> | |
23 [TestClass] | |
24 public class BreakpointInfoTest { | |
25 ///<summary> | |
26 /// Gets or sets the test context which provides | |
27 /// information about and functionality for the current test run. | |
28 ///</summary> | |
29 public TestContext TestContext { get; set; } | |
30 | |
31 #region Additional test attributes | |
32 | |
33 #endregion | |
34 | |
35 /// <summary> | |
36 /// This test checks to make sure that an error is returned if a bogus lin
e number is | |
37 /// requested. | |
38 /// </summary> | |
39 [TestMethod] | |
40 public void GetBindErrorsTestCritical() { | |
41 var expectedErrorTypes = new List<enum_BP_ERROR_TYPE>(); | |
42 const enum_BP_ERROR_TYPE kExpectedErrorType = enum_BP_ERROR_TYPE.BPET_GENE
RAL_ERROR; | |
43 expectedErrorTypes.Add(kExpectedErrorType); | |
44 TestGetBindErrors(100000000, VSConstants.S_FALSE, expectedErrorTypes); | |
45 } | |
46 | |
47 /// <summary> | |
48 /// A test for the case where there are no bind errors. | |
49 /// </summary> | |
50 [TestMethod] | |
51 public void GetBindErrorsTestNoErrors() { | |
52 TestGetBindErrors( | |
53 NaClPackageTestUtils.kMainStartRow, | |
54 VSConstants.S_OK, | |
55 new List<enum_BP_ERROR_TYPE>()); | |
56 } | |
57 | |
58 /// <summary> | |
59 /// This test checks what happens when a breakpoint is requested on a line
that does not | |
60 /// contain any code. The expected outcome is to have a breakpoint on the
next line with | |
61 /// code. | |
62 /// </summary> | |
63 [TestMethod] | |
64 public void GetBindErrorsTestNonCritical() { | |
65 var expectedErrorTypes = new List<enum_BP_ERROR_TYPE>(); | |
66 const enum_BP_ERROR_TYPE kExpectedResolutionType = | |
67 enum_BP_ERROR_TYPE.BPET_SEV_LOW | enum_BP_ERROR_TYPE.BPET_TYPE_WARNING
; | |
68 expectedErrorTypes.Add(kExpectedResolutionType); | |
69 TestGetBindErrors( | |
70 NaClPackageTestUtils.kBlankLineInPrintLoop, | |
71 BreakpointInfo.kBindErrorWarning, | |
72 expectedErrorTypes); | |
73 } | |
74 | |
75 ///<summary> | |
76 /// A test for GetBindAddresses at the end of a function. | |
77 ///</summary> | |
78 [TestMethod] | |
79 public void GetBindAddressesTestEndOfMain() { | |
80 TestGetBindAddresses(NaClPackageTestUtils.kMainEndRow, 1); | |
81 } | |
82 | |
83 ///<summary> | |
84 /// A test for GetBindAddresses in the body of a function. | |
85 ///</summary> | |
86 [TestMethod] | |
87 public void GetBindAddressesTestStartOfMain() { | |
88 TestGetBindAddresses(NaClPackageTestUtils.kMainStartRow, 1); | |
89 } | |
90 | |
91 /// <summary> | |
92 /// This tests to make sure that Breakpoint Info will work inside of a | |
93 /// function. | |
94 /// </summary> | |
95 [TestMethod] | |
96 public void GetBreakpointLocationsAtStartOfMainTest() { | |
97 var expectedSymbols = new List<string> { | |
98 "x", | |
99 "y", | |
100 "test_string", | |
101 "argc", | |
102 "argv", | |
103 "g_GlobalData" | |
104 }; | |
105 | |
106 TestLoopCCLocation( | |
107 NaClPackageTestUtils.kMainStartRow, | |
108 "main", | |
109 expectedSymbols); | |
110 } | |
111 | |
112 /// <summary> | |
113 /// This tests to make sure that Breakpoint Info will work at the end of a | |
114 /// scope. | |
115 /// </summary> | |
116 [TestMethod] | |
117 public void GetBreakpointLocationsAtEndOfMainTest() { | |
118 var expectedSymbols = new List<string> { | |
119 "argc", | |
120 "argv", | |
121 "g_GlobalData" | |
122 }; | |
123 | |
124 TestLoopCCLocation( | |
125 NaClPackageTestUtils.kMainEndRow, | |
126 "main", | |
127 expectedSymbols); | |
128 } | |
129 | |
130 // None of our tests should modify the SymbolProvider, so it should be OK | |
131 // to instantiate it once. This saves seconds for each instantiation. | |
132 | |
133 #region Private Implementation | |
134 | |
135 NaClSymbolProvider symbolProvider_; | |
136 | |
137 #endregion | |
138 | |
139 #region Private Implementation | |
140 | |
141 /// <summary> | |
142 /// Sets up the SymbolProvider. This function only has an effect the | |
143 /// first time it is called and initializes symbolProvider_. If a test | |
144 /// modifies the contents of SymbolProvider or of the SymbolDB, then it | |
145 /// should use its own instances of both. | |
146 /// </summary> | |
147 private void InitializeSymbolProvider() { | |
148 if (null == symbolProvider_) { | |
149 symbolProvider_ = NaClPackageTestUtils.LoadLoopNexe(); | |
150 Assert.IsNotNull(symbolProvider_); | |
151 } | |
152 } | |
153 | |
154 /// <summary> | |
155 /// Runs BreakpointInfo.GetBindAddresses for the given location in loop.cc | |
156 /// and verifies that the expected number of addresses was returned. | |
157 /// While this function could work for locations at which no bind address | |
158 /// was expected, it does not support calls that would result in an error. | |
159 /// Those should be tested separately. | |
160 /// </summary> | |
161 /// <param name = "lineToTest"> | |
162 /// The line of code to test. | |
163 /// </param> | |
164 /// <param name = "expectedBindAddressCount"> | |
165 /// The number of addresses to expect (Usually 1) | |
166 /// </param> | |
167 private void TestGetBindAddresses(uint lineToTest, | |
168 int expectedBindAddressCount) { | |
169 InitializeSymbolProvider(); | |
170 var symbolProviderPrivates = new PrivateObject(symbolProvider_); | |
171 var database = symbolProviderPrivates.GetField("db_") as SymbolDatabase; | |
172 var target = new BreakpointInfo(database, symbolProvider_); | |
173 var position = new DocumentPosition( | |
174 NaClPackageTestUtils.GetLoopCCPath(), | |
175 lineToTest); | |
176 IEnumerable<ulong> outAddresses; | |
177 IEnumDebugErrorBreakpoints2 outErrorEnum; | |
178 const int kExpected = VSConstants.S_OK; | |
179 var actual = target.GetBindAddresses( | |
180 position, out outAddresses, out outErrorEnum); | |
181 Assert.AreEqual(expectedBindAddressCount, outAddresses.Count()); | |
182 uint errorCount; | |
183 outErrorEnum.GetCount(out errorCount); | |
184 Assert.AreEqual((uint) 0, errorCount); | |
185 Assert.AreEqual(kExpected, actual); | |
186 } | |
187 | |
188 /// <summary> | |
189 /// Runs BreakpointInfo.GetBindErrors for the given location in loop.cc an
d verifies that | |
190 /// the expected error types were returned. | |
191 /// </summary> | |
192 /// <param name = "lineToTest">The line of code to test.</param> | |
193 /// <param name = "expectedReturnCode">What return code to expect from GetBi
ndErrors()</param> | |
194 /// <param name = "expectedTypes">What error resolutions are expected to res
ult from this | |
195 /// call.</param> | |
196 private void TestGetBindErrors(uint lineToTest, | |
197 int expectedReturnCode, | |
198 List<enum_BP_ERROR_TYPE> expectedTypes) { | |
199 InitializeSymbolProvider(); | |
200 var symbolProviderPrivates = new PrivateObject(symbolProvider_); | |
201 var database = symbolProviderPrivates.GetField("db_") as SymbolDatabase; | |
202 var target = new BreakpointInfo(database, symbolProvider_); | |
203 var position = new DocumentPosition( | |
204 NaClPackageTestUtils.GetLoopCCPath(), | |
205 lineToTest); | |
206 IEnumDebugErrorBreakpoints2 outErrorEnum; | |
207 var actualReturnCode = target.GetBindErrors( | |
208 position, out outErrorEnum); | |
209 Assert.AreEqual(expectedReturnCode, actualReturnCode); | |
210 uint errorCount; | |
211 outErrorEnum.GetCount(out errorCount); | |
212 Assert.AreEqual((uint) expectedTypes.Count(), errorCount); | |
213 if (0 != expectedTypes.Count()) { | |
214 var errorsFetched = 0u; | |
215 var errorBreakpointArray = new IDebugErrorBreakpoint2[errorCount]; | |
216 outErrorEnum.Next(errorCount, errorBreakpointArray, ref errorsFetched); | |
217 Assert.AreEqual(errorsFetched, errorCount); | |
218 Assert.AreEqual(expectedTypes.Count(), errorBreakpointArray.Length); | |
219 for (var i = 0; i < expectedTypes.Count(); ++i) { | |
220 IDebugErrorBreakpointResolution2 actualBreakpointResolution; | |
221 errorBreakpointArray[i].GetBreakpointResolution(out actualBreakpointRe
solution); | |
222 Assert.AreEqual( | |
223 expectedTypes[i], | |
224 ((ErrorBreakpointResolution) actualBreakpointResolution).Type); | |
225 } | |
226 } | |
227 } | |
228 | |
229 /// <summary> | |
230 /// Tests the call to GetBreakpointLocations individually, using a | |
231 /// private object. For this test, we depend on SymbolProvider's test | |
232 /// suite passing. If it does, then we can validate a source code | |
233 /// location by using the SymbolProvider to get it's address, and then | |
234 /// to get its position. If the position we end up with is the same one | |
235 /// we started at, then the test passes. | |
236 /// </summary> | |
237 /// <param name = "lineToTest"> | |
238 /// The line at which to check for breakpoint info. | |
239 /// </param> | |
240 /// <param name = "expectedFunctionName"> | |
241 /// The function in which the breakpoint is expected to occur.</param> | |
242 /// <param name = "expectedSymbols"> | |
243 /// A container of Symbols that should be expected to exist at the locatio
n of the breakpoint. | |
244 /// </param> | |
245 private void TestLoopCCLocation(uint lineToTest, | |
246 string expectedFunctionName, | |
247 IEnumerable<string> expectedSymbols) { | |
248 InitializeSymbolProvider(); | |
249 var symbolProviderPrivates = new PrivateObject(symbolProvider_); | |
250 var database = symbolProviderPrivates.GetField("db_") as SymbolDatabase; | |
251 Assert.IsNotNull(database); | |
252 var breakpointInfo = new BreakpointInfo(database, symbolProvider_); | |
253 var breakpointInfoPrivates = new PrivateObject(breakpointInfo); | |
254 | |
255 var files = database.SourceFilesByFilename["loop.cc"]; | |
256 var msvcPosition = new DocumentPosition( | |
257 NaClPackageTestUtils.GetLoopCCPath(), | |
258 lineToTest); | |
259 // Normally GetBindAddresses handles the conversion from the MSVC Line | |
260 // to the DWARF line position, but we're bypassing the public interface, | |
261 // so we have to do it ourselves. | |
262 var sourceLocations = | |
263 (IEnumerable<SymbolDatabase.SourceLocation>) | |
264 breakpointInfoPrivates.Invoke( | |
265 "GetBreakpointLocations", | |
266 files.First(), | |
267 NaClSymbolProvider.GetDwarfLineIndex(msvcPosition.BeginPos.dwLine)
); | |
268 Assert.AreEqual(1, sourceLocations.Count()); | |
269 | |
270 var breakpointLocation = sourceLocations.First(); | |
271 var breakpointAddress = breakpointLocation.StartAddress + | |
272 symbolProvider_.BaseAddress; | |
273 var function = | |
274 symbolProvider_.FunctionFromAddress( | |
275 breakpointLocation.StartAddress + | |
276 symbolProvider_.BaseAddress); | |
277 var breakpointPosition = | |
278 symbolProvider_.PositionFromAddress(breakpointAddress); | |
279 Assert.AreEqual(expectedFunctionName, function.Name); | |
280 Assert.AreEqual( | |
281 msvcPosition.BeginPos.dwLine, breakpointPosition.BeginPos.dwLine); | |
282 | |
283 var symbols = symbolProvider_.GetSymbolsInScope(breakpointAddress); | |
284 Assert.AreEqual(expectedSymbols.Count(), symbols.Count()); | |
285 | |
286 foreach (var symbol in symbols) { | |
287 Assert.IsTrue(expectedSymbols.Contains(symbol.Name)); | |
288 } | |
289 } | |
290 | |
291 #endregion | |
292 } | |
293 } | |
OLD | NEW |