Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 50 additions & 1 deletion idownloadjob_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ limitations under the License.

package windowsupdate

import "testing"
import (
"testing"

"github.com/go-ole/go-ole"
)

func TestToIDownloadJob_NilDispatch(t *testing.T) {
result, err := toIDownloadJob(nil)
Expand Down Expand Up @@ -64,3 +68,48 @@ func TestIDownloadJob_Methods_NilDispatch(t *testing.T) {
}
}()
}

// TestIDownloadJob_BeginDownloadAndMethods exercises toIDownloadJob, CleanUp, RequestAbort, GetProgress via real COM.
func TestIDownloadJob_BeginDownloadAndMethods(t *testing.T) {
ole.CoInitialize(0)
defer ole.CoUninitialize()

session, err := NewUpdateSession()
if err != nil {
t.Fatalf("NewUpdateSession failed: %v", err)
}

downloader, err := session.CreateUpdateDownloader()
if err != nil {
t.Fatalf("CreateUpdateDownloader failed: %v", err)
}

// BeginDownload with empty updates yields a job that completes immediately or very quickly
job, err := downloader.BeginDownload([]*IUpdate{})
if err != nil {
t.Skipf("BeginDownload failed (may need WU service): %v", err)
return
}
if job == nil {
t.Fatal("BeginDownload returned nil job")
}

// GetProgress returns current progress (covers toIDownloadProgress path when used from job)
progress, err := job.GetProgress()
if err != nil {
t.Logf("GetProgress returned error (non-fatal): %v", err)
}
if progress != nil {
// If we got progress, calling GetUpdateResult(0) covers IDownloadProgress.GetUpdateResult
_, _ = progress.GetUpdateResult(0)
}

// RequestAbort before CleanUp so disp is still valid
_ = job.RequestAbort()

// CleanUp releases resources; safe to call on completed job
err = job.CleanUp()
if err != nil {
t.Logf("CleanUp returned error (non-fatal): %v", err)
}
}
4 changes: 4 additions & 0 deletions idownloadresult.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ type IDownloadResult struct {
}

