1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
//! Tests for the tool-output compression savings producer.
//!
//! Why: the producer's contract is "claim only what the compression genuinely
//! avoided". The passthrough case is the one that matters most: `tm compress`
//! returns short output unchanged, and a row written for such a run would carry
//! a `tokens_before` into the fold while saving nothing — dragging the `💸`
//! segment's per-session percentage, and therefore its average, down.
//! What: the row builder is driven with hand-supplied byte counts and an
//! injected price, so every decline branch is asserted with no configured model
//! and no process-wide env mutation; the write path is driven against a tempdir.
//! Test: this file.
use super::*;
use crate::core::savings::{fold_session, savings_log_in};
use crate::core::session_model::MODEL_SOURCE_STATUSLINE;
/// A price stand-in: Sonnet's published input rate, as the shared table carries
/// it. Used so the arithmetic below is hand-checkable.
fn sonnet_price() -> Option<ParentModel> {
Some(ParentModel {
id: "claude-sonnet-4-6".to_string(),
input_per_million: 3.0,
source: MODEL_SOURCE_STATUSLINE,
})
}
/// Why: the hand-computed delta is the whole claim. 400,000 bytes of gate output
/// are 100,000 tokens at four bytes each; the 40,000-byte compressed form is
/// 10,000; the delta is 90,000 tokens, which at Sonnet's $3/Mtok input rate is
/// $0.27.
/// Test: itself.
#[test]
fn a_hand_computed_byte_delta_matches_the_row() {
let row = compress_row("sess-a", 400_000, 40_000, "rtk_binary", sonnet_price).expect("a row");
assert_eq!(row.session_id, "sess-a");
assert_eq!(row.tokens_saved, 90_000);
assert_eq!(row.tokens_before, 100_000);
assert!(
(row.cost_saved_usd - 0.27).abs() < 1e-9,
"expected $0.27, got {}",
row.cost_saved_usd
);
}
/// Why: the fold and any later attribution pass both key on this string, so it
/// is pinned rather than left to whatever the format call happens to emit.
/// Test: itself.
#[test]
fn a_compress_row_carries_the_named_technique() {
let row = compress_row("sess-a", 400_000, 40_000, "rtk_binary", sonnet_price).expect("a row");
assert_eq!(row.technique, TECHNIQUE_COMPRESS);
assert_eq!(row.technique, "compress");
}
/// Why: `rtk_binary` and `native_fallback` compress by different mechanisms and
/// will need splitting apart later. Carrying the label in `basis` is what makes
/// that possible off the ledger line alone.
/// Test: itself.
#[test]
fn the_basis_names_the_compression_path() {
let row =
compress_row("sess-a", 400_000, 40_000, "native_fallback", sonnet_price).expect("a row");
assert!(
row.basis.contains("native_fallback"),
"basis must name the compression path, got: {}",
row.basis
);
assert!(
row.basis.contains("claude-sonnet-4-6"),
"basis must name the model it priced at, got: {}",
row.basis
);
}
/// Why: `tm compress` passes output under its size gate through unchanged. That
/// run avoided nothing, and a zero-saving row would still fold a `tokens_before`
/// into the percentage and pull the average down.
/// Test: itself.
#[test]
fn passthrough_output_writes_no_row() {
assert!(compress_row("sess-a", 1_159, 1_159, "native_fallback", sonnet_price).is_none());
}
/// Why: compression can expand its input (a short, non-repetitive payload plus
/// a header). Rounding must never turn that into a positive claim.
/// Test: itself.
#[test]
fn an_expanded_output_writes_no_row() {
assert!(compress_row("sess-a", 4_000, 5_000, "native_fallback", sonnet_price).is_none());
}
/// Why: a row keyed by nothing is a row the statusline can never fold, so the
/// producer declines rather than writing one.
/// Test: itself.
#[test]
fn no_row_without_a_session_id() {
let dir = tempfile::tempdir().expect("temp dir");
record_compress_with(
dir.path(),
" ",
400_000,
40_000,
"rtk_binary",
sonnet_price,
);
assert!(!savings_log_in(dir.path()).exists());
}
/// Why: an unpriceable model must decline rather than substitute a guessed rate
/// — the same rule the divert producer holds.
/// Test: itself.
#[test]
fn no_row_when_the_session_model_cannot_be_priced() {
assert!(compress_row("sess-a", 400_000, 40_000, "rtk_binary", || None).is_none());
}
/// Why: proves the whole write path — one run, one row, folding back under the
/// session it was keyed by.
/// Test: itself.
#[test]
fn a_compress_run_appends_exactly_one_row() {
let dir = tempfile::tempdir().expect("temp dir");
let ledger = savings_log_in(dir.path());
record_compress_with(
dir.path(),
"sess-a",
400_000,
40_000,
"rtk_binary",
sonnet_price,
);
let contents = std::fs::read_to_string(&ledger).expect("read ledger");
assert_eq!(
contents.lines().filter(|l| !l.trim().is_empty()).count(),
1,
"one run must write exactly one row, got: {contents}"
);
let total = fold_session(&ledger, "sess-a");
assert_eq!(total.rows, 1);
assert_eq!(total.tokens_saved, 90_000);
assert_eq!(total.tokens_before, 100_000);
}
/// Why: the compressed text is already the caller's return value by the time
/// this runs. An unwritable ledger must not turn a compression that worked into
/// one that failed.
/// Test: itself.
#[test]
fn a_ledger_write_failure_does_not_fail_the_compression() {
let dir = tempfile::tempdir().expect("temp dir");
// A regular file where the `usage/` directory must go: `create_dir_all`
// inside the writer cannot succeed, so the append returns an IO error.
let blocker = dir.path().join("usage");
std::fs::write(&blocker, "not a directory").expect("write blocker");
let ledger = savings_log_in(dir.path());
record_compress_with(
dir.path(),
"sess-a",
400_000,
40_000,
"rtk_binary",
sonnet_price,
);
assert!(
!ledger.exists(),
"the unwritable ledger must stay unwritten, not partially created"
);
assert!(
blocker.is_file(),
"the blocking file must be left exactly as it was"
);
}