# `Mix.Statifier.Corpus.Upstream`
[🔗](https://github.com/riddler/statifier-ex/blob/v2.6.0/lib/mix/statifier/corpus/upstream.ex#L1)

Reads the fetched and transformed upstream suites into corpus cases, in the
shape `conformance/schema/case.json` fixes, without running them.

The upstream tree is the gitignored scratch directory `mise run corpus:fetch`
and `mise run corpus:transform` populate (`tools/corpus/README.md`):
`scion/cases/<spec>/<name>.{json,scxml}` and
`scxml_w3/cases/<conformance>/<spec>/<id>.{scxml,description}` beside the
W3C IRP `manifest.xml`. Nothing here fetches or transforms.

The filters are the ones the test generators under `tools/corpus/` apply,
in the same order, so a case is in the corpus exactly when a generated test
module exists for it:

  * SCION: a case is left out when its spec directory, or its
    `directory/name` pair, is a key in the SCION exclusion list.
  * W3C: a test is left out when its id is a key in the W3C exclusion list,
    when it is a manifest sub-document, or when the predicator transform
    left it on another datamodel.

An exclusion key that matches no upstream document is refused, as the
generators refuse it.

A SCION case carries its upstream document as fetched (with the upstream's
own licence header comment, where it has one) and the configurations its
`.json` file expects. The fetch changes one SCION document, and that
case's `upstream` carries a `modified` notice saying so (`modified/0`), as
the Apache License 2.0's section 4(b) requires of a modified file. A W3C
case carries the transformed document as
`Mix.Statifier.Corpus.XmlFormat` formats it, and the IRP's own expectation:
a test passes by reaching the final state `pass` with no event sent.

# `corpus_case`

```elixir
@type corpus_case() :: %{required(String.t()) =&gt; term()}
```

One corpus case, with the string keys of `conformance/schema/case.json`.

# `modified`

```elixir
@spec modified() :: %{required(String.t()) =&gt; String.t()}
```

The SCION documents the fetch changes, keyed by `spec/name`, each with the
notice the case's `upstream.modified` carries.

# `notices`

```elixir
@spec notices() :: [String.t()]
```

The notice files every upstream case points at, relative to `conformance/`.

# `read`

```elixir
@spec read(scratch :: Path.t(), exclusions :: [map()], sub_documents :: [String.t()]) ::
  {:ok, [corpus_case()]} | {:error, String.t()}
```

Reads every SCION and W3C case under `scratch`, sorted by id, leaving out
what `exclusions` (the entries `Mix.Statifier.Corpus.Exclusions.read/1`
returns) and `sub_documents` (W3C test ids) name.

# `required_features`

```elixir
@spec required_features(source :: String.t()) :: [String.t()]
```

The feature names `Statifier.Testing.FeatureDetector` finds in `source`, as
sorted strings: a case's `required_features`.

# `scion_dir`

```elixir
@spec scion_dir(scratch :: Path.t()) :: Path.t()
```

The SCION cases directory under `scratch`.

# `upstreams`

```elixir
@spec upstreams() :: [map()]
```

The manifest's `upstreams` entries: each upstream suite, where it is
published, its licence and the notice file under `conformance/` it is
redistributed with.

# `w3c_dir`

```elixir
@spec w3c_dir(scratch :: Path.t()) :: Path.t()
```

The W3C cases directory under `scratch`, which also holds the IRP manifest.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