func toIDownloadResult(downloadResultDisp *ole.IDispatch) (*IDownloadResult, error) {
if downloadResultDisp == nil {
return nil, nil
}

var err error
iDownloadResult := &IDownloadResult{
disp: downloadResultDisp,
Expand Down
31 changes: 9 additions & 22 deletions idownloadresult_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,30 +64,17 @@ func TestIDownloadResult_ResultCodes(t *testing.T) {
}
}

// TestToIDownloadResult_NilDispatch covers the nil-dispatch path of toIDownloadResult.
func TestToIDownloadResult_NilDispatch(t *testing.T) {
defer func() {
// If a panic occurs when using a nil dispatch, that's acceptable
// as the COM layer may not handle nil pointers uniformly.
_ = recover()
}()

result, err := toIDownloadResult(nil)
if err == nil && result != nil {
t.Errorf("expected error or panic for nil dispatch, got result=%v, err=%v", result, err)
}
}

func TestIDownloadResult_GetUpdateResult_NilDispatch(t *testing.T) {
defer func() {
// Allow panic as a valid behavior when the underlying COM dispatch is nil.
_ = recover()
}()

dr := &IDownloadResult{
disp: nil,
if err != nil {
t.Errorf("expected no error for nil dispatch, got %v", err)
}
updateResult, err := dr.GetUpdateResult(0)
if err == nil && updateResult != nil {
t.Errorf("expected error or panic for nil dispatch, got result=%v, err=%v", updateResult, err)
if result != nil {
t.Errorf("expected nil result for nil dispatch, got %v", result)
}
}

// Note: toIDownloadResult with real COM and GetUpdateResult are covered by
// TestIUpdateDownloader_Download_EmptyUpdates and TestIUpdateDownloader_BeginDownloadEndDownload
// in iupdatedownloader_test.go when run on Windows.
4 changes: 4 additions & 0 deletions iimageinformation.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ type IImageInformation struct {
}

func toIImageInformation(imageInformationDisp *ole.IDispatch) (*IImageInformation, error) {
if imageInformationDisp == nil {
return nil, nil
}

var err error
iImageInformation := &IImageInformation{
disp: imageInformationDisp,
Expand Down
21 changes: 10 additions & 11 deletions iimageinformation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@ package windowsupdate

import "testing"

func TestToIImageInformation_NilDispatch(t *testing.T) {
result, err := toIImageInformation(nil)
if err != nil {
t.Errorf("expected no error for nil dispatch, got %v", err)
}
if result != nil {
t.Errorf("expected nil result for nil dispatch, got %v", result)
}
}

func TestIImageInformation_StructureFields(t *testing.T) {
image := &IImageInformation{
AltText: "Image alt text",
Expand All @@ -38,14 +48,3 @@ func TestIImageInformation_StructureFields(t *testing.T) {
t.Errorf("Source not set correctly, got %s", image.Source)
}
}

func TestToIImageInformation_NilDispatch(t *testing.T) {
defer func() {
_ = recover()
}()

result, err := toIImageInformation(nil)
if err == nil && result != nil {
t.Errorf("expected error or panic for nil dispatch, got result=%v, err=%v", result, err)
}
}
40 changes: 40 additions & 0 deletions iinstallationjob_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,43 @@ func TestIInstallationJob_Methods(t *testing.T) {
t.Error("IsCompleted should be true")
}
}

// TestIInstallationJob_BeginInstallAndMethods exercises toIInstallationJob, CleanUp, RequestAbort, GetProgress via real COM.
func TestIInstallationJob_BeginInstallAndMethods(t *testing.T) {
ole.CoInitialize(0)
defer ole.CoUninitialize()

session, err := NewUpdateSession()
if err != nil {
t.Fatalf("NewUpdateSession failed: %v", err)
}

installer, err := session.CreateUpdateInstaller()
if err != nil {
t.Fatalf("CreateUpdateInstaller failed: %v", err)
}

job, err := installer.BeginInstall([]*IUpdate{})
if err != nil {
t.Skipf("BeginInstall failed (may need WU service): %v", err)
return
}
if job == nil {
t.Fatal("BeginInstall returned nil job")
}

// GetProgress covers toIInstallationProgress and IInstallationProgress.GetUpdateResult when progress is used
progress, err := job.GetProgress()
if err != nil {
t.Logf("GetProgress returned error (non-fatal): %v", err)
}
if progress != nil {
_, _ = progress.GetUpdateResult(0)
}

_ = job.RequestAbort()
err = job.CleanUp()
if err != nil {
t.Logf("CleanUp returned error (non-fatal): %v", err)
}
}
4 changes: 4 additions & 0 deletions iinstallationresult.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ type IInstallationResult struct {
}

func toIInstallationResult(installationResultDisp *ole.IDispatch) (*IInstallationResult, error) {
if installationResultDisp == nil {
return nil, nil
}

var err error
iInstallationResult := &IInstallationResult{
disp: installationResultDisp,
Expand Down
35 changes: 10 additions & 25 deletions iinstallationresult_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@ package windowsupdate

import "testing"

func TestToIInstallationResult_NilDispatch(t *testing.T) {
result, err := toIInstallationResult(nil)
if err != nil {
t.Errorf("expected no error for nil dispatch, got %v", err)
}
if result != nil {
t.Errorf("expected nil result for nil dispatch, got %v", result)
}
}

func TestIInstallationResult_StructureFields(t *testing.T) {
result := &IInstallationResult{
HResult: 0,
Expand Down Expand Up @@ -76,28 +86,3 @@ func TestIInstallationResult_ErrorScenarios(t *testing.T) {
})
}
}

func TestToIInstallationResult_NilDispatch(t *testing.T) {
defer func() {
_ = recover()
}()

result, err := toIInstallationResult(nil)
if err == nil && result != nil {
t.Errorf("expected error or panic for nil dispatch, got result=%v, err=%v", result, err)
}
}

func TestIInstallationResult_GetUpdateResult_NilDispatch(t *testing.T) {
defer func() {
_ = recover()
}()

ir := &IInstallationResult{
disp: nil,
}
updateResult, err := ir.GetUpdateResult(0)
if err == nil && updateResult != nil {
t.Errorf("expected error or panic for nil dispatch, got result=%v, err=%v", updateResult, err)
}
}
39 changes: 38 additions & 1 deletion isearchjob_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ limitations under the License.

package windowsupdate

import "testing"
import (
"testing"

"github.com/go-ole/go-ole"
)

func TestToISearchJob_NilDispatch(t *testing.T) {
result, err := toISearchJob(nil)
Expand Down Expand Up @@ -55,3 +59,36 @@ func TestISearchJob_Methods_NilDispatch(t *testing.T) {
_ = job.RequestAbort()
}()
}

// TestISearchJob_CleanUpRequestAbort exercises CleanUp and RequestAbort via a real search job from BeginSearch.
func TestISearchJob_CleanUpRequestAbort(t *testing.T) {
ole.CoInitialize(0)
defer ole.CoUninitialize()

session, err := NewUpdateSession()
if err != nil {
t.Fatalf("NewUpdateSession failed: %v", err)
}

searcher, err := session.CreateUpdateSearcher()
if err != nil {
t.Fatalf("CreateUpdateSearcher failed: %v", err)
}

job, err := searcher.BeginSearch("IsInstalled=1")
if err != nil {
t.Skipf("BeginSearch failed: %v", err)
return
}
if job == nil {
t.Fatal("BeginSearch returned nil job")
}

// RequestAbort before CleanUp so disp is still valid
_ = job.RequestAbort()

err = job.CleanUp()
if err != nil {
t.Logf("CleanUp returned error (non-fatal): %v", err)
}
}
61 changes: 61 additions & 0 deletions iupdatedownloader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,64 @@ func TestIUpdateDownloader_Methods_NilDispatch(t *testing.T) {
}
}()
}

// TestIUpdateDownloader_Download_EmptyUpdates exercises toIDownloadResult via Download with no updates.
func TestIUpdateDownloader_Download_EmptyUpdates(t *testing.T) {
ole.CoInitialize(0)
defer ole.CoUninitialize()

session, err := NewUpdateSession()
if err != nil {
t.Fatalf("NewUpdateSession failed: %v", err)
}

downloader, err := session.CreateUpdateDownloader()
if err != nil {
t.Fatalf("CreateUpdateDownloader failed: %v", err)
}

result, err := downloader.Download([]*IUpdate{})
if err != nil {
t.Skipf("Download with empty updates failed (may need WU service): %v", err)
return
}
if result == nil {
t.Fatal("Download returned nil result")
}
// Cover IDownloadResult.GetUpdateResult (may error for index 0 on empty result)
_, _ = result.GetUpdateResult(0)
}

// TestIUpdateDownloader_BeginDownloadEndDownload exercises toIDownloadResult via EndDownload.
func TestIUpdateDownloader_BeginDownloadEndDownload(t *testing.T) {
ole.CoInitialize(0)
defer ole.CoUninitialize()

session, err := NewUpdateSession()
if err != nil {
t.Fatalf("NewUpdateSession failed: %v", err)
}

downloader, err := session.CreateUpdateDownloader()
if err != nil {
t.Fatalf("CreateUpdateDownloader failed: %v", err)
}

job, err := downloader.BeginDownload([]*IUpdate{})
if err != nil {
t.Skipf("BeginDownload failed: %v", err)
return
}
if job == nil {
t.Fatal("BeginDownload returned nil job")
}

result, err := downloader.EndDownload(job)
if err != nil {
t.Skipf("EndDownload failed (job may not be complete): %v", err)
return
}
if result != nil {
_, _ = result.GetUpdateResult(0)
}
}
Loading