Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

76 changes: 55 additions & 21 deletions crates/labcolors-core/src/appearance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1367,6 +1367,16 @@ pub(crate) enum ExactFinalOwnedPointDomainV1 {
Singleton { visible: [u8; 3] },
}

impl ExactFinalOwnedPointDomainV1 {
fn from_roots(normal: [u8; 3], counterfactual: [u8; 3]) -> Self {
if normal == counterfactual {
Self::Empty
} else {
Self::Singleton { visible: normal }
}
}
}

/// Один точный шаг версионированной интервенции отсутствия.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum PointOccurrenceAbsenceStepV1 {
Expand Down Expand Up @@ -1402,6 +1412,44 @@ impl PointOccurrenceAbsenceStepV1 {
}
}

/// Нейтральная сводка непустой истории пересчёта. В отличие от Replay она не
/// выдаёт право на происхождение шагов: authority остаётся у вычисления либо
/// у владеющего ими revision-bound отчёта.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) struct PointOccurrenceAbsenceSummaryV1 {
first: PointOccurrenceAbsenceStepV1,
last: PointOccurrenceAbsenceStepV1,
}

impl PointOccurrenceAbsenceSummaryV1 {
pub(crate) fn from_nonempty_steps(steps: &[PointOccurrenceAbsenceStepV1]) -> Option<Self> {
Some(Self {
first: steps.first().copied()?,
last: steps.last().copied()?,
})
}

pub(crate) const fn target(self) -> OccurrenceId {
self.first.occurrence()
}

pub(crate) const fn root(self) -> OccurrenceId {
self.last.occurrence()
}

pub(crate) const fn normal_root(self) -> [u8; 3] {
self.last.normal().output_rgb()
}

pub(crate) const fn counterfactual_root(self) -> [u8; 3] {
self.last.counterfactual_output()
}

pub(crate) fn domain(self) -> ExactFinalOwnedPointDomainV1 {
ExactFinalOwnedPointDomainV1::from_roots(self.normal_root(), self.counterfactual_root())
}
}

/// Заимствованный результат одного точного контрфактического пересчёта.
///
/// Результат связывает версию интервенции и профили композиции шагов, но сам по
Expand All @@ -1416,47 +1464,33 @@ pub(crate) struct PointOccurrenceAbsenceReplayV1<'steps> {
}

impl PointOccurrenceAbsenceReplayV1<'_> {
fn first(&self) -> PointOccurrenceAbsenceStepV1 {
self.steps
.first()
.copied()
.unwrap_or_else(|| unreachable!("созданный компилятором пересчёт непуст"))
}

fn last(&self) -> PointOccurrenceAbsenceStepV1 {
self.steps
.last()
.copied()
fn summary(&self) -> PointOccurrenceAbsenceSummaryV1 {
PointOccurrenceAbsenceSummaryV1::from_nonempty_steps(self.steps)
.unwrap_or_else(|| unreachable!("созданный компилятором пересчёт непуст"))
}

pub(crate) fn target(&self) -> OccurrenceId {
self.first().occurrence()
self.summary().target()
}

pub(crate) fn root(&self) -> OccurrenceId {
self.last().occurrence()
self.summary().root()
}

pub(crate) const fn release(&self) -> PointOccurrenceAbsenceReleaseV1 {
self.release
}

pub(crate) fn normal_root(&self) -> [u8; 3] {
self.last().normal().output_rgb()
self.summary().normal_root()
}

pub(crate) fn counterfactual_root(&self) -> [u8; 3] {
self.last().counterfactual_output()
self.summary().counterfactual_root()
}

pub(crate) fn domain(&self) -> ExactFinalOwnedPointDomainV1 {
let normal = self.normal_root();
if normal == self.counterfactual_root() {
ExactFinalOwnedPointDomainV1::Empty
} else {
ExactFinalOwnedPointDomainV1::Singleton { visible: normal }
}
self.summary().domain()
}

pub(crate) const fn steps(&self) -> &[PointOccurrenceAbsenceStepV1] {
Expand Down
3 changes: 3 additions & 0 deletions crates/labcolors-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ mod program_lcs_integration_tests;
#[cfg(test)]
mod program_joint_integration_tests;

#[cfg(test)]
mod program_point_causality_tests;

#[cfg(test)]
mod program_mixed_evaluator_tests;

Expand Down
38 changes: 38 additions & 0 deletions crates/labcolors-core/src/program_boundary_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,44 @@ fn evidence_cell_bounds_report_both_checked_multiplication_overflows() {
));
}

#[test]
fn evidence_cell_bounds_are_independent_of_internal_causal_replay_storage() {
let source = SourceIdV1::new(1);
let target = TargetIdV1::new(2);
let input = SurfaceInputPortIdV1::new(3);
let paint = PaintIdV1::new(4);
let input_surface = SurfaceIdV1::new(5);
let derived_surface = SurfaceIdV1::new(6);
let inner = OccurrenceIdV1::new(7);
let terminal = OccurrenceIdV1::new(8);
let constraint = ConstraintIdV1::new(9);
let output = OutputSlotIdV1::new(10);
let root = PresentationRootIdV1::new(11);
let context = AppearanceContextV1::try_new(64.0, 0.2, SurroundV1::Average).unwrap();

let mut draft = DraftV1::new();
draft.push_source(source, Srgb8::new([0; 3]));
draft.push_fixed_target(target, source);
draft.push_surface_input_port(input);
draft.push_solid_paint(paint, target);
draft.push_input_surface(input_surface, input);
draft.push_source_over_occurrence(inner, paint, input_surface, context);
draft.push_occurrence_surface(derived_surface, inner);
draft.push_source_over_occurrence(terminal, paint, derived_surface, context);
draft.push_exact_hard(constraint, terminal, Srgb8::new([0; 3]));
draft.push_point_presentation_root(root, terminal);
draft.push_point_presentation_target(root, inner);
draft.push_output(output, paint);
let owner = draft.compile().unwrap();

// One cell per scenario still fits. The two-step causal replay would not,
// but that private arena is outside this cell-only prospective query.
let scenario_count = usize::MAX / 2 + 1;
let bounds = owner.evidence_cell_bounds(scenario_count).unwrap();
assert_eq!(bounds.verified_cells(), scenario_count);
assert_eq!(bounds.conflict_cells(), scenario_count);
}

#[test]
fn evidence_cell_bounds_cover_actual_joint_conflict_and_duplicate_case_reduction() {
let joint = joint_draft(true).compile().unwrap();
Expand Down
46 changes: 34 additions & 12 deletions crates/labcolors-core/src/program_joint_integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1485,7 +1485,9 @@ fn evaluation_cell_cardinality_checks_both_products_without_a_numeric_cap() {

#[test]
fn every_fallible_joint_preflight_reservation_precedes_evaluator_work() {
for reservation_index in 0..3 {
const FIRST_UNUSED_RESERVATION_INDEX: usize = 3;

for reservation_index in 0..=FIRST_UNUSED_RESERVATION_INDEX {
let evaluator = CountingProgramWcag22Srgb8V1::default();
let calls = evaluator.clone();
let compiled = Program::new(
Expand Down Expand Up @@ -1530,12 +1532,21 @@ fn every_fallible_joint_preflight_reservation_precedes_evaluator_work() {
.unwrap();
let mut session = compiled.instantiate(STREAM).unwrap();

let error = {
let result = {
let _failure = fail_program_preflight_reservation_for_test(reservation_index);
match session.update(update(1, 0x00)) {
Ok(_) => panic!("injected preflight failure must abort the update"),
Err(error) => error,
}
session.update(update(1, 0x00))
};
if reservation_index == FIRST_UNUSED_RESERVATION_INDEX {
assert!(
matches!(result, Ok(SessionState::Ready { .. })),
"the first unused reservation index must leave the Session Ready"
);
assert!(!calls.calls().is_empty());
continue;
}
let error = match result {
Ok(_) => panic!("injected preflight failure must abort the update"),
Err(error) => error,
};
assert_eq!(
error,
Expand All @@ -1548,7 +1559,9 @@ fn every_fallible_joint_preflight_reservation_precedes_evaluator_work() {

#[test]
fn every_fallible_fixed_preflight_reservation_precedes_evaluator_work() {
for reservation_index in 0..2 {
const FIRST_UNUSED_RESERVATION_INDEX: usize = 2;

for reservation_index in 0..=FIRST_UNUSED_RESERVATION_INDEX {
let evaluator = CountingProgramWcag22Srgb8V1::default();
let calls = evaluator.clone();
let compiled = Program::new(
Expand Down Expand Up @@ -1586,12 +1599,21 @@ fn every_fallible_fixed_preflight_reservation_precedes_evaluator_work() {
.unwrap();
let mut session = compiled.instantiate(STREAM).unwrap();

let error = {
let result = {
let _failure = fail_program_preflight_reservation_for_test(reservation_index);
match session.update(update(1, 0x00)) {
Ok(_) => panic!("injected fixed preflight failure must abort the update"),
Err(error) => error,
}
session.update(update(1, 0x00))
};
if reservation_index == FIRST_UNUSED_RESERVATION_INDEX {
assert!(
matches!(result, Ok(SessionState::Ready { .. })),
"the first unused reservation index must leave the Session Ready"
);
assert!(!calls.calls().is_empty());
continue;
}
let error = match result {
Ok(_) => panic!("injected fixed preflight failure must abort the update"),
Err(error) => error,
};
assert_eq!(
error,
Expand Down
Loading
Loading