personal memory agent
0

Configure Feed

Select the types of activity you want to include in your feed.

solstone / tests / test_user_config.py
3.3 kB 123 lines
1# SPDX-License-Identifier: AGPL-3.0-only 2# Copyright (c) 2026 sol pbc 3 4from __future__ import annotations 5 6from pathlib import Path 7 8import pytest 9 10from solstone.think.user_config import ( 11 config_path, 12 default_journal, 13 read_user_config, 14 write_user_config, 15) 16 17 18@pytest.fixture 19def fake_home(tmp_path, monkeypatch): 20 monkeypatch.setenv("HOME", str(tmp_path)) 21 return tmp_path 22 23 24@pytest.mark.parametrize("home_value", ["~", "~/", "~/x", "~~", "~x"]) 25def test_home_rejects_tilde_leading_expanded_values(monkeypatch, home_value): 26 monkeypatch.setenv("HOME", home_value) 27 28 for resolve in (default_journal, config_path): 29 with pytest.raises(RuntimeError, match="tilde-leading"): 30 resolve() 31 32 33@pytest.mark.parametrize( 34 ("home_value", "expected_journal", "expected_config"), 35 [ 36 ("./~", "~/journal", Path("~/.config/solstone/config.toml")), 37 ("x~", "x~/journal", Path("x~/.config/solstone/config.toml")), 38 ], 39) 40def test_home_allows_non_tilde_leading_edges( 41 monkeypatch, home_value, expected_journal, expected_config 42): 43 monkeypatch.setenv("HOME", home_value) 44 45 assert default_journal() == expected_journal 46 assert config_path() == expected_config 47 48 49def test_default_journal_returns_home_journal(fake_home): 50 assert default_journal() == str(fake_home / "journal") 51 52 53def test_config_path_returns_user_dot_config(fake_home): 54 assert config_path() == fake_home / ".config" / "solstone" / "config.toml" 55 56 57def test_read_missing_file_returns_empty_dict(fake_home): 58 assert read_user_config() == {} 59 60 61def test_read_malformed_toml_returns_empty_dict(fake_home): 62 cfg = config_path() 63 cfg.parent.mkdir(parents=True) 64 cfg.write_text("this is not = toml", encoding="utf-8") 65 66 assert read_user_config() == {} 67 68 69def test_read_missing_journal_key_returns_empty_dict_keys(fake_home): 70 cfg = config_path() 71 cfg.parent.mkdir(parents=True) 72 cfg.write_text('other = "x"\n', encoding="utf-8") 73 74 assert read_user_config() == {"other": "x"} 75 76 77def test_read_drops_non_string_values(fake_home): 78 cfg = config_path() 79 cfg.parent.mkdir(parents=True) 80 cfg.write_text('journal = 123\nname = "ok"\n', encoding="utf-8") 81 82 assert read_user_config() == {"name": "ok"} 83 84 85def test_write_then_read_roundtrip_plain_path(fake_home): 86 write_user_config(journal="/tmp/x") 87 88 assert read_user_config() == {"journal": "/tmp/x"} 89 90 91def test_write_then_read_roundtrip_path_with_spaces(fake_home): 92 write_user_config(journal="/tmp/some path/journal") 93 94 assert read_user_config() == {"journal": "/tmp/some path/journal"} 95 96 97def test_write_then_read_roundtrip_path_with_quotes_and_backslashes(fake_home): 98 journal = '/tmp/with"quote/and\\backslash' 99 100 write_user_config(journal=journal) 101 102 assert read_user_config() == {"journal": journal} 103 104 105def test_write_creates_parent_directory(fake_home): 106 write_user_config(journal="/x") 107 108 assert config_path().parent.is_dir() 109 110 111def test_write_atomic_no_tmp_left_behind(fake_home): 112 write_user_config(journal="/x") 113 114 leftovers = [ 115 path 116 for path in config_path().parent.iterdir() 117 if path.name.startswith(".tmp_config") 118 ] 119 assert leftovers == [] 120 121 122def test_write_returns_config_path(fake_home): 123 assert write_user_config(journal="/x") == config_path()