diff --git a/tables/alt_system_info/alt_system_info_test.go b/tables/alt_system_info/alt_system_info_test.go index 220f426..421c070 100644 --- a/tables/alt_system_info/alt_system_info_test.go +++ b/tables/alt_system_info/alt_system_info_test.go @@ -1,6 +1,7 @@ package alt_system_info_test import ( + "errors" "testing" "github.com/macadmins/osquery-extension/pkg/utils" @@ -10,6 +11,29 @@ import ( "github.com/stretchr/testify/require" ) +type errorOsqueryClienter struct { + err error +} + +func (e errorOsqueryClienter) NewOsqueryClient() (utils.OsqueryClient, error) { + return nil, e.err +} + +type errorOsqueryClient struct { + rowsErr error + rowErr error +} + +func (e errorOsqueryClient) QueryRows(query string) ([]map[string]string, error) { + return nil, e.rowsErr +} + +func (e errorOsqueryClient) QueryRow(query string) (map[string]string, error) { + return nil, e.rowErr +} + +func (e errorOsqueryClient) Close() {} + var mockIOReg = ` @@ -65,6 +89,13 @@ func TestGetCPUType(t *testing.T) { assert.Equal(t, "arm64e", cpuType) } +func TestGetCPUTypeCommandError(t *testing.T) { + _, err := alt_system_info.GetCPUType(utils.MockCmdRunner{Err: errors.New("machine failed")}) + require.Error(t, err) + assert.ErrorContains(t, err, "could not run machine command") + assert.ErrorContains(t, err, "machine failed") +} + func TestGetIORegData(t *testing.T) { data, err := alt_system_info.GetIORegData(mockCmdRunner) require.NoError(t, err) @@ -75,6 +106,27 @@ func TestGetIORegData(t *testing.T) { assert.Equal(t, "MYSERIAL", data.HardwareSerial) } +func TestGetIORegDataErrors(t *testing.T) { + t.Run("command error", func(t *testing.T) { + _, err := alt_system_info.GetIORegData(utils.MockCmdRunner{Err: errors.New("ioreg failed")}) + require.Error(t, err) + assert.ErrorContains(t, err, "could not run ioreg command") + }) + + t.Run("invalid plist", func(t *testing.T) { + _, err := alt_system_info.GetIORegData(utils.MockCmdRunner{Output: "not plist"}) + require.Error(t, err) + assert.ErrorContains(t, err, "could not unmarshal plist") + }) + + t.Run("no children", func(t *testing.T) { + plistWithoutChildren := `` + _, err := alt_system_info.GetIORegData(utils.MockCmdRunner{Output: plistWithoutChildren}) + require.Error(t, err) + assert.ErrorContains(t, err, "no children found") + }) +} + func TestGetSysctlData(t *testing.T) { data, err := alt_system_info.GetSysctlData(mockCmdRunner) require.NoError(t, err) @@ -84,6 +136,25 @@ func TestGetSysctlData(t *testing.T) { assert.Equal(t, "34359738368", data.PhysicalMemory) } +func TestGetSysctlDataCommandError(t *testing.T) { + _, err := alt_system_info.GetSysctlData(utils.MockCmdRunner{Err: errors.New("sysctl failed")}) + require.Error(t, err) + assert.ErrorContains(t, err, "could not run sysctl command") +} + +func TestGetSysctlDataIgnoresMalformedLines(t *testing.T) { + data, err := alt_system_info.GetSysctlData(utils.MockCmdRunner{Output: `ignored line +machdep.cpu.brand_string: Apple M3 +too:many:colons +hw.memsize: 17179869184 +`}) + require.NoError(t, err) + assert.Equal(t, "Apple M3", data.CPUBrand) + assert.Equal(t, "17179869184", data.PhysicalMemory) + assert.Empty(t, data.CPUPhysicalCores) + assert.Empty(t, data.CPULogicalCores) +} + func TestGetHostData(t *testing.T) { data, err := alt_system_info.GetHostData(mockCmdRunner) require.NoError(t, err) @@ -92,6 +163,20 @@ func TestGetHostData(t *testing.T) { assert.Equal(t, "mylocalhostname", data.LocalHostname) } +func TestGetHostDataCommandError(t *testing.T) { + runner := &utils.MultiMockCmdRunner{ + Commands: map[string]utils.MockCmdRunner{ + "hostname": {Output: "myhostname.local\n"}, + "scutil --get ComputerName": {Err: errors.New("scutil failed")}, + "scutil --get LocalHostName": {Output: "mylocalhostname\n"}, + }, + } + + _, err := alt_system_info.GetHostData(runner) + require.Error(t, err) + assert.ErrorContains(t, err, "could not run scutil --get ComputerName command") +} + var ( isMacOS15Query = "select * from os_version where name = 'macOS' and major = '15' and minor = 0;" systemInfoQuery = "select * from system_info;" @@ -114,6 +199,12 @@ func TestIsMacOS15(t *testing.T) { assert.True(t, isMacOS15) } +func TestIsMacOS15QueryError(t *testing.T) { + _, err := alt_system_info.IsMacOS150(errorOsqueryClient{rowsErr: errors.New("query failed")}) + require.Error(t, err) + assert.ErrorContains(t, err, "query failed") +} + func TestFallback(t *testing.T) { mockOsquery := &utils.MockOsqueryClient{ Data: map[string][]map[string]string{ @@ -126,6 +217,12 @@ func TestFallback(t *testing.T) { assert.Equal(t, mockOsquery.Data[systemInfoQuery], value) } +func TestFallbackQueryError(t *testing.T) { + _, err := alt_system_info.Fallback(errorOsqueryClient{rowErr: errors.New("system_info failed")}) + require.Error(t, err) + assert.ErrorContains(t, err, "system_info failed") +} + func TestGenerateInfo(t *testing.T) { mockOsquery := &utils.MockOsqueryClienter{ Data: map[string][]map[string]string{ @@ -169,3 +266,35 @@ func TestGenerateInfo(t *testing.T) { assert.False(t, *cache.IsMacOS15) } } + +func TestGenerateInfoClientCreationError(t *testing.T) { + _, err := alt_system_info.GenerateInfo( + mockCmdRunner, + errorOsqueryClienter{err: errors.New("socket unavailable")}, + new(alt_system_info.Cache), + ) + require.Error(t, err) + assert.ErrorContains(t, err, "could not create osquery client") +} + +func TestGenerateInfoCommandError(t *testing.T) { + mockOsquery := &utils.MockOsqueryClienter{ + Data: map[string][]map[string]string{ + isMacOS15Query: {{"version": "15.0"}}, + }, + } + runner := &utils.MultiMockCmdRunner{ + Commands: map[string]utils.MockCmdRunner{ + "machine": {Err: errors.New("machine failed")}, + "ioreg -d2 -c IOPlatformExpertDevice -a": {Output: mockIOReg}, + "sysctl machdep.cpu.brand_string machdep.cpu.core_count machdep.cpu.thread_count hw.memsize": {Output: mockSysctl}, + "hostname": {Output: "myhostname.local\n"}, + "scutil --get ComputerName": {Output: "mycomputername\n"}, + "scutil --get LocalHostName": {Output: "mylocalhostname\n"}, + }, + } + + _, err := alt_system_info.GenerateInfo(runner, mockOsquery, new(alt_system_info.Cache)) + require.Error(t, err) + assert.ErrorContains(t, err, "could not get cpu type") +}