void Request_profile_baseline(FunctionIDCollection functionIds, ThreadIDCollection threadIds, out Int32 hr) { var snapshot = NativeMethods.GetProfileWithRelease(out hr); Assert.GreaterOrEqual(hr, 0); Assert.IsNotNull(snapshot, "snapshot is null"); Assert.Greater(snapshot.Length, 0, "snapshot.Length count is <= 0"); foreach (var snap in snapshot) { //GetSnapshot will never return a null for the FunctionIDs Assert.IsNotNull(snap.FunctionIDs, "snapshot has a null list of function ids"); Assert.AreNotEqual(snap.ThreadId, IntPtr.Zero, "ThreadId should be non-zero"); if (snap.ThreadId != UIntPtr.Zero) { threadIds?.Add(snap.ThreadId); } if (snap.ErrorCode < 0) { Assert.AreEqual(snap.FunctionIDs.Length, 0, "non empty list of function ids was return with an error code."); } else { Assert.AreNotEqual(snap.FunctionIDs.Length, 0, "empty list of function ids was return with an successful error code."); functionIds?.AddRange(snap.FunctionIDs); } } }
public void RequestProfile_VerifyThreadIDs() { //create a number of thread that recurses to a specified depth and block on a ManualResetEvent... this thread should save their threadids (GetCurrentExecutionEngineThreadId) //GetSnapshot on this thread //Set ManualResetEvent and allow the thread/task to complete/terminate //verify that all of the recurse thread ids are in the snapshot //call ShutdownThreadProfiler. using (var RecurseEvent = new ManualResetEventSlim(false)) { const int ThreadsToCreate = 10; const int FramesPerThread = 1; int threadsWaiting = 0; var RecurseThreadIds = new ConcurrentBag <UIntPtr>(); RecurseEvent.Reset(); Thread[] threads = new Thread[ThreadsToCreate]; for (int i = 0; i != threads.Length; ++i) { threads[i] = new Thread(() => RecurseFunc(FramesPerThread, ref threadsWaiting, RecurseThreadIds, RecurseEvent), 4096 * 16) { IsBackground = true }; threads[i].Start(); } while (threadsWaiting != ThreadsToCreate) { Thread.Yield(); } var tidfidmap = new ThreadIDFunctionIDMap(); Request_profile_baseline(tidfidmap, out Int32 hr); //free all of the recurse threads to terminate RecurseEvent.Set(); for (int i = 0; i != threads.Length; ++i) { threads[i].Join(); threads[i] = null; } CollectionAssert.IsSubsetOf(RecurseThreadIds, tidfidmap.Keys); var fids = new FunctionIDCollection(); foreach (var pr in tidfidmap) { fids.AddRange(pr.Value); } var FidTypeMethodNames = Request_function_names_baseline(fids); Assert.IsNotNull(FidTypeMethodNames); Assert.Greater(FidTypeMethodNames.Length, 0); foreach (var tid in RecurseThreadIds) { int matchingMethods = 0; foreach (var fid in tidfidmap[tid]) { foreach (var ftm in FidTypeMethodNames) { if (ftm.FunctionID == fid) { if (ftm.MethodName.Equals("RecurseFunc")) { ++matchingMethods; } break; } } } Assert.AreEqual(matchingMethods, FramesPerThread); } NativeMethods.ShutdownThreadProfiler(); } }