Skip to content

Commit 0c7a472

Browse files
czunkerclaude
andcommitted
🟢 Add Windows-native test coverage for OS provider
Add _windows_test.go files to exercise native Windows code paths (registry API, WMI, IP Helper API, fsutil) that were previously untested. These tests complement the Windows CI workflow from PR #6687. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 7834a12 commit 0c7a472

File tree

5 files changed

+475
-0
lines changed

5 files changed

+475
-0
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright (c) Mondoo, Inc.
2+
// SPDX-License-Identifier: BUSL-1.1
3+
4+
//go:build windows
5+
6+
package windows
7+
8+
import (
9+
"testing"
10+
11+
"github.com/spf13/afero"
12+
"github.com/stretchr/testify/assert"
13+
"github.com/stretchr/testify/require"
14+
"go.mondoo.com/mql/v13/providers-sdk/v1/inventory"
15+
"go.mondoo.com/mql/v13/providers/os/connection/shared"
16+
)
17+
18+
// mockLocalConnection implements shared.Connection and returns Type_Local
19+
type mockLocalConnection struct{}
20+
21+
func (m *mockLocalConnection) ID() uint32 { return 0 }
22+
func (m *mockLocalConnection) ParentID() uint32 { return 0 }
23+
func (m *mockLocalConnection) RunCommand(command string) (*shared.Command, error) { return nil, nil }
24+
func (m *mockLocalConnection) FileInfo(path string) (shared.FileInfoDetails, error) {
25+
return shared.FileInfoDetails{}, nil
26+
}
27+
func (m *mockLocalConnection) FileSystem() afero.Fs { return afero.NewOsFs() }
28+
func (m *mockLocalConnection) Name() string { return "mock-local" }
29+
func (m *mockLocalConnection) Type() shared.ConnectionType { return shared.Type_Local }
30+
func (m *mockLocalConnection) Asset() *inventory.Asset { return &inventory.Asset{} }
31+
func (m *mockLocalConnection) UpdateAsset(asset *inventory.Asset) {}
32+
func (m *mockLocalConnection) Capabilities() shared.Capabilities {
33+
return shared.Capability_None
34+
}
35+
36+
func TestGetWindowsOSBuild_Integration(t *testing.T) {
37+
conn := &mockLocalConnection{}
38+
ver, err := GetWindowsOSBuild(conn)
39+
require.NoError(t, err)
40+
require.NotNil(t, ver)
41+
42+
assert.NotEmpty(t, ver.CurrentBuild, "CurrentBuild should not be empty")
43+
assert.NotEmpty(t, ver.ProductName, "ProductName should not be empty")
44+
assert.NotEmpty(t, ver.Architecture, "Architecture should not be empty")
45+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Copyright (c) Mondoo, Inc.
2+
// SPDX-License-Identifier: BUSL-1.1
3+
4+
//go:build windows
5+
6+
package windows
7+
8+
import (
9+
"testing"
10+
11+
"github.com/stretchr/testify/assert"
12+
"github.com/stretchr/testify/require"
13+
)
14+
15+
func TestToString(t *testing.T) {
16+
t.Run("nil returns empty string", func(t *testing.T) {
17+
assert.Equal(t, "", toString(nil))
18+
})
19+
20+
t.Run("non-nil returns value", func(t *testing.T) {
21+
s := "hello"
22+
assert.Equal(t, "hello", toString(&s))
23+
})
24+
25+
t.Run("empty string returns empty string", func(t *testing.T) {
26+
s := ""
27+
assert.Equal(t, "", toString(&s))
28+
})
29+
}
30+
31+
func TestIntToString(t *testing.T) {
32+
t.Run("nil returns empty string", func(t *testing.T) {
33+
assert.Equal(t, "", intToString(nil))
34+
})
35+
36+
t.Run("non-nil returns string representation", func(t *testing.T) {
37+
i := 42
38+
assert.Equal(t, "42", intToString(&i))
39+
})
40+
41+
t.Run("zero returns 0", func(t *testing.T) {
42+
i := 0
43+
assert.Equal(t, "0", intToString(&i))
44+
})
45+
}
46+
47+
func TestGetWmiInformation_Integration(t *testing.T) {
48+
// Reuse the same mock connection type from build_version_windows_test.go
49+
conn := &mockLocalConnection{}
50+
info, err := GetWmiInformation(conn)
51+
require.NoError(t, err)
52+
require.NotNil(t, info)
53+
54+
assert.NotEmpty(t, info.Version, "Version should not be empty")
55+
assert.NotEmpty(t, info.BuildNumber, "BuildNumber should not be empty")
56+
assert.NotEmpty(t, info.Caption, "Caption should not be empty")
57+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// Copyright (c) Mondoo, Inc.
2+
// SPDX-License-Identifier: BUSL-1.1
3+
4+
//go:build windows
5+
6+
package fsutil
7+
8+
import (
9+
"errors"
10+
"os"
11+
"testing"
12+
13+
"github.com/stretchr/testify/assert"
14+
"github.com/stretchr/testify/require"
15+
)
16+
17+
func TestHandleFsError(t *testing.T) {
18+
tests := []struct {
19+
name string
20+
err error
21+
wantSkip bool
22+
wantErr error
23+
}{
24+
{
25+
name: "nil error",
26+
err: nil,
27+
wantSkip: false,
28+
wantErr: nil,
29+
},
30+
{
31+
name: "permission denied is skipped",
32+
err: os.ErrPermission,
33+
wantSkip: true,
34+
wantErr: nil,
35+
},
36+
{
37+
name: "not exist is skipped",
38+
err: os.ErrNotExist,
39+
wantSkip: true,
40+
wantErr: nil,
41+
},
42+
{
43+
name: "invalid is skipped",
44+
err: os.ErrInvalid,
45+
wantSkip: true,
46+
wantErr: nil,
47+
},
48+
{
49+
name: "other error is propagated",
50+
err: errors.New("some other error"),
51+
wantSkip: true,
52+
wantErr: errors.New("some other error"),
53+
},
54+
}
55+
56+
for _, tt := range tests {
57+
t.Run(tt.name, func(t *testing.T) {
58+
skip, err := handleFsError(tt.err)
59+
assert.Equal(t, tt.wantSkip, skip)
60+
if tt.wantErr != nil {
61+
require.Error(t, err)
62+
assert.Equal(t, tt.wantErr.Error(), err.Error())
63+
} else {
64+
require.NoError(t, err)
65+
}
66+
})
67+
}
68+
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
// Copyright (c) Mondoo, Inc.
2+
// SPDX-License-Identifier: BUSL-1.1
3+
4+
//go:build windows
5+
6+
package registry
7+
8+
import (
9+
"testing"
10+
11+
"github.com/stretchr/testify/assert"
12+
"github.com/stretchr/testify/require"
13+
"golang.org/x/sys/windows/registry"
14+
)
15+
16+
func TestParseRegistryKeyPath(t *testing.T) {
17+
tests := []struct {
18+
name string
19+
path string
20+
wantKey registry.Key
21+
wantPath string
22+
wantErr bool
23+
errContains string
24+
}{
25+
{
26+
name: "HKEY_LOCAL_MACHINE full prefix",
27+
path: `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft`,
28+
wantKey: registry.LOCAL_MACHINE,
29+
wantPath: `SOFTWARE\Microsoft`,
30+
},
31+
{
32+
name: "HKLM short prefix",
33+
path: `HKLM\SOFTWARE\Microsoft`,
34+
wantKey: registry.LOCAL_MACHINE,
35+
wantPath: `SOFTWARE\Microsoft`,
36+
},
37+
{
38+
name: "HKEY_CURRENT_USER full prefix",
39+
path: `HKEY_CURRENT_USER\Software\Classes`,
40+
wantKey: registry.CURRENT_USER,
41+
wantPath: `Software\Classes`,
42+
},
43+
{
44+
name: "HKCU short prefix",
45+
path: `HKCU\Software\Classes`,
46+
wantKey: registry.CURRENT_USER,
47+
wantPath: `Software\Classes`,
48+
},
49+
{
50+
name: "HKEY_USERS prefix",
51+
path: `HKEY_USERS\.DEFAULT`,
52+
wantKey: registry.USERS,
53+
wantPath: `.DEFAULT`,
54+
},
55+
{
56+
name: "invalid hive returns error",
57+
path: `HKEY_INVALID\Some\Path`,
58+
wantErr: true,
59+
errContains: "invalid registry key hive",
60+
},
61+
}
62+
63+
for _, tt := range tests {
64+
t.Run(tt.name, func(t *testing.T) {
65+
key, path, err := parseRegistryKeyPath(tt.path)
66+
if tt.wantErr {
67+
require.Error(t, err)
68+
assert.Contains(t, err.Error(), tt.errContains)
69+
return
70+
}
71+
require.NoError(t, err)
72+
assert.Equal(t, tt.wantKey, key)
73+
assert.Equal(t, tt.wantPath, path)
74+
})
75+
}
76+
}
77+
78+
func TestGetNativeRegistryKeyItems_Integration(t *testing.T) {
79+
// This key exists on every Windows installation
80+
items, err := GetNativeRegistryKeyItems(`HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion`)
81+
require.NoError(t, err)
82+
require.NotEmpty(t, items, "CurrentVersion should have registry values")
83+
84+
// Check that well-known values exist
85+
found := make(map[string]bool)
86+
for _, item := range items {
87+
found[item.Key] = true
88+
}
89+
assert.True(t, found["CurrentBuild"], "expected CurrentBuild value")
90+
assert.True(t, found["ProductName"], "expected ProductName value")
91+
}
92+
93+
func TestGetNativeRegistryKeyChildren_Integration(t *testing.T) {
94+
// This key exists on every Windows installation and has children
95+
children, err := GetNativeRegistryKeyChildren(`HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft`)
96+
require.NoError(t, err)
97+
require.NotEmpty(t, children, "HKLM\\SOFTWARE\\Microsoft should have subkeys")
98+
99+
// Check that at least "Windows NT" subkey exists
100+
found := false
101+
for _, child := range children {
102+
if child.Name == "Windows NT" {
103+
found = true
104+
break
105+
}
106+
}
107+
assert.True(t, found, "expected 'Windows NT' subkey under HKLM\\SOFTWARE\\Microsoft")
108+
}
109+
110+
func TestGetNativeRegistryKeyItems_NotFound(t *testing.T) {
111+
_, err := GetNativeRegistryKeyItems(`HKEY_LOCAL_MACHINE\SOFTWARE\NonExistentKey12345`)
112+
require.Error(t, err)
113+
}

0 commit comments

Comments
 (0)