Skip to main content

max / makenotwork

6.6 KB · 242 lines History Blame Raw
1 //! Unit tests for the `CreatorTier` enum and its price/limit envelope.
2
3 use super::*;
4
5 // ── CreatorTier::label ───────────────────────────────────────────────
6
7 #[test]
8 fn label_basic() {
9 assert_eq!(CreatorTier::Basic.label(), "Basic");
10 }
11
12 #[test]
13 fn label_small_files() {
14 assert_eq!(CreatorTier::SmallFiles.label(), "Small Files");
15 }
16
17 #[test]
18 fn label_big_files() {
19 assert_eq!(CreatorTier::BigFiles.label(), "Big Files");
20 }
21
22 #[test]
23 fn label_everything() {
24 assert_eq!(CreatorTier::Everything.label(), "Everything");
25 }
26
27 // ── CreatorTier price + envelope invariants ────────────────────────
28 //
29 // Concrete cents/bytes come from `assumptions.toml` via the installed
30 // `TierPrices` global. Tests pin only structural invariants (positive,
31 // monotone, per-file ≤ storage) so a future toml edit doesn't rewrite
32 // this file. Literal-value pins live in `docs/business/assumptions.toml`
33 // itself and are guarded by the docengine `tier_bytes ↔ tier_limits`
34 // validator.
35
36 fn all_tiers() -> [CreatorTier; 4] {
37 [
38 CreatorTier::Basic,
39 CreatorTier::SmallFiles,
40 CreatorTier::BigFiles,
41 CreatorTier::Everything,
42 ]
43 }
44
45 #[test]
46 fn prices_positive_and_strictly_increasing() {
47 crate::tier_prices::TierPrices::install_test_default();
48 let tiers = all_tiers();
49 assert!(tiers[0].price_cents() > 0);
50 for pair in tiers.windows(2) {
51 assert!(
52 pair[0].price_cents() < pair[1].price_cents(),
53 "{:?} should cost less than {:?}",
54 pair[0],
55 pair[1],
56 );
57 }
58 }
59
60 #[test]
61 fn max_file_bytes_non_decreasing() {
62 crate::tier_prices::TierPrices::install_test_default();
63 let tiers = all_tiers();
64 assert!(tiers[0].max_file_bytes() > 0);
65 for pair in tiers.windows(2) {
66 assert!(
67 pair[0].max_file_bytes() <= pair[1].max_file_bytes(),
68 "{:?} file limit should not exceed {:?}",
69 pair[0],
70 pair[1],
71 );
72 }
73 }
74
75 #[test]
76 fn max_storage_bytes_non_decreasing() {
77 crate::tier_prices::TierPrices::install_test_default();
78 let tiers = all_tiers();
79 assert!(tiers[0].max_storage_bytes() > 0);
80 for pair in tiers.windows(2) {
81 assert!(
82 pair[0].max_storage_bytes() <= pair[1].max_storage_bytes(),
83 "{:?} storage limit should not exceed {:?}",
84 pair[0],
85 pair[1],
86 );
87 }
88 }
89
90 #[test]
91 fn top_tier_matches_big_files_envelope() {
92 // BigFiles and Everything share the same envelope by product design.
93 // (Everything differentiates on features, not caps.)
94 crate::tier_prices::TierPrices::install_test_default();
95 assert_eq!(
96 CreatorTier::Everything.max_file_bytes(),
97 CreatorTier::BigFiles.max_file_bytes(),
98 );
99 assert_eq!(
100 CreatorTier::Everything.max_storage_bytes(),
101 CreatorTier::BigFiles.max_storage_bytes(),
102 );
103 }
104
105 // ── CreatorTier::allows_file_uploads ─────────────────────────────────
106
107 #[test]
108 fn basic_tier_disallows_file_uploads() {
109 assert!(!CreatorTier::Basic.allows_file_uploads());
110 }
111
112 #[test]
113 fn small_files_allows_file_uploads() {
114 assert!(CreatorTier::SmallFiles.allows_file_uploads());
115 }
116
117 #[test]
118 fn big_files_allows_file_uploads() {
119 assert!(CreatorTier::BigFiles.allows_file_uploads());
120 }
121
122 #[test]
123 fn everything_allows_file_uploads() {
124 assert!(CreatorTier::Everything.allows_file_uploads());
125 }
126
127 // ── format_bytes helper ─────────────────────────────────────────────
128
129 #[test]
130 fn format_bytes_zero() {
131 assert_eq!(format_bytes(0), "0 B");
132 }
133
134 #[test]
135 fn format_bytes_one_byte() {
136 assert_eq!(format_bytes(1), "1 B");
137 }
138
139 #[test]
140 fn format_bytes_below_kb() {
141 assert_eq!(format_bytes(1023), "1023 B");
142 }
143
144 #[test]
145 fn format_bytes_exactly_1kb() {
146 assert_eq!(format_bytes(1024), "1.0 KB");
147 }
148
149 #[test]
150 fn format_bytes_exactly_1mb() {
151 assert_eq!(format_bytes(1024 * 1024), "1.0 MB");
152 }
153
154 #[test]
155 fn format_bytes_exactly_1gb() {
156 assert_eq!(format_bytes(1024 * 1024 * 1024), "1.0 GB");
157 }
158
159 #[test]
160 fn format_bytes_negative_clamped_to_zero() {
161 assert_eq!(format_bytes(-999), "0 B");
162 }
163
164 #[test]
165 fn format_bytes_large_storage_cap() {
166 // 500 GB (Everything tier cap)
167 assert_eq!(format_bytes(500 * 1024 * 1024 * 1024), "500.0 GB");
168 }
169
170 // ── StorageBreakdown ────────────────────────────────────────────────
171
172 #[test]
173 fn storage_breakdown_default_is_all_zeros() {
174 let sb = StorageBreakdown::default();
175 assert_eq!(sb.audio_bytes, 0);
176 assert_eq!(sb.cover_bytes, 0);
177 assert_eq!(sb.download_bytes, 0);
178 assert_eq!(sb.insertion_bytes, 0);
179 assert_eq!(sb.video_bytes, 0);
180 assert_eq!(sb.media_bytes, 0);
181 assert_eq!(sb.total_bytes, 0);
182 }
183
184 #[test]
185 fn storage_breakdown_total_is_sum_of_categories() {
186 let sb = StorageBreakdown {
187 audio_bytes: 100,
188 cover_bytes: 200,
189 download_bytes: 300,
190 insertion_bytes: 400,
191 video_bytes: 500,
192 media_bytes: 600,
193 gallery_bytes: 700,
194 total_bytes: 100 + 200 + 300 + 400 + 500 + 600 + 700,
195 };
196 assert_eq!(
197 sb.total_bytes,
198 sb.audio_bytes
199 + sb.cover_bytes
200 + sb.download_bytes
201 + sb.insertion_bytes
202 + sb.video_bytes
203 + sb.media_bytes
204 + sb.gallery_bytes,
205 );
206 }
207
208 #[test]
209 fn storage_breakdown_single_category() {
210 let sb = StorageBreakdown {
211 audio_bytes: 1_000_000,
212 total_bytes: 1_000_000,
213 ..Default::default()
214 };
215 assert_eq!(sb.total_bytes, 1_000_000);
216 assert_eq!(sb.cover_bytes, 0);
217 }
218
219 // ── Boundary / cross-cutting ────────────────────────────────────────
220
221 #[test]
222 fn basic_file_limit_less_than_storage_limit() {
223 crate::tier_prices::TierPrices::install_test_default();
224 assert!(CreatorTier::Basic.max_file_bytes() < CreatorTier::Basic.max_storage_bytes());
225 }
226
227 #[test]
228 fn every_tier_file_limit_within_storage_limit() {
229 crate::tier_prices::TierPrices::install_test_default();
230 for tier in [
231 CreatorTier::Basic,
232 CreatorTier::SmallFiles,
233 CreatorTier::BigFiles,
234 CreatorTier::Everything,
235 ] {
236 assert!(
237 tier.max_file_bytes() <= tier.max_storage_bytes(),
238 "{tier:?} file limit exceeds its own storage limit",
239 );
240 }
241 }
242