PageRenderTime 52ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/test/powershell/Modules/Microsoft.PowerShell.Diagnostics/CounterTestHelperFunctions.ps1

https://gitlab.com/unofficial-mirrors/PowerShell
Powershell | 300 lines | 275 code | 11 blank | 14 comment | 8 complexity | 37df115381a36d3270ef1f9e533dd17f MD5 | raw file
  1. # Copyright (c) Microsoft Corporation. All rights reserved.
  2. # Licensed under the MIT License.
  3. <############################################################################################
  4. # File: CounterTestHelperFunctions.ps1
  5. # Provides functions common to the performance counter Pester tests.
  6. ############################################################################################>
  7. # Create a helper class providing facilities for translation of
  8. # counter names and counter paths
  9. $helperSource = @"
  10. using System;
  11. using System.Globalization;
  12. using System.Runtime.InteropServices;
  13. using System.Text;
  14. public class TestCounterHelper
  15. {
  16. private const long PDH_MORE_DATA = 0x800007D2L;
  17. private const int PDH_MAX_COUNTER_NAME = 1024;
  18. private const int PDH_MAX_COUNTER_PATH = 2048;
  19. private const string SubKeyPath = @"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\009";
  20. [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
  21. private struct PDH_COUNTER_PATH_ELEMENTS
  22. {
  23. [MarshalAs(UnmanagedType.LPWStr)]
  24. public string MachineName;
  25. [MarshalAs(UnmanagedType.LPWStr)]
  26. public string ObjectName;
  27. [MarshalAs(UnmanagedType.LPWStr)]
  28. public string InstanceName;
  29. [MarshalAs(UnmanagedType.LPWStr)]
  30. public string ParentInstance;
  31. public UInt32 InstanceIndex;
  32. [MarshalAs(UnmanagedType.LPWStr)]
  33. public string CounterName;
  34. }
  35. [DllImport("pdh.dll", CharSet = CharSet.Unicode)]
  36. private static extern uint PdhMakeCounterPath(ref PDH_COUNTER_PATH_ELEMENTS pCounterPathElements,
  37. StringBuilder szFullPathBuffer,
  38. ref uint pcchBufferSize,
  39. UInt32 dwFlags);
  40. [DllImport("pdh.dll", CharSet = CharSet.Unicode)]
  41. private static extern uint PdhParseCounterPath(string szFullPathBuffer,
  42. IntPtr pCounterPathElements, //PDH_COUNTER_PATH_ELEMENTS
  43. ref IntPtr pdwBufferSize,
  44. uint dwFlags);
  45. [DllImport("pdh.dll", SetLastError=true, CharSet=CharSet.Unicode)]
  46. private static extern UInt32 PdhLookupPerfNameByIndex(string szMachineName,
  47. uint dwNameIndex,
  48. System.Text.StringBuilder szNameBuffer,
  49. ref uint pcchNameBufferSize);
  50. private string[] _counters;
  51. public TestCounterHelper(string[] counters)
  52. {
  53. _counters = counters;
  54. }
  55. public string TranslateCounterName(string name)
  56. {
  57. var loweredName = name.ToLowerInvariant();
  58. for (var i = 1; i < _counters.Length - 1; i += 2)
  59. {
  60. if (_counters[i].ToLowerInvariant() == loweredName)
  61. {
  62. try
  63. {
  64. var index = Convert.ToUInt32(_counters[i - 1], CultureInfo.InvariantCulture);
  65. var sb = new StringBuilder(PDH_MAX_COUNTER_NAME);
  66. var bufSize = (uint)sb.Capacity;
  67. var result = PdhLookupPerfNameByIndex(null, index, sb, ref bufSize);
  68. if (result == 0)
  69. return sb.ToString().Substring(0, (int)bufSize - 1);
  70. }
  71. catch
  72. {
  73. // do nothing, we just won't translate
  74. }
  75. break;
  76. }
  77. }
  78. // return original path if translation failed
  79. return name;
  80. }
  81. public string TranslateCounterPath(string path)
  82. {
  83. var bufSize = new IntPtr(0);
  84. var result = PdhParseCounterPath(path,
  85. IntPtr.Zero,
  86. ref bufSize,
  87. 0);
  88. if (result != 0 && result != PDH_MORE_DATA)
  89. return path;
  90. IntPtr structPointer = Marshal.AllocHGlobal(bufSize.ToInt32());
  91. try
  92. {
  93. result = PdhParseCounterPath(path,
  94. structPointer,
  95. ref bufSize,
  96. 0);
  97. if (result == 0)
  98. {
  99. var cpe = Marshal.PtrToStructure<PDH_COUNTER_PATH_ELEMENTS>(structPointer);
  100. cpe.ObjectName = TranslateCounterName(cpe.ObjectName);
  101. cpe.CounterName = TranslateCounterName(cpe.CounterName);
  102. var sb = new StringBuilder(PDH_MAX_COUNTER_NAME);
  103. var pathSize = (uint)sb.Capacity;
  104. result = PdhMakeCounterPath(ref cpe, sb, ref pathSize, 0);
  105. if (result == 0)
  106. return sb.ToString().Substring(0, (int)pathSize - 1);
  107. }
  108. }
  109. finally
  110. {
  111. Marshal.FreeHGlobal(structPointer);
  112. }
  113. // return original path if translation failed
  114. return path;
  115. }
  116. }
  117. "@
  118. if ( $IsWindows )
  119. {
  120. Add-Type -TypeDefinition $helperSource
  121. }
  122. # Strip off machine name, if present, from counter path
  123. function RemoveMachineName
  124. {
  125. param (
  126. [Parameter(Mandatory=$true)]
  127. [ValidateNotNullOrEmpty()]
  128. [String]
  129. $path
  130. )
  131. if ($path.StartsWith("\\"))
  132. {
  133. return $path.SubString($path.IndexOf("\", 2))
  134. }
  135. else
  136. {
  137. return $path
  138. }
  139. }
  140. # Retrieve the counters array from the Registry
  141. function GetCounters
  142. {
  143. if ( $IsWindows )
  144. {
  145. $key = 'Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\CurrentLanguage'
  146. return (Get-ItemProperty -Path $key -Name Counter).Counter
  147. }
  148. }
  149. # Translate a counter name from English to a localized counter name
  150. function TranslateCounterName
  151. {
  152. param (
  153. [Parameter(Mandatory=$true)]
  154. [ValidateNotNullOrEmpty()]
  155. [String]
  156. $counterName
  157. )
  158. $counters = GetCounters
  159. if ($counters -and ($counters.Length -gt 1))
  160. {
  161. $counterHelper = New-Object -TypeName "TestCounterHelper" -ArgumentList (, $counters)
  162. return $counterHelper.TranslateCounterName($counterName)
  163. }
  164. return $counterName
  165. }
  166. # Translate a counter path from English to a localized counter path
  167. function TranslateCounterPath
  168. {
  169. param (
  170. [Parameter(Mandatory=$true)]
  171. [ValidateNotNullOrEmpty()]
  172. [String]
  173. $path
  174. )
  175. $counters = GetCounters
  176. if ($counters -and ($counters.Length -gt 1))
  177. {
  178. $counterHelper = New-Object -TypeName "TestCounterHelper" -ArgumentList (, $counters)
  179. $rv = $counterHelper.TranslateCounterPath($path)
  180. # if our original path had no machine name,
  181. # we don't want one on our translated path
  182. if (-not $path.StartsWith("\\"))
  183. {
  184. $rv = RemoveMachineName $rv
  185. }
  186. return $rv
  187. }
  188. return $path
  189. }
  190. # Compare two DateTime objects for relative equality.
  191. #
  192. # Exporting lops fractional milliseconds off the time stamp,
  193. # so simply comparing the DateTime values isn't sufficient
  194. function DateTimesAreEqualish
  195. {
  196. param (
  197. [Parameter(Mandatory=$true)]
  198. [ValidateNotNull()]
  199. [DateTime]
  200. $dtA,
  201. [Parameter(Mandatory)]
  202. [ValidateNotNull()]
  203. [DateTime]
  204. $dtB
  205. )
  206. $span = $dtA - $dtB
  207. return ([math]::Floor([math]::Abs($span.TotalMilliseconds)) -eq 0)
  208. }
  209. # Compare the content of counter sets
  210. function CompareCounterSets
  211. {
  212. param (
  213. [Parameter(Mandatory=$true)]
  214. [ValidateNotNullOrEmpty()]
  215. $setA,
  216. [Parameter(Mandatory=$true)]
  217. [ValidateNotNullOrEmpty()]
  218. $setB
  219. )
  220. $setA.Length | Should -Be $setB.Length
  221. # Depending on the kinds of counters used, the first record in
  222. # exported counters are likely to have embty items, so we'll
  223. # start comparing at the second item.
  224. #
  225. # Note that this is not a bug in either the cmdlets or the tests
  226. # script, but rather is the behavior of the underlying Windows
  227. # PDH functions that perform the actual exporting of counter data.
  228. for ($i = 1; $i -lt $setA.Length; $i++)
  229. {
  230. $setA[$i].CounterSamples.Length | Should -Be $setB[$i].CounterSamples.Length
  231. $samplesA = ($setA[$i].CounterSamples | sort -Property Path)
  232. $samplesB = ($setB[$i].CounterSamples | sort -Property Path)
  233. (DateTimesAreEqualish $setA[$i].TimeStamp $setB[$i].TimeStamp) | Should -BeTrue
  234. for ($j = 0; $j -lt $samplesA.Length; $j++)
  235. {
  236. $sampleA = $samplesA[$j]
  237. $sampleB = $samplesB[$j]
  238. (DateTimesAreEqualish $sampleA.TimeStamp $sampleB.TimeStamp) | Should -BeTrue
  239. $sampleA.Path | Should -BeExactly $sampleB.Path
  240. $sampleA.CookedValue | Should -Be $sampleB.CookedValue
  241. }
  242. }
  243. }
  244. function SkipCounterTests
  245. {
  246. if ([System.Management.Automation.Platform]::IsLinux -or
  247. [System.Management.Automation.Platform]::IsMacOS -or
  248. [System.Management.Automation.Platform]::IsIoT)
  249. {
  250. return $true
  251. }
  252. return $false
  253. }