use super::*;

#[test]
fn premise_keys_arity_order_and_prior_frontier_are_authenticated() {
    let mut ar = Arena::try_new_boxed().unwrap();
    let object = atom(&mut ar, 0);
    let other = atom(&mut ar, 1);
    let qa = quote(&mut ar, 7);
    let qb = quote(&mut ar, 9);
    let formula = binary(&mut ar, 5, qa, qb);
    let mut records = Vec::new();
    derive(&mut ar, object, formula, &mut records);
    let extra = derive(&mut ar, other, qa, &mut records);
    let memory = import(&ar);
    let mut evals = store(&memory);
    evals.append(records[0].candidate).unwrap();
    evals.append(records[1].candidate).unwrap();
    let foreign = evals.append(records[extra as usize].candidate).unwrap();
    let good = records[2].candidate;
    for premises in [
        Premises::None,
        Premises::One(0),
        Premises::Three([0, 1, 0]),
        Premises::Two([1, 0]),
        Premises::Two([foreign, 1]),
        Premises::Two([3, 1]),
        Premises::Two([4, 1]),
        Premises::Two([u32::MAX, 1]),
    ] {
        let before = evals.records.clone();
        assert!(evals.append(Candidate { premises, ..good }).is_err());
        assert_eq!(evals.records, before);
    }
    assert_eq!(evals.append(good), Ok(3));
}

#[test]
fn computed_continuation_binds_both_child_results_as_its_key() {
    let mut ar = Arena::try_new_boxed().unwrap();
    let object = atom(&mut ar, 0);
    let qa = quote(&mut ar, 7);
    let one = atom(&mut ar, 1);
    let identity = op(&mut ar, 0, one);
    let qf = op(&mut ar, 1, identity);
    let formula = binary(&mut ar, 2, qa, qf);
    let mut records = Vec::new();
    derive(&mut ar, object, formula, &mut records);
    let wrong = derive(&mut ar, object, identity, &mut records);
    let computed_object = records[0].candidate.result;
    let wrong_formula = derive(&mut ar, computed_object, qa, &mut records);
    let memory = import(&ar);
    let mut evals = verified(&memory, &records[..3]);
    let wrong_id = evals.append(records[wrong as usize].candidate).unwrap();
    let wrong_formula_id = evals
        .append(records[wrong_formula as usize].candidate)
        .unwrap();
    let good = records[3].candidate;
    assert_eq!(
        evals.append(Candidate {
            premises: Premises::Three([0, 1, wrong_id]),
            ..good
        }),
        Err(Error::Premise)
    );
    assert_eq!(
        evals.append(Candidate {
            premises: Premises::Three([0, 1, wrong_formula_id]),
            ..good
        }),
        Err(Error::Premise)
    );
    assert_eq!(evals.append(good), Ok(5));
}

#[test]
fn changing_the_selected_arm_rejects_even_when_the_forged_result_matches_it() {
    for condition in [0, 1, nebu::field::P - 1] {
        let mut ar = Arena::try_new_boxed().unwrap();
        let object = atom(&mut ar, 0);
        let test = quote(&mut ar, condition);
        let yes = quote(&mut ar, 7);
        let no = quote(&mut ar, 9);
        let formula = branch(&mut ar, test, yes, no);
        let mut records = Vec::new();
        derive(&mut ar, object, formula, &mut records);
        let unselected = if condition == 0 { no } else { yes };
        let wrong = derive(&mut ar, object, unselected, &mut records);
        let memory = import(&ar);
        let mut evals = verified(&memory, &records[..2]);
        let wrong_id = evals.append(records[wrong as usize].candidate).unwrap();
        let forged = Candidate {
            result: records[wrong as usize].candidate.result,
            premises: Premises::Two([0, wrong_id]),
            ..records[2].candidate
        };
        assert_eq!(evals.append(forged), Err(Error::Premise));
        assert_eq!(evals.len(), 3);
        assert_eq!(evals.append(records[2].candidate), Ok(3));
    }
}

