aboutsummaryrefslogblamecommitdiff
path: root/cmd/apple-silicon-info/main_test.go
blob: a9b7caf51f81a6991a5109a1ddbbdd5c83edcfe7 (plain) (tree)




































































































































































































                                                                                                          
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
}