lib/alloc/phase/src/capacity/test.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

  1 const std = @import("std");
  2 const capacity = @import("capacity");
  3 const phase = @import("../root.zig");
  4 
  5 const Allocator = std.mem.Allocator;
  6 const OwnerShapeViolation = capacity.OwnerShapeViolation;
  7 const Phase = capacity.Phase;
  8 const ProvisionedExactFixture = capacity.ProvisionedExactFixture;
  9 const ProvisionedRejectingFixture = capacity.ProvisionedRejectingFixture;
 10 
 11 const TestLimits = struct {
 12     slots: u32,
 13 };
 14 
 15 const TestCapacity = struct {
 16     slots: usize,
 17 
 18     pub fn derive(limits: TestLimits) error{InvalidLimit}!TestCapacity {
 19         if (limits.slots == 0) return error.InvalidLimit;
 20         return .{ .slots = limits.slots };
 21     }
 22 };
 23 
 24 const TestExhaustion = error{Full};
 25 
 26 const TestOwner = struct {
 27     pub const Limits = TestLimits;
 28     pub const Capacity = TestCapacity;
 29     pub const Exhaustion = TestExhaustion;
 30 
 31     pub const claim: capacity.Declaration = .{
 32         .source = .{
 33             .id = "alloc.shape_fixture",
 34             .kind = .phase_static,
 35             .limit_source = .caller,
 36             .storage = .{
 37                 .covered = &.{.{
 38                     .id = "slot_storage",
 39                     .lifetime = .steady,
 40                     .detail = "slot storage",
 41                 }},
 42                 .excluded = &.{"caller-owned payloads"},
 43             },
 44             .capacity = .{
 45                 .inputs = &.{capacity.bindInput(Limits, "slots", "slots")},
 46                 .nodes = &.{.{ .input = 0 }},
 47                 .assertions = &.{.{
 48                     .scope = .closure_total,
 49                     .measure = .retained,
 50                     .relation = .exact,
 51                     .expression = 0,
 52                 }},
 53             },
 54             .overload = .{
 55                 .kind = .reject_before_mutation,
 56                 .detail = "take returns Full before any slot mutates",
 57             },
 58             .risks = .{
 59                 .transitive = .{ .status = .open, .detail = "fixture has no callees" },
 60                 .foreign = .{ .status = .open, .detail = "fixture crosses no foreign resources" },
 61             },
 62             .obligations = &.{
 63                 .{ .key = "capacity", .role = .capacity_model },
 64                 .{ .key = "overload", .role = .overload },
 65             },
 66         },
 67         .bindings = .{
 68             .owner = @This(),
 69             .seal = .{
 70                 .family = capacity.selector(@This().activate),
 71                 .premise = .{
 72                     .class = .checked_semantic_fact,
 73                     .authority = .checker,
 74                 },
 75             },
 76             .teardown = .{
 77                 .family = capacity.selector(@This().deinit),
 78                 .premise = .{
 79                     .class = .checked_semantic_fact,
 80                     .authority = .checker,
 81                 },
 82             },
 83         },
 84     };
 85 
 86     phase: Phase,
 87     capacity: TestCapacity,
 88     storage: []u8,
 89 
 90     pub fn init(allocator: Allocator, limits: TestLimits) !TestOwner {
 91         const derived = try TestCapacity.derive(limits);
 92         return .{
 93             .phase = .initialization,
 94             .capacity = derived,
 95             .storage = try allocator.alloc(u8, derived.slots),
 96         };
 97     }
 98 
 99     pub fn activate(self: *TestOwner) void {
100         self.phase = .steady;
101     }
102 
103     pub fn available(self: *const TestOwner) usize {
104         std.debug.assert(self.phase == .steady);
105         return self.storage.len;
106     }
107 
108     pub fn take(self: *TestOwner) Exhaustion!void {
109         if (self.storage.len == 0) return error.Full;
110     }
111 
112     pub fn deinit(self: *TestOwner, allocator: Allocator) void {
113         self.phase = .teardown;
114         allocator.free(self.storage);
115     }
116 };
117 
118 const TypedOwner = struct {
119     pub const Limits = struct {
120         shape: struct { slots: u16 },
121         slot_bytes: u32,
122     };
123     pub const Capacity = struct {
124         storage_bytes: usize,
125 
126         pub fn derive(limits: Limits) error{ InvalidLimit, CapacityOverflow }!Capacity {
127             if (limits.shape.slots == 0 or limits.slot_bytes == 0) {
128                 return error.InvalidLimit;
129             }
130             return .{
131                 .storage_bytes = try capacity.mul(
132                     usize,
133                     limits.shape.slots,
134                     limits.slot_bytes,
135                 ),
136             };
137         }
138     };
139     pub const claim: capacity.Declaration = .{
140         .source = .{
141             .id = "alloc.typed_shape_fixture",
142             .kind = .phase_static,
143             .limit_source = .application_default,
144             .storage = .{
145                 .covered = &.{
146                     .{
147                         .id = "scratch",
148                         .lifetime = .initialization,
149                         .detail = "capacity derivation scratch",
150                     },
151                     .{
152                         .id = "slots",
153                         .lifetime = .steady,
154                         .detail = "retained slot storage",
155                     },
156                     .{
157                         .id = "handoff",
158                         .lifetime = .transferred,
159                         .detail = "returned payload storage",
160                     },
161                 },
162                 .excluded = &.{"caller-owned payloads"},
163             },
164             .capacity = .{
165                 .inputs = &.{
166                     capacity.bindInput(Limits, "slots", "shape.slots"),
167                     capacity.bindInput(Limits, "slot_bytes", "slot_bytes"),
168                 },
169                 .nodes = &.{
170                     .{ .constant = 1 },
171                     .{ .input = 0 },
172                     .{ .input = 1 },
173                     .{ .add = .{ .left = 1, .right = 2 } },
174                     .{ .maximum = .{ .left = 0, .right = 3 } },
175                     .{ .scale = .{ .node = 4, .coefficient = .{ .literal = 2 } } },
176                     .{ .scale = .{
177                         .node = 5,
178                         .coefficient = .{ .unsigned_comptime_parameter = 0 },
179                     } },
180                     .{ .scale = .{
181                         .node = 6,
182                         .coefficient = .{ .size_of_type_parameter = 0 },
183                     } },
184                 },
185                 .assertions = &.{
186                     .{
187                         .scope = .closure_total,
188                         .measure = .retained,
189                         .relation = .upper_bound,
190                         .expression = 7,
191                     },
192                     .{
193                         .scope = .closure_total,
194                         .measure = .retained,
195                         .relation = .exact,
196                         .expression = 3,
197                     },
198                 },
199             },
200             .overload = .{
201                 .kind = .reject_before_seal,
202                 .detail = "capacity admission rejects before owner construction",
203             },
204             .risks = .{
205                 .transitive = .{
206                     .status = .witnessed,
207                     .detail = "the fixture has no transitive owners",
208                 },
209                 .foreign = .{
210                     .status = .excluded,
211                     .detail = "the fixture crosses no foreign boundary",
212                 },
213             },
214             .work = .{ .equation = "transition steps are at most one" },
215             .dependencies = &.{"alloc.fixture_support"},
216             .obligations = &.{
217                 .{ .key = "capacity", .role = .capacity_model },
218                 .{ .key = "acquire", .role = .acquisition },
219                 .{ .key = "init_failure", .role = .initialization_failure },
220                 .{ .key = "overload", .role = .overload },
221                 .{ .key = "seal", .role = .seal },
222                 .{ .key = "teardown", .role = .teardown },
223                 .{ .key = "work", .role = .work_bound },
224                 .{ .key = "transitive", .role = .transitive_risk },
225                 .{ .key = "foreign", .role = .foreign_risk },
226                 .{ .key = "integration", .role = .integration },
227                 .{ .key = "extension", .role = .custom },
228             },
229         },
230         .bindings = .{
231             .owner = @This(),
232             .default_limits = capacity.selector(defaultLimits),
233             .seal = .{
234                 .family = capacity.selector(@This().activate),
235                 .premise = .{
236                     .class = .checked_semantic_fact,
237                     .authority = .checker,
238                 },
239             },
240             .teardown = .{
241                 .family = capacity.selector(@This().deinit),
242                 .premise = .{
243                     .class = .theorem_domain,
244                     .authority = .{ .theorem = .{ .key = "teardown" } },
245                 },
246             },
247         },
248     };
249 
250     phase: Phase,
251     capacity: Capacity,
252     storage: []u8,
253 
254     fn defaultLimits() Limits {
255         return .{ .shape = .{ .slots = 4 }, .slot_bytes = 1 };
256     }
257 
258     pub fn init(allocator: Allocator, limits: Limits) !TypedOwner {
259         const derived = try Capacity.derive(limits);
260         return .{
261             .phase = .initialization,
262             .capacity = derived,
263             .storage = try allocator.alloc(u8, derived.storage_bytes),
264         };
265     }
266 
267     pub fn activate(self: *TypedOwner) void {
268         std.debug.assert(self.phase == .initialization);
269         self.phase = .steady;
270     }
271 
272     pub fn deinit(self: *TypedOwner, allocator: Allocator) void {
273         std.debug.assert(self.phase == .steady);
274         self.phase = .teardown;
275         allocator.free(self.storage);
276     }
277 };
278 
279 const ExactOwnerFixture = struct {
280     pub const Limits = TestLimits;
281     pub const Capacity = TestCapacity;
282 
283     phase: Phase,
284     capacity: TestCapacity,
285 
286     pub fn init(_: Allocator, limits: TestLimits) !@This() {
287         return .{
288             .phase = .initialization,
289             .capacity = try TestCapacity.derive(limits),
290         };
291     }
292 
293     pub fn activate(self: *@This()) void {
294         self.phase = .steady;
295     }
296 
297     pub fn run(self: *const @This()) usize {
298         return self.capacity.slots;
299     }
300 
301     pub fn deinit(self: *@This(), _: Allocator) void {
302         self.phase = .teardown;
303     }
304 };
305 
306 const StoredAllocatorOwnerFixture = struct {
307     pub const Limits = TestLimits;
308     pub const Capacity = TestCapacity;
309     pub const Exhaustion = TestExhaustion;
310 
311     phase: Phase,
312     capacity: TestCapacity,
313     allocator: Allocator,
314 
315     pub fn init(allocator: Allocator, limits: TestLimits) !@This() {
316         return .{
317             .phase = .initialization,
318             .capacity = try TestCapacity.derive(limits),
319             .allocator = allocator,
320         };
321     }
322 
323     pub fn activate(self: *@This()) void {
324         self.phase = .steady;
325     }
326 
327     pub fn deinit(self: *@This(), allocator: Allocator) void {
328         _ = self;
329         _ = allocator;
330     }
331 };
332 
333 const SteadyAllocatorOwnerFixture = struct {
334     pub const Limits = TestLimits;
335     pub const Capacity = TestCapacity;
336     pub const Exhaustion = TestExhaustion;
337 
338     phase: Phase,
339     capacity: TestCapacity,
340 
341     pub fn init(_: Allocator, limits: TestLimits) !@This() {
342         return .{ .phase = .initialization, .capacity = try TestCapacity.derive(limits) };
343     }
344 
345     pub fn activate(self: *@This()) void {
346         self.phase = .steady;
347     }
348 
349     pub fn grow(_: *@This(), _: Allocator) void {}
350 
351     pub fn deinit(self: *@This(), allocator: Allocator) void {
352         _ = self;
353         _ = allocator;
354     }
355 };
356 
357 const InvalidCapacityFixture = struct {
358     pub fn derive(_: usize) @This() {
359         return .{};
360     }
361 };
362 
363 const CapacityDerivationOwnerFixture = struct {
364     pub const Limits = TestLimits;
365     pub const Capacity = InvalidCapacityFixture;
366     pub const Exhaustion = TestExhaustion;
367 
368     phase: Phase,
369     capacity: InvalidCapacityFixture,
370 
371     pub fn init(_: Allocator, _: TestLimits) @This() {
372         return .{ .phase = .initialization, .capacity = .{} };
373     }
374 
375     pub fn activate(self: *@This()) void {
376         self.phase = .steady;
377     }
378 
379     pub fn deinit(self: *@This(), allocator: Allocator) void {
380         _ = self;
381         _ = allocator;
382     }
383 };
384 
385 const WrongExhaustionOwnerFixture = struct {
386     pub const Limits = TestLimits;
387     pub const Capacity = TestCapacity;
388     pub const Exhaustion = usize;
389 
390     phase: Phase,
391     capacity: TestCapacity,
392 
393     pub fn init(_: Allocator, limits: TestLimits) !@This() {
394         return .{ .phase = .initialization, .capacity = try TestCapacity.derive(limits) };
395     }
396 
397     pub fn activate(self: *@This()) void {
398         self.phase = .steady;
399     }
400 
401     pub fn deinit(self: *@This(), allocator: Allocator) void {
402         _ = self;
403         _ = allocator;
404     }
405 };
406 
407 const PrimitiveLimitsOwnerFixture = struct {
408     pub const Limits = usize;
409     pub const Capacity = TestCapacity;
410     pub const Exhaustion = TestExhaustion;
411 };
412 
413 const PrimitiveCapacityOwnerFixture = struct {
414     pub const Limits = TestLimits;
415     pub const Capacity = usize;
416     pub const Exhaustion = TestExhaustion;
417 
418     phase: Phase,
419     capacity: usize,
420 };
421 
422 const SteadyAllocatorResultOwnerFixture = struct {
423     pub const Limits = TestLimits;
424     pub const Capacity = TestCapacity;
425     pub const Exhaustion = TestExhaustion;
426 
427     phase: Phase,
428     capacity: TestCapacity,
429 
430     pub fn init(_: Allocator, limits: TestLimits) !@This() {
431         return .{ .phase = .initialization, .capacity = try TestCapacity.derive(limits) };
432     }
433 
434     pub fn activate(self: *@This()) void {
435         self.phase = .steady;
436     }
437 
438     pub fn currentAllocator(_: *const @This()) Allocator {
439         return undefined;
440     }
441 
442     pub fn deinit(self: *@This(), allocator: Allocator) void {
443         _ = self;
444         _ = allocator;
445     }
446 };
447 
448 const ByValueAllocatorResultOwnerFixture = struct {
449     pub const Limits = TestLimits;
450     pub const Capacity = TestCapacity;
451     pub const Exhaustion = TestExhaustion;
452 
453     phase: Phase,
454     capacity: TestCapacity,
455 
456     pub fn init(_: Allocator, limits: TestLimits) !@This() {
457         return .{ .phase = .initialization, .capacity = try TestCapacity.derive(limits) };
458     }
459 
460     pub fn activate(self: *@This()) void {
461         self.phase = .steady;
462     }
463 
464     pub fn currentAllocator(_: @This()) Allocator {
465         return undefined;
466     }
467 
468     pub fn deinit(self: *@This(), allocator: Allocator) void {
469         _ = self;
470         _ = allocator;
471     }
472 };
473 
474 const UnobservableExhaustionOwnerFixture = struct {
475     pub const Limits = TestLimits;
476     pub const Capacity = TestCapacity;
477     pub const Exhaustion = TestExhaustion;
478 
479     phase: Phase,
480     capacity: TestCapacity,
481 
482     pub fn init(_: Allocator, limits: TestLimits) !@This() {
483         return .{ .phase = .initialization, .capacity = try TestCapacity.derive(limits) };
484     }
485 
486     pub fn activate(self: *@This()) void {
487         self.phase = .steady;
488     }
489 
490     pub fn unrelated() Exhaustion!void {}
491 
492     pub fn available(_: *const @This()) usize {
493         return 0;
494     }
495 
496     pub fn deinit(self: *@This(), allocator: Allocator) void {
497         _ = self;
498         _ = allocator;
499     }
500 };
501 
502 test "phase owner shape accepts an allocator-free steady surface" {
503     comptime capacity.requireAllocatorRejectingOwnerShape(TestOwner);
504     try std.testing.expect(
505         capacity.validateAllocatorRejectingOwnerShape(TestOwner) == null,
506     );
507 
508     var owner = try TestOwner.init(std.testing.allocator, .{ .slots = 4 });
509     defer owner.deinit(std.testing.allocator);
510     owner.activate();
511     try std.testing.expectEqual(@as(usize, 4), owner.available());
512 }
513 
514 test "typed claim declaration covers the complete authoring surface" {
515     comptime capacity.requireAllocatorExactOwnerShape(TypedOwner);
516     try std.testing.expect(
517         capacity.validateAllocatorExactOwnerShape(TypedOwner) == null,
518     );
519     var owner = try TypedOwner.init(std.testing.allocator, .{
520         .shape = .{ .slots = 4 },
521         .slot_bytes = 2,
522     });
523     owner.activate();
524     try std.testing.expectEqual(@as(usize, 8), owner.storage.len);
525     owner.deinit(std.testing.allocator);
526 }
527 
528 test "phase owner shape accepts exact work without steady exhaustion" {
529     comptime capacity.requireAllocatorExactOwnerShape(ExactOwnerFixture);
530     try std.testing.expect(
531         capacity.validateAllocatorExactOwnerShape(ExactOwnerFixture) == null,
532     );
533     try std.testing.expectEqual(
534         OwnerShapeViolation.missing_exhaustion_declaration,
535         capacity.validateAllocatorRejectingOwnerShape(ExactOwnerFixture).?,
536     );
537 }
538 
539 test "phase owner shape classifies incomplete declarations" {
540     const MissingLimits = struct {};
541     const WrongLimits = struct {
542         pub const Limits = 1;
543     };
544     const MissingCapacity = struct {
545         pub const Limits = TestLimits;
546     };
547     try std.testing.expectEqual(
548         OwnerShapeViolation.owner_not_struct,
549         capacity.validateAllocatorExactOwnerShape(usize).?,
550     );
551     try std.testing.expectEqual(
552         OwnerShapeViolation.missing_limits_declaration,
553         capacity.validateAllocatorExactOwnerShape(MissingLimits).?,
554     );
555     try std.testing.expectEqual(
556         OwnerShapeViolation.wrong_limits_declaration,
557         capacity.validateAllocatorExactOwnerShape(WrongLimits).?,
558     );
559     try std.testing.expectEqual(
560         OwnerShapeViolation.missing_capacity_declaration,
561         capacity.validateAllocatorExactOwnerShape(MissingCapacity).?,
562     );
563 }
564 
565 test "phase owner shape rejects a stored allocator" {
566     try std.testing.expectEqual(
567         OwnerShapeViolation.stored_allocator,
568         capacity.validateAllocatorExactOwnerShape(StoredAllocatorOwnerFixture).?,
569     );
570 }
571 
572 test "phase owner shape rejects allocator-bearing steady methods" {
573     try std.testing.expectEqual(
574         OwnerShapeViolation.steady_allocator_parameter,
575         capacity.validateAllocatorExactOwnerShape(SteadyAllocatorOwnerFixture).?,
576     );
577 }
578 
579 test "phase owner shape checks capacity derivation" {
580     try std.testing.expectEqual(
581         OwnerShapeViolation.wrong_capacity_derive,
582         capacity.validateAllocatorExactOwnerShape(CapacityDerivationOwnerFixture).?,
583     );
584 }
585 
586 test "phase owner shape requires a domain exhaustion error" {
587     try std.testing.expectEqual(
588         OwnerShapeViolation.wrong_exhaustion_declaration,
589         capacity.validateAllocatorRejectingOwnerShape(WrongExhaustionOwnerFixture).?,
590     );
591 }
592 
593 test "phase owner shape requires domain limit and capacity containers" {
594     try std.testing.expectEqual(
595         OwnerShapeViolation.wrong_limits_declaration,
596         capacity.validateAllocatorExactOwnerShape(PrimitiveLimitsOwnerFixture).?,
597     );
598     try std.testing.expectEqual(
599         OwnerShapeViolation.wrong_capacity_declaration,
600         capacity.validateAllocatorExactOwnerShape(PrimitiveCapacityOwnerFixture).?,
601     );
602 }
603 
604 test "phase owner shape rejects allocator-bearing steady results" {
605     try std.testing.expectEqual(
606         OwnerShapeViolation.steady_allocator_result,
607         capacity.validateAllocatorExactOwnerShape(SteadyAllocatorResultOwnerFixture).?,
608     );
609     try std.testing.expectEqual(
610         OwnerShapeViolation.steady_allocator_result,
611         capacity.validateAllocatorExactOwnerShape(ByValueAllocatorResultOwnerFixture).?,
612     );
613 }
614 
615 test "phase owner shape requires exhaustion on an owner operation" {
616     try std.testing.expectEqual(
617         OwnerShapeViolation.exhaustion_not_observable,
618         capacity.validateAllocatorRejectingOwnerShape(UnobservableExhaustionOwnerFixture).?,
619     );
620 }
621 
622 test "provisioned exact owner returns its exact caller storage" {
623     comptime {
624         @stardustClaim(
625             capacity.witness(ProvisionedExactFixture, "alloc_provisioned_exact_capacity_capacity_model"),
626             null,
627             null,
628             null,
629             null,
630             null,
631             null,
632         );
633     }
634     comptime {
635         @stardustClaim(
636             capacity.witness(ProvisionedExactFixture, "alloc_provisioned_exact_capacity_overload"),
637             null,
638             null,
639             null,
640             null,
641             null,
642             null,
643         );
644     }
645     comptime {
646         @stardustClaim(
647             capacity.witness(ProvisionedExactFixture, "alloc_provisioned_exact_capacity_work_bound"),
648             null,
649             null,
650             null,
651             null,
652             null,
653             null,
654         );
655     }
656 
657     const Owner = ProvisionedExactFixture;
658     comptime capacity.requireProvisionedExactOwnerShape(Owner);
659     try std.testing.expect(capacity.validateProvisionedExactOwnerShape(Owner) == null);
660 
661     var bytes: [32]u8 align(Owner.storage_alignment) = @splat(0);
662     const storage: Owner.Storage = bytes[0..];
663     var owner = try Owner.init(storage, .{ .bytes = 24 });
664     owner.activate();
665     try std.testing.expectEqual(@as(usize, 24), owner.bytes());
666 
667     const returned = owner.deinit();
668     try std.testing.expectEqual(@intFromPtr(storage.ptr), @intFromPtr(returned.ptr));
669     try std.testing.expectEqual(storage.len, returned.len);
670 }
671 
672 test "provisioned owner rejects one-byte-short storage without mutation" {
673     const Owner = ProvisionedRejectingFixture;
674     var bytes: [16]u8 align(Owner.storage_alignment) = @splat(0xa5);
675     const before = bytes;
676     const short: Owner.Storage = bytes[0 .. bytes.len - 1];
677 
678     try std.testing.expectError(
679         error.StorageTooShort,
680         Owner.init(short, .{ .slots = Owner.slots_max, .slot_bytes = 2 }),
681     );
682     try std.testing.expectEqualSlices(u8, &before, &bytes);
683 }
684 
685 test "provisioned capacity rejects overflow and semantic max plus one" {
686     const Owner = ProvisionedRejectingFixture;
687     try std.testing.expectError(
688         error.CapacityOverflow,
689         Owner.Capacity.derive(.{
690             .slots = std.math.maxInt(usize),
691             .slot_bytes = 2,
692         }),
693     );
694     try std.testing.expectError(
695         error.CapacityExceeded,
696         Owner.Capacity.derive(.{
697             .slots = Owner.slots_max + 1,
698             .slot_bytes = 1,
699         }),
700     );
701 }
702 
703 test "provisioned rejecting owner preserves state at capacity plus one" {
704     comptime {
705         @stardustClaim(
706             capacity.witness(ProvisionedRejectingFixture, "alloc_provisioned_rejecting_capacity_capacity_model"),
707             null,
708             null,
709             null,
710             null,
711             null,
712             null,
713         );
714     }
715     comptime {
716         @stardustClaim(
717             capacity.witness(ProvisionedRejectingFixture, "alloc_provisioned_rejecting_capacity_overload"),
718             null,
719             null,
720             null,
721             null,
722             null,
723             null,
724         );
725     }
726     comptime {
727         @stardustClaim(
728             capacity.witness(ProvisionedRejectingFixture, "alloc_provisioned_rejecting_capacity_work_bound"),
729             null,
730             null,
731             null,
732             null,
733             null,
734             null,
735         );
736     }
737 
738     const Owner = ProvisionedRejectingFixture;
739     comptime capacity.requireProvisionedRejectingOwnerShape(Owner);
740     try std.testing.expect(
741         capacity.validateProvisionedRejectingOwnerShape(Owner) == null,
742     );
743     var bytes: [Owner.slots_max * 2]u8 align(Owner.storage_alignment) = @splat(0);
744     var owner = try Owner.init(bytes[0..], .{
745         .slots = Owner.slots_max,
746         .slot_bytes = 2,
747     });
748     owner.activate();
749     for (0..Owner.slots_max) |index| try owner.submit(@intCast(index + 1));
750 
751     const before_bytes = bytes;
752     var expected_owner = owner;
753     const storage_pointer = @intFromPtr(owner.storage.ptr);
754     const storage_length = owner.storage.len;
755     expected_owner.usage.submitted += 1;
756     expected_owner.usage.rejected += 1;
757     try std.testing.expectError(error.Full, owner.submit(0xff));
758 
759     try std.testing.expectEqualSlices(u8, &before_bytes, &bytes);
760     try std.testing.expectEqualDeep(expected_owner, owner);
761     try std.testing.expectEqual(storage_pointer, @intFromPtr(owner.storage.ptr));
762     try std.testing.expectEqual(storage_length, owner.storage.len);
763     _ = owner.deinit();
764 }
765 
766 test "provisioned accounting rejects max plus one before mutation" {
767     const Owner = ProvisionedRejectingFixture;
768     var bytes: [Owner.slots_max]u8 align(Owner.storage_alignment) = @splat(0);
769     var owner = try Owner.init(bytes[0..], .{
770         .slots = Owner.slots_max,
771         .slot_bytes = 1,
772     });
773     owner.activate();
774     owner.usage.submitted = std.math.maxInt(usize);
775     const empty_bytes = bytes;
776     const empty_owner = owner;
777     const empty_storage_pointer = @intFromPtr(owner.storage.ptr);
778     const empty_storage_length = owner.storage.len;
779     try std.testing.expectError(error.AccountingOverflow, owner.submit(1));
780     try std.testing.expectEqualDeep(empty_owner, owner);
781     try std.testing.expectEqual(
782         empty_storage_pointer,
783         @intFromPtr(owner.storage.ptr),
784     );
785     try std.testing.expectEqual(empty_storage_length, owner.storage.len);
786     try std.testing.expectEqualSlices(u8, &empty_bytes, &bytes);
787 
788     owner.usage = .{};
789     for (0..Owner.slots_max) |index| try owner.submit(@intCast(index + 1));
790     owner.usage.submitted = std.math.maxInt(usize) - 1;
791     owner.usage.rejected = std.math.maxInt(usize);
792     const full_bytes = bytes;
793     const full_owner = owner;
794     const full_storage_pointer = @intFromPtr(owner.storage.ptr);
795     const full_storage_length = owner.storage.len;
796     try std.testing.expectError(error.AccountingOverflow, owner.submit(0xff));
797     try std.testing.expectEqualDeep(full_owner, owner);
798     try std.testing.expectEqual(
799         full_storage_pointer,
800         @intFromPtr(owner.storage.ptr),
801     );
802     try std.testing.expectEqual(full_storage_length, owner.storage.len);
803     try std.testing.expectEqualSlices(u8, &full_bytes, &bytes);
804     _ = owner.deinit();
805 }
806 
807 test "provisioned cleanup completes within literal work limits" {
808     const Owner = ProvisionedRejectingFixture;
809     var bytes: [Owner.slots_max]u8 align(Owner.storage_alignment) = @splat(0);
810     var owner = try Owner.init(bytes[0..], .{
811         .slots = Owner.slots_max,
812         .slot_bytes = 1,
813     });
814     owner.activate();
815     for (0..Owner.slots_max) |index| try owner.submit(@intCast(index + 1));
816 
817     var cleanup_calls: usize = 0;
818     var cleanup_steps: usize = 0;
819     while (owner.cleanupOne()) {
820         cleanup_calls += 1;
821         cleanup_steps += 1;
822         try std.testing.expect(cleanup_steps <= cleanup_calls);
823         try std.testing.expectEqual(Owner.slots_max - cleanup_calls, owner.used);
824     }
825     try std.testing.expectEqual(
826         Owner.work_limits.cleanup_calls_at_capacity_max,
827         cleanup_calls,
828     );
829     try std.testing.expect(
830         cleanup_steps <= cleanup_calls * Owner.work_limits.cleanup_steps_per_call_max,
831     );
832     try std.testing.expectEqualSlices(u8, &@as([Owner.slots_max]u8, @splat(0)), &bytes);
833     _ = owner.deinit();
834 }
835 
836 test "provisioned owner surface carries no allocator capability" {
837     try std.testing.expect(
838         !capacity.typeHasAllocatorCapability(ProvisionedExactFixture),
839     );
840     try std.testing.expect(
841         !capacity.typeHasAllocatorCapability(ProvisionedRejectingFixture),
842     );
843 }
844 
845 test "provisioned owner lifecycle performs zero observed allocations" {
846     const Owner = ProvisionedRejectingFixture;
847     var observer = try phase.ObservingPhaseAllocator.init(std.testing.allocator);
848     const initialization_allocator = observer.initializationAllocator();
849     const bytes = try initialization_allocator.alignedAlloc(
850         u8,
851         .fromByteUnits(Owner.storage_alignment),
852         Owner.slots_max,
853     );
854     @memset(bytes, 0);
855     defer {
856         if (observer.phase() == .initialization) {
857             observer.abortInitialization();
858         } else if (observer.phase() == .steady) {
859             observer.beginTeardown();
860         }
861         observer.teardownAllocator().free(bytes);
862         observer.deinit();
863     }
864     var owner = try Owner.init(bytes[0..], .{
865         .slots = Owner.slots_max,
866         .slot_bytes = 1,
867     });
868 
869     observer.seal();
870     owner.activate();
871     for (0..Owner.slots_max) |index| {
872         try owner.submit(@intCast(index + 1));
873     }
874     try std.testing.expectError(error.Full, owner.submit(0xff));
875     while (owner.cleanupOne()) {}
876     _ = owner.deinit();
877 
878     try std.testing.expectEqual(@as(u64, 0), observer.violations().total());
879 }
880 
881 test "capacity package namespace" {
882     std.testing.refAllDecls(capacity);
883 }