github.com/klauspost/cpuid/v2@v2.2.7/cpuid_test.go (about) 1 // Copyright (c) 2015 Klaus Post, released under MIT License. See LICENSE file. 2 3 package cpuid 4 5 import ( 6 "fmt" 7 "strings" 8 "testing" 9 ) 10 11 func TestLastID(t *testing.T) { 12 if lastID.String() != "lastID" { 13 t.Fatal("stringer not updated, run go generate") 14 } 15 } 16 17 func TestLastVendorID(t *testing.T) { 18 if lastVendor.String() != "lastVendor" { 19 t.Fatal("stringer not updated, run go generate") 20 } 21 } 22 23 // There is no real way to test a CPU identifier, since results will 24 // obviously differ on each machine. 25 func TestCPUID(t *testing.T) { 26 Detect() 27 n := maxFunctionID() 28 t.Logf("Max Function:0x%x", n) 29 n = maxExtendedFunction() 30 t.Logf("Max Extended Function:0x%x", n) 31 t.Log("VendorString:", CPU.VendorString) 32 t.Log("VendorID:", CPU.VendorID) 33 t.Log("Name:", CPU.BrandName) 34 t.Log("PhysicalCores:", CPU.PhysicalCores) 35 t.Log("ThreadsPerCore:", CPU.ThreadsPerCore) 36 t.Log("LogicalCores:", CPU.LogicalCores) 37 t.Log("Family", CPU.Family, "Model:", CPU.Model, "Stepping:", CPU.Stepping) 38 t.Log("Features:", strings.Join(CPU.FeatureSet(), ",")) 39 t.Log("Cacheline bytes:", CPU.CacheLine) 40 t.Log("L1 Instruction Cache:", CPU.Cache.L1I, "bytes") 41 t.Log("L1 Data Cache:", CPU.Cache.L1D, "bytes") 42 t.Log("L2 Cache:", CPU.Cache.L2, "bytes") 43 t.Log("L3 Cache:", CPU.Cache.L3, "bytes") 44 t.Log("Hz:", CPU.Hz, "Hz") 45 t.Log("VM:", CPU.VM()) 46 t.Log("BoostFreq:", CPU.BoostFreq, "Hz") 47 } 48 49 func TestExample(t *testing.T) { 50 Detect() 51 // Print basic CPU information: 52 fmt.Println("Name:", CPU.BrandName) 53 fmt.Println("PhysicalCores:", CPU.PhysicalCores) 54 fmt.Println("ThreadsPerCore:", CPU.ThreadsPerCore) 55 fmt.Println("LogicalCores:", CPU.LogicalCores) 56 fmt.Println("Family", CPU.Family, "Model:", CPU.Model, "Vendor ID:", CPU.VendorID) 57 fmt.Println("Features:", strings.Join(CPU.FeatureSet(), ",")) 58 fmt.Println("Cacheline bytes:", CPU.CacheLine) 59 fmt.Println("L1 Data Cache:", CPU.Cache.L1D, "bytes") 60 fmt.Println("L1 Instruction Cache:", CPU.Cache.L1D, "bytes") 61 fmt.Println("L2 Cache:", CPU.Cache.L2, "bytes") 62 fmt.Println("L3 Cache:", CPU.Cache.L3, "bytes") 63 fmt.Println("Frequency", CPU.Hz, "hz") 64 65 // Test if we have these specific features: 66 if CPU.Supports(SSE, SSE2) { 67 fmt.Println("We have Streaming SIMD 2 Extensions") 68 } 69 } 70 func TestDumpCPUID(t *testing.T) { 71 n := int(maxFunctionID()) 72 for i := 0; i <= n; i++ { 73 a, b, c, d := cpuidex(uint32(i), 0) 74 t.Logf("CPUID %08x: %08x-%08x-%08x-%08x", i, a, b, c, d) 75 ex := uint32(1) 76 for { 77 a2, b2, c2, d2 := cpuidex(uint32(i), ex) 78 if a2 == a && b2 == b && d2 == d || ex > 50 || a2 == 0 { 79 break 80 } 81 t.Logf("CPUID %08x: %08x-%08x-%08x-%08x", i, a2, b2, c2, d2) 82 a, b, c, d = a2, b2, c2, d2 83 ex++ 84 } 85 } 86 n2 := maxExtendedFunction() 87 for i := uint32(0x80000000); i <= n2; i++ { 88 a, b, c, d := cpuid(i) 89 t.Logf("CPUID %08x: %08x-%08x-%08x-%08x", i, a, b, c, d) 90 } 91 } 92 93 func Example() { 94 // Print basic CPU information: 95 fmt.Println("Name:", CPU.BrandName) 96 fmt.Println("PhysicalCores:", CPU.PhysicalCores) 97 fmt.Println("ThreadsPerCore:", CPU.ThreadsPerCore) 98 fmt.Println("LogicalCores:", CPU.LogicalCores) 99 fmt.Println("Family", CPU.Family, "Model:", CPU.Model) 100 fmt.Println("Features:", CPU.FeatureSet()) 101 fmt.Println("Cacheline bytes:", CPU.CacheLine) 102 } 103 104 func TestBrandNameZero(t *testing.T) { 105 if len(CPU.BrandName) > 0 { 106 // Cut out last byte 107 last := []byte(CPU.BrandName[len(CPU.BrandName)-1:]) 108 if last[0] == 0 { 109 t.Fatal("last byte was zero") 110 } else if last[0] == 32 { 111 t.Fatal("whitespace wasn't trimmed") 112 } 113 } 114 } 115 116 // TestSGX tests SGX detection 117 func TestSGX(t *testing.T) { 118 got := CPU.SGX.Available 119 expected := CPU.featureSet.inSet(SGX) 120 if got != expected { 121 t.Fatalf("SGX: expected %v, got %v", expected, got) 122 } 123 t.Log("SGX Support:", got) 124 125 if CPU.SGX.Available { 126 var total uint64 = 0 127 leaves := false 128 for _, s := range CPU.SGX.EPCSections { 129 t.Logf("SGX EPC section: base address 0x%x, size %v", s.BaseAddress, s.EPCSize) 130 total += s.EPCSize 131 leaves = true 132 } 133 if leaves && total == 0 { 134 t.Fatal("SGX enabled without any available EPC memory") 135 } 136 } 137 } 138 139 // TestAMDMemEncryption tests AMDMemEncryption detection 140 func TestAMDMemEncryption(t *testing.T) { 141 got := CPU.AMDMemEncryption.Available 142 expected := CPU.featureSet.inSet(SME) || CPU.featureSet.inSet(SEV) 143 if got != expected { 144 t.Fatalf("AMDMemEncryption: expected %v, got %v", expected, got) 145 } 146 t.Log("AMDMemEncryption Support:", got) 147 } 148 149 func TestHas(t *testing.T) { 150 Detect() 151 defer Detect() 152 feats := CPU.FeatureSet() 153 for _, feat := range feats { 154 f := ParseFeature(feat) 155 if f == UNKNOWN { 156 t.Error("Got unknown feature:", feat) 157 continue 158 } 159 if !CPU.Has(f) { 160 t.Error("CPU.Has returned false, want true") 161 } 162 if !CPU.Supports(f) { 163 t.Error("CPU.Supports returned false, want true") 164 } 165 // Disable it. 166 CPU.Disable(f) 167 if CPU.Has(f) { 168 t.Error("CPU.Has returned true, want false") 169 } 170 if CPU.Supports(f) { 171 t.Error("CPU.Supports returned true, want false") 172 } 173 // Reenable 174 CPU.Enable(f) 175 if !CPU.Has(f) { 176 t.Error("CPU.Has returned false, want true") 177 } 178 if !CPU.Supports(f) { 179 t.Error("CPU.Supports returned false, want true") 180 } 181 } 182 } 183 184 // TestSGXLC tests SGX Launch Control detection 185 func TestSGXLC(t *testing.T) { 186 got := CPU.SGX.LaunchControl 187 expected := CPU.featureSet.inSet(SGXLC) 188 if got != expected { 189 t.Fatalf("SGX: expected %v, got %v", expected, got) 190 } 191 t.Log("SGX Launch Control Support:", got) 192 } 193 194 // Test VM function 195 func TestVM(t *testing.T) { 196 got := CPU.VM() 197 expected := CPU.featureSet.inSet(HYPERVISOR) 198 if got != expected { 199 t.Fatalf("TestVM: expected %v, got %v", expected, got) 200 } 201 t.Log("TestVM:", got) 202 } 203 204 // Test RTCounter function 205 func TestRtCounter(t *testing.T) { 206 a := CPU.RTCounter() 207 b := CPU.RTCounter() 208 t.Log("CPU Counter:", a, b, b-a) 209 } 210 211 // Prints the value of Ia32TscAux() 212 func TestIa32TscAux(t *testing.T) { 213 ecx := CPU.Ia32TscAux() 214 t.Logf("Ia32TscAux:0x%x\n", ecx) 215 if ecx != 0 { 216 chip := (ecx & 0xFFF000) >> 12 217 core := ecx & 0xFFF 218 t.Log("Likely chip, core:", chip, core) 219 } 220 } 221 222 func TestThreadsPerCoreNZ(t *testing.T) { 223 if CPU.ThreadsPerCore == 0 { 224 t.Fatal("threads per core is zero") 225 } 226 } 227 228 // Prints the value of LogicalCPU() 229 func TestLogicalCPU(t *testing.T) { 230 t.Log("Currently executing on cpu:", CPU.LogicalCPU()) 231 } 232 233 func TestMaxFunction(t *testing.T) { 234 expect := maxFunctionID() 235 if CPU.maxFunc != expect { 236 t.Fatal("Max function does not match, expected", expect, "but got", CPU.maxFunc) 237 } 238 expect = maxExtendedFunction() 239 if CPU.maxExFunc != expect { 240 t.Fatal("Max Extended function does not match, expected", expect, "but got", CPU.maxFunc) 241 } 242 } 243 244 // This example will calculate the chip/core number on Linux 245 // Linux encodes numa id (<<12) and core id (8bit) into TSC_AUX. 246 func ExampleCPUInfo_Ia32TscAux() { 247 ecx := CPU.Ia32TscAux() 248 if ecx == 0 { 249 fmt.Println("Unknown CPU ID") 250 return 251 } 252 chip := (ecx & 0xFFF000) >> 12 253 core := ecx & 0xFFF 254 fmt.Println("Chip, Core:", chip, core) 255 } 256 257 func TestCombineFeatures(t *testing.T) { 258 cpu := CPU 259 for i := FeatureID(0); i < lastID; i++ { 260 if cpu.Has(i) != cpu.HasAll(CombineFeatures(i)) { 261 t.Errorf("id %d:%s mismatch", i, i.String()) 262 } 263 } 264 } 265 266 func BenchmarkFlags(b *testing.B) { 267 var a bool 268 var cpu = CPU 269 b.Run("ids", func(b *testing.B) { 270 for i := 0; i < b.N; i++ { 271 a = cpu.Supports(CMOV, CMPXCHG8, X87, FXSR, MMX, SYSCALL, SSE, SSE2, CX16, LAHF, POPCNT, SSE3, SSE4, SSE42, SSSE3, AVX, AVX2, BMI1, BMI2, F16C, FMA3, LZCNT, MOVBE, OSXSAVE) || a 272 } 273 _ = a 274 }) 275 b.Run("features", func(b *testing.B) { 276 f := CombineFeatures(CMOV, CMPXCHG8, X87, FXSR, MMX, SYSCALL, SSE, SSE2, CX16, LAHF, POPCNT, SSE3, SSE4, SSE42, SSSE3, AVX, AVX2, BMI1, BMI2, F16C, FMA3, LZCNT, MOVBE, OSXSAVE) 277 for i := 0; i < b.N; i++ { 278 a = cpu.HasAll(f) || a 279 } 280 _ = a 281 }) 282 b.Run("id", func(b *testing.B) { 283 for i := 0; i < b.N; i++ { 284 a = cpu.Has(CMOV) || a 285 } 286 _ = a 287 }) 288 b.Run("feature", func(b *testing.B) { 289 f := CombineFeatures(CMOV) 290 for i := 0; i < b.N; i++ { 291 a = cpu.HasAll(f) || a 292 } 293 _ = a 294 }) 295 }