mltrail-verifiable-provenan.../tests/test_ledger.py

44 lines
1.8 KiB
Python

import pytest
from mltrail_verifiable_provenance_ledger_for.ledger import Ledger, delta_sync
from mltrail_verifiable_provenance_ledger_for.contracts import Experiment, Run, Dataset, Model, Environment, EvaluationMetric, Policy
def test_ledger_append_and_chain():
ledger = Ledger()
e = Experiment(id="exp1", name="Demo", version=1, description="test", metadata={"owner": "alice"})
ledger.add_record("Experiment", e.to_dict())
head1 = ledger.head
assert head1.index == 1
assert head1.previous_hash == "0" * 64
assert len(head1.data) == 1
# Add a Run in a new block
r = Run(id="run1", experiment_id="exp1", parameters={"lr": 0.01}, metrics={"acc": 0.9}, environment_hash="abc123")
ledger.add_record("Run", r.to_dict())
head2 = ledger.head
assert head2.index == 2
assert head2.previous_hash == head1.hash
assert len(head2.data) == 1
def test_delta_sync_basic():
a = Ledger()
b = Ledger()
# A has two blocks now
a.add_record("Experiment", Experiment(id="exp1", name="Demo", version=1, description="test", metadata={}).to_dict())
a.add_record("Run", Run(id="run1", experiment_id="exp1", parameters={}, metrics={}, environment_hash="e1").to_dict())
# B only has genesis and first block (simulate partition)
b.add_record("Experiment", Experiment(id="exp1", name="Demo", version=1, description="test", metadata={}).to_dict())
delta = delta_sync(a, b.head_hash())
assert isinstance(delta, list)
assert len(delta) == 1 or len(delta) == 2 # depending on whether b's head matches a's first block
def test_environment_hash_reproducibility():
from mltrail_verifiable_provenance_ledger_for.util import environment_hash
deps1 = {"numpy": "1.26.0", "pandas": "2.0.0"}
deps2 = {"pandas": "2.0.0", "numpy": "1.26.0"}
assert environment_hash(deps1) == environment_hash(deps2)