feat(test): Implement robust loading strategies for Wox settings

- Added `loadWoxSettingWithFallback` to handle various corrupted JSON scenarios.
- Introduced multiple strategies for loading settings, including normal decoding, JSON repair, and partial loading.
- Enhanced error handling to log issues and default to safe settings when loading fails.
- Created comprehensive tests for loading settings with various corrupted JSON files.
This commit is contained in:
qianlifeng 2025-06-08 21:58:13 +08:00
parent d423296d73
commit c1a87df75b
No known key found for this signature in database
2 changed files with 662 additions and 33 deletions

View File

@ -6,8 +6,10 @@ import (
"fmt"
"os"
"path"
"regexp"
"slices"
"strconv"
"strings"
"sync"
"wox/common"
"wox/i18n"
@ -79,6 +81,7 @@ func (m *Manager) loadWoxSetting(ctx context.Context) error {
woxSettingPath := util.GetLocation().GetWoxSettingPath()
if _, statErr := os.Stat(woxSettingPath); os.IsNotExist(statErr) {
// Create default setting file if not exists
defaultWoxSettingJson, marshalErr := json.Marshal(defaultWoxSetting)
if marshalErr != nil {
return marshalErr
@ -88,44 +91,20 @@ func (m *Manager) loadWoxSetting(ctx context.Context) error {
if writeErr != nil {
return writeErr
}
m.woxSetting = &defaultWoxSetting
return nil
}
woxSettingFile, openErr := os.Open(woxSettingPath)
if openErr != nil {
return openErr
}
defer woxSettingFile.Close()
woxSetting := &WoxSetting{}
decodeErr := json.NewDecoder(woxSettingFile).Decode(woxSetting)
if decodeErr != nil {
return decodeErr
}
// some settings were added later, json file may not have them, so we need to set them to default value
if woxSetting.MainHotkey.Get() == "" {
woxSetting.MainHotkey.Set(defaultWoxSetting.MainHotkey.Get())
}
if woxSetting.SelectionHotkey.Get() == "" {
woxSetting.SelectionHotkey.Set(defaultWoxSetting.SelectionHotkey.Get())
}
if woxSetting.LangCode == "" {
woxSetting.LangCode = defaultWoxSetting.LangCode
}
if woxSetting.LastQueryMode == "" {
woxSetting.LastQueryMode = defaultWoxSetting.LastQueryMode
}
if woxSetting.AppWidth == 0 {
woxSetting.AppWidth = defaultWoxSetting.AppWidth
}
if woxSetting.MaxResultCount == 0 {
woxSetting.MaxResultCount = defaultWoxSetting.MaxResultCount
}
if woxSetting.ThemeId == "" {
woxSetting.ThemeId = defaultWoxSetting.ThemeId
// Try to load setting with maximum tolerance for errors
woxSetting, err := m.loadWoxSettingWithFallback(ctx, woxSettingPath, defaultWoxSetting)
if err != nil {
// If all attempts fail, log error and use defaults
logger.Error(ctx, fmt.Sprintf("Failed to load setting file, using defaults: %v", err))
m.woxSetting = &defaultWoxSetting
return nil // Don't return error, just use defaults
}
m.woxSetting = woxSetting
return nil
}
@ -366,6 +345,272 @@ func (m *Manager) LoadPluginSetting(ctx context.Context, pluginId string, plugin
return pluginSetting, nil
}
// loadWoxSettingWithFallback attempts to load setting with multiple fallback strategies
func (m *Manager) loadWoxSettingWithFallback(ctx context.Context, settingPath string, defaultSetting WoxSetting) (*WoxSetting, error) {
// Strategy 1: Try normal JSON decoding
if setting, err := m.tryLoadWoxSetting(settingPath, defaultSetting); err == nil {
logger.Info(ctx, "Successfully loaded setting with normal JSON decoding")
return setting, nil
} else {
logger.Warn(ctx, fmt.Sprintf("Normal JSON decoding failed: %v", err))
}
// Strategy 2: Try to fix common JSON issues and reload
if setting, err := m.tryLoadWithJSONRepair(settingPath, defaultSetting); err == nil {
logger.Info(ctx, "Successfully loaded setting after JSON repair")
return setting, nil
} else {
logger.Warn(ctx, fmt.Sprintf("JSON repair failed: %v", err))
}
// Strategy 3: Try field-by-field parsing to salvage what we can
if setting, err := m.tryPartialLoad(settingPath, defaultSetting); err == nil {
logger.Info(ctx, "Successfully loaded setting with partial parsing")
return setting, nil
} else {
logger.Warn(ctx, fmt.Sprintf("Partial parsing failed: %v", err))
}
return nil, fmt.Errorf("all loading strategies failed")
}
// tryLoadWoxSetting attempts normal JSON decoding
func (m *Manager) tryLoadWoxSetting(settingPath string, defaultSetting WoxSetting) (*WoxSetting, error) {
fileContent, err := os.ReadFile(settingPath)
if err != nil {
return nil, fmt.Errorf("failed to read file: %w", err)
}
// Check for empty file
if len(fileContent) == 0 {
return nil, fmt.Errorf("file is empty")
}
woxSetting := &WoxSetting{}
if err := json.Unmarshal(fileContent, woxSetting); err != nil {
return nil, fmt.Errorf("JSON decode error: %w", err)
}
// Apply defaults and sanitize values
m.applyDefaultsToWoxSetting(woxSetting, defaultSetting)
m.sanitizeWoxSetting(woxSetting, defaultSetting)
return woxSetting, nil
}
// tryLoadWithJSONRepair attempts to fix common JSON syntax issues
func (m *Manager) tryLoadWithJSONRepair(settingPath string, defaultSetting WoxSetting) (*WoxSetting, error) {
fileContent, err := os.ReadFile(settingPath)
if err != nil {
return nil, fmt.Errorf("failed to read file: %w", err)
}
// Try to repair common JSON issues
repairedContent := m.repairJSONContent(fileContent)
woxSetting := &WoxSetting{}
if err := json.Unmarshal(repairedContent, woxSetting); err != nil {
return nil, fmt.Errorf("JSON decode error after repair: %w", err)
}
// Apply defaults and sanitize values
m.applyDefaultsToWoxSetting(woxSetting, defaultSetting)
m.sanitizeWoxSetting(woxSetting, defaultSetting)
return woxSetting, nil
}
// repairJSONContent attempts to fix common JSON syntax issues
func (m *Manager) repairJSONContent(content []byte) []byte {
contentStr := string(content)
// If completely empty, return empty object
if len(contentStr) == 0 {
return []byte("{}")
}
// Remove trailing commas before } or ]
contentStr = regexp.MustCompile(`,(\s*[}\]])`).ReplaceAllString(contentStr, "$1")
// Try to fix missing closing braces/brackets by counting
openBraces := strings.Count(contentStr, "{")
closeBraces := strings.Count(contentStr, "}")
if openBraces > closeBraces {
for i := 0; i < openBraces-closeBraces; i++ {
contentStr += "}"
}
}
openBrackets := strings.Count(contentStr, "[")
closeBrackets := strings.Count(contentStr, "]")
if openBrackets > closeBrackets {
for i := 0; i < openBrackets-closeBrackets; i++ {
contentStr += "]"
}
}
return []byte(contentStr)
}
// tryPartialLoad attempts to parse individual fields to salvage what we can
func (m *Manager) tryPartialLoad(settingPath string, defaultSetting WoxSetting) (*WoxSetting, error) {
fileContent, err := os.ReadFile(settingPath)
if err != nil {
return nil, fmt.Errorf("failed to read file: %w", err)
}
// Start with default setting
woxSetting := defaultSetting
// Try to parse as a generic map to extract individual fields
var rawData map[string]interface{}
if err := json.Unmarshal(fileContent, &rawData); err != nil {
return nil, fmt.Errorf("failed to parse as map: %w", err)
}
// Extract fields one by one with error tolerance
m.extractFieldSafely(rawData, "UsePinYin", &woxSetting.UsePinYin)
m.extractFieldSafely(rawData, "SwitchInputMethodABC", &woxSetting.SwitchInputMethodABC)
m.extractFieldSafely(rawData, "HideOnStart", &woxSetting.HideOnStart)
m.extractFieldSafely(rawData, "HideOnLostFocus", &woxSetting.HideOnLostFocus)
m.extractFieldSafely(rawData, "ShowTray", &woxSetting.ShowTray)
m.extractFieldSafely(rawData, "EnableAutoBackup", &woxSetting.EnableAutoBackup)
m.extractFieldSafely(rawData, "EnableAutoUpdate", &woxSetting.EnableAutoUpdate)
// Extract numeric fields
m.extractIntFieldSafely(rawData, "AppWidth", &woxSetting.AppWidth)
m.extractIntFieldSafely(rawData, "MaxResultCount", &woxSetting.MaxResultCount)
// Extract string fields
m.extractStringFieldSafely(rawData, "LangCode", (*string)(&woxSetting.LangCode))
m.extractStringFieldSafely(rawData, "LastQueryMode", &woxSetting.LastQueryMode)
m.extractStringFieldSafely(rawData, "ThemeId", &woxSetting.ThemeId)
// Sanitize the loaded values
m.sanitizeWoxSetting(&woxSetting, defaultSetting)
return &woxSetting, nil
}
// extractFieldSafely safely extracts a boolean field from raw JSON data
func (m *Manager) extractFieldSafely(rawData map[string]interface{}, fieldName string, target *bool) {
if value, exists := rawData[fieldName]; exists {
if boolVal, ok := value.(bool); ok {
*target = boolVal
}
}
}
// extractIntFieldSafely safely extracts an integer field from raw JSON data
func (m *Manager) extractIntFieldSafely(rawData map[string]interface{}, fieldName string, target *int) {
if value, exists := rawData[fieldName]; exists {
switch v := value.(type) {
case float64:
*target = int(v)
case int:
*target = v
case int64:
*target = int(v)
}
}
}
// extractStringFieldSafely safely extracts a string field from raw JSON data
func (m *Manager) extractStringFieldSafely(rawData map[string]interface{}, fieldName string, target *string) {
if value, exists := rawData[fieldName]; exists {
if strVal, ok := value.(string); ok {
*target = strVal
}
}
}
// sanitizeWoxSetting ensures all values are within acceptable ranges
func (m *Manager) sanitizeWoxSetting(setting *WoxSetting, defaultSetting WoxSetting) {
// Sanitize AppWidth
if setting.AppWidth <= 0 || setting.AppWidth > 10000 {
setting.AppWidth = defaultSetting.AppWidth
}
// Sanitize MaxResultCount
if setting.MaxResultCount <= 0 || setting.MaxResultCount > 1000 {
setting.MaxResultCount = defaultSetting.MaxResultCount
}
// Sanitize LangCode
validLangCodes := []string{"en_US", "zh_CN", "zh_TW", "ja_JP", "ko_KR", "fr_FR", "de_DE", "es_ES", "pt_BR", "ru_RU"}
isValidLang := false
for _, code := range validLangCodes {
if string(setting.LangCode) == code {
isValidLang = true
break
}
}
if !isValidLang {
setting.LangCode = defaultSetting.LangCode
}
// Sanitize LastQueryMode
if setting.LastQueryMode != LastQueryModePreserve && setting.LastQueryMode != LastQueryModeEmpty {
setting.LastQueryMode = defaultSetting.LastQueryMode
}
// Sanitize ShowPosition
validPositions := []PositionType{PositionTypeMouseScreen, PositionTypeActiveScreen, PositionTypeLastLocation}
isValidPosition := false
for _, pos := range validPositions {
if setting.ShowPosition == pos {
isValidPosition = true
break
}
}
if !isValidPosition {
setting.ShowPosition = defaultSetting.ShowPosition
}
}
// applyDefaultsToWoxSetting applies default values for missing or zero-value fields
func (m *Manager) applyDefaultsToWoxSetting(setting *WoxSetting, defaultSetting WoxSetting) {
// Apply defaults for hotkeys
if setting.MainHotkey.Get() == "" {
setting.MainHotkey.Set(defaultSetting.MainHotkey.Get())
}
if setting.SelectionHotkey.Get() == "" {
setting.SelectionHotkey.Set(defaultSetting.SelectionHotkey.Get())
}
// Apply defaults for string fields
if setting.LangCode == "" {
setting.LangCode = defaultSetting.LangCode
}
if setting.LastQueryMode == "" {
setting.LastQueryMode = defaultSetting.LastQueryMode
}
if setting.ThemeId == "" {
setting.ThemeId = defaultSetting.ThemeId
}
// Apply defaults for numeric fields (only if zero)
if setting.AppWidth == 0 {
setting.AppWidth = defaultSetting.AppWidth
}
if setting.MaxResultCount == 0 {
setting.MaxResultCount = defaultSetting.MaxResultCount
}
// Apply defaults for position if empty
if setting.ShowPosition == "" {
setting.ShowPosition = defaultSetting.ShowPosition
}
// Apply defaults for slices if nil
if setting.QueryShortcuts == nil {
setting.QueryShortcuts = defaultSetting.QueryShortcuts
}
if setting.AIProviders == nil {
setting.AIProviders = defaultSetting.AIProviders
}
}
func (m *Manager) SavePluginSetting(ctx context.Context, pluginId string, pluginSetting *PluginSetting) error {
pluginSettingPath := path.Join(util.GetLocation().GetPluginSettingDirectory(), fmt.Sprintf("%s.json", pluginId))
pluginSettingJson, marshalErr := json.Marshal(pluginSetting)

View File

@ -0,0 +1,384 @@
package test
import (
"context"
"os"
"path/filepath"
"strings"
"testing"
"wox/setting"
)
// ConfigBlackboxTestSuite tests configuration loading with various corrupted JSON files
type ConfigBlackboxTestSuite struct {
*TestSuite
testDir string
}
// NewConfigBlackboxTestSuite creates a new configuration blackbox test suite
func NewConfigBlackboxTestSuite(t *testing.T) *ConfigBlackboxTestSuite {
suite := &ConfigBlackboxTestSuite{
TestSuite: NewTestSuite(t),
}
// Create isolated test directory for config tests
testConfig := GetCurrentTestConfig()
suite.testDir = filepath.Join(testConfig.TestDataDirectory, "config_blackbox_test")
err := os.MkdirAll(suite.testDir, 0755)
if err != nil {
t.Fatalf("Failed to create test directory: %v", err)
}
return suite
}
// TestConfigBlackbox runs all configuration blackbox tests
func TestConfigBlackbox(t *testing.T) {
suite := NewConfigBlackboxTestSuite(t)
defer suite.cleanup()
// Test loadWoxSetting with various corrupted JSON files
t.Run("LoadWoxSetting", func(t *testing.T) {
suite.testLoadWoxSettingBlackbox(t)
})
// TODO: Add loadWoxAppData tests later
// t.Run("LoadWoxAppData", func(t *testing.T) {
// suite.testLoadWoxAppDataBlackbox(t)
// })
}
// testLoadWoxSettingBlackbox tests loadWoxSetting method with various corrupted JSON scenarios
func (suite *ConfigBlackboxTestSuite) testLoadWoxSettingBlackbox(t *testing.T) {
testCases := []struct {
name string
jsonContent string
expectError bool
expectDefaults bool
description string
}{
{
name: "EmptyFile",
jsonContent: "",
expectError: false,
expectDefaults: true,
description: "Empty configuration file should load with defaults",
},
{
name: "InvalidJSON_MissingBrace",
jsonContent: `{"MainHotkey": {"WinValue": "alt+space"`,
expectError: false,
expectDefaults: true,
description: "Missing closing brace should be repaired and load with defaults",
},
{
name: "InvalidJSON_ExtraComma",
jsonContent: `{"MainHotkey": {"WinValue": "alt+space",}, "UsePinYin": true,}`,
expectError: false,
expectDefaults: true,
description: "Extra trailing commas should be repaired and load successfully",
},
{
name: "ValidJSON_MissingFields",
jsonContent: `{"UsePinYin": true}`,
expectError: false,
expectDefaults: true,
description: "Valid JSON with missing fields should load with defaults",
},
{
name: "ValidJSON_NullValues",
jsonContent: `{"MainHotkey": null, "UsePinYin": null, "QueryShortcuts": null}`,
expectError: false,
expectDefaults: true,
description: "Null values should load with defaults",
},
{
name: "ValidJSON_ExtraFields",
jsonContent: `{"UsePinYin": true, "UnknownField": "value", "AnotherUnknown": 123}`,
expectError: false,
expectDefaults: true,
description: "Extra unknown fields should be ignored",
},
{
name: "ValidJSON_PartialData",
jsonContent: `{"UsePinYin": true, "ShowTray": false, "AppWidth": 1200}`,
expectError: false,
expectDefaults: true,
description: "Partial data should load with defaults for missing fields",
},
{
name: "InvalidJSON_WrongDataTypes",
jsonContent: `{"UsePinYin": "not_a_boolean", "AppWidth": "not_a_number"}`,
expectError: false,
expectDefaults: true,
description: "Wrong data types should be ignored and load with defaults",
},
{
name: "InvalidJSON_CorruptedNestedObject",
jsonContent: `{"MainHotkey": {"WinValue": "alt+space", "MacValue": }, "UsePinYin": true}`,
expectError: false,
expectDefaults: true,
description: "Corrupted nested object should be repaired and load with defaults",
},
{
name: "InvalidJSON_CorruptedArray",
jsonContent: `{"QueryShortcuts": [{"Shortcut": "test", "Query": "test"}, {"Shortcut": "test2",}], "UsePinYin": true}`,
expectError: false,
expectDefaults: true,
description: "Corrupted array element should be repaired and load with defaults",
},
{
name: "ValidJSON_EmptyArrays",
jsonContent: `{"QueryShortcuts": [], "AIProviders": [], "UsePinYin": true}`,
expectError: false,
expectDefaults: true,
description: "Empty arrays should load successfully",
},
{
name: "InvalidJSON_VeryLargeNumbers",
jsonContent: `{"AppWidth": 999999999999999999999999999999, "MaxResultCount": -999999999999999999999999999999}`,
expectError: false,
expectDefaults: true,
description: "Numbers too large for int type should be sanitized to defaults",
},
{
name: "ValidJSON_ComplexNestedStructures",
jsonContent: `{"MainHotkey": {"WinValue": "ctrl+space", "MacValue": "cmd+space"}, "QueryShortcuts": [{"Shortcut": "g", "Query": "google {0}"}], "AIProviders": [{"Name": "openai", "ApiKey": "test", "Host": "api.openai.com"}]}`,
expectError: false,
expectDefaults: true,
description: "Complex nested structures should load successfully",
},
{
name: "InvalidJSON_CorruptedPlatformSettings",
jsonContent: `{"MainHotkey": {"WinValue": "ctrl+space", "MacValue": }, "EnableAutostart": {"WinValue": "not_a_bool"}}`,
expectError: false,
expectDefaults: true,
description: "Corrupted platform-specific settings should be repaired",
},
{
name: "ValidJSON_InvalidLangCode",
jsonContent: `{"LangCode": "invalid_lang", "UsePinYin": true}`,
expectError: false,
expectDefaults: true,
description: "Invalid language code should be sanitized to default",
},
{
name: "ValidJSON_InvalidShowPosition",
jsonContent: `{"ShowPosition": "invalid_position", "AppWidth": 1000}`,
expectError: false,
expectDefaults: true,
description: "Invalid show position should be sanitized to default",
},
{
name: "ValidJSON_InvalidLastQueryMode",
jsonContent: `{"LastQueryMode": "invalid_mode", "MaxResultCount": 15}`,
expectError: false,
expectDefaults: true,
description: "Invalid last query mode should be sanitized to default",
},
{
name: "InvalidJSON_MalformedArrayElements",
jsonContent: `{"QueryShortcuts": [{"Shortcut": "g"}, {"Query": "test"}], "AIProviders": [{"Name": "openai"}, {"ApiKey": "test"}]}`,
expectError: false,
expectDefaults: true,
description: "Malformed array elements should be handled gracefully",
},
{
name: "ValidJSON_BoundaryValues",
jsonContent: `{"AppWidth": 1, "MaxResultCount": 999, "UsePinYin": false}`,
expectError: false,
expectDefaults: true,
description: "Boundary values should be accepted",
},
{
name: "ValidJSON_NegativeNumbers",
jsonContent: `{"AppWidth": -100, "MaxResultCount": -5}`,
expectError: false,
expectDefaults: true,
description: "Negative numbers should be sanitized to defaults",
},
{
name: "InvalidJSON_UnterminatedString",
jsonContent: `{"ThemeId": "some-theme-id, "UsePinYin": true}`,
expectError: false,
expectDefaults: true,
description: "Unterminated string should be repaired",
},
{
name: "InvalidJSON_MissingQuotes",
jsonContent: `{ThemeId: some-theme-id, UsePinYin: true}`,
expectError: false,
expectDefaults: true,
description: "Missing quotes should be handled gracefully",
},
{
name: "ValidJSON_UnicodeContent",
jsonContent: `{"LangCode": "zh_CN", "QueryShortcuts": [{"Shortcut": "测试", "Query": "test 中文"}]}`,
expectError: false,
expectDefaults: true,
description: "Unicode content should be handled correctly",
},
{
name: "InvalidJSON_OnlyBraces",
jsonContent: `{}`,
expectError: false,
expectDefaults: true,
description: "Empty JSON object should load with all defaults",
},
{
name: "InvalidJSON_OnlyWhitespace",
jsonContent: " \n\t \r\n ",
expectError: false,
expectDefaults: true,
description: "Whitespace-only content should be treated as empty",
},
{
name: "InvalidJSON_BinaryData",
jsonContent: string([]byte{0x00, 0x01, 0x02, 0xFF, 0xFE}),
expectError: false,
expectDefaults: true,
description: "Binary data should be handled gracefully",
},
{
name: "ValidJSON_ExtremelyLongString",
jsonContent: `{"ThemeId": "` + strings.Repeat("a", 10000) + `", "UsePinYin": true}`,
expectError: false,
expectDefaults: true,
description: "Extremely long strings should be handled",
},
{
name: "InvalidJSON_NestedBracesOverflow",
jsonContent: `{"MainHotkey": ` + strings.Repeat("{", 100) + `"test"` + strings.Repeat("}", 100) + `}`,
expectError: false,
expectDefaults: true,
description: "Deeply nested structures should be handled",
},
{
name: "ValidJSON_ZeroValues",
jsonContent: `{"AppWidth": 0, "MaxResultCount": 0, "UsePinYin": false, "ShowTray": false}`,
expectError: false,
expectDefaults: true,
description: "Zero values should be replaced with defaults",
},
{
name: "InvalidJSON_SpecialCharacters",
jsonContent: `{"ThemeId": "theme\n\t\r\"\\\/\b\f", "UsePinYin": true}`,
expectError: false,
expectDefaults: true,
description: "Special characters should be handled correctly",
},
{
name: "ValidJSON_FloatAsInt",
jsonContent: `{"AppWidth": 800.5, "MaxResultCount": 10.9}`,
expectError: false,
expectDefaults: true,
description: "Float values for int fields should be converted",
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
suite.runLoadWoxSettingTest(t, tc.name, tc.jsonContent, tc.expectError, tc.expectDefaults, tc.description)
})
}
}
// runLoadWoxSettingTest runs a single loadWoxSetting blackbox test
func (suite *ConfigBlackboxTestSuite) runLoadWoxSettingTest(t *testing.T, name, jsonContent string, expectError, expectDefaults bool, description string) {
// Create a temporary setting file in the test location
testLocation := GetTestLocation()
if testLocation == nil {
t.Fatalf("Test location not available")
}
settingPath := testLocation.GetWoxSettingPath()
// Ensure the settings directory exists
settingsDir := testLocation.GetPluginSettingDirectory()
err := os.MkdirAll(settingsDir, 0755)
if err != nil {
t.Fatalf("Failed to create settings directory: %v", err)
}
// Write the test JSON content
err = os.WriteFile(settingPath, []byte(jsonContent), 0644)
if err != nil {
t.Fatalf("Failed to write test setting file: %v", err)
}
defer os.Remove(settingPath)
t.Logf("Testing: %s - %s", name, description)
t.Logf("JSON content: %s", jsonContent)
t.Logf("Setting path: %s", settingPath)
// Create a new manager and try to initialize it (which calls loadWoxSetting internally)
manager := &setting.Manager{}
ctx := context.Background()
err = manager.Init(ctx)
if expectError {
if err == nil {
t.Errorf("Expected error but got none for test case: %s", name)
} else {
t.Logf("Got expected error: %v", err)
}
} else {
if err != nil {
t.Errorf("Unexpected error for test case %s: %v", name, err)
} else {
t.Logf("Successfully loaded setting")
// Verify the loaded setting
loadedSetting := manager.GetWoxSetting(ctx)
suite.validateLoadedWoxSetting(t, loadedSetting, expectDefaults, name)
}
}
}
// validateLoadedWoxSetting validates that a loaded WoxSetting has reasonable values
func (suite *ConfigBlackboxTestSuite) validateLoadedWoxSetting(t *testing.T, woxSetting *setting.WoxSetting, expectDefaults bool, testName string) {
if woxSetting == nil {
t.Errorf("Loaded setting is nil for test %s", testName)
return
}
defaultSetting := setting.GetDefaultWoxSetting(context.Background())
// Check critical fields have reasonable values
if expectDefaults {
// When expecting defaults, missing fields should be filled with default values
if woxSetting.AppWidth == 0 {
t.Errorf("AppWidth should have default value, got 0 in test %s", testName)
}
if woxSetting.MaxResultCount == 0 {
t.Errorf("MaxResultCount should have default value, got 0 in test %s", testName)
}
if woxSetting.ThemeId == "" {
t.Errorf("ThemeId should have default value, got empty string in test %s", testName)
}
if woxSetting.LangCode == "" {
t.Errorf("LangCode should have default value, got empty string in test %s", testName)
}
if woxSetting.MainHotkey.Get() == "" {
t.Errorf("MainHotkey should have default value, got empty string in test %s", testName)
}
}
// Log the loaded values for debugging
t.Logf("Loaded setting values for %s:", testName)
t.Logf(" AppWidth: %d (default: %d)", woxSetting.AppWidth, defaultSetting.AppWidth)
t.Logf(" MaxResultCount: %d (default: %d)", woxSetting.MaxResultCount, defaultSetting.MaxResultCount)
t.Logf(" UsePinYin: %t (default: %t)", woxSetting.UsePinYin, defaultSetting.UsePinYin)
t.Logf(" ShowTray: %t (default: %t)", woxSetting.ShowTray, defaultSetting.ShowTray)
t.Logf(" LangCode: %s (default: %s)", woxSetting.LangCode, defaultSetting.LangCode)
t.Logf(" ThemeId: %s (default: %s)", woxSetting.ThemeId, defaultSetting.ThemeId)
t.Logf(" MainHotkey: %s (default: %s)", woxSetting.MainHotkey.Get(), defaultSetting.MainHotkey.Get())
}
// cleanup cleans up test resources
func (suite *ConfigBlackboxTestSuite) cleanup() {
if suite.testDir != "" {
os.RemoveAll(suite.testDir)
}
}