Commit c0cd2769 authored by Eric Myhre's avatar Eric Myhre

Start new 'corpus' package for tests.

Getting *enough* and sufficiently *organized* corpuses becomes a
legitimate challenge.

The docs outline some of the directions this will go while describing
the naming convention.

This naming convention has already been cropping up in an ad-hoc way in
recent commits; this is a step towards documenting it consistently.

There aren't many entries yet; expect it to grow.

Using JSON as the defacto format is a little aggressive, perhaps,
because it makes sort of a wide dependency span.
But since we've already long had unmarshalling of json working,
it seems viable in practice.
And it means we get the marshalling output target corpuses for free
for at least one of our formats.
And it means we can readily make comparisons to stdlib json,
which is nice for having baselines to frame comparisons against.
It also has the interesting sideeffect of making these corpuses
immune to change in the face of refactors to NodeBuilder (which
will be an absurd concern at any time except... right now).
(We'll see.  Maybe I'll regret this after some time passes.  But if so,
this content probably just pivots to being still useful in json
marshal and unmarshal tests.)

I'd like to put this to work in writing more traversal benchmarks...
but that's going to have to wait a few commits, because I've found some
import cycles that get very problematic when I try to proceed there,
and it looks like they might take a few steps to sort out.
parent d12fcaa4
......@@ -60,3 +60,10 @@ func TypedNode(n ipld.Node, e error) typed.Node {
}
return n.(typed.Node)
}
// must.True panics if the given bool is false.
func True(v bool) {
if !v {
panic("must.True")
}
}
/*
The corpus package exports some values useful for building tests and benchmarks.
Values come as JSON strings. It is assumed you can unmarshal those.
The reason we do this is so that this corpus package doesn't import
any particular concrete implementation of ipld.Node... since that would
make it ironically incapable of being used for that Node's tests.
The naming convention is roughly as follows:
- {Kind}{{Count}|N}{KeyKind}{ValueKind}
- 'Kind' is usually 'Map' or 'List'.
It can also be a scalar like 'Int', in which case that's it.
- If a specific int is given for 'Count', that's the size of the thing;
- if 'N' is present, it's a scalable corpus and you can decide the size.
- 'KeyKind' is present for maps (it will be string...).
- 'ValueKind' is present for maps and lists. It can recurse.
Of course, this naming convention is not perfectly specific,
but it's usually enough for our needs, or at least enough to get started.
Some corpuses designed for probing (for example) tuple-represented structs
will end up with interesting designations for various reasons:
- some corpuses are meant to test struct semantics.
This is usually what it means when you see fixed size maps.
"List5Various" can also be this reason (it's for tuple-represented structs).
- some corpuses are meant to test nullable or optional semantics.
These might have name suffixes like "WithNull" to indicate this.
Everything is exported as a function, for consistency.
Many functions need no args.
Some functions need an argument for "N".
If you're using these corpuses in a benchmark, don't forget to call
`b.ResetTimer()` after getting the corpus.
*/
package corpus
import (
"fmt"
)
func Map3StrInt() string {
return `{"whee":1,"woot":2,"waga":3}`
}
func MapNStrInt(n int) string {
return `{` + ents(n, func(i int) string {
return fmt.Sprintf(`"k%d":%d`, i, i)
}) + `}`
}
package corpus
import (
"encoding/json"
"testing"
"github.com/ipld/go-ipld-prime/must"
)
/*
Sanity check that our corpuses are actually correct JSON in this package,
before we start letting other packages find that out for us the hard way.
*/
func TestCorpusValidity(t *testing.T) {
must.True(json.Valid([]byte(MapNStrInt(0))))
must.True(json.Valid([]byte(MapNStrInt(1))))
must.True(json.Valid([]byte(MapNStrInt(2))))
}
package corpus
import (
"bytes"
)
func ents(n int, segFn func(i int) string) string {
if n <= 0 {
return ""
}
var buf bytes.Buffer
for i := 0; i < n; i++ {
buf.WriteString(segFn(i))
buf.WriteString(`,`)
}
buf.Truncate(buf.Len() - 1)
return buf.String()
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment