Mix.Statifier.Corpus.Exclusions (Statifier v2.6.0)

Copy Markdown View Source

Reads this repository's corpus exclusion lists and the W3C sub-document set, as input for the conformance corpus emitter (ADR-0070).

Two exclusion lists live under tools/corpus/ as Elixir map literals, one per upstream suite, each entry key => {reason_atom, "prose"} (ADR-0004's reason atoms):

  • tools/corpus/scion/exclusions.exs - suite "scion"; a key is a SCION spec directory (every case under it) or one directory/name pair.
  • tools/corpus/scxml_w3/exclusions.exs - suite "w3c"; a key is a bare W3C test id ("test509").

read/1 returns one entry per key, sorted by suite then key. A key is emitted as written: a directory key stays one directory entry and is never expanded against the fetched upstream tree, so what this reader returns does not depend on whether that tree is present. Where an entry's prose cites a decision record (ADR-NNNN), the entry carries that record's number in :adr. to_document/1 renders the entries as the conformance/exclusions.json document, in the shape conformance/schema/exclusions.json fixes, carrying that number as the optional adr member on each entry that has one.

The files are parsed, never evaluated: each must be one map literal whose keys are strings and whose values are {atom, string} tuples, and anything else - a function call, an interpolated string, a repeated key - is refused with the file named.

sub_documents/2 returns the W3C manifest's sub-documents (the <dep> documents an <invoke> loads, which are never standalone tests) by running Cases.SubDocuments from tools/corpus/scxml_w3/sub_documents.exs over the manifest. They are a separate list, not exclusions.

Neither read/1 nor sub_documents/2 returns an empty list: an exclusion file with no entries, an absent manifest, an absent sub_documents.exs and a manifest that names no sub-document are each refused with a sentence, so the emitter never writes an empty list in their place.

Summary

Types

One exclusion: the upstream key, its reason atom and prose, and the record its prose cites.

An upstream suite, as the exclusions schema names it.

Functions

Where mise run corpus:fetch puts the W3C manifest, relative to the project root. The path is gitignored scratch; a fresh checkout does not have it.

Parses one exclusion file's source into entries for suite, sorted by key. label names the file in a refusal.

Reads both exclusion files under root into entries sorted by suite, then key.

The exclusion files, as {suite, path} pairs with paths relative to the project root.

Returns the W3C sub-document ids, sorted, by running Cases.SubDocuments from root's tools/corpus/scxml_w3/sub_documents.exs over manifest_path. A relative manifest_path is resolved against root, as the script's path is.

Renders entries as the conformance/exclusions.json document, with string keys and the reason atom as a string.

Types

entry()

@type entry() :: %{
  suite: suite(),
  key: String.t(),
  reason: atom(),
  detail: String.t(),
  adr: pos_integer() | nil
}

One exclusion: the upstream key, its reason atom and prose, and the record its prose cites.

suite()

@type suite() :: String.t()

An upstream suite, as the exclusions schema names it.

Functions

manifest_path()

@spec manifest_path() :: Path.t()

Where mise run corpus:fetch puts the W3C manifest, relative to the project root. The path is gitignored scratch; a fresh checkout does not have it.

parse(source, suite, label)

@spec parse(source :: String.t(), suite :: suite(), label :: String.t()) ::
  {:ok, [entry()]} | {:error, String.t()}

Parses one exclusion file's source into entries for suite, sorted by key. label names the file in a refusal.

read(root \\ ".")

@spec read(root :: Path.t()) :: {:ok, [entry()]} | {:error, String.t()}

Reads both exclusion files under root into entries sorted by suite, then key.

sources()

@spec sources() :: [{suite(), Path.t()}]

The exclusion files, as {suite, path} pairs with paths relative to the project root.

Examples

iex> Mix.Statifier.Corpus.Exclusions.sources()
[{"scion", "tools/corpus/scion/exclusions.exs"}, {"w3c", "tools/corpus/scxml_w3/exclusions.exs"}]

sub_documents(manifest_path, root \\ ".")

@spec sub_documents(manifest_path :: Path.t(), root :: Path.t()) ::
  {:ok, [String.t()]} | {:error, String.t()}

Returns the W3C sub-document ids, sorted, by running Cases.SubDocuments from root's tools/corpus/scxml_w3/sub_documents.exs over manifest_path. A relative manifest_path is resolved against root, as the script's path is.

Refuses an absent manifest, an absent script, and a manifest that names no sub-document, rather than returning an empty list or raising.

to_document(entries)

@spec to_document(entries :: [entry()]) :: %{required(String.t()) => [map()]}

Renders entries as the conformance/exclusions.json document, with string keys and the reason atom as a string.

Examples

iex> Mix.Statifier.Corpus.Exclusions.to_document([
...>   %{suite: "w3c", key: "test509", reason: :needs_basichttp, detail: "POST", adr: nil},
...>   %{suite: "scion", key: "error", reason: :lcca, detail: "see ADR-0022", adr: 22}
...> ])
%{"exclusions" => [
  %{"suite" => "w3c", "key" => "test509", "reason" => "needs_basichttp", "detail" => "POST"},
  %{"suite" => "scion", "key" => "error", "reason" => "lcca", "detail" => "see ADR-0022", "adr" => 22}
]}