mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-06-14 02:19:58 +08:00
🐛 fix(driver-manager/sql-editor): 优化驱动代理更新提示和事务提交控件
- 调整 driver-agent revision 为提示性校验,允许旧代理继续安装使用并保留需重装提示 - 精简 SQL 编辑器 DML 事务模式与自动提交档位展示 - 补充旧 revision 安装回归和事务控件断言
This commit is contained in:
@@ -3727,9 +3727,12 @@ describe('QueryEditor external SQL save', () => {
|
||||
expect(transactionSettingsSource).toContain('gn-v2-query-toolbar-transaction-mode-select');
|
||||
expect(transactionSettingsSource).toContain('gn-v2-query-toolbar-transaction-delay-select');
|
||||
expect(transactionSettingsSource).toContain('参考 DBeaver');
|
||||
expect(transactionSettingsSource).toContain("label: '手动提交'");
|
||||
expect(transactionSettingsSource).toContain("label: '自动提交'");
|
||||
expect(transactionSettingsSource).toContain("label: '手动'");
|
||||
expect(transactionSettingsSource).toContain("label: '自动'");
|
||||
expect(transactionSettingsSource).not.toContain("label: '手动提交'");
|
||||
expect(transactionSettingsSource).not.toContain("label: '自动提交'");
|
||||
expect(transactionSettingsSource).toContain("label: '立即'");
|
||||
expect(transactionSettingsSource).toContain("label: '3s'");
|
||||
expect(source).toContain('QueryEditorTransactionToolbar');
|
||||
expect(transactionToolbarSource).toContain("className={isV2Ui ? 'gn-v2-query-transaction-toolbar' : undefined}");
|
||||
expect(transactionToolbarSource).toContain("'未提交'");
|
||||
@@ -3738,12 +3741,15 @@ describe('QueryEditor external SQL save', () => {
|
||||
expect(transactionToolbarSource).toContain("'自动提交中'");
|
||||
expect(transactionToolbarSource).toContain('onFinish');
|
||||
expect(toolbarSource).toContain('gn-v2-query-toolbar-action-group');
|
||||
expect(transactionSettingsSource).toContain('style={isV2Ui ? undefined : { width: 118 }}');
|
||||
expect(transactionSettingsSource).toContain('style={isV2Ui ? undefined : { width: 78 }}');
|
||||
expect(transactionSettingsSource).toContain('style={isV2Ui ? undefined : { width: 68 }}');
|
||||
expect(toolbarSource).toContain('style={isV2Ui ? undefined : { width: 200 }}');
|
||||
expect(toolbarSource).toContain('style={isV2Ui ? undefined : { width: 170 }}');
|
||||
|
||||
expect(css).toContain('body[data-ui-version="v2"] .gn-v2-query-toolbar-selects');
|
||||
expect(css).toContain('body[data-ui-version="v2"] .gn-v2-query-toolbar-actions');
|
||||
expect(css).toContain('width: 74px !important;');
|
||||
expect(css).toContain('width: 62px !important;');
|
||||
expect(css).toContain('flex: 0 1 auto !important;');
|
||||
expect(css).toContain('justify-content: flex-start;');
|
||||
expect(css).toContain('height: 32px !important;');
|
||||
@@ -3755,8 +3761,6 @@ describe('QueryEditor external SQL save', () => {
|
||||
expect(css).toContain('width: 140px !important;');
|
||||
expect(css).toContain('width: 166px !important;');
|
||||
expect(css).toContain('width: 132px !important;');
|
||||
expect(css).toContain('width: 118px !important;');
|
||||
expect(css).toContain('width: 82px !important;');
|
||||
expect(css).toContain('width: 34px !important;');
|
||||
expect(css).toContain('@media (max-width: 900px)');
|
||||
|
||||
|
||||
@@ -5,10 +5,10 @@ export type SqlEditorCommitMode = 'manual' | 'auto';
|
||||
|
||||
export const SQL_EDITOR_AUTO_COMMIT_DELAY_OPTIONS = [
|
||||
{ value: 0, label: '立即' },
|
||||
{ value: 3000, label: '3 秒后' },
|
||||
{ value: 5000, label: '5 秒后' },
|
||||
{ value: 10000, label: '10 秒后' },
|
||||
{ value: 30000, label: '30 秒后' },
|
||||
{ value: 3000, label: '3s' },
|
||||
{ value: 5000, label: '5s' },
|
||||
{ value: 10000, label: '10s' },
|
||||
{ value: 30000, label: '30s' },
|
||||
];
|
||||
|
||||
type QueryEditorTransactionSettingsProps = {
|
||||
@@ -30,19 +30,19 @@ const QueryEditorTransactionSettings: React.FC<QueryEditorTransactionSettingsPro
|
||||
<Tooltip title="参考 DBeaver:SQL 编辑器执行 INSERT/UPDATE/DELETE/MERGE/REPLACE 等 DML 时先进入 GoNavi 托管事务;手动提交需要手动提交/回滚,自动提交会在执行成功后自动 COMMIT。">
|
||||
<Select
|
||||
className={isV2Ui ? 'gn-v2-query-toolbar-select gn-v2-query-toolbar-transaction-mode-select' : undefined}
|
||||
style={isV2Ui ? undefined : { width: 118 }}
|
||||
style={isV2Ui ? undefined : { width: 78 }}
|
||||
value={commitMode}
|
||||
onChange={(mode) => onCommitModeChange(mode === 'auto' ? 'auto' : 'manual')}
|
||||
options={[
|
||||
{ label: '手动提交', value: 'manual' },
|
||||
{ label: '自动提交', value: 'auto' },
|
||||
{ label: '手动', value: 'manual' },
|
||||
{ label: '自动', value: 'auto' },
|
||||
]}
|
||||
/>
|
||||
</Tooltip>
|
||||
{commitMode === 'auto' && (
|
||||
<Select
|
||||
className={isV2Ui ? 'gn-v2-query-toolbar-select gn-v2-query-toolbar-transaction-delay-select' : undefined}
|
||||
style={isV2Ui ? undefined : { width: 96 }}
|
||||
style={isV2Ui ? undefined : { width: 68 }}
|
||||
value={autoCommitDelayMs}
|
||||
onChange={(delayMs) => onAutoCommitDelayMsChange(Number(delayMs))}
|
||||
options={SQL_EDITOR_AUTO_COMMIT_DELAY_OPTIONS}
|
||||
|
||||
@@ -4840,13 +4840,13 @@ body[data-ui-version="v2"] .gn-v2-query-toolbar-max-rows-select {
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-query-toolbar-transaction-mode-select {
|
||||
width: 118px !important;
|
||||
flex: 0 0 118px !important;
|
||||
width: 74px !important;
|
||||
flex: 0 0 74px !important;
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-query-toolbar-transaction-delay-select {
|
||||
width: 82px !important;
|
||||
flex: 0 0 82px !important;
|
||||
width: 62px !important;
|
||||
flex: 0 0 62px !important;
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-query-toolbar .ant-select-selector {
|
||||
@@ -4891,15 +4891,19 @@ body[data-ui-version="v2"] .gn-v2-query-transaction-commit-button {
|
||||
display: inline-flex !important;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
border-color: transparent !important;
|
||||
background: var(--gn-accent-soft) !important;
|
||||
color: var(--gn-accent-2) !important;
|
||||
font-weight: 750 !important;
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-query-transaction-commit-button .gn-v2-toolbar-kbd {
|
||||
margin-left: 0;
|
||||
min-width: 18px;
|
||||
justify-content: center;
|
||||
background: rgba(255, 255, 255, 0.18);
|
||||
color: #fff;
|
||||
border-color: rgba(255, 255, 255, 0.22);
|
||||
border: none;
|
||||
background: rgba(22, 163, 74, 0.18);
|
||||
color: var(--gn-accent-2);
|
||||
}
|
||||
|
||||
body[data-ui-version="v2"] .gn-v2-query-toolbar-icon-action.ant-btn,
|
||||
|
||||
@@ -2868,6 +2868,33 @@ func verifyInstalledOptionalDriverAgentRevision(driverType string, executablePat
|
||||
return actual, nil
|
||||
}
|
||||
|
||||
func observeInstalledOptionalDriverAgentRevision(driverType string, executablePath string, selectedVersion string) string {
|
||||
if !shouldVerifyOptionalDriverAgentRevision(driverType, selectedVersion) {
|
||||
return ""
|
||||
}
|
||||
expected := strings.TrimSpace(db.OptionalDriverAgentRevision(driverType))
|
||||
actual, current, err := optionalDriverAgentRevisionCurrent(driverType, executablePath)
|
||||
if expected == "" {
|
||||
return strings.TrimSpace(actual)
|
||||
}
|
||||
displayName := resolveDriverDisplayName(driverDefinition{Type: driverType})
|
||||
if err != nil {
|
||||
logger.Warnf("%s 驱动代理版本元数据不可用,已保留安装:path=%s version=%s err=%v;建议在驱动管理中重装",
|
||||
displayName, executablePath, normalizeVersion(selectedVersion), err)
|
||||
return ""
|
||||
}
|
||||
actual = strings.TrimSpace(actual)
|
||||
if !current {
|
||||
actualLabel := actual
|
||||
if actualLabel == "" {
|
||||
actualLabel = "空"
|
||||
}
|
||||
logger.Warnf("%s 驱动代理 revision 不匹配,已保留安装:已安装=%s 当前需要=%s path=%s version=%s;建议在驱动管理中重装",
|
||||
displayName, actualLabel, expected, executablePath, normalizeVersion(selectedVersion))
|
||||
}
|
||||
return actual
|
||||
}
|
||||
|
||||
func shouldVerifyOptionalDriverAgentRevision(driverType string, selectedVersion string) bool {
|
||||
switch normalizeDriverType(driverType) {
|
||||
case "mongodb":
|
||||
@@ -2963,10 +2990,7 @@ func installOptionalDriverAgentPackage(a *App, definition driverDefinition, sele
|
||||
if strings.TrimSpace(downloadSource) == "" {
|
||||
downloadSource = strings.TrimSpace(downloadURL)
|
||||
}
|
||||
agentRevision, revisionErr := verifyInstalledOptionalDriverAgentRevision(driverType, runtimePath, selectedVersion)
|
||||
if revisionErr != nil {
|
||||
return installedDriverPackage{}, revisionErr
|
||||
}
|
||||
agentRevision := observeInstalledOptionalDriverAgentRevision(driverType, runtimePath, selectedVersion)
|
||||
return installedDriverPackage{
|
||||
DriverType: driverType,
|
||||
Version: strings.TrimSpace(selectedVersion),
|
||||
@@ -3039,10 +3063,7 @@ func installOptionalDriverAgentFromLocalPath(definition driverDefinition, filePa
|
||||
return installedDriverPackage{}, validateErr
|
||||
}
|
||||
|
||||
agentRevision, revisionErr := verifyInstalledOptionalDriverAgentRevision(driverType, executablePath, selectedVersion)
|
||||
if revisionErr != nil {
|
||||
return installedDriverPackage{}, revisionErr
|
||||
}
|
||||
agentRevision := observeInstalledOptionalDriverAgentRevision(driverType, executablePath, selectedVersion)
|
||||
hash, hashErr := hashFileSHA256(executablePath)
|
||||
if hashErr != nil {
|
||||
return installedDriverPackage{}, fmt.Errorf("计算 %s 驱动代理摘要失败:%w", displayName, hashErr)
|
||||
@@ -3403,15 +3424,8 @@ func ensureOptionalDriverAgentBinary(a *App, definition driverDefinition, execut
|
||||
if a != nil {
|
||||
a.emitDriverDownloadProgress(driverType, "downloading", 10, 100, planMessage)
|
||||
}
|
||||
validateInstalledCandidateRevision := func() error {
|
||||
if _, revisionErr := verifyInstalledOptionalDriverAgentRevision(driverType, executablePath, selectedVersion); revisionErr != nil {
|
||||
_ = os.Remove(executablePath)
|
||||
for _, supportName := range optionalDriverSupportFileNames(driverType) {
|
||||
_ = os.Remove(filepath.Join(filepath.Dir(executablePath), supportName))
|
||||
}
|
||||
return revisionErr
|
||||
}
|
||||
return nil
|
||||
observeInstalledCandidateRevision := func() {
|
||||
observeInstalledOptionalDriverAgentRevision(driverType, executablePath, selectedVersion)
|
||||
}
|
||||
if !skipReuseCandidate {
|
||||
if sourcePath, ok := findExistingOptionalDriverAgentCandidate(definition, executablePath); ok {
|
||||
@@ -3426,9 +3440,7 @@ func ensureOptionalDriverAgentBinary(a *App, definition driverDefinition, execut
|
||||
if hashErr != nil {
|
||||
return "", "", fmt.Errorf("计算预置 %s 驱动代理摘要失败:%w", displayName, hashErr)
|
||||
}
|
||||
if revisionErr := validateInstalledCandidateRevision(); revisionErr != nil {
|
||||
return "", "", fmt.Errorf("预置 %s 驱动代理 revision 校验失败(来源:%s):%w", displayName, sourcePath, revisionErr)
|
||||
}
|
||||
observeInstalledCandidateRevision()
|
||||
return "file://" + sourcePath, hash, nil
|
||||
}
|
||||
}
|
||||
@@ -3463,11 +3475,7 @@ func ensureOptionalDriverAgentBinary(a *App, definition driverDefinition, execut
|
||||
}
|
||||
hash, dlErr := downloadOptionalDriverAgentBinary(a, definition, candidateURL, executablePath)
|
||||
if dlErr == nil {
|
||||
if revisionErr := validateInstalledCandidateRevision(); revisionErr != nil {
|
||||
logger.Warnf("预编译 %s 驱动代理 revision 校验失败,url=%s err=%v", displayName, candidateURL, revisionErr)
|
||||
downloadErrs = appendOptionalDriverAttemptError(downloadErrs, candidateURL, revisionErr)
|
||||
continue
|
||||
}
|
||||
observeInstalledCandidateRevision()
|
||||
return candidateURL, hash, nil
|
||||
}
|
||||
logger.Warnf("下载预编译 %s 驱动代理失败,url=%s err=%v", displayName, candidateURL, dlErr)
|
||||
@@ -3486,11 +3494,7 @@ func ensureOptionalDriverAgentBinary(a *App, definition driverDefinition, execut
|
||||
}
|
||||
source, hash, bundleErr := downloadOptionalDriverAgentFromBundle(a, definition, bundleURL, executablePath)
|
||||
if bundleErr == nil {
|
||||
if revisionErr := validateInstalledCandidateRevision(); revisionErr != nil {
|
||||
logger.Warnf("驱动总包 %s 代理 revision 校验失败,source=%s err=%v", displayName, source, revisionErr)
|
||||
downloadErrs = appendOptionalDriverAttemptError(downloadErrs, source, revisionErr)
|
||||
continue
|
||||
}
|
||||
observeInstalledCandidateRevision()
|
||||
return source, hash, nil
|
||||
}
|
||||
logger.Warnf("从驱动总包提取 %s 驱动代理失败,url=%s err=%v", displayName, bundleURL, bundleErr)
|
||||
@@ -4922,7 +4926,7 @@ func findExistingOptionalDriverAgentCandidate(definition driverDefinition, targe
|
||||
if validateErr := validateOptionalDriverAgentExecutableFunc(driverType, absPath); validateErr != nil {
|
||||
continue
|
||||
}
|
||||
if !isReusableOptionalDriverAgentRevisionCurrent(driverType, absPath) {
|
||||
if !isReusableOptionalDriverAgentCandidateRevisionAcceptable(driverType, absPath) {
|
||||
continue
|
||||
}
|
||||
return absPath, true
|
||||
@@ -4930,7 +4934,7 @@ func findExistingOptionalDriverAgentCandidate(definition driverDefinition, targe
|
||||
return "", false
|
||||
}
|
||||
|
||||
func isReusableOptionalDriverAgentRevisionCurrent(driverType string, executablePath string) bool {
|
||||
func isReusableOptionalDriverAgentCandidateRevisionAcceptable(driverType string, executablePath string) bool {
|
||||
expected := strings.TrimSpace(db.OptionalDriverAgentRevision(driverType))
|
||||
if expected == "" {
|
||||
return true
|
||||
@@ -4938,12 +4942,16 @@ func isReusableOptionalDriverAgentRevisionCurrent(driverType string, executableP
|
||||
actual, current, err := optionalDriverAgentRevisionCurrent(driverType, executablePath)
|
||||
displayName := resolveDriverDisplayName(driverDefinition{Type: driverType})
|
||||
if err != nil {
|
||||
logger.Warnf("跳过可复用 %s 驱动代理候选:版本元数据不可用 path=%s err=%v", displayName, executablePath, err)
|
||||
return false
|
||||
logger.Warnf("可复用 %s 驱动代理候选版本元数据不可用,仍允许安装:path=%s err=%v;建议在驱动管理中重装", displayName, executablePath, err)
|
||||
return true
|
||||
}
|
||||
if !current {
|
||||
logger.Warnf("跳过可复用 %s 驱动代理候选:revision 不匹配 path=%s actual=%s expected=%s", displayName, executablePath, strings.TrimSpace(actual), expected)
|
||||
return false
|
||||
actualLabel := strings.TrimSpace(actual)
|
||||
if actualLabel == "" {
|
||||
actualLabel = "空"
|
||||
}
|
||||
logger.Warnf("可复用 %s 驱动代理候选 revision 不匹配,仍允许安装:path=%s actual=%s expected=%s;建议在驱动管理中重装", displayName, executablePath, actualLabel, expected)
|
||||
return true
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -538,6 +538,13 @@ func TestDownloadOptionalDriverAgentBinaryInstallsDuckDBDedicatedZip(t *testing.
|
||||
http.ServeFile(w, r, zipPath)
|
||||
}))
|
||||
defer server.Close()
|
||||
proxySnapshot := currentGlobalProxyConfig()
|
||||
if _, err := setGlobalProxyConfig(false, proxySnapshot.Proxy); err != nil {
|
||||
t.Fatalf("disable global proxy failed: %v", err)
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
_, _ = setGlobalProxyConfig(proxySnapshot.Enabled, proxySnapshot.Proxy)
|
||||
})
|
||||
|
||||
target := filepath.Join(tmpDir, "install", "duckdb-driver-agent.exe")
|
||||
if err := os.MkdirAll(filepath.Dir(target), 0o755); err != nil {
|
||||
@@ -916,12 +923,10 @@ func TestDownloadOptionalDriverAgentFromBundleSharesConcurrentDownload(t *testin
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnsureOptionalDriverAgentBinaryFallsBackAfterStaleDownloadRevision(t *testing.T) {
|
||||
func TestInstallOptionalDriverAgentPackageAcceptsStaleDownloadRevision(t *testing.T) {
|
||||
originalProbe := optionalDriverAgentMetadataProbe
|
||||
originalGoBinaryLookPath := goBinaryLookPath
|
||||
t.Cleanup(func() {
|
||||
optionalDriverAgentMetadataProbe = originalProbe
|
||||
goBinaryLookPath = originalGoBinaryLookPath
|
||||
})
|
||||
|
||||
tmpDir := t.TempDir()
|
||||
@@ -935,73 +940,46 @@ func TestEnsureOptionalDriverAgentBinaryFallsBackAfterStaleDownloadRevision(t *t
|
||||
http.ServeFile(w, r, staleAgent)
|
||||
}))
|
||||
defer staleServer.Close()
|
||||
|
||||
projectRoot := filepath.Join(tmpDir, "project")
|
||||
if err := os.MkdirAll(filepath.Join(projectRoot, "cmd", "optional-driver-agent"), 0o755); err != nil {
|
||||
t.Fatalf("create project root failed: %v", err)
|
||||
}
|
||||
if err := os.WriteFile(filepath.Join(projectRoot, "go.mod"), []byte("module GoNavi-Wails\n"), 0o644); err != nil {
|
||||
t.Fatalf("write go.mod failed: %v", err)
|
||||
}
|
||||
if err := os.WriteFile(filepath.Join(projectRoot, "cmd", "optional-driver-agent", "main.go"), []byte("package main\n"), 0o644); err != nil {
|
||||
t.Fatalf("write optional agent main failed: %v", err)
|
||||
}
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatalf("getwd failed: %v", err)
|
||||
}
|
||||
if err := os.Chdir(projectRoot); err != nil {
|
||||
t.Fatalf("chdir project root failed: %v", err)
|
||||
proxySnapshot := currentGlobalProxyConfig()
|
||||
if _, err := setGlobalProxyConfig(false, proxySnapshot.Proxy); err != nil {
|
||||
t.Fatalf("disable global proxy failed: %v", err)
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
if err := os.Chdir(wd); err != nil {
|
||||
t.Fatalf("restore cwd failed: %v", err)
|
||||
}
|
||||
_, _ = setGlobalProxyConfig(proxySnapshot.Enabled, proxySnapshot.Proxy)
|
||||
})
|
||||
goScript := filepath.Join(tmpDir, "fake-go")
|
||||
if runtime.GOOS == "windows" {
|
||||
goScript += ".bat"
|
||||
}
|
||||
if runtime.GOOS == "windows" {
|
||||
if err := os.WriteFile(goScript, []byte("@echo off\r\nsetlocal\r\nset \"out=\"\r\n:loop\r\nif \"%~1\"==\"\" goto done\r\nif \"%~1\"==\"-o\" goto capture\r\nshift\r\ngoto loop\r\n:capture\r\nset \"out=%~2\"\r\nshift\r\nshift\r\ngoto loop\r\n:done\r\nif \"%out%\"==\"\" exit /b 1\r\ncopy /Y \"%GONAVI_TEST_BUILT_AGENT%\" \"%out%\" >nul\r\n"), 0o755); err != nil {
|
||||
t.Fatalf("write fake go script failed: %v", err)
|
||||
}
|
||||
} else {
|
||||
if err := os.WriteFile(goScript, []byte("#!/usr/bin/env sh\nout=\"\"\nwhile [ \"$#\" -gt 0 ]; do\n if [ \"$1\" = \"-o\" ]; then out=\"$2\"; shift 2; continue; fi\n shift\ndone\ncp \"$GONAVI_TEST_BUILT_AGENT\" \"$out\"\n"), 0o755); err != nil {
|
||||
t.Fatalf("write fake go script failed: %v", err)
|
||||
}
|
||||
}
|
||||
goBinaryLookPath = func(file string) (string, error) {
|
||||
return goScript, nil
|
||||
}
|
||||
t.Setenv("GONAVI_TEST_BUILT_AGENT", staleAgent)
|
||||
|
||||
probeCount := 0
|
||||
optionalDriverAgentMetadataProbe = func(driverType string, executablePath string) (db.OptionalDriverAgentMetadata, error) {
|
||||
probeCount++
|
||||
revision := "src-stale-agent"
|
||||
if probeCount > 1 {
|
||||
revision = db.OptionalDriverAgentRevision(driverType)
|
||||
}
|
||||
return db.OptionalDriverAgentMetadata{
|
||||
DriverType: driverType,
|
||||
AgentRevision: revision,
|
||||
AgentRevision: "src-stale-agent",
|
||||
}, nil
|
||||
}
|
||||
|
||||
targetPath := filepath.Join(tmpDir, optionalDriverExecutableBaseName("sqlserver"))
|
||||
source, _, err := ensureOptionalDriverAgentBinary(
|
||||
meta, err := installOptionalDriverAgentPackage(
|
||||
nil,
|
||||
driverDefinition{Type: "sqlserver", Name: "SQL Server"},
|
||||
targetPath,
|
||||
staleServer.URL,
|
||||
"1.9.6",
|
||||
filepath.Join(tmpDir, "drivers"),
|
||||
staleServer.URL,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("expected stale direct download to fall back to source build, got %v", err)
|
||||
t.Fatalf("expected stale direct download to be installed with an update hint, got %v", err)
|
||||
}
|
||||
if source != "local://go-build/sqlserver-driver-agent" {
|
||||
t.Fatalf("expected source build fallback, got %q", source)
|
||||
if meta.DownloadURL != staleServer.URL {
|
||||
t.Fatalf("expected direct download source to be preserved, got %q", meta.DownloadURL)
|
||||
}
|
||||
if meta.AgentRevision != "src-stale-agent" {
|
||||
t.Fatalf("expected stale agent revision to be recorded, got %q", meta.AgentRevision)
|
||||
}
|
||||
if _, err := os.Stat(meta.ExecutablePath); err != nil {
|
||||
t.Fatalf("expected runtime executable to stay installed, got %v", err)
|
||||
}
|
||||
needsUpdate, reason, expectedRevision := optionalDriverAgentRevisionStatus("sqlserver", meta, true)
|
||||
if !needsUpdate {
|
||||
t.Fatalf("expected stale installed revision to be surfaced as needsUpdate; expected=%q", expectedRevision)
|
||||
}
|
||||
if !strings.Contains(reason, "强烈建议重装") {
|
||||
t.Fatalf("expected advisory reinstall reason, got %q", reason)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user