mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-06-07 06:59:32 +08:00
- 新增 JVM provider 工厂与 JMX、Endpoint 骨架实现 - 暴露 TestJVMConnection 和 JVMProbeCapabilities 并统一 QueryResult 返回 - 刷新 Wails 绑定与 JVM 连接模型,补齐前后端方法签名 - 补充 App 编排测试与 provider 契约测试,避免假成功和静默成功 - 更新需求追踪,记录 Task 2 审查结论与验证证据
241 lines
6.7 KiB
Go
241 lines
6.7 KiB
Go
package app
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"strings"
|
|
"testing"
|
|
|
|
"GoNavi-Wails/internal/connection"
|
|
"GoNavi-Wails/internal/jvm"
|
|
)
|
|
|
|
type fakeJVMProvider struct {
|
|
testErr error
|
|
probe []jvm.Capability
|
|
probeErr error
|
|
list []jvm.ResourceSummary
|
|
value jvm.ValueSnapshot
|
|
apply jvm.ApplyResult
|
|
}
|
|
|
|
func (f fakeJVMProvider) Mode() string { return jvm.ModeJMX }
|
|
func (f fakeJVMProvider) TestConnection(context.Context, connection.ConnectionConfig) error {
|
|
return f.testErr
|
|
}
|
|
func (f fakeJVMProvider) ProbeCapabilities(context.Context, connection.ConnectionConfig) ([]jvm.Capability, error) {
|
|
return f.probe, f.probeErr
|
|
}
|
|
func (f fakeJVMProvider) ListResources(context.Context, connection.ConnectionConfig, string) ([]jvm.ResourceSummary, error) {
|
|
return f.list, nil
|
|
}
|
|
func (f fakeJVMProvider) GetValue(context.Context, connection.ConnectionConfig, string) (jvm.ValueSnapshot, error) {
|
|
return f.value, nil
|
|
}
|
|
func (f fakeJVMProvider) PreviewChange(context.Context, connection.ConnectionConfig, jvm.ChangeRequest) (jvm.ChangePreview, error) {
|
|
return jvm.ChangePreview{Allowed: true, Summary: "preview"}, nil
|
|
}
|
|
func (f fakeJVMProvider) ApplyChange(context.Context, connection.ConnectionConfig, jvm.ChangeRequest) (jvm.ApplyResult, error) {
|
|
return f.apply, nil
|
|
}
|
|
|
|
func swapJVMProviderFactory(factory func(mode string) (jvm.Provider, error)) func() {
|
|
prev := newJVMProvider
|
|
newJVMProvider = factory
|
|
return func() { newJVMProvider = prev }
|
|
}
|
|
|
|
func TestTestJVMConnectionUsesPreferredProvider(t *testing.T) {
|
|
app := NewAppWithSecretStore(nil)
|
|
var gotMode string
|
|
restore := swapJVMProviderFactory(func(mode string) (jvm.Provider, error) {
|
|
gotMode = mode
|
|
return fakeJVMProvider{}, nil
|
|
})
|
|
defer restore()
|
|
|
|
res := app.TestJVMConnection(connection.ConnectionConfig{
|
|
Type: "jvm",
|
|
Host: "orders.internal",
|
|
JVM: connection.JVMConfig{
|
|
PreferredMode: "endpoint",
|
|
AllowedModes: []string{"jmx", "endpoint"},
|
|
},
|
|
})
|
|
|
|
if !res.Success {
|
|
t.Fatalf("expected success, got %+v", res)
|
|
}
|
|
if gotMode != "endpoint" {
|
|
t.Fatalf("expected provider mode endpoint, got %q", gotMode)
|
|
}
|
|
if res.Message != "JVM 连接成功" {
|
|
t.Fatalf("expected success message %q, got %q", "JVM 连接成功", res.Message)
|
|
}
|
|
}
|
|
|
|
func TestTestJVMConnectionReturnsProviderError(t *testing.T) {
|
|
app := NewAppWithSecretStore(nil)
|
|
restore := swapJVMProviderFactory(func(mode string) (jvm.Provider, error) {
|
|
return fakeJVMProvider{testErr: errors.New("dial failed")}, nil
|
|
})
|
|
defer restore()
|
|
|
|
res := app.TestJVMConnection(connection.ConnectionConfig{
|
|
Type: "jvm",
|
|
Host: "orders.internal",
|
|
JVM: connection.JVMConfig{
|
|
PreferredMode: "jmx",
|
|
AllowedModes: []string{"jmx"},
|
|
},
|
|
})
|
|
|
|
if res.Success {
|
|
t.Fatalf("expected failure, got %+v", res)
|
|
}
|
|
if res.Message != "dial failed" {
|
|
t.Fatalf("expected message %q, got %q", "dial failed", res.Message)
|
|
}
|
|
}
|
|
|
|
func TestTestJVMConnectionReturnsProviderFactoryError(t *testing.T) {
|
|
app := NewAppWithSecretStore(nil)
|
|
restore := swapJVMProviderFactory(func(mode string) (jvm.Provider, error) {
|
|
return nil, errors.New("factory unavailable")
|
|
})
|
|
defer restore()
|
|
|
|
res := app.TestJVMConnection(connection.ConnectionConfig{
|
|
Type: "jvm",
|
|
Host: "orders.internal",
|
|
JVM: connection.JVMConfig{
|
|
PreferredMode: "endpoint",
|
|
AllowedModes: []string{"endpoint"},
|
|
},
|
|
})
|
|
|
|
if res.Success {
|
|
t.Fatalf("expected failure, got %+v", res)
|
|
}
|
|
if res.Message != "factory unavailable" {
|
|
t.Fatalf("expected message %q, got %q", "factory unavailable", res.Message)
|
|
}
|
|
}
|
|
|
|
func TestJVMProbeCapabilitiesReturnsCapabilityArray(t *testing.T) {
|
|
app := NewAppWithSecretStore(nil)
|
|
restore := swapJVMProviderFactory(func(mode string) (jvm.Provider, error) {
|
|
return fakeJVMProvider{
|
|
probe: []jvm.Capability{{Mode: jvm.ModeJMX, CanBrowse: true, CanWrite: false, CanPreview: false, DisplayLabel: "JMX"}},
|
|
}, nil
|
|
})
|
|
defer restore()
|
|
|
|
res := app.JVMProbeCapabilities(connection.ConnectionConfig{
|
|
Type: "jvm",
|
|
Host: "orders.internal",
|
|
JVM: connection.JVMConfig{
|
|
PreferredMode: "jmx",
|
|
AllowedModes: []string{"jmx"},
|
|
},
|
|
})
|
|
|
|
if !res.Success {
|
|
t.Fatalf("expected success, got %+v", res)
|
|
}
|
|
items, ok := res.Data.([]jvm.Capability)
|
|
if !ok || len(items) != 1 {
|
|
t.Fatalf("expected one capability, got %#v", res.Data)
|
|
}
|
|
}
|
|
|
|
func TestJVMProbeCapabilitiesIncludesReasonWhenProbeFails(t *testing.T) {
|
|
app := NewAppWithSecretStore(nil)
|
|
restore := swapJVMProviderFactory(func(mode string) (jvm.Provider, error) {
|
|
return fakeJVMProvider{
|
|
probeErr: errors.New("probe failed"),
|
|
}, nil
|
|
})
|
|
defer restore()
|
|
|
|
res := app.JVMProbeCapabilities(connection.ConnectionConfig{
|
|
Type: "jvm",
|
|
Host: "orders.internal",
|
|
JVM: connection.JVMConfig{
|
|
PreferredMode: "jmx",
|
|
AllowedModes: []string{"jmx"},
|
|
},
|
|
})
|
|
|
|
if !res.Success {
|
|
t.Fatalf("expected success, got %+v", res)
|
|
}
|
|
items, ok := res.Data.([]jvm.Capability)
|
|
if !ok || len(items) != 1 {
|
|
t.Fatalf("expected one capability, got %#v", res.Data)
|
|
}
|
|
if items[0].Reason != "probe failed" {
|
|
t.Fatalf("expected reason %q, got %#v", "probe failed", items[0])
|
|
}
|
|
}
|
|
|
|
func TestJVMProbeCapabilitiesIncludesReasonWhenProviderFactoryFails(t *testing.T) {
|
|
app := NewAppWithSecretStore(nil)
|
|
restore := swapJVMProviderFactory(func(mode string) (jvm.Provider, error) {
|
|
return nil, errors.New("provider disabled")
|
|
})
|
|
defer restore()
|
|
|
|
res := app.JVMProbeCapabilities(connection.ConnectionConfig{
|
|
Type: "jvm",
|
|
Host: "orders.internal",
|
|
JVM: connection.JVMConfig{
|
|
PreferredMode: "endpoint",
|
|
AllowedModes: []string{"endpoint"},
|
|
},
|
|
})
|
|
|
|
if !res.Success {
|
|
t.Fatalf("expected success, got %+v", res)
|
|
}
|
|
items, ok := res.Data.([]jvm.Capability)
|
|
if !ok || len(items) != 1 {
|
|
t.Fatalf("expected one capability, got %#v", res.Data)
|
|
}
|
|
if items[0].Reason != "provider disabled" {
|
|
t.Fatalf("expected reason %q, got %#v", "provider disabled", items[0])
|
|
}
|
|
if items[0].DisplayLabel != "Endpoint" {
|
|
t.Fatalf("expected display label %q, got %#v", "Endpoint", items[0])
|
|
}
|
|
}
|
|
|
|
func TestJVMProbeCapabilitiesUsesReadableLabelForUnsupportedMode(t *testing.T) {
|
|
app := NewAppWithSecretStore(nil)
|
|
restore := swapJVMProviderFactory(jvm.NewProvider)
|
|
defer restore()
|
|
|
|
res := app.JVMProbeCapabilities(connection.ConnectionConfig{
|
|
Type: "jvm",
|
|
Host: "orders.internal",
|
|
JVM: connection.JVMConfig{
|
|
PreferredMode: "agent",
|
|
AllowedModes: []string{"agent"},
|
|
},
|
|
})
|
|
|
|
if !res.Success {
|
|
t.Fatalf("expected success, got %+v", res)
|
|
}
|
|
items, ok := res.Data.([]jvm.Capability)
|
|
if !ok || len(items) != 1 {
|
|
t.Fatalf("expected one capability, got %#v", res.Data)
|
|
}
|
|
if items[0].DisplayLabel != "Agent" {
|
|
t.Fatalf("expected display label %q, got %#v", "Agent", items[0])
|
|
}
|
|
if !strings.Contains(items[0].Reason, "unsupported jvm provider mode") {
|
|
t.Fatalf("expected unsupported mode error, got %#v", items[0])
|
|
}
|
|
}
|