107 lines
3.2 KiB
Go
107 lines
3.2 KiB
Go
//go:build windows
|
||
|
||
package main
|
||
|
||
import (
|
||
"errors"
|
||
"syscall"
|
||
"testing"
|
||
)
|
||
|
||
func withMessageBoxW(t *testing.T, fn func(hwnd, text, caption, flags uintptr) (uintptr, error)) {
|
||
t.Helper()
|
||
|
||
old := callMessageBoxW
|
||
callMessageBoxW = fn
|
||
t.Cleanup(func() {
|
||
callMessageBoxW = old
|
||
})
|
||
}
|
||
|
||
func TestMessageBoxW_WindowsOnly_InvalidUTF16(t *testing.T) {
|
||
err := messageBox("bad\x00title", "测试消息", mbIconInformation)
|
||
if err == nil {
|
||
t.Fatal("包含 NUL 字符时应该返回错误")
|
||
}
|
||
}
|
||
|
||
func TestMessageBoxW_WindowsOnly_SuccessIgnoresLastError(t *testing.T) {
|
||
withMessageBoxW(t, func(_, _, _, _ uintptr) (uintptr, error) {
|
||
return 1, syscall.Errno(123)
|
||
})
|
||
|
||
if err := messageBox("测试标题", "测试消息", mbIconInformation); err != nil {
|
||
t.Fatalf("MessageBoxW 返回成功时应忽略 last error: %v", err)
|
||
}
|
||
}
|
||
|
||
func TestMessageBoxW_WindowsOnly_FailureUsesReturnValue(t *testing.T) {
|
||
withMessageBoxW(t, func(_, _, _, _ uintptr) (uintptr, error) {
|
||
return 0, syscall.Errno(5)
|
||
})
|
||
|
||
err := messageBox("测试标题", "测试消息", mbIconInformation)
|
||
if !errors.Is(err, syscall.Errno(5)) {
|
||
t.Fatalf("MessageBoxW 返回 0 时应返回调用错误: %v", err)
|
||
}
|
||
}
|
||
|
||
func TestShowError_WindowsBranch(t *testing.T) {
|
||
old := buildPromptChannels
|
||
buildPromptChannels = func(commandRunner) []promptChannel {
|
||
return []promptChannel{{
|
||
name: "fake-failed-channel",
|
||
available: func() error { return nil },
|
||
run: func(promptRequest) error { return syscall.Errno(5) },
|
||
}}
|
||
}
|
||
t.Cleanup(func() { buildPromptChannels = old })
|
||
|
||
defer func() {
|
||
if recovered := recover(); recovered != nil {
|
||
t.Fatalf("showError 不应因 MessageBoxW 失败而 panic: %v", recovered)
|
||
}
|
||
}()
|
||
|
||
showError("测试错误", "这是一条测试错误消息")
|
||
}
|
||
|
||
func TestMessageBoxW_WindowsOnly_StartupFlags(t *testing.T) {
|
||
var gotFlags uintptr
|
||
withMessageBoxW(t, func(_, _, _, flags uintptr) (uintptr, error) {
|
||
gotFlags = flags
|
||
return 1, syscall.Errno(0)
|
||
})
|
||
|
||
if err := messageBox("测试标题", "测试消息", messageBoxStartupFlags()); err != nil {
|
||
t.Fatalf("MessageBoxW 应成功: %v", err)
|
||
}
|
||
|
||
for _, flag := range []uint{mbIconError, mbTaskModal, mbSetForeground, mbTopMost} {
|
||
if gotFlags&uintptr(flag) == 0 {
|
||
t.Fatalf("startup flags 缺少 0x%x,实际: 0x%x", flag, gotFlags)
|
||
}
|
||
}
|
||
}
|
||
|
||
func TestWindowsStartupChannelsUseToastBeforeMessageBox(t *testing.T) {
|
||
runner := &fakeCommandRunner{paths: map[string]bool{"powershell.exe": true}}
|
||
channels := platformStartupChannels(runner)
|
||
if len(channels) != 2 {
|
||
t.Fatalf("Windows 应有 Toast 和 MessageBox 两级通道,实际: %d", len(channels))
|
||
}
|
||
|
||
if channels[0].name != "windows-toast" || channels[1].name != "windows-messagebox" {
|
||
t.Fatalf("Windows 通道顺序错误: %s, %s", channels[0].name, channels[1].name)
|
||
}
|
||
if err := channels[0].available(); err != nil {
|
||
t.Fatalf("PowerShell 存在时 Toast 通道应可用: %v", err)
|
||
}
|
||
if err := channels[0].run(promptRequest{title: "Nex 启动失败", message: "端口被占用"}); err != nil {
|
||
t.Fatalf("Toast fake runner 应执行成功: %v", err)
|
||
}
|
||
if len(runner.calls) != 1 || runner.calls[0].name != "powershell.exe" {
|
||
t.Fatalf("Toast 应调用 powershell.exe,实际: %#v", runner.calls)
|
||
}
|
||
}
|