# Hash conformance fixture `hash-conformance.json` records what this package's hasher does with a set of values, so that an implementation of `hashOf()` in another language can test itself against the same cases. The hash is specified in [`2-hash-byte-format.md`](../../../../docs/specs/space-model-formal-spec/2-hash-byte-format.md), and its agreement with value equality in section 6.7 of [`1-fabric-values.md`](../../../../docs/specs/space-model-formal-spec/1-fabric-values.md). The file is generated by `deno task regenerate-hash-conformance`, run in `packages/data-model`, from the cases in `src/hash-conformance.ts`, and `test/hash-conformance.test.ts` fails whenever the file and the hasher disagree. Edit the cases, not the file. ## Entries The file is JSON, holding only ASCII: every other character is escaped. Its `cases` list holds one object per case: - `name`: unique among the cases. - `section`: the part of the spec the case exercises. - `value`: the value hashed, as a descriptor in the notation [`value-descriptors.md`](value-descriptors.md) defines. - `hash`: what hashing the value yields, or `refused: "unhashable"`. A hash is three strings: `stream`, the bytes fed to SHA-256, in lowercase hexadecimal; `digest`, the 32 bytes SHA-256 makes of them, likewise; and `string`, the digest's string form, `fid1:` and the digest in unpadded base64url, which is what a `FabricHash` of the digest writes. - `equals`: present where the case's value equals an earlier case's under `valueEqual()`, naming that case. The two hashes are then the same. - `divergence`: present where this package falls short of the spec. The `hash` beside it is then the spec's outcome, and `divergence.hash` is this package's. `divergence.note` says what the spec requires. A refusal is recorded only where the hasher refused; a fault in the hasher fails generation instead. ## What generating holds The stream is the whole of what an implementation has to match. The digest and the string follow from it, and an implementation whose digest differs can find where by comparing streams. Where the spec gives a value's bytes outright, in the examples of its section 7 or in a section 4 that states every byte, the case quotes them, and the `hash` recorded is computed from the quote rather than from this package. A case whose quote this package does not feed has to say so as a divergence, and a divergence that does not hold fails generation, so that a fix here retires the mark rather than leaving it to mislead. Every two hashed cases hold to the spec's rule on equality: their hashes are the same exactly when their values are `valueEqual()`, and `test/hash-conformance.test.ts` fails otherwise. A pair may describe one value made in two ways the notation does not record — keys made in another order, a container shared rather than copied, a deep-frozen value whose hash was cached — and then has one descriptor. A pair whose descriptors differ, as a link and an unknown value preserving a link's tag and state do, has to be named under `equals`, and generating fails otherwise, so that an equal hash for two different descriptors is always one the cases expected. The digest recorded is the one this package's hasher makes of the stream, and the test holds `hashOf()`, `hashStringOf()` and `taggedHashStringOf()` to it, for each case's value as the case makes it. ## What is not among the cases The spec gives `FabricMap` and `FabricSet` a byte form, under the type tags `Map@1` and `Set@1` (section 6.4 of `1-fabric-values.md`, and section 4.14), which this package does not yet produce: their codecs are stubs, pending general `FabricInstance` support, and hashing one throws. They are left out of the cases, and `test/hash-conformance.test.ts` fails once hashing one succeeds, so that their cases are added then. A key pair holding `CryptoKey` handles, which section 8 refuses, has no descriptor, nor does a value with a cycle through an instance. The refusals the file records are those of unregistered symbols, alone and inside containers.