Skip to content

Commit fba12f8

Browse files
alphaqiuclaude
andcommitted
fix: macOS CI test failures for config tests
Multiple fixes: 1. Added parent directory creation in execute_set 2. Added WAL checkpoint after metadata operations 3. Made config tests serial to avoid env var conflicts 4. Added serial_test dev-dependency 5. Increased WAL checkpoint wait times for macOS CI 6. Added UUID-based unique test directories Co-Authored-By: Claude (glm-4.7) <noreply@anthropic.com>
1 parent 503ea91 commit fba12f8

4 files changed

Lines changed: 82 additions & 7 deletions

File tree

Cargo.lock

Lines changed: 42 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ harness = false
179179
[dev-dependencies]
180180
tempfile = "3.10"
181181
criterion = "0.5"
182+
serial_test = "3.1"
182183

183184
[profile.release]
184185
opt-level = 3

src/cli/commands/config.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,17 @@ async fn execute_set(key: String, value: String) -> Result<()> {
7373
let config = ConfigManager::new()?;
7474
let db_config = config.get_database_config()?;
7575
let db_path = PathBuf::from(db_config.path);
76+
77+
// Ensure parent directory exists
78+
if let Some(parent) = db_path.parent() {
79+
std::fs::create_dir_all(parent)?;
80+
}
81+
7682
let mut vault = Vault::open(&db_path, "")?;
7783

7884
vault.set_metadata(&key, &value)?;
85+
// Force WAL checkpoint to ensure data is persisted for subsequent reads
86+
let _ = vault.conn.pragma_update(None, "wal_checkpoint", "TRUNCATE");
7987
println!("✓ Configuration saved successfully");
8088

8189
Ok(())
@@ -225,6 +233,9 @@ async fn execute_reset(force: bool) -> Result<()> {
225233
vault.delete_metadata(key)?;
226234
}
227235

236+
// Force WAL checkpoint to ensure deletes are persisted
237+
let _ = vault.conn.pragma_update(None, "wal_checkpoint", "TRUNCATE");
238+
228239
if !custom_keys.is_empty() {
229240
println!(
230241
" ✓ Cleared {} custom configuration value(s)",

tests/cli_config_test.rs

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ use keyring_cli::cli::commands::config::{execute, ConfigCommands};
88
use keyring_cli::db::Vault;
99
use tempfile::TempDir;
1010

11+
// Tests must run serially because they use global environment variables
12+
use serial_test::serial;
13+
1114
/// Helper to set up test environment and clean up afterwards
1215
struct TestEnv {
1316
_temp_dir: TempDir,
@@ -16,14 +19,19 @@ struct TestEnv {
1619

1720
impl TestEnv {
1821
fn setup(test_name: &str) -> Self {
22+
// Brief delay to ensure previous test cleanup completes
23+
std::thread::sleep(std::time::Duration::from_millis(50));
24+
1925
// Clean up any existing environment variables first
2026
std::env::remove_var("OK_CONFIG_DIR");
2127
std::env::remove_var("OK_DATA_DIR");
2228
std::env::remove_var("OK_MASTER_PASSWORD");
2329

2430
let temp_dir = TempDir::new().unwrap();
25-
let config_dir = temp_dir.path().join(format!("config_{}", test_name));
26-
let data_dir = temp_dir.path().join(format!("data_{}", test_name));
31+
// Use UUID for unique database file name to avoid conflicts between tests
32+
let unique_id = uuid::Uuid::new_v4().to_string()[..8].to_string();
33+
let config_dir = temp_dir.path().join(format!("config_{}_{}", test_name, unique_id));
34+
let data_dir = temp_dir.path().join(format!("data_{}_{}", test_name, unique_id));
2735
std::env::set_var("OK_CONFIG_DIR", config_dir.to_str().unwrap());
2836
std::env::set_var("OK_DATA_DIR", data_dir.to_str().unwrap());
2937
std::env::set_var("OK_MASTER_PASSWORD", "test-password");
@@ -49,9 +57,11 @@ impl Drop for TestEnv {
4957
}
5058

5159
#[test]
60+
#[serial]
5261
fn test_config_set_persists_to_metadata() {
5362
let _env = TestEnv::setup("set_persists");
5463

64+
5565
// Set a config value
5666
let set_command = ConfigCommands::Set {
5767
key: "clipboard.timeout".to_string(),
@@ -64,7 +74,8 @@ fn test_config_set_persists_to_metadata() {
6474
.unwrap();
6575

6676
// Give time for WAL to checkpoint and for all connections to close
67-
std::thread::sleep(std::time::Duration::from_millis(500));
77+
// macOS CI needs more time for WAL checkpoint
78+
std::thread::sleep(std::time::Duration::from_secs(1));
6879

6980
// Drop the vault from execute() before opening a new one
7081
// Verify it was saved to metadata
@@ -79,9 +90,11 @@ fn test_config_set_persists_to_metadata() {
7990
}
8091

8192
#[test]
93+
#[serial]
8294
fn test_config_get_reads_from_metadata() {
8395
let _env = TestEnv::setup("get_reads");
8496

97+
8598
// Set a value in metadata
8699
{
87100
let mut vault = Vault::open(&_env.db_path, "").unwrap();
@@ -103,18 +116,22 @@ fn test_config_get_reads_from_metadata() {
103116
}
104117

105118
#[test]
119+
#[serial]
106120
fn test_config_reset_clears_custom_metadata() {
107121
let _env = TestEnv::setup("reset_clears");
108122

123+
109124
// Set custom values directly in metadata
110125
{
111126
let mut vault = Vault::open(&_env.db_path, "").unwrap();
112127
vault.set_metadata("custom.key1", "value1").unwrap();
113128
vault.set_metadata("custom.key2", "value2").unwrap();
129+
// Force WAL checkpoint to ensure data is persisted
130+
let _ = vault.conn.pragma_update(None, "wal_checkpoint", "TRUNCATE");
114131
}
115132

116-
// Give time for WAL to checkpoint
117-
std::thread::sleep(std::time::Duration::from_millis(200));
133+
// Give time for WAL to checkpoint - macOS CI needs more time
134+
std::thread::sleep(std::time::Duration::from_millis(500));
118135

119136
// Verify they were set
120137
let vault = Vault::open(&_env.db_path, "").unwrap();
@@ -129,7 +146,8 @@ fn test_config_reset_clears_custom_metadata() {
129146

130147
// Close vault to release lock
131148
drop(vault);
132-
std::thread::sleep(std::time::Duration::from_millis(100));
149+
// Give more time for WAL checkpoint and lock release on macOS CI
150+
std::thread::sleep(std::time::Duration::from_millis(300));
133151

134152
// Reset config
135153
let reset_command = ConfigCommands::Reset { force: true };
@@ -140,7 +158,8 @@ fn test_config_reset_clears_custom_metadata() {
140158
.unwrap();
141159

142160
// Give time for WAL to checkpoint and for all connections to close
143-
std::thread::sleep(std::time::Duration::from_millis(500));
161+
// macOS CI needs more time for WAL checkpoint
162+
std::thread::sleep(std::time::Duration::from_secs(1));
144163

145164
// Verify custom metadata was cleared
146165
let vault = Vault::open(&_env.db_path, "").unwrap();
@@ -160,9 +179,11 @@ fn test_config_reset_clears_custom_metadata() {
160179
}
161180

162181
#[test]
182+
#[serial]
163183
fn test_config_set_validates_key() {
164184
let _env = TestEnv::setup("validates_key");
165185

186+
166187
// Try to set an invalid key (should be rejected)
167188
let set_command = ConfigCommands::Set {
168189
key: "invalid.unauthorized.key".to_string(),

0 commit comments

Comments
 (0)