#[test]
fn outputs_bind_ordered_topology_and_all_root_particle_limbs() {
    let mut ar = Arena::try_new_boxed().unwrap();
    let object = atom(&mut ar, 0);
    let qa = quote(&mut ar, 7);
    let qb = quote(&mut ar, 9);
    let f = binary(&mut ar, 3, qa, qb);
    let mut records = Vec::new();
    derive(&mut ar, object, f, &mut records);
    let a = records[0].candidate.result;
    let b = records[1].candidate.result;
    let reversed = ar.pair(b, a).unwrap();
    let memory = import(&ar);
    let mut evals = verified(&memory, &records[..2]);
    let good = records[2];
    for result in [a, reversed, u32::MAX] {
        assert!(
            evals
                .append(Candidate {
                    result,
                    ..good.candidate
                })
                .is_err()
        );
        assert_eq!(evals.len(), 2);
    }
    evals.append(good.candidate).unwrap();
    let expected = claim(&ar, good);
    for field in 0..3 {
        for limb in 0..4 {
            let mut changed = expected;
            match field {
                0 => changed.object[limb] ^= 1,
                1 => changed.formula[limb] ^= 1,
                _ => changed.result[limb] ^= 1,
            }
            assert_eq!(evals.bind_last(changed), Err(Error::Claim));
        }
    }
    for changed in [
        Claim {
            cost: good.cost + 1,
            ..expected
        },
        Claim {
            cost: good.cost ^ (1 << 32),
            ..expected
        },
        Claim {
            budget: good.cost - 1,
            ..expected
        },
        Claim {
            max_frames: good.peak - 1,
            ..expected
        },
        Claim {
            max_frames: limits().max_frames + 1,
            ..expected
        },
    ] {
        assert_eq!(evals.bind_last(changed), Err(Error::Claim));
    }
    assert_eq!(evals.bind_last(expected).unwrap().remaining(), 0);
    assert_eq!(
        evals
            .bind_last(Claim {
                budget: expected.budget + 1,
                ..expected
            })
            .unwrap()
            .remaining(),
        1
    );
    evals.append(records[0].candidate).unwrap();
    assert_eq!(evals.bind_last(expected), Err(Error::Claim));
}

#[test]
fn equality_and_premise_keys_use_particles_across_duplicate_occurrences() {
    let mut ar = Arena::try_new_boxed().unwrap();
    let object = atom(&mut ar, 0);
    let value = atom(&mut ar, 7);
    let q = op(&mut ar, 1, value);
    let f = binary(&mut ar, 9, q, q);
    let mut records = Vec::new();
    derive(&mut ar, object, f, &mut records);
    let mut memory = Memory::new(
        ar.count() + 3,
        (ar.count() as usize + 3) * size_of::<VerifiedNode>(),
    )
    .unwrap();
    let native = import(&ar);
    for i in 0..native.len() {
        let view = native.view(native.len()).unwrap();
        let n = view.get(i).unwrap();
        memory
            .append(Definition {
                value: n.value(),
                particle: n.particle(),
                cost: n.cost(),
            })
            .unwrap();
    }
    let duplicate = |id| {
        let view = native.view(native.len()).unwrap();
        let n = view.get(id).unwrap();
        Definition {
            value: n.value(),
            particle: n.particle(),
            cost: n.cost(),
        }
    };
    let object2 = memory.append(duplicate(object)).unwrap();
    let value2 = memory.append(duplicate(value)).unwrap();
    let q2 = memory.append(duplicate(q)).unwrap();
    let mut evals = store(&memory);
    evals.append(records[0].candidate).unwrap();
    let second = evals
        .append(Candidate {
            object: object2,
            formula: q2,
            result: value2,
            premises: Premises::None,
        })
        .unwrap();
    let root = Candidate {
        premises: Premises::Two([0, second]),
        ..records[2].candidate
    };
    assert_eq!(evals.append(root), Ok(2));
    assert_eq!(evals.particles(0).unwrap(), evals.particles(1).unwrap());
}

