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  }