|
1 |
| -namespace StackExchange.Profiling.Tests |
| 1 | +using System.Collections; |
| 2 | +using System.Data.Common; |
| 3 | + |
| 4 | +namespace StackExchange.Profiling.Tests |
2 | 5 | {
|
3 | 6 | using System;
|
4 | 7 | using System.Collections.Generic;
|
@@ -55,14 +58,16 @@ public static IDisposable GetRequest(string url = DefaultRequestUrl, bool startA
|
55 | 58 | }
|
56 | 59 |
|
57 | 60 | /// <summary>
|
58 |
| - /// Returns a profiler for <paramref name="url"/>. Only child steps will take any time, e.g. when <paramref name="childDepth"/> is 0, the |
59 |
| - /// resulting <see cref="MiniProfiler.DurationMilliseconds"/> will be zero. |
| 61 | + /// Returns a profiler for <paramref name="url"/>. Only child steps will take any time, |
| 62 | + /// e.g. when <paramref name="childDepth"/> is 0, the resulting <see cref="MiniProfiler.DurationMilliseconds"/> will be zero. |
60 | 63 | /// </summary>
|
61 |
| - /// <param name="url">the url</param> |
62 | 64 | /// <param name="childDepth">number of levels of child steps underneath result's <see cref="MiniProfiler.Root"/></param>
|
63 | 65 | /// <param name="stepsEachTakeMilliseconds">Amount of time each step will "do work for" in each step</param>
|
64 | 66 | /// <returns>the mini profiler</returns>
|
65 |
| - public static MiniProfiler GetProfiler(string url = DefaultRequestUrl, int childDepth = 0, int stepsEachTakeMilliseconds = StepTimeMilliseconds) |
| 67 | + public static MiniProfiler GetProfiler( |
| 68 | + string url = DefaultRequestUrl, |
| 69 | + int childDepth = 0, |
| 70 | + int stepsEachTakeMilliseconds = StepTimeMilliseconds) |
66 | 71 | {
|
67 | 72 | MiniProfiler result = null;
|
68 | 73 | Action step = null;
|
@@ -104,10 +109,6 @@ public static void IncrementStopwatch(int milliseconds = StepTimeMilliseconds)
|
104 | 109 | /// <summary>
|
105 | 110 | /// Creates a <c>SqlCe</c> file database named after <typeparamref name="T"/>, returning the connection string to the database.
|
106 | 111 | /// </summary>
|
107 |
| - /// <typeparam name="T">the database type</typeparam> |
108 |
| - /// <param name="deleteIfExists">delete if exists.</param> |
109 |
| - /// <param name="sqlToExecute">The SQL To execute.</param> |
110 |
| - /// <returns>a string containing the SQL database</returns> |
111 | 112 | public static string CreateSqlCeDatabase<T>(bool deleteIfExists = false, IEnumerable<string> sqlToExecute = null)
|
112 | 113 | {
|
113 | 114 | var filename = GetSqlCeFileNameFor<T>();
|
@@ -159,91 +160,116 @@ public static SqlCeConnection GetOpenSqlCeConnection<T>()
|
159 | 160 | return result;
|
160 | 161 | }
|
161 | 162 |
|
| 163 | + /// <summary> |
| 164 | + /// Returns an open connection that will have its queries profiled. |
| 165 | + /// </summary> |
| 166 | + public static DbConnection GetSqliteConnection() |
| 167 | + { |
| 168 | + DbConnection cnn = new System.Data.SQLite.SQLiteConnection("Data Source=:memory:"); |
| 169 | + |
| 170 | + // to get profiling times, we have to wrap whatever connection we're using in a ProfiledDbConnection |
| 171 | + // when MiniProfiler.Current is null, this connection will not record any database timings |
| 172 | + if (MiniProfiler.Current != null) |
| 173 | + { |
| 174 | + cnn = new Data.ProfiledDbConnection(cnn, MiniProfiler.Current); |
| 175 | + } |
| 176 | + |
| 177 | + cnn.Open(); |
| 178 | + return cnn; |
| 179 | + } |
| 180 | + |
162 | 181 | /// <summary>
|
163 | 182 | /// The assert profilers are equal.
|
164 | 183 | /// </summary>
|
165 |
| - /// <param name="mp1">the first profiler.</param> |
166 |
| - /// <param name="mp2">The second profiler.</param> |
167 | 184 | public void AssertProfilersAreEqual(MiniProfiler mp1, MiniProfiler mp2)
|
168 | 185 | {
|
169 | 186 | Assert.AreEqual(mp1, mp2);
|
170 | 187 | AssertPublicPropertiesAreEqual(mp1, mp2);
|
| 188 | + AssertTimingsAreEqualAndRecurse(mp1.Root, mp2.Root); |
| 189 | + } |
171 | 190 |
|
172 |
| - var timings1 = mp1.GetTimingHierarchy().ToList(); |
173 |
| - var timings2 = mp2.GetTimingHierarchy().ToList(); |
| 191 | + protected void AssertTimingsAreEqualAndRecurse(Timing t1, Timing t2) |
| 192 | + { |
| 193 | + Console.WriteLine(); |
| 194 | + Console.WriteLine(); |
174 | 195 |
|
175 |
| - Assert.That(timings1.Count == timings2.Count); |
176 |
| - for (int i = 0; i < timings1.Count; i++) |
177 |
| - { |
178 |
| - var t1 = timings1[i]; |
179 |
| - var t2 = timings2[i]; |
180 |
| - Assert.AreEqual(t1, t2); |
| 196 | + Assert.NotNull(t1); |
| 197 | + Assert.NotNull(t2); |
181 | 198 |
|
182 |
| - Console.WriteLine(); |
183 |
| - AssertPublicPropertiesAreEqual(t1, t2); |
| 199 | + AssertPublicPropertiesAreEqual(t1, t2); |
184 | 200 |
|
185 |
| - //if (!t1.HasSqlTimings && !t2.HasSqlTimings) continue; |
| 201 | + if (t1.CustomTimings != null || t2.CustomTimings != null) |
| 202 | + { |
| 203 | + Assert.NotNull(t1.CustomTimings); |
| 204 | + Assert.NotNull(t2.CustomTimings); |
186 | 205 |
|
187 |
| - //Assert.NotNull(t1.SqlTimings); |
188 |
| - //Assert.NotNull(t2.SqlTimings); |
| 206 | + Assert.AreEqual(t1.CustomTimings.Count, t2.CustomTimings.Count); |
189 | 207 |
|
190 |
| - //for (int j = 0; j < t1.SqlTimings.Count; j++) |
191 |
| - //{ |
192 |
| - // var s1 = t1.SqlTimings[j]; |
193 |
| - // var s2 = t2.SqlTimings[j]; |
194 |
| - // Assert.AreEqual(s1, s2); |
| 208 | + foreach (var pair1 in t1.CustomTimings) |
| 209 | + { |
| 210 | + Console.WriteLine(); |
195 | 211 |
|
196 |
| - // Console.WriteLine(); |
197 |
| - // AssertPublicPropertiesAreEqual(s1, s2); |
| 212 | + var ct1 = pair1.Value; |
| 213 | + List<CustomTiming> ct2; |
| 214 | + Assert.True(t2.CustomTimings.TryGetValue(pair1.Key, out ct2)); |
198 | 215 |
|
199 |
| - // if (s1.Parameters == null && s2.Parameters == null) continue; |
| 216 | + for (int i = 0; i < ct1.Count; i++) |
| 217 | + { |
| 218 | + AssertPublicPropertiesAreEqual(ct1[i], ct2[i]); |
| 219 | + } |
| 220 | + } |
| 221 | + } |
200 | 222 |
|
201 |
| - // Assert.NotNull(s1.Parameters); |
202 |
| - // Assert.NotNull(s2.Parameters); |
| 223 | + if (t1.Children != null || t2.Children != null) |
| 224 | + { |
| 225 | + Assert.NotNull(t1.Children); |
| 226 | + Assert.NotNull(t2.Children); |
203 | 227 |
|
204 |
| - // for (int k = 0; k < s1.Parameters.Count; k++) |
205 |
| - // { |
206 |
| - // var p1 = s1.Parameters[k]; |
207 |
| - // var p2 = s2.Parameters[k]; |
208 |
| - // Assert.AreEqual(p1, p2); |
| 228 | + Assert.AreEqual(t1.Children.Count, t2.Children.Count); |
209 | 229 |
|
210 |
| - // Console.WriteLine(); |
211 |
| - // AssertPublicPropertiesAreEqual(p1, p2); |
212 |
| - // } |
213 |
| - //} |
| 230 | + for (int i = 0; i < t1.Children.Count; i++) |
| 231 | + { |
| 232 | + AssertTimingsAreEqualAndRecurse(t1.Children[i], t2.Children[i]); |
| 233 | + } |
214 | 234 | }
|
215 | 235 | }
|
216 | 236 |
|
217 | 237 | /// <summary>
|
218 |
| - /// The assert public properties are equal. |
| 238 | + /// Doesn't handle collection properties! |
219 | 239 | /// </summary>
|
220 |
| - /// <param name="t1">first instance.</param> |
221 |
| - /// <param name="t2">second instance.</param> |
222 |
| - /// <typeparam name="T">the property type</typeparam> |
223 | 240 | protected void AssertPublicPropertiesAreEqual<T>(T t1, T t2)
|
224 | 241 | {
|
225 | 242 | Assert.NotNull(t1);
|
226 | 243 | Assert.NotNull(t2);
|
227 | 244 |
|
228 |
| - // check public properties |
| 245 | + // we'll handle any collections elsewhere |
229 | 246 | var props = from p in typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance)
|
| 247 | + where p.IsDefined(typeof(System.Runtime.Serialization.DataMemberAttribute), false) |
| 248 | + && !p.PropertyType.GetInterfaces().Any(i => i.Equals(typeof(IDictionary)) || i.Equals(typeof(IList))) |
230 | 249 | select p;
|
231 | 250 |
|
232 | 251 | foreach (var p in props)
|
233 | 252 | {
|
234 |
| - var val1 = p.GetValue(t1, null); |
235 |
| - var val2 = p.GetValue(t2, null); |
| 253 | + try |
| 254 | + { |
| 255 | + var val1 = p.GetValue(t1, null); |
| 256 | + var val2 = p.GetValue(t2, null); |
236 | 257 |
|
237 |
| - // datetimes are sometimes serialized with different precisions - just look care about the 10th of a second |
238 |
| - if (p.PropertyType == typeof(DateTime)) |
| 258 | + // datetimes are sometimes serialized with different precisions - just look care about the 10th of a second |
| 259 | + if (p.PropertyType == typeof(DateTime)) |
| 260 | + { |
| 261 | + val1 = TrimToDecisecond((DateTime)val1); |
| 262 | + val2 = TrimToDecisecond((DateTime)val2); |
| 263 | + } |
| 264 | + |
| 265 | + var name = typeof(T).Name + "." + p.Name; |
| 266 | + Assert.AreEqual(val1, val2, name + " have different values"); |
| 267 | + Console.WriteLine("{0, 50}: {1} == {2}", name, val1 ?? "<null>", val2 ?? "<null>"); |
| 268 | + } |
| 269 | + catch (Exception ex) |
239 | 270 | {
|
240 |
| - val1 = TrimToDecisecond((DateTime)val1); |
241 |
| - val2 = TrimToDecisecond((DateTime)val2); |
| 271 | + Assert.Fail("AssertPublicPropertiesAreEqual had an exception on " + p.Name + "; " + ex); |
242 | 272 | }
|
243 |
| - |
244 |
| - var name = typeof(T).Name + "." + p.Name; |
245 |
| - Assert.AreEqual(val1, val2, name + " have different values"); |
246 |
| - Console.WriteLine("{0, 50}: {1} == {2}", name, val1 ?? "<null>", val2 ?? "<null>"); |
247 | 273 | }
|
248 | 274 | }
|
249 | 275 |
|
|
0 commit comments