package main import ( "errors" "testing" ) type MockCommand struct { output string err error } func NewMockCommand(output string) *MockCommand { return &MockCommand{output: output} } func NewMockCommandWithError(err error) *MockCommand { return &MockCommand{err: err} } func (m *MockCommand) Execute(binary string, args ...string) ([]byte, error) { if m.err != nil { return nil, m.err } return []byte(m.output), nil } func TestGetGPUInfo(t *testing.T) { mockOutput := `Graphics/Displays: Apple M2: Total Number of Cores: 10` cmd := NewMockCommand(mockOutput) result, err := getGPUInfo(cmd) if err != nil { t.Fatalf("Expected no error, got: %v", err) } expected := CoreCount(10) if result != expected { t.Errorf("Expected %d GPU cores, got %d", expected, result) } } func TestGetGPUInfoNotFound(t *testing.T) { mockOutput := `Graphics/Displays: Apple M2: Some other field: 10` cmd := NewMockCommand(mockOutput) _, err := getGPUInfo(cmd) if err == nil { t.Fatal("Expected error when GPU cores not found, got nil") } } func TestGetCPUInfoSuccess(t *testing.T) { mockOutput := "Apple M2\n8\n4\n4\n" cmd := NewMockCommand(mockOutput) brand, cores, pCores, eCores, err := getCPUInfo(cmd) if err != nil { t.Fatalf("Expected no error, got: %v", err) } if brand != "Apple M2" { t.Errorf("Expected brand 'Apple M2', got '%s'", brand) } if cores != 8 { t.Errorf("Expected 8 cores, got %d", cores) } if pCores != 4 { t.Errorf("Expected 4 performance cores, got %d", pCores) } if eCores != 4 { t.Errorf("Expected 4 efficiency cores, got %d", eCores) } } func TestGetCPUInfoMissingCoreCount(t *testing.T) { mockOutput := "Apple M2\n" cmd := NewMockCommand(mockOutput) _, _, _, _, err := getCPUInfo(cmd) if err == nil { t.Fatal("Expected error with insufficient output, got nil") } } func TestGetCPUInfoInvalidCoreCount(t *testing.T) { mockOutput := "Apple M2\ninvalid\n4\n4\n" cmd := NewMockCommand(mockOutput) _, _, _, _, err := getCPUInfo(cmd) if err == nil { t.Fatal("Expected error with invalid core count, got nil") } } func TestFromBrandString(t *testing.T) { tests := []struct { brand string expected AppleChip }{ {"Apple M1", M1}, {"Apple M1 Pro", M1Pro}, {"Apple M1 Max", M1Max}, {"Apple M1 Ultra", M1Ultra}, {"Apple M2", M2}, {"Apple M2 Pro", M2Pro}, {"Apple M2 Max", M2Max}, {"Apple M2 Ultra", M2Ultra}, {"Apple M3", M3}, {"Apple M3 Pro", M3Pro}, {"Apple M3 Max", M3Max}, {"Intel Core i7", Unknown}, } for _, test := range tests { result := fromBrandString(test.brand) if result != test.expected { t.Errorf("For brand '%s', expected %v, got %v", test.brand, test.expected, result) } } } func TestChipGetSpecs(t *testing.T) { tests := []struct { chip AppleChip expected ChipSpecs }{ {M1, ChipSpecs{CPUTDP: 20, GPUTDP: 20, CPUBW: 70, GPUBW: 70}}, {M1Pro, ChipSpecs{CPUTDP: 30, GPUTDP: 30, CPUBW: 200, GPUBW: 200}}, {M2, ChipSpecs{CPUTDP: 25, GPUTDP: 15, CPUBW: 100, GPUBW: 100}}, {Unknown, ChipSpecs{CPUTDP: 0, GPUTDP: 0, CPUBW: 0, GPUBW: 0}}, } for _, test := range tests { result := test.chip.getSpecs() if result != test.expected { t.Errorf("For chip %v, expected %+v, got %+v", test.chip, test.expected, result) } } } func TestNewSocInfoWithCommand(t *testing.T) { sysctlOutput := "Apple M2\n8\n4\n4\n" profilerOutput := `Graphics/Displays: Apple M2: Total Number of Cores: 10` cmd := &MockCommandMultiple{ outputs: map[string]string{ "/usr/sbin/sysctl": sysctlOutput, "/usr/sbin/system_profiler": profilerOutput, }, } socInfo, err := NewSocInfoWithCommand(cmd) if err != nil { t.Fatalf("Expected no error, got: %v", err) } if socInfo.CPUBrandName != "Apple M2" { t.Errorf("Expected CPU brand 'Apple M2', got '%s'", socInfo.CPUBrandName) } if socInfo.NumCPUCores != 8 { t.Errorf("Expected 8 CPU cores, got %d", socInfo.NumCPUCores) } if socInfo.NumGPUCores != 10 { t.Errorf("Expected 10 GPU cores, got %d", socInfo.NumGPUCores) } if socInfo.CPUMaxPower == nil || *socInfo.CPUMaxPower != 25 { t.Errorf("Expected CPU max power 25W, got %v", socInfo.CPUMaxPower) } } type MockCommandMultiple struct { outputs map[string]string err error } func (m *MockCommandMultiple) Execute(binary string, args ...string) ([]byte, error) { if m.err != nil { return nil, m.err } output, exists := m.outputs[binary] if !exists { return nil, errors.New("binary not found in mock") } return []byte(output), nil }