1 /* Copyright (c) 2018 Daniel Widdis, All Rights Reserved 2 * 3 * The contents of this file is dual-licensed under 2 4 * alternative Open Source/Free licenses: LGPL 2.1 or later and 5 * Apache License 2.0. (starting with JNA version 4.0.0). 6 * 7 * You can freely decide which license you want to apply to 8 * the project. 9 * 10 * You may obtain a copy of the LGPL License at: 11 * 12 * http://www.gnu.org/licenses/licenses.html 13 * 14 * A copy is also included in the downloadable source code package 15 * containing JNA, in file "LGPL2.1". 16 * 17 * You may obtain a copy of the Apache License at: 18 * 19 * http://www.apache.org/licenses/ 20 * 21 * A copy is also included in the downloadable source code package 22 * containing JNA, in file "AL2.0". 23 */ 24 // package com.sun.jna.platform.win32; 25 package com.sun.jna.platform.win32; 26 27 import java.util.HashSet; 28 import java.util.Set; 29 30 import org.junit.Test; 31 32 import com.sun.jna.Memory; 33 import com.sun.jna.Native; 34 import com.sun.jna.Pointer; 35 import com.sun.jna.platform.win32.WinDef.DWORDByReference; 36 import com.sun.jna.platform.win32.WinPerf.PERF_COUNTER_BLOCK; 37 import com.sun.jna.platform.win32.WinPerf.PERF_COUNTER_DEFINITION; 38 import com.sun.jna.platform.win32.WinPerf.PERF_DATA_BLOCK; 39 import com.sun.jna.platform.win32.WinPerf.PERF_INSTANCE_DEFINITION; 40 import com.sun.jna.platform.win32.WinPerf.PERF_OBJECT_TYPE; 41 import com.sun.jna.ptr.IntByReference; 42 43 /** 44 * Tests structures in WinPerf 45 * 46 * @author dbwiddis 47 */ 48 public class WinPerfTest extends AbstractWin32TestSupport { 49 @Test testPerfDataBLock()50 public void testPerfDataBLock() { 51 // This method tests: 52 // PERF_DATA_BLOCK, 53 // PERF_OBJECT_TYPE, 54 // PERF_COUNTER_DEFINITION, 55 // PERF_INSTANCE_DEFINITION, 56 // PERF_COUNTER_BLOCK 57 // 58 // See Performance Data format at 59 // https://msdn.microsoft.com/en-us/library/windows/desktop/aa373105(v=vs.85).aspx 60 // [ ] Perf_Data_block 61 // Then one or more objects repeating everything below: 62 // [ ] Object Type 63 // [ ][ ][ ] Multiple counter definitions 64 // Then multiple instances repeating: 65 // [ ] Instance Definition 66 // [ ] Instance name 67 // [ ] Counter Block 68 // [ ][ ][ ] Counter data for each definition above 69 70 if (AbstractWin32TestSupport.isEnglishLocale) { 71 // To test the structures we'll get the data block for Process 72 // performance data 73 DWORDByReference index = new DWORDByReference(); 74 Pdh.INSTANCE.PdhLookupPerfIndexByName(null, "Process", index); 75 int processIndex = index.getValue().intValue(); 76 String processIndexStr = Integer.toString(processIndex); 77 // And one of the counters, for PID: 78 Pdh.INSTANCE.PdhLookupPerfIndexByName(null, "ID Process", index); 79 int idProcessIndex = index.getValue().intValue(); 80 81 // now load the Process registry entry 82 // Sequentially increase the buffer until everything fits. 83 int perfDataBufferSize = 4096; 84 IntByReference lpcbData = new IntByReference(perfDataBufferSize); 85 Pointer pPerfData = new Memory(perfDataBufferSize); 86 while (WinError.ERROR_MORE_DATA == Advapi32.INSTANCE.RegQueryValueEx(WinReg.HKEY_PERFORMANCE_DATA, 87 processIndexStr, 0, null, pPerfData, lpcbData)) { 88 perfDataBufferSize += 4096; 89 lpcbData.setValue(perfDataBufferSize); 90 pPerfData = new Memory(perfDataBufferSize); 91 } 92 // When this loop exits, pPerfData points to the PERF_DATA_BLOCK. 93 94 // PERF_DATA_BLOCK test 95 // Test the signature, a char[] containing [P, E, R, F] 96 PERF_DATA_BLOCK perfData = new PERF_DATA_BLOCK(pPerfData); 97 assertEquals("PERF", Native.toString(perfData.Signature)); 98 99 // PERF_OBJECT_TYPE test 100 // Process object title index should match process object 101 // Object type begins after header offset 102 long perfObjectOffset = perfData.HeaderLength; 103 PERF_OBJECT_TYPE perfObject = new PERF_OBJECT_TYPE(pPerfData.share(perfObjectOffset)); 104 assertEquals(processIndex, perfObject.ObjectNameTitleIndex); 105 106 // PERF_COUNTER_DEFINITION test 107 // Counter offsets will be at least 4, and a multiple of 4 108 // Identify where counter definitions start 109 long perfCounterOffset = perfObjectOffset + perfObject.HeaderLength; 110 // Iterate through counter definitions to get the offset for the PID 111 int idProcessOffset = 0; 112 for (int counter = 0; counter < perfObject.NumCounters; counter++) { 113 PERF_COUNTER_DEFINITION perfCounter = new PERF_COUNTER_DEFINITION(pPerfData.share(perfCounterOffset)); 114 assertTrue(perfCounter.CounterOffset >= 4); 115 assertEquals(0, perfCounter.CounterOffset % 4); 116 if (perfCounter.CounterNameTitleIndex == idProcessIndex) { 117 idProcessOffset = perfCounter.CounterOffset; 118 } 119 // Increment for next Counter 120 perfCounterOffset += perfCounter.ByteLength; 121 } 122 123 // PERF_INSTANCE_DEFINITION test 124 long perfInstanceOffset = perfObjectOffset + perfObject.DefinitionLength; 125 Set<Integer> pidSet = new HashSet<Integer>(); 126 for (int inst = 0; inst < perfObject.NumInstances; inst++) { 127 PERF_INSTANCE_DEFINITION perfInstance = new PERF_INSTANCE_DEFINITION( 128 pPerfData.share(perfInstanceOffset)); 129 // Definitions align to 8 byte boundaries 130 assertEquals(0, perfInstance.ByteLength % 8); 131 132 // PERF_COUNTER_BLOCK test 133 // ByteLength should be at least pid offset + 4, 134 // and a multiple of 4 135 long perfCounterBlockOffset = perfInstanceOffset + perfInstance.ByteLength; 136 PERF_COUNTER_BLOCK perfCounterBlock = new PERF_COUNTER_BLOCK(pPerfData.share(perfCounterBlockOffset)); 137 assertTrue(perfCounterBlock.ByteLength >= 4 + idProcessOffset); 138 assertEquals(0, perfCounterBlock.ByteLength % 4); 139 int pid = pPerfData.getInt(perfCounterBlockOffset + idProcessOffset); 140 // PID 0 exists as idle process and will repeat for the _Total 141 // instance. All other PIDs should be unique 142 assertTrue(pid >= 0); 143 if (pid > 0) { 144 assertFalse(pidSet.contains(pid)); 145 pidSet.add(pid); 146 } 147 } 148 } 149 } 150 } 151