diff --git a/tables/macosrsr/rsr.go b/tables/macosrsr/rsr.go
index c0a73fc..3a54c6e 100644
--- a/tables/macosrsr/rsr.go
+++ b/tables/macosrsr/rsr.go
@@ -75,7 +75,9 @@ func generateResults(rsrOutput RSROutput) []map[string]string {
return results
}
-func runSwVersCmd() ([]byte, error) {
+var runSwVersCmd = runSwVersCmdCommand
+
+func runSwVersCmdCommand() ([]byte, error) {
cmd := exec.Command("/usr/bin/sw_vers", "--ProductVersionExtra")
out, err := cmd.Output()
if err != nil {
@@ -113,7 +115,9 @@ func getSystemVersion() (SystemVersionPlist, error) {
return unmarshalSystemVersionBytesToStruct(bytes)
}
-func readSystemVersionPlistToBytes() ([]byte, error) {
+var readSystemVersionPlistToBytes = readSystemVersionPlistToBytesFile
+
+func readSystemVersionPlistToBytesFile() ([]byte, error) {
var byteValue []byte
plistFile, err := os.Open(systemVersionPath)
diff --git a/tables/macosrsr/rsr_test.go b/tables/macosrsr/rsr_test.go
index a346f40..ff274fb 100644
--- a/tables/macosrsr/rsr_test.go
+++ b/tables/macosrsr/rsr_test.go
@@ -1,15 +1,46 @@
package macosrsr
import (
+ "context"
_ "embed"
+ "errors"
"testing"
+ "github.com/osquery/osquery-go/plugin/table"
"github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
)
//go:embed test_SystemVersion.plist
var testSystemVersion []byte
+func withReadSystemVersionPlistToBytes(t *testing.T, fn func() ([]byte, error)) {
+ t.Helper()
+ original := readSystemVersionPlistToBytes
+ readSystemVersionPlistToBytes = fn
+ t.Cleanup(func() {
+ readSystemVersionPlistToBytes = original
+ })
+}
+
+func withRunSwVersCmd(t *testing.T, fn func() ([]byte, error)) {
+ t.Helper()
+ original := runSwVersCmd
+ runSwVersCmd = fn
+ t.Cleanup(func() {
+ runSwVersCmd = original
+ })
+}
+
+func TestMacOSRsrColumns(t *testing.T) {
+ assert.Equal(t, []table.ColumnDefinition{
+ table.TextColumn("rsr_version"),
+ table.TextColumn("macos_version"),
+ table.TextColumn("full_macos_version"),
+ table.TextColumn("rsr_supported"),
+ }, MacOSRsrColumns())
+}
+
func TestMacOSRsrGenerate(t *testing.T) {
t.Parallel()
type testData struct {
@@ -146,6 +177,97 @@ func TestUnmarshalSystemVersionBytesToStruct(t *testing.T) {
assert.Equal(t, expectedOutput, out, "output from unmarshalSystemVersionBytesToStruct does not match expected output")
}
+func TestUnmarshalSystemVersionBytesToStructInvalidPlist(t *testing.T) {
+ t.Parallel()
+ out, err := unmarshalSystemVersionBytesToStruct([]byte("not plist"))
+ assert.Error(t, err)
+ assert.Empty(t, out)
+}
+
+func TestGetSystemVersionReadError(t *testing.T) {
+ withReadSystemVersionPlistToBytes(t, func() ([]byte, error) {
+ return nil, errors.New("read failed")
+ })
+
+ out, err := getSystemVersion()
+ assert.Error(t, err)
+ assert.Empty(t, out)
+ assert.ErrorContains(t, err, "readSystemVersionPlistToBytes")
+}
+
+func TestMacOSRsrGenerateSupportedWithRsr(t *testing.T) {
+ withReadSystemVersionPlistToBytes(t, func() ([]byte, error) {
+ return testSystemVersion, nil
+ })
+ withRunSwVersCmd(t, func() ([]byte, error) {
+ return []byte("(a)\n"), nil
+ })
+
+ rows, err := MacOSRsrGenerate(context.Background(), table.QueryContext{})
+ require.NoError(t, err)
+ assert.Equal(t, []map[string]string{{
+ "full_macos_version": "13.3.1 (a)",
+ "macos_version": "13.3.1",
+ "rsr_supported": "true",
+ "rsr_version": "(a)",
+ }}, rows)
+}
+
+func TestMacOSRsrGenerateUnsupportedSkipsSwVers(t *testing.T) {
+ withReadSystemVersionPlistToBytes(t, func() ([]byte, error) {
+ return []byte(`
+
+
+ProductVersion12.6.1
+ProductBuildVersion21G217
+`), nil
+ })
+ swVersCalled := false
+ withRunSwVersCmd(t, func() ([]byte, error) {
+ swVersCalled = true
+ return []byte("(a)\n"), nil
+ })
+
+ rows, err := MacOSRsrGenerate(context.Background(), table.QueryContext{})
+ require.NoError(t, err)
+ assert.False(t, swVersCalled)
+ assert.Equal(t, []map[string]string{{
+ "full_macos_version": "12.6.1",
+ "macos_version": "12.6.1",
+ "rsr_supported": "false",
+ "rsr_version": "",
+ }}, rows)
+}
+
+func TestMacOSRsrGenerateSwVersError(t *testing.T) {
+ withReadSystemVersionPlistToBytes(t, func() ([]byte, error) {
+ return testSystemVersion, nil
+ })
+ withRunSwVersCmd(t, func() ([]byte, error) {
+ return nil, errors.New("sw_vers failed")
+ })
+
+ rows, err := MacOSRsrGenerate(context.Background(), table.QueryContext{})
+ assert.Error(t, err)
+ assert.Nil(t, rows)
+ assert.ErrorContains(t, err, "run sw_vers command")
+}
+
+func TestMacOSRsrGenerateCompatibilityError(t *testing.T) {
+ withReadSystemVersionPlistToBytes(t, func() ([]byte, error) {
+ return []byte(`
+
+
+ProductVersionnot-a-version
+`), nil
+ })
+
+ rows, err := MacOSRsrGenerate(context.Background(), table.QueryContext{})
+ assert.Error(t, err)
+ assert.Nil(t, rows)
+ assert.ErrorContains(t, err, "rsrCompatible")
+}
+
func TestRsrCompatible(t *testing.T) {
type testData struct {
input SystemVersionPlist