/// <summary> /// /// </summary> /// <param name="TestNameOrTestContext">When running from MSTest, the TestContext can be used to get TestName as well as various other properties. When run from VSix, the compiled code test name /// When run from command line there will be no TestContext</param> ///<param name="stressUtilOptions">Set of options to use</param> /// <param name="sampleType"></param> public MeasurementHolder(object TestNameOrTestContext, StressUtilOptions stressUtilOptions, SampleType sampleType) { if (TestNameOrTestContext is TestContextWrapper) { this.testContext = TestNameOrTestContext as TestContextWrapper; this.TestName = testContext.TestName; this.testContext.Properties[StressUtil.PropNameListFileResults] = lstFileResults; } else { this.TestName = TestNameOrTestContext as string; } this.stressUtilOptions = stressUtilOptions; this.sampleType = sampleType; foreach (var entry in stressUtilOptions.lstPerfCountersToUse) { measurements[entry.perfCounterType] = new List <uint>(); } IsMeasuringCurrentProcess = LstPerfCounterData[0].ProcToMonitor.Id == Process.GetCurrentProcess().Id; }
/// <summary> /// if we're being called from a test, pass the test in. Else being called from a dynamic asm in devenv process from vsix (in which case SetTest is not called) /// </summary> /// <returns>false if recurring</returns> internal async Task <bool> SetTest(object test) { theTest = test; var testType = test.GetType(); var methGetContext = testType.GetMethod($"get_TestContext"); if (methGetContext == null) { throw new InvalidOperationException("can't get TestContext from test. Test must have 'public TestContext TestContext { get; set; }' (perhaps inherited)"); } var val = methGetContext.Invoke(test, null); testContext = new TestContextWrapper(val); if (testContext.Properties[StressUtil.PropNameRecursionPrevention] != null) { return(false); // we're recurring } testContext.Properties[StressUtil.PropNameRecursionPrevention] = 1; _theTestMethod = testType.GetMethod(testContext.TestName); if (logger == null) { var loggerFld = testType.GetField("logger", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (loggerFld != null) { logger = loggerFld.GetValue(test) as ILogger; } if (logger == null) { logger = new Logger(testContext); } if (logger is Logger mylogger) { mylogger.LogOutputToDesktopFile = LoggerLogOutputToDestkop; } } testContext.Properties[StressUtil.PropNameLogger] = logger; /* * probs: the curdir is not empty, so results will be overwritten (might have ClrObjExplorer or WinDbg open with a result dump) * The Test*dirs are all deleted after the run. * Can use a Runsettings * <DeleteDeploymentDirectoryAfterTestRunIsComplete>False</DeleteDeploymentDirectoryAfterTestRunIsComplete> * https://docs.microsoft.com/en-us/visualstudio/test/configure-unit-tests-by-using-a-dot-runsettings-file?view=vs-2019 * CurDir = 'C:\Users\calvinh\Source\Repos\PerfGraphVSIX\TestStress\bin\Debug' * TestDeploymentDir = 'C:\Users\calvinh\Source\Repos\PerfGraphVSIX\TestResults\Deploy_calvinh 2019-11-15 12_04_59\Out' * TestRunDirectory = 'C:\Users\calvinh\Source\Repos\PerfGraphVSIX\TestResults\Deploy_calvinh 2019-11-15 12_04_59' * TestResultsDirectory='C:\Users\calvinh\Source\Repos\PerfGraphVSIX\TestResults\Deploy_calvinh 2019-11-15 12_04_59\In' * TestRunResultsDirectory='C:\Users\calvinh\Source\Repos\PerfGraphVSIX\TestResults\Deploy_calvinh 2019-11-15 12_04_59\In\CALVINH2' * apex local: * CurDir = 'C:\VS\src\Tests\Stress\Project\TestResults\Deploy_calvinh 2019-11-14 18_09_34\Out' * TestRunDirectory = 'C:\VS\src\Tests\Stress\Project\TestResults\Deploy_calvinh 2019-11-14 18_09_34' * TestResultsDirectory='C:\VS\src\Tests\Stress\Project\TestResults\Deploy_calvinh 2019-11-14 18_09_34\In' * TestRunResultsDirectory='C:\VS\src\Tests\Stress\Project\TestResults\Deploy_calvinh 2019-11-14 18_09_34\In\calvinhW7' * * */ var optFile = Path.Combine(testContext.TestDeploymentDir, "Assets", $"{testContext.TestName}.settings.xml"); if (File.Exists(optFile)) { logger.LogMessage($"Reading settings from {optFile}"); ReadOptionsFromFile(optFile); if (logger is Logger mylogger) // since logger was already instantiated, apply logger options after reading from file { mylogger.LogOutputToDesktopFile = LoggerLogOutputToDestkop; } } testContext.Properties[StressUtil.PropNameNumIterations] = NumIterations; logger.LogMessage($@"TestName = {testContext.TestName} IsApexTest={IsTestApexTest()} NumIterations = {NumIterations} DateTime = {DateTime.Now} TimeZone = {TimeZone.CurrentTimeZone.StandardName} {TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now)} Sensitivity = {Sensitivity} UserName = {Environment.GetEnvironmentVariable("USERNAME")} COMPUTERNAME = {Environment.GetEnvironmentVariable("COMPUTERNAME")} CurProc = {Process.GetCurrentProcess().Id} {Process.GetCurrentProcess().ProcessName} IntPtr.Size = {IntPtr.Size} CurDir = '{Environment.CurrentDirectory}' TestDeploymentDir = '{testContext.TestDeploymentDir}' TestRunDirectory = '{testContext.TestRunDirectory}' TestResultsDirectory='{testContext.TestResultsDirectory}' TestRunResultsDirectory='{testContext.TestRunResultsDirectory}' "); if ((PerfCounterOverrideSettings != null) && (PerfCounterOverrideSettings.Count > 0)) { logger.LogMessage("The following perf counter thresholds are being overridden:"); foreach (PerfCounterOverrideThreshold thresholdOverride in PerfCounterOverrideSettings) { logger.LogMessage($"\t{thresholdOverride.perfCounterType} = {thresholdOverride.regressionThreshold}."); } logger.LogMessage(""); } else { logger.LogMessage("No perf counter thresholds are being overridden."); } VSHandler theVSHandler = null; if (string.IsNullOrEmpty(ProcNamesToMonitor)) { if (lstPerfCountersToUse == null) // allow tests to override { lstPerfCountersToUse = PerfCounterData.GetPerfCountersToUse(Process.GetCurrentProcess(), IsForStress: true); } } else { var vsHandlerFld = testType.GetFields( BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) .Where(m => m.FieldType.Name == nameof(VSHandler)).FirstOrDefault(); if (vsHandlerFld != null) { theVSHandler = vsHandlerFld.GetValue(test) as VSHandler; if (theVSHandler._DelayMultiplier > DelayMultiplier) //take the longer of the delaymultipliers { DelayMultiplier = theVSHandler._DelayMultiplier; } } if (theVSHandler == null) { theVSHandler = testContext.Properties[StressUtil.PropNameVSHandler] as VSHandler; if (theVSHandler == null) { theVSHandler = new VSHandler(logger, DelayMultiplier); testContext.Properties[StressUtil.PropNameVSHandler] = theVSHandler; } } // ensure we get the DTE. Even for Apex tests, we need to Tools.ForceGC if (TargetDevEnvProcessId == 0) { await theVSHandler?.EnsureGotDTE(TimeSpan.FromSeconds(SecsToWaitForDevenv *DelayMultiplier)); } else { await theVSHandler?.EnsureGotDTE(TargetDevEnvProcessId); } VSHandler = theVSHandler; lstPerfCountersToUse = PerfCounterData.GetPerfCountersToUse(VSHandler.vsProc, IsForStress: true); } SetPerfCounterOverrideSettings(); return(true); // not recurring }
/// <summary> /// Pass in a TestContext. Or null /// </summary> /// <param name="testContext"></param> public Logger(TestContextWrapper testContext) { this.testContext = testContext; }