#[test]
fn malformed_formulas_invalid_types_and_inverse_zero_have_no_success_rule() {
    for tag in [0, 2, 4, 5, 8, 10, 11, 12, 13, 14, 16, 17, 99] {
        let mut ar = Arena::try_new_boxed().unwrap();
        let zero = atom(&mut ar, 0);
        let wide = atom(&mut ar, 1 << 32);
        let pair = ar.pair(zero, wide).unwrap();
        let value = if tag == 8 {
            zero
        } else if [11, 12, 13, 14].contains(&tag) {
            wide
        } else {
            pair
        };
        let q = op(&mut ar, 1, value);
        let mut records = Vec::new();
        derive(&mut ar, zero, q, &mut records);
        let formula = match tag {
            8 | 13 => op(&mut ar, tag, q),
            5 | 10 | 11 | 12 | 14 => binary(&mut ar, tag, q, q),
            _ => op(&mut ar, tag, pair),
        };
        let premises = match tag {
            8 | 13 => Premises::One(0),
            2 => Premises::Three([0, 0, 0]),
            0 | 16 | 17 | 99 => Premises::None,
            _ => Premises::Two([0, 0]),
        };
        let memory = import(&ar);
        let mut evals = verified(&memory, &records);
        assert!(
            evals
                .append(Candidate {
                    object: zero,
                    formula,
                    result: zero,
                    premises
                })
                .is_err(),
            "tag {tag}"
        );
        assert_eq!(evals.len(), 1);
        assert!(
            evals
                .append(Candidate {
                    object: zero,
                    formula: zero,
                    result: zero,
                    premises: Premises::None
                })
                .is_err()
        );
    }
}

#[test]
fn exact_and_one_below_resource_limits_fail_without_mutation() {
    let mut ar = Arena::try_new_boxed().unwrap();
    let object = atom(&mut ar, 0);
    let q = quote(&mut ar, 7);
    let f = binary(&mut ar, 3, q, q);
    let mut records = Vec::new();
    derive(&mut ar, object, f, &mut records);
    let memory = import(&ar);
    let exact = Limits {
        max_evaluations: 3,
        max_buffer_bytes: 3 * size_of::<VerifiedEvaluation>(),
        max_cost: 3,
        max_frames: 2,
        max_steps: 6,
    };
    assert!(
        Evaluations::new(
            memory.view(memory.len()).unwrap(),
            Limits {
                max_buffer_bytes: exact.max_buffer_bytes - 1,
                ..exact
            }
        )
        .is_err()
    );
    for limits in [
        exact,
        Limits {
            max_evaluations: 2,
            ..exact
        },
        Limits {
            max_cost: 2,
            ..exact
        },
        Limits {
            max_frames: 1,
            ..exact
        },
        Limits {
            max_steps: 5,
            ..exact
        },
    ] {
        let mut evals = Evaluations::new(memory.view(memory.len()).unwrap(), limits).unwrap();
        for record in &records[..2] {
            evals.append(record.candidate).unwrap();
        }
        let before = evals.records.clone();
        let got = evals.append(records[2].candidate);
        if limits.max_evaluations == 3
            && limits.max_cost == 3
            && limits.max_frames == 2
            && limits.max_steps == 6
        {
            assert_eq!(got, Ok(2));
            assert!(evals.buffer_bytes() <= exact.max_buffer_bytes);
        } else {
            assert_eq!(got, Err(Error::Limit));
            assert_eq!(evals.records, before);
        }
    }
    let mut empty = Evaluations::new(memory.view(0).unwrap(), limits()).unwrap();
    assert_eq!(empty.append(records[0].candidate), Err(Error::Noun));
    assert!(empty.bind_last(claim(&ar, records[0])).is_err());
}

#[test]
fn expanded_steps_and_exact_cost_overflow_reject_shared_derivations() {
    for tag in [3, 10] {
        let mut ar = Arena::try_new_boxed().unwrap();
        let object = atom(&mut ar, 0);
        let mut result = atom(&mut ar, 1);
        let mut formula = op(&mut ar, 1, result);
        let mut candidates = vec![Candidate {
            object,
            formula,
            result,
            premises: Premises::None,
        }];
        for i in 0..64 {
            formula = binary(&mut ar, tag, formula, formula);
            result = if tag == 3 {
                ar.pair(result, result).unwrap()
            } else {
                atom(&mut ar, 1)
            };
            candidates.push(Candidate {
                object,
                formula,
                result,
                premises: Premises::Two([i, i]),
            });
        }
        let memory = import(&ar);
        let mut evals = store(&memory);
        let mut failed = false;
        for candidate in candidates {
            let before = evals.records.clone();
            match evals.append(candidate) {
                Ok(_) => {}
                Err(error) => {
                    assert_eq!(error, Error::Limit);
                    assert_eq!(evals.records, before);
                    failed = true;
                    break;
                }
            }
        }
        assert!(failed);
    }
}

Homonyms

soft3/zheng/rs/src/execution/tagged/node_cost_tests/adversarial.rs
soft3/zheng/rs/src/execution/disclosed/stream/tests/adversarial.rs

Graph