mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-10-24 06:23:06 +08:00
Preserve the current selector, frozen-input inventory, result codec, coverage collection, runner filtering, and isolated Windows venue work. Component-level regression proofs are recorded in the PR handover. The live classified provider, public execution integration, artifact admission, fresh oracle/shadow evidence, and full platform gates remain incomplete. This checkpoint does not enable or claim verified narrowing. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
731 lines
23 KiB
Python
731 lines
23 KiB
Python
"""Pure bounded single-image profile-map v2 encoding and row reduction.
|
|
|
|
Evidence fields are caller claims, not authentication or closure certificates.
|
|
Names/hashes/shapes retain exact profile identity; source names are not inferred.
|
|
Limits count logical data, not interpreter RSS. Runtime allocation/deallocation
|
|
is not preemptible. This module performs no I/O and leaves format 1 unchanged.
|
|
"""
|
|
|
|
from dataclasses import dataclass
|
|
from enum import Enum
|
|
import hashlib
|
|
import sys
|
|
from typing import Callable, Optional, Tuple
|
|
|
|
from profile_text_parser import (
|
|
LimitExceededError, MalformedProfileError, ParseCancelledError,
|
|
ParseLimits, parse_profile_text,
|
|
)
|
|
|
|
|
|
class SuiteOutcome(Enum):
|
|
PASSED = "passed"
|
|
FAILED = "failed"
|
|
TIMED_OUT = "timed_out"
|
|
UNKNOWN = "unknown"
|
|
|
|
|
|
class ObservationRole(Enum):
|
|
PARENT = "parent"
|
|
SETUP = "setup"
|
|
CHILD = "child"
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class ExpectedSuite:
|
|
__slots__ = ("suite", "tests", "outcome")
|
|
|
|
suite: bytes
|
|
tests: Tuple[bytes, ...]
|
|
outcome: SuiteOutcome
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class ProfileObservation:
|
|
__slots__ = ("suite", "test", "key", "role", "text")
|
|
|
|
suite: bytes
|
|
test: bytes
|
|
key: bytes
|
|
role: ObservationRole
|
|
text: Optional[bytes] # None means an explicitly unavailable observation.
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class RowEvidence:
|
|
__slots__ = (
|
|
"suite", "test", "interval_complete", "runtime_compatible",
|
|
"same_image", "children_complete",
|
|
)
|
|
|
|
suite: bytes
|
|
test: bytes
|
|
interval_complete: bool
|
|
runtime_compatible: bool
|
|
same_image: bool
|
|
children_complete: bool
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class ProfileMapLimits:
|
|
__slots__ = (
|
|
"max_input_bytes", "max_rows", "max_observations", "max_ids",
|
|
"max_records", "max_counter_values", "max_name_bytes",
|
|
"max_id_references", "max_output_bytes",
|
|
)
|
|
|
|
max_input_bytes: int
|
|
max_rows: int
|
|
max_observations: int
|
|
max_ids: int
|
|
max_records: int
|
|
max_counter_values: int
|
|
max_name_bytes: int
|
|
max_id_references: int
|
|
max_output_bytes: int
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class ProducedMap:
|
|
__slots__ = (
|
|
"profiles_tsv", "tests_tsv", "profiles_sha256", "tests_sha256",
|
|
)
|
|
|
|
profiles_tsv: bytes
|
|
tests_tsv: bytes
|
|
profiles_sha256: bytes
|
|
tests_sha256: bytes
|
|
|
|
|
|
class ProfileMapError(ValueError):
|
|
"""Base for classified build failures; no ProducedMap is returned."""
|
|
|
|
|
|
class ProfileMapInvalidArgumentError(ProfileMapError):
|
|
"""Invalid exact type, field, routing, membership, duplicate or callback result."""
|
|
|
|
|
|
class ProfileMapEnumerationError(ProfileMapError):
|
|
"""Enumeration text is malformed or unsupported, including empty text."""
|
|
|
|
|
|
class ProfileMapCompatibilityError(ProfileMapError):
|
|
"""An observation contains an unknown full identity or mismatching shape."""
|
|
|
|
|
|
class ProfileMapLimitExceededError(ProfileMapError):
|
|
"""A declared logical or fixed representation bound would be exceeded."""
|
|
|
|
|
|
class ProfileMapCancelledError(ProfileMapError):
|
|
"""The caller's pure prompt predicate requested cancellation."""
|
|
|
|
|
|
_INT_MAX = 2147483647
|
|
_SHA_BYTES_MAX = ((1 << 64) - 1) // 8
|
|
_POLL_INTERVAL = 4096
|
|
_HEX = b"0123456789abcdef"
|
|
_REASONS = (
|
|
b"suite_failed", b"suite_timeout", b"suite_unknown",
|
|
b"row_evidence_missing", b"interval_unproved", b"runtime_unproved",
|
|
b"image_unproved", b"children_unproved", b"missing_parent",
|
|
b"missing_setup", b"observation_unavailable", b"observation_malformed",
|
|
b"partial_stream",
|
|
)
|
|
_SUITE_FAILED, _SUITE_TIMEOUT, _SUITE_UNKNOWN = 0, 1, 2
|
|
_NO_EVIDENCE, _INTERVAL, _RUNTIME, _IMAGE, _CHILDREN = 3, 4, 5, 6, 7
|
|
_NO_PARENT, _NO_SETUP, _UNAVAILABLE, _MALFORMED, _PARTIAL = 8, 9, 10, 11, 12
|
|
|
|
|
|
class _Gate:
|
|
__slots__ = ("cancel", "context", "work", "callback_error")
|
|
|
|
def __init__(self, cancel, context):
|
|
self.cancel = cancel
|
|
self.context = context
|
|
self.work = 0
|
|
self.callback_error = None
|
|
|
|
def poll(self):
|
|
self.work = 0
|
|
if self.cancel is None:
|
|
return
|
|
try:
|
|
answer = self.cancel(self.context)
|
|
except BaseException as error:
|
|
# Identity distinguishes a callback's parser-shaped exception from
|
|
# a parser failure; neither its class nor message is sufficient.
|
|
self.callback_error = error
|
|
raise
|
|
if type(answer) is not bool:
|
|
raise ProfileMapInvalidArgumentError("cancel must return bool")
|
|
if answer:
|
|
raise ProfileMapCancelledError("profile map build cancelled")
|
|
|
|
def step(self):
|
|
self.work += 1
|
|
if self.work == _POLL_INTERVAL:
|
|
self.poll()
|
|
|
|
def parser_cancel(self, _context):
|
|
self.poll()
|
|
return False
|
|
|
|
|
|
def _bounded_add(current, amount, cap, label):
|
|
if amount > cap - current:
|
|
raise ProfileMapLimitExceededError(label)
|
|
return current + amount
|
|
|
|
|
|
class _Budget:
|
|
__slots__ = (
|
|
"limits", "input_bytes", "rows", "records", "counter_values",
|
|
"name_bytes", "id_references", "output_bytes",
|
|
)
|
|
|
|
def __init__(self, limits, enumeration_text):
|
|
self.limits = limits
|
|
self.input_bytes = _bounded_add(
|
|
32, len(enumeration_text), limits.max_input_bytes, "input byte limit"
|
|
)
|
|
self.rows = 0
|
|
self.records = 0
|
|
self.counter_values = 0
|
|
self.name_bytes = 0
|
|
self.id_references = 0
|
|
self.output_bytes = 0
|
|
|
|
def name(self, value):
|
|
self.input_bytes = _bounded_add(
|
|
self.input_bytes, len(value), self.limits.max_input_bytes,
|
|
"input byte limit",
|
|
)
|
|
self.name_bytes = _bounded_add(
|
|
self.name_bytes, len(value), self.limits.max_name_bytes,
|
|
"name byte limit",
|
|
)
|
|
|
|
def text(self, value):
|
|
self.input_bytes = _bounded_add(
|
|
self.input_bytes, len(value), self.limits.max_input_bytes,
|
|
"input byte limit",
|
|
)
|
|
|
|
def add_rows(self, count):
|
|
self.rows = _bounded_add(
|
|
self.rows, count, min(self.limits.max_rows, _INT_MAX), "row limit"
|
|
)
|
|
|
|
def parsed(self, records, gate):
|
|
self.records = _bounded_add(
|
|
self.records, len(records), self.limits.max_records, "record limit"
|
|
)
|
|
for record in records:
|
|
gate.step()
|
|
self.counter_values = _bounded_add(
|
|
self.counter_values, len(record.counters),
|
|
self.limits.max_counter_values, "counter value limit",
|
|
)
|
|
self.name_bytes = _bounded_add(
|
|
self.name_bytes, len(record.raw_name),
|
|
self.limits.max_name_bytes, "name byte limit",
|
|
)
|
|
|
|
def reference(self):
|
|
self.id_references = _bounded_add(
|
|
self.id_references, 1, self.limits.max_id_references,
|
|
"ID reference limit",
|
|
)
|
|
|
|
def output(self, count):
|
|
self.output_bytes = _bounded_add(
|
|
self.output_bytes, count,
|
|
min(self.limits.max_output_bytes, _SHA_BYTES_MAX), "output byte limit",
|
|
)
|
|
|
|
|
|
class _Row:
|
|
__slots__ = (
|
|
"suite", "test", "outcome", "evidence", "observations", "ids",
|
|
"reasons", "parent_seen", "primary_parsed",
|
|
)
|
|
|
|
def __init__(self, suite, test, outcome):
|
|
self.suite = suite
|
|
self.test = test
|
|
self.outcome = outcome
|
|
self.evidence = None
|
|
self.observations = []
|
|
self.ids = set()
|
|
self.reasons = 0
|
|
self.parent_seen = False
|
|
self.primary_parsed = False
|
|
|
|
def mark(self, reason):
|
|
self.reasons |= 1 << reason
|
|
|
|
|
|
def _exact(value, cls, label):
|
|
if type(value) is not cls:
|
|
raise ProfileMapInvalidArgumentError(label)
|
|
|
|
|
|
def _validate_top(image, enumeration, suites, observations, evidence, limits, cancel):
|
|
_exact(image, bytes, "image digest must be bytes")
|
|
if len(image) != 32:
|
|
raise ProfileMapInvalidArgumentError("image digest must contain 32 bytes")
|
|
_exact(enumeration, bytes, "enumeration must be bytes")
|
|
_exact(suites, tuple, "expected suites must be a tuple")
|
|
_exact(observations, tuple, "observations must be a tuple")
|
|
_exact(evidence, tuple, "row evidence must be a tuple")
|
|
_exact(limits, ProfileMapLimits, "invalid limits type")
|
|
for field in ProfileMapLimits.__slots__:
|
|
value = getattr(limits, field)
|
|
if type(value) is not int or value <= 0 or value > sys.maxsize:
|
|
raise ProfileMapInvalidArgumentError("limits must be positive bounded ints")
|
|
if limits.max_ids > _INT_MAX:
|
|
raise ProfileMapInvalidArgumentError("max_ids exceeds INT_MAX")
|
|
if cancel is not None and not callable(cancel):
|
|
raise ProfileMapInvalidArgumentError("cancel must be callable or None")
|
|
|
|
|
|
def _name(value, budget, gate, *, suite=False, declared_test=False):
|
|
_exact(value, bytes, "names and keys must be bytes")
|
|
if not value:
|
|
raise ProfileMapInvalidArgumentError("empty name or key")
|
|
budget.name(value)
|
|
for char in value:
|
|
gate.step()
|
|
if char in (0, 9, 10, 13) or (suite and char == 58):
|
|
raise ProfileMapInvalidArgumentError("unrepresentable name or key")
|
|
if declared_test and _is_setup(value):
|
|
raise ProfileMapInvalidArgumentError("setup name is reserved")
|
|
|
|
|
|
def _is_setup(test):
|
|
return len(test) == 1 and test[0] == 42
|
|
|
|
|
|
def _compare_bytes(left, right, gate):
|
|
for index in range(min(len(left), len(right))):
|
|
gate.step()
|
|
a, b = left[index], right[index]
|
|
if a != b:
|
|
return -1 if a < b else 1
|
|
gate.step()
|
|
return (len(left) > len(right)) - (len(left) < len(right))
|
|
|
|
|
|
def _compare_fields(left, right, fields, gate):
|
|
for field in fields:
|
|
gate.step()
|
|
order = _compare_bytes(getattr(left, field), getattr(right, field), gate)
|
|
if order:
|
|
return order
|
|
return 0
|
|
|
|
|
|
def _merge(source, target, start, middle, end, compare, gate):
|
|
left, right = start, middle
|
|
for destination in range(start, end):
|
|
gate.step()
|
|
take_left = right == end or (
|
|
left < middle and compare(source[left], source[right]) <= 0
|
|
)
|
|
if take_left:
|
|
target[destination] = source[left]
|
|
left += 1
|
|
else:
|
|
target[destination] = source[right]
|
|
right += 1
|
|
|
|
|
|
def _sort(values, compare, gate):
|
|
source, target = [], []
|
|
for value in values:
|
|
gate.step()
|
|
source.append(value)
|
|
target.append(None)
|
|
width = 1
|
|
count = len(source)
|
|
while width < count:
|
|
gate.step()
|
|
for start in range(0, count, width * 2):
|
|
gate.step()
|
|
middle, end = min(start + width, count), min(start + width * 2, count)
|
|
_merge(source, target, start, middle, end, compare, gate)
|
|
source, target = target, source
|
|
width *= 2
|
|
return source
|
|
|
|
|
|
def _sort_unique(values, fields, gate, label):
|
|
compare = lambda left, right: _compare_fields(left, right, fields, gate)
|
|
result = _sort(values, compare, gate)
|
|
for index in range(1, len(result)):
|
|
gate.step()
|
|
if compare(result[index - 1], result[index]) == 0:
|
|
raise ProfileMapInvalidArgumentError(label)
|
|
return result
|
|
|
|
|
|
def _suites(suites, budget, gate):
|
|
rows = []
|
|
if len(suites) > min(budget.limits.max_rows, _INT_MAX):
|
|
raise ProfileMapLimitExceededError("row limit")
|
|
for suite in suites:
|
|
gate.step()
|
|
_exact(suite, ExpectedSuite, "invalid expected suite type")
|
|
_name(suite.suite, budget, gate, suite=True)
|
|
_exact(suite.tests, tuple, "expected tests must be a tuple")
|
|
_exact(suite.outcome, SuiteOutcome, "invalid suite outcome")
|
|
budget.add_rows(1 + len(suite.tests))
|
|
rows.append(_Row(suite.suite, b"*", suite.outcome))
|
|
for test in suite.tests:
|
|
gate.step()
|
|
_name(test, budget, gate, declared_test=True)
|
|
rows.append(_Row(suite.suite, test, suite.outcome))
|
|
_sort_unique(suites, ("suite",), gate, "duplicate expected suite")
|
|
return _sort_unique(rows, ("suite", "test"), gate, "duplicate expected test")
|
|
|
|
|
|
def _compare_target(row, suite, test, gate):
|
|
order = _compare_bytes(row.suite, suite, gate)
|
|
return order if order else _compare_bytes(row.test, test, gate)
|
|
|
|
|
|
def _find_row(rows, suite, test, gate):
|
|
low, high = 0, len(rows)
|
|
while low < high:
|
|
gate.step()
|
|
middle = (low + high) // 2
|
|
order = _compare_target(rows[middle], suite, test, gate)
|
|
if order == 0:
|
|
return rows[middle]
|
|
if order < 0:
|
|
low = middle + 1
|
|
else:
|
|
high = middle
|
|
raise ProfileMapInvalidArgumentError("observation/evidence outside expected rows")
|
|
|
|
|
|
def _observation_schema(observation, budget, gate):
|
|
_exact(observation, ProfileObservation, "invalid observation type")
|
|
_name(observation.suite, budget, gate, suite=True)
|
|
_name(observation.test, budget, gate)
|
|
_name(observation.key, budget, gate)
|
|
_exact(observation.role, ObservationRole, "invalid observation role")
|
|
if observation.text is not None:
|
|
_exact(observation.text, bytes, "observation text must be bytes or None")
|
|
budget.text(observation.text)
|
|
|
|
|
|
def _route_observation(observation, row):
|
|
setup = _is_setup(row.test)
|
|
if ((setup and observation.role is ObservationRole.PARENT)
|
|
or (not setup and observation.role is ObservationRole.SETUP)):
|
|
raise ProfileMapInvalidArgumentError("invalid role for row")
|
|
if observation.role is ObservationRole.PARENT:
|
|
if row.parent_seen:
|
|
raise ProfileMapInvalidArgumentError("multiple parent observations")
|
|
row.parent_seen = True
|
|
row.observations.append(observation)
|
|
|
|
|
|
def _observations(observations, rows, budget, gate):
|
|
if len(observations) > budget.limits.max_observations:
|
|
raise ProfileMapLimitExceededError("observation limit")
|
|
for observation in observations:
|
|
gate.step()
|
|
_observation_schema(observation, budget, gate)
|
|
ordered = _sort_unique(
|
|
observations, ("suite", "test", "key"), gate, "duplicate observation key"
|
|
)
|
|
for observation in ordered:
|
|
gate.step()
|
|
row = _find_row(rows, observation.suite, observation.test, gate)
|
|
_route_observation(observation, row)
|
|
|
|
|
|
def _evidence(evidence, rows, budget, gate):
|
|
if len(evidence) > len(rows):
|
|
raise ProfileMapInvalidArgumentError("too many row evidence records")
|
|
for item in evidence:
|
|
gate.step()
|
|
_exact(item, RowEvidence, "invalid row evidence type")
|
|
_name(item.suite, budget, gate, suite=True)
|
|
_name(item.test, budget, gate)
|
|
for field in ("interval_complete", "runtime_compatible", "same_image", "children_complete"):
|
|
gate.step()
|
|
_exact(getattr(item, field), bool, "evidence claims must be bool")
|
|
ordered = _sort_unique(evidence, ("suite", "test"), gate, "duplicate row evidence")
|
|
for item in ordered:
|
|
gate.step()
|
|
_find_row(rows, item.suite, item.test, gate).evidence = item
|
|
|
|
|
|
def _preflight(suites, observations, evidence, budget, gate):
|
|
rows = _suites(suites, budget, gate)
|
|
_observations(observations, rows, budget, gate)
|
|
_evidence(evidence, rows, budget, gate)
|
|
gate.poll()
|
|
return rows
|
|
|
|
|
|
def _parser_limits(budget, enumeration):
|
|
limits = budget.limits
|
|
records = limits.max_records - budget.records
|
|
counters = limits.max_counter_values - budget.counter_values
|
|
names = limits.max_name_bytes - budget.name_bytes
|
|
if enumeration:
|
|
records = min(records, limits.max_ids)
|
|
if records <= 0 or counters <= 0 or names <= 0:
|
|
raise ProfileMapLimitExceededError("no remaining parser item allowance")
|
|
return ParseLimits(limits.max_input_bytes, records, counters, names)
|
|
|
|
|
|
def _parse(text, budget, gate, *, enumeration=False):
|
|
limits = _parser_limits(budget, enumeration)
|
|
try:
|
|
records = parse_profile_text(text, limits, cancel=gate.parser_cancel)
|
|
except MalformedProfileError as error:
|
|
if error is gate.callback_error:
|
|
raise
|
|
if enumeration:
|
|
raise ProfileMapEnumerationError("invalid profile enumeration") from error
|
|
return None
|
|
except LimitExceededError as error:
|
|
if error is gate.callback_error:
|
|
raise
|
|
raise ProfileMapLimitExceededError("profile parser resource limit") from error
|
|
except ParseCancelledError as error:
|
|
if error is gate.callback_error:
|
|
raise
|
|
raise ProfileMapCancelledError("profile parsing cancelled") from error
|
|
budget.parsed(records, gate)
|
|
return records
|
|
|
|
|
|
def _record_order(left, right, gate):
|
|
order = _compare_bytes(left.raw_name, right.raw_name, gate)
|
|
if order:
|
|
return order
|
|
gate.step()
|
|
return (left.function_hash > right.function_hash) - (left.function_hash < right.function_hash)
|
|
|
|
|
|
def _has_hit(record, gate):
|
|
for value in record.counters:
|
|
gate.step()
|
|
if value:
|
|
return True
|
|
return False
|
|
|
|
|
|
def _join(records, universe, row, budget, gate):
|
|
position = 0
|
|
for record in records:
|
|
gate.step()
|
|
while position < len(universe):
|
|
gate.step()
|
|
order = _record_order(universe[position], record, gate)
|
|
if order >= 0:
|
|
break
|
|
position += 1
|
|
if position == len(universe) or order != 0:
|
|
raise ProfileMapCompatibilityError("observation identity outside universe")
|
|
if len(record.counters) != len(universe[position].counters):
|
|
raise ProfileMapCompatibilityError("observation counter shape mismatch")
|
|
if _has_hit(record, gate) and position not in row.ids:
|
|
budget.reference()
|
|
row.ids.add(position)
|
|
position += 1
|
|
if len(records) != len(universe):
|
|
row.mark(_PARTIAL)
|
|
|
|
|
|
def _base_reasons(row, gate):
|
|
outcomes = (
|
|
(SuiteOutcome.FAILED, _SUITE_FAILED),
|
|
(SuiteOutcome.TIMED_OUT, _SUITE_TIMEOUT),
|
|
(SuiteOutcome.UNKNOWN, _SUITE_UNKNOWN),
|
|
)
|
|
for outcome, reason in outcomes:
|
|
gate.step()
|
|
if row.outcome is outcome:
|
|
row.mark(reason)
|
|
if row.evidence is None:
|
|
row.mark(_NO_EVIDENCE)
|
|
return
|
|
for field, reason in (
|
|
("interval_complete", _INTERVAL), ("runtime_compatible", _RUNTIME),
|
|
("same_image", _IMAGE), ("children_complete", _CHILDREN),
|
|
):
|
|
gate.step()
|
|
if not getattr(row.evidence, field):
|
|
row.mark(reason)
|
|
|
|
|
|
def _reduce_row(row, universe, budget, gate):
|
|
_base_reasons(row, gate)
|
|
for observation in row.observations:
|
|
gate.step()
|
|
if observation.text is None:
|
|
row.mark(_UNAVAILABLE)
|
|
continue
|
|
records = _parse(observation.text, budget, gate)
|
|
if records is None:
|
|
row.mark(_MALFORMED)
|
|
continue
|
|
_join(records, universe, row, budget, gate)
|
|
if observation.role in (ObservationRole.PARENT, ObservationRole.SETUP):
|
|
row.primary_parsed = True
|
|
if not row.primary_parsed:
|
|
row.mark(_NO_SETUP if _is_setup(row.test) else _NO_PARENT)
|
|
|
|
|
|
class _Wire:
|
|
__slots__ = ("budget", "gate", "data")
|
|
|
|
def __init__(self, budget, gate):
|
|
self.budget = budget
|
|
self.gate = gate
|
|
self.data = bytearray()
|
|
|
|
def emit(self, value):
|
|
self.budget.output(len(value))
|
|
for char in value:
|
|
self.gate.step()
|
|
self.data.append(char)
|
|
|
|
def hex(self, value):
|
|
self.budget.output(len(value) * 2)
|
|
for char in value:
|
|
self.gate.step()
|
|
self.gate.step()
|
|
self.data.append(_HEX[char >> 4])
|
|
self.gate.step()
|
|
self.data.append(_HEX[char & 15])
|
|
|
|
def decimal(self, value):
|
|
# All emitted integers are <= uint64, so conversion is <=20 digits.
|
|
self.gate.poll()
|
|
self.emit(str(value).encode("ascii"))
|
|
|
|
def _values(self):
|
|
for char in self.data:
|
|
self.gate.step()
|
|
yield char
|
|
|
|
def finish(self):
|
|
self.gate.poll()
|
|
result = bytes(self._values())
|
|
self.gate.poll()
|
|
return result
|
|
|
|
|
|
def _profile_wire(image, universe, budget, gate):
|
|
out = _Wire(budget, gate)
|
|
out.emit(b"CBM_PROFILE_MAP\t2\t")
|
|
out.hex(image)
|
|
out.emit(b"\t")
|
|
out.decimal(len(universe))
|
|
out.emit(b"\n")
|
|
for ident, record in enumerate(universe):
|
|
gate.step()
|
|
out.decimal(ident)
|
|
out.emit(b"\t")
|
|
out.hex(record.raw_name)
|
|
out.emit(b"\t")
|
|
gate.poll()
|
|
out.emit(format(record.function_hash, "016x").encode("ascii"))
|
|
out.emit(b"\t")
|
|
out.decimal(len(record.counters))
|
|
out.emit(b"\n")
|
|
return out.finish()
|
|
|
|
|
|
def _reason_wire(row, out, gate):
|
|
first = True
|
|
for index, reason in enumerate(_REASONS):
|
|
gate.step()
|
|
if row.reasons & (1 << index):
|
|
if not first:
|
|
out.emit(b";")
|
|
out.emit(reason)
|
|
first = False
|
|
|
|
|
|
def _id_wire(row, out, gate):
|
|
def compare(left, right):
|
|
gate.step()
|
|
return (left > right) - (left < right)
|
|
|
|
ordered = _sort(row.ids, compare, gate)
|
|
for index, ident in enumerate(ordered):
|
|
gate.step()
|
|
if index:
|
|
out.emit(b" ")
|
|
out.decimal(ident)
|
|
|
|
|
|
def _test_wire(rows, budget, gate):
|
|
out = _Wire(budget, gate)
|
|
for row in rows:
|
|
gate.step()
|
|
out.emit(row.suite)
|
|
out.emit(b":")
|
|
out.emit(row.test)
|
|
out.emit(b"\tincomplete\t" if row.reasons else b"\tcomplete\t")
|
|
_reason_wire(row, out, gate)
|
|
out.emit(b"\t")
|
|
_id_wire(row, out, gate)
|
|
out.emit(b"\n")
|
|
return out.finish()
|
|
|
|
|
|
def _digest(data, gate):
|
|
digest = hashlib.sha256()
|
|
for start in range(0, len(data), _POLL_INTERVAL):
|
|
gate.poll()
|
|
chunk = data[start:start + _POLL_INTERVAL]
|
|
gate.poll()
|
|
digest.update(chunk)
|
|
gate.poll()
|
|
return digest.digest()
|
|
|
|
|
|
def build_profile_map_v2(
|
|
image_sha256: bytes,
|
|
enumeration_text: bytes,
|
|
expected_suites: Tuple[ExpectedSuite, ...],
|
|
observations: Tuple[ProfileObservation, ...],
|
|
row_evidence: Tuple[RowEvidence, ...],
|
|
limits: ProfileMapLimits,
|
|
*,
|
|
cancel: Optional[Callable[[object], bool]] = None,
|
|
cancel_context: object = None,
|
|
) -> ProducedMap:
|
|
"""Produce exact v2 wires or raise, without I/O or a partial result.
|
|
|
|
Inputs are immutable exact types. Evidence is supplied by the caller;
|
|
parsing cannot establish image/process closure, provenance or admission.
|
|
"""
|
|
_validate_top(image_sha256, enumeration_text, expected_suites, observations,
|
|
row_evidence, limits, cancel)
|
|
gate = _Gate(cancel, cancel_context)
|
|
gate.poll()
|
|
budget = _Budget(limits, enumeration_text)
|
|
rows = _preflight(expected_suites, observations, row_evidence, budget, gate)
|
|
universe = _parse(enumeration_text, budget, gate, enumeration=True)
|
|
for row in rows:
|
|
gate.step()
|
|
_reduce_row(row, universe, budget, gate)
|
|
profiles = _profile_wire(image_sha256, universe, budget, gate)
|
|
tests = _test_wire(rows, budget, gate)
|
|
profiles_digest = _digest(profiles, gate)
|
|
tests_digest = _digest(tests, gate)
|
|
gate.poll()
|
|
return ProducedMap(profiles, tests, profiles_digest, tests_digest)
|