mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-07-14 00:42:17 +08:00
175 lines
5.7 KiB
Go
175 lines
5.7 KiB
Go
package app
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"os"
|
|
"strings"
|
|
"testing"
|
|
|
|
"GoNavi-Wails/internal/connection"
|
|
"GoNavi-Wails/shared/i18n"
|
|
)
|
|
|
|
type fakeExplainErrorDatabase struct {
|
|
explainErr error
|
|
}
|
|
|
|
func (db *fakeExplainErrorDatabase) Connect(config connection.ConnectionConfig) error { return nil }
|
|
func (db *fakeExplainErrorDatabase) Close() error { return nil }
|
|
func (db *fakeExplainErrorDatabase) Ping() error { return nil }
|
|
func (db *fakeExplainErrorDatabase) Query(query string) ([]map[string]interface{}, []string, error) {
|
|
return nil, nil, nil
|
|
}
|
|
func (db *fakeExplainErrorDatabase) Exec(query string) (int64, error) { return 0, nil }
|
|
func (db *fakeExplainErrorDatabase) GetDatabases() ([]string, error) { return nil, nil }
|
|
func (db *fakeExplainErrorDatabase) GetTables(dbName string) ([]string, error) {
|
|
return nil, nil
|
|
}
|
|
func (db *fakeExplainErrorDatabase) GetCreateStatement(dbName, tableName string) (string, error) {
|
|
return "", nil
|
|
}
|
|
func (db *fakeExplainErrorDatabase) GetColumns(dbName, tableName string) ([]connection.ColumnDefinition, error) {
|
|
return nil, nil
|
|
}
|
|
func (db *fakeExplainErrorDatabase) GetAllColumns(dbName string) ([]connection.ColumnDefinitionWithTable, error) {
|
|
return nil, nil
|
|
}
|
|
func (db *fakeExplainErrorDatabase) GetIndexes(dbName, tableName string) ([]connection.IndexDefinition, error) {
|
|
return nil, nil
|
|
}
|
|
func (db *fakeExplainErrorDatabase) GetForeignKeys(dbName, tableName string) ([]connection.ForeignKeyDefinition, error) {
|
|
return nil, nil
|
|
}
|
|
func (db *fakeExplainErrorDatabase) GetTriggers(dbName, tableName string) ([]connection.TriggerDefinition, error) {
|
|
return nil, nil
|
|
}
|
|
func (db *fakeExplainErrorDatabase) Explain(ctx context.Context, query string) (string, connection.ExplainFormat, error) {
|
|
return "", connection.ExplainFormatJSON, db.explainErr
|
|
}
|
|
|
|
func TestMethodsExplainBackendErrorSourcesUseLocalizedText(t *testing.T) {
|
|
sourceBytes, err := os.ReadFile("methods_explain.go")
|
|
if err != nil {
|
|
t.Fatalf("read methods_explain.go: %v", err)
|
|
}
|
|
source := string(sourceBytes)
|
|
|
|
checks := map[string]struct {
|
|
rawMessages []string
|
|
keys []string
|
|
}{
|
|
"func (a *App) executeExplain": {
|
|
rawMessages: []string{
|
|
`fmt.Errorf("驱动 EXPLAIN 执行失败`,
|
|
`fmt.Errorf("执行 EXPLAIN 失败`,
|
|
},
|
|
keys: []string{
|
|
"sql_analysis.backend.error.driver_explain_failed",
|
|
"sql_analysis.backend.error.explain_execution_failed",
|
|
},
|
|
},
|
|
"func collectExplainRawWithText": {
|
|
rawMessages: []string{
|
|
`fmt.Errorf("未返回 EXPLAIN 结果集")`,
|
|
`fmt.Errorf("EXPLAIN 结果集为空")`,
|
|
},
|
|
keys: []string{
|
|
"sql_analysis.backend.error.explain_result_missing",
|
|
"sql_analysis.backend.error.explain_result_empty",
|
|
},
|
|
},
|
|
"func parseExplainRawWithText": {
|
|
rawMessages: []string{
|
|
`fmt.Errorf("当前数据源`,
|
|
},
|
|
keys: []string{
|
|
"sql_analysis.backend.error.explain_dialect_unsupported",
|
|
},
|
|
},
|
|
"func buildExplainQueryWithText": {
|
|
rawMessages: []string{
|
|
`fmt.Errorf("当前数据源`,
|
|
},
|
|
keys: []string{
|
|
"sql_analysis.backend.error.explain_query_not_implemented",
|
|
},
|
|
},
|
|
}
|
|
|
|
for signature, check := range checks {
|
|
functionSource := methodsExplainFunctionSource(t, source, signature)
|
|
for _, rawMessage := range check.rawMessages {
|
|
if strings.Contains(functionSource, rawMessage) {
|
|
t.Fatalf("%s still contains raw explain backend text %q", signature, rawMessage)
|
|
}
|
|
}
|
|
for _, key := range check.keys {
|
|
if !strings.Contains(functionSource, key) {
|
|
t.Fatalf("%s does not reference explain backend i18n key %q", signature, key)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestMethodsExplainBackendErrorCatalogKeysExist(t *testing.T) {
|
|
catalogs, err := i18n.LoadCatalogs()
|
|
if err != nil {
|
|
t.Fatalf("LoadCatalogs() error = %v", err)
|
|
}
|
|
|
|
keys := []string{
|
|
"sql_analysis.backend.error.driver_explain_failed",
|
|
"sql_analysis.backend.error.explain_execution_failed",
|
|
"sql_analysis.backend.error.explain_result_missing",
|
|
"sql_analysis.backend.error.explain_result_empty",
|
|
"sql_analysis.backend.error.explain_dialect_unsupported",
|
|
"sql_analysis.backend.error.explain_query_not_implemented",
|
|
}
|
|
|
|
for _, language := range i18n.SupportedLanguages() {
|
|
catalog := catalogs[language]
|
|
for _, key := range keys {
|
|
if strings.TrimSpace(catalog[key]) == "" {
|
|
t.Fatalf("%s catalog missing explain backend key %q", language, key)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestMethodsExplainBackendErrorsUseEnglishMessages(t *testing.T) {
|
|
app := NewAppWithSecretStore(newFakeAppSecretStore())
|
|
app.configDir = t.TempDir()
|
|
app.SetLanguage(string(i18n.LanguageEnUS))
|
|
|
|
t.Run("driver explain failure", func(t *testing.T) {
|
|
_, err := app.executeExplain(&fakeExplainErrorDatabase{explainErr: errors.New("driver exploded")}, connection.ConnectionConfig{}, "mysql", "select 1")
|
|
if err == nil {
|
|
t.Fatal("expected executeExplain to fail")
|
|
}
|
|
if got, want := err.Error(), "Driver EXPLAIN execution failed: driver exploded"; got != want {
|
|
t.Fatalf("expected %q, got %q", want, got)
|
|
}
|
|
})
|
|
|
|
t.Run("missing explain result", func(t *testing.T) {
|
|
_, _, err := collectExplainRawWithText(nil, connection.ExplainFormatJSON, app.appText)
|
|
if err == nil {
|
|
t.Fatal("expected collectExplainRawWithText to fail")
|
|
}
|
|
if got, want := err.Error(), "No EXPLAIN result set was returned"; got != want {
|
|
t.Fatalf("expected %q, got %q", want, got)
|
|
}
|
|
})
|
|
|
|
t.Run("unsupported explain query generation", func(t *testing.T) {
|
|
_, _, _, _, err := buildExplainQueryWithText("redis", "select 1", app.appText)
|
|
if err == nil {
|
|
t.Fatal("expected buildExplainQueryWithText to fail")
|
|
}
|
|
if got, want := err.Error(), "EXPLAIN query generation is not implemented for redis"; got != want {
|
|
t.Fatalf("expected %q, got %q", want, got)
|
|
}
|
|
})
|
|
}
|