Commit c1fe53eb authored by Jonathan Mace's avatar Jonathan Mace

WIP

parent 859fa010
......@@ -3,24 +3,23 @@ package atomlayer
import (
"bytes"
"github.com/golang/protobuf/proto"
"encoding/base64"
"fmt"
)
// Provides the base declaration of BaggageContext and Atoms. BaggageContext is just a slice of atoms.
// Also provides implementation of the five fundamental propagation primitives:
// The atomlayer is the lowest-level representation used by the tracing plane. It represents a BaggageContext using
// atoms -- an Atom is a slice of bytes, and a BaggageContext as defined by the atomlayer is a slice of Atoms. The
// AtomLayer provides an implementation of the five propagation primitives:
// * Branch -- duplicate a context because execution is branching
// * Merge -- merge two contexts from merging execution branches
// * Serialize / Deserialize --
// * Trim -- impose size restrictions on context
type Atom []byte
type BaggageContext []Atom
// Merges two BaggageContexts by lexicographically comparing their atoms
func Merge(a, b BaggageContext) BaggageContext {
func Merge(a, b []Atom) []Atom {
if a == nil && b == nil { return nil }
merged := BaggageContext(make([]Atom, 0, len(a)+len(b)))
merged := make([]Atom, 0, len(a)+len(b))
i, j := 0, 0
for i < len(a) && j < len(b) {
switch bytes.Compare(a[i], b[j]) {
......@@ -35,12 +34,12 @@ func Merge(a, b BaggageContext) BaggageContext {
}
// Duplicates a BaggageContext
func Branch(a BaggageContext) BaggageContext {
return append(BaggageContext(nil), a...)
func Branch(a []Atom) (b []Atom) {
return append(b, a...)
}
// Returns the serialized size in bytes of this atom array.
func (atoms BaggageContext) SerializedSize() (size int) {
func SerializedSize(atoms []Atom) (size int) {
for _, atom := range atoms { size += atom.serializedSize() }
return
}
......@@ -51,9 +50,9 @@ func (atom Atom) serializedSize() int {
}
// Serializes the baggage context by varint-prefixing each atom.]
func Serialize(atoms BaggageContext) []byte {
if atoms == nil { return nil }
length := atoms.SerializedSize()
func Serialize(atoms []Atom) []byte {
if len(atoms) == 0 { return nil }
length := SerializedSize(atoms)
serializedAtoms := make([]byte, 0, length)
for _, atom := range atoms {
serializedAtoms = append(serializedAtoms, proto.EncodeVarint(uint64(len(atom)))...)
......@@ -63,7 +62,7 @@ func Serialize(atoms BaggageContext) []byte {
}
// Deserializes a baggage context from bytes
func Deserialize(bytes []byte) (atoms BaggageContext, err error) {
func Deserialize(bytes []byte) (atoms []Atom, err error) {
pos := 0
for len(bytes) > 0 {
x, n := proto.DecodeVarint(bytes)
......@@ -81,44 +80,30 @@ func Deserialize(bytes []byte) (atoms BaggageContext, err error) {
return
}
// Serializes the provided BaggageContext then base64 encodes it into a string
func EncodeBase64(ctx BaggageContext) string {
return base64.StdEncoding.EncodeToString(Serialize(ctx))
}
// Decodes and deserializes a BaggageContext from the provided base64-encoded string
func DecodeBase64(encoded string) (BaggageContext, error) {
bytes, err := base64.StdEncoding.DecodeString(encoded)
if err != nil {
return nil, err
}
return Deserialize(bytes)
}
var trimMarker = Atom(make([]byte, 0, 0)) // Special zero-length atom used to indicate trim
var TrimMarker = Atom(make([]byte, 0, 0)) // Special zero-length atom used to indicate trim
func IsTrimMarker(a Atom) bool {
return bytes.Equal(trimMarker, a)
return bytes.Equal(TrimMarker, a)
}
// Drop atoms from the BaggageContext so that it fits into the specified number of bytes
func Trim(atoms BaggageContext, maxSize int) BaggageContext {
switch trimAt := atoms.indexForTrim(maxSize); {
func Trim(atoms []Atom, maxSize int) []Atom {
switch trimAt := indexForTrim(atoms, maxSize); {
case trimAt == len(atoms): return atoms
default: return append(atoms[:trimAt], trimMarker)
default: return append(atoms[:trimAt], TrimMarker)
}
}
// Calculates the index at which to trim the baggage to fit in the specified size
func (baggage BaggageContext) indexForTrim(size int) int {
for i, atom := range baggage {
func indexForTrim(atoms []Atom, size int) int {
for i, atom := range atoms {
switch atomSize := atom.serializedSize(); {
case atomSize < size: size -= atomSize;
case atomSize > size: return i
case i == len(baggage)-1: size -= atomSize;
case i == len(atoms)-1: size -= atomSize;
default: return i
}
}
return len(baggage)
return len(atoms)
}
......@@ -6,31 +6,31 @@ import (
)
func TestLexicographicMerge(t *testing.T) {
a := BaggageContext{Atom{0,1,1,1}, Atom{1}}
b := BaggageContext{Atom{0,1,1,1}, Atom{2}}
assert.Equal(t, BaggageContext{Atom{0,1,1,1}, Atom{1}, Atom{2}}, Merge(a, b))
a := []Atom{Atom{0,1,1,1}, Atom{1}}
b := []Atom{Atom{0,1,1,1}, Atom{2}}
assert.Equal(t, []Atom{Atom{0,1,1,1}, Atom{1}, Atom{2}}, Merge(a, b))
c := BaggageContext{Atom{1}, Atom{0,1,1,1}}
assert.Equal(t, BaggageContext{Atom{0,1,1,1}, Atom{1}, Atom{0,1,1,1}}, Merge(a, c))
assert.Equal(t, BaggageContext{Atom{0,1,1,1}, Atom{1}, Atom{0,1,1,1}, Atom{2}}, Merge(b, c))
c := []Atom{Atom{1}, Atom{0,1,1,1}}
assert.Equal(t, []Atom{Atom{0,1,1,1}, Atom{1}, Atom{0,1,1,1}}, Merge(a, c))
assert.Equal(t, []Atom{Atom{0,1,1,1}, Atom{1}, Atom{0,1,1,1}, Atom{2}}, Merge(b, c))
}
func TestLexicographicMerge2(t *testing.T) {
a := BaggageContext{Atom{1}, Atom{0,3,1,6}, Atom{3,1,1,1}, }
b := BaggageContext{Atom{1}, Atom{2,10}}
assert.Equal(t, BaggageContext{Atom{1}, Atom{0,3,1,6}, Atom{2,10}, Atom{3,1,1,1}}, Merge(a, b))
a := []Atom{Atom{1}, Atom{0,3,1,6}, Atom{3,1,1,1}, }
b := []Atom{Atom{1}, Atom{2,10}}
assert.Equal(t, []Atom{Atom{1}, Atom{0,3,1,6}, Atom{2,10}, Atom{3,1,1,1}}, Merge(a, b))
}
func TestLexicographicMergeNils(t *testing.T) {
assert.Equal(t, BaggageContext(nil), Merge(nil, nil))
assert.Equal(t, BaggageContext{Atom{1}}, Merge(BaggageContext{Atom{1}}, nil))
assert.Equal(t, BaggageContext{Atom{1}}, Merge(nil, BaggageContext{Atom{1}}))
assert.Equal(t, BaggageContext{}, Merge(nil, BaggageContext{}))
assert.Equal(t, []Atom(nil), Merge(nil, nil))
assert.Equal(t, []Atom{Atom{1}}, Merge([]Atom{Atom{1}}, nil))
assert.Equal(t, []Atom{Atom{1}}, Merge(nil, []Atom{Atom{1}}))
assert.Equal(t, []Atom{}, Merge(nil, []Atom{}))
}
func TestSerializeEmptyAtoms(t *testing.T) {
atomContext := BaggageContext{Atom{}}
atomContext := []Atom{Atom{}}
assert.Equal(t, 1, len(atomContext))
assert.Equal(t, 0, len(atomContext[0]))
serialized := Serialize(atomContext)
......@@ -38,7 +38,7 @@ func TestSerializeEmptyAtoms(t *testing.T) {
assert.Equal(t, 1, len(serialized))
assert.Equal(t, byte(0), serialized[0])
atomContext = BaggageContext{Atom{}, Atom{}, Atom{}}
atomContext = []Atom{Atom{}, Atom{}, Atom{}}
assert.Equal(t, 3, len(atomContext))
assert.Equal(t, 0, len(atomContext[0]))
assert.Equal(t, 0, len(atomContext[1]))
......@@ -52,7 +52,7 @@ func TestSerializeEmptyAtoms(t *testing.T) {
}
func TestSerializeOneAtom(t *testing.T) {
atomContext := BaggageContext{Atom{5, 10, 20}}
atomContext := []Atom{Atom{5, 10, 20}}
assert.Equal(t, 1, len(atomContext))
assert.Equal(t, 3, len(atomContext[0]))
serialized := Serialize(atomContext)
......@@ -96,7 +96,7 @@ func TestBadVarintPrefix(t *testing.T) {
}
func TestSerializeDeserialize(t *testing.T) {
atomContext := BaggageContext{Atom{1,2,3,4,5}, Atom{7,3,7}, Atom{}, Atom{1}, Atom{1}}
atomContext := []Atom{Atom{1,2,3,4,5}, Atom{7,3,7}, Atom{}, Atom{1}, Atom{1}}
bytes := Serialize(atomContext)
assert.Equal(t, 15, len(bytes))
......@@ -111,45 +111,26 @@ func TestSerializeDeserialize(t *testing.T) {
assert.Equal(t, atomContext[:4], deserializedContext[:4])
}
func TestBase64EncodeDecodeNilContext(t *testing.T) {
atomContext, err := DecodeBase64(EncodeBase64(nil))
assert.Nil(t, err)
assert.Equal(t, 0, len(atomContext))
}
func TestBase64EncodeDecode(t *testing.T) {
atomContext := BaggageContext{Atom{1,2,3,4,5}, Atom{7,3,7}, Atom{}, Atom{1}, Atom{1}}
decodedContext, err := DecodeBase64(EncodeBase64(atomContext))
assert.Nil(t, err)
assert.Equal(t, atomContext, decodedContext)
}
func TestBase64Decode(t *testing.T) {
decodedContext, err := DecodeBase64("")
assert.Nil(t, err)
assert.Equal(t, 0, len(decodedContext))
}
func TestTrim(t *testing.T) {
assert.Equal(t, BaggageContext{Atom{1,2,3,4,5}}, Trim(BaggageContext{Atom{1,2,3,4,5}}, 6))
assert.Equal(t, BaggageContext{Atom{}}, Trim(BaggageContext{Atom{1,2,3,4,5}}, 5))
assert.Equal(t, BaggageContext{Atom{}}, Trim(BaggageContext{Atom{1,2,3,4,5}}, 4))
assert.Equal(t, BaggageContext{Atom{}}, Trim(BaggageContext{Atom{1,2,3,4,5}}, 3))
assert.Equal(t, BaggageContext{Atom{}}, Trim(BaggageContext{Atom{1,2,3,4,5}}, 2))
assert.Equal(t, BaggageContext{Atom{}}, Trim(BaggageContext{Atom{1,2,3,4,5}}, 1))
assert.Equal(t, BaggageContext{Atom{}}, Trim(BaggageContext{Atom{1,2,3,4,5}}, 0))
assert.Equal(t, BaggageContext(nil), Trim(nil, 3))
assert.Equal(t, BaggageContext{Atom{1,2,3,4,5}, Atom{3, 2, 1}}, Trim(BaggageContext{Atom{1,2,3,4,5}, Atom{3, 2, 1}}, 10))
assert.Equal(t, BaggageContext{Atom{1,2,3,4,5}, Atom{}}, Trim(BaggageContext{Atom{1,2,3,4,5}, Atom{3, 2, 1}}, 9))
assert.Equal(t, BaggageContext{Atom{1,2,3,4,5}, Atom{}}, Trim(BaggageContext{Atom{1,2,3,4,5}, Atom{3, 2, 1}}, 8))
assert.Equal(t, BaggageContext{Atom{1,2,3,4,5}, Atom{}}, Trim(BaggageContext{Atom{1,2,3,4,5}, Atom{3, 2, 1}}, 7))
assert.Equal(t, BaggageContext{Atom{}}, Trim(BaggageContext{Atom{1,2,3,4,5}, Atom{3, 2, 1}}, 6))
assert.Equal(t, BaggageContext{Atom{}}, Trim(BaggageContext{Atom{1,2,3,4,5}, Atom{3, 2, 1}}, 5))
assert.Equal(t, BaggageContext{Atom{}}, Trim(BaggageContext{Atom{1,2,3,4,5}, Atom{3, 2, 1}}, 4))
assert.Equal(t, BaggageContext{Atom{}}, Trim(BaggageContext{Atom{1,2,3,4,5}, Atom{3, 2, 1}}, 3))
assert.Equal(t, BaggageContext{Atom{}}, Trim(BaggageContext{Atom{1,2,3,4,5}, Atom{3, 2, 1}}, 2))
assert.Equal(t, BaggageContext{Atom{}}, Trim(BaggageContext{Atom{1,2,3,4,5}, Atom{3, 2, 1}}, 1))
assert.Equal(t, BaggageContext{Atom{}}, Trim(BaggageContext{Atom{1,2,3,4,5}, Atom{3, 2, 1}}, 0))
assert.Equal(t, []Atom{Atom{1,2,3,4,5}}, Trim([]Atom{Atom{1,2,3,4,5}}, 6))
assert.Equal(t, []Atom{Atom{}}, Trim([]Atom{Atom{1,2,3,4,5}}, 5))
assert.Equal(t, []Atom{Atom{}}, Trim([]Atom{Atom{1,2,3,4,5}}, 4))
assert.Equal(t, []Atom{Atom{}}, Trim([]Atom{Atom{1,2,3,4,5}}, 3))
assert.Equal(t, []Atom{Atom{}}, Trim([]Atom{Atom{1,2,3,4,5}}, 2))
assert.Equal(t, []Atom{Atom{}}, Trim([]Atom{Atom{1,2,3,4,5}}, 1))
assert.Equal(t, []Atom{Atom{}}, Trim([]Atom{Atom{1,2,3,4,5}}, 0))
assert.Equal(t, []Atom(nil), Trim(nil, 3))
assert.Equal(t, []Atom{Atom{1,2,3,4,5}, Atom{3, 2, 1}}, Trim([]Atom{Atom{1,2,3,4,5}, Atom{3, 2, 1}}, 10))
assert.Equal(t, []Atom{Atom{1,2,3,4,5}, Atom{}}, Trim([]Atom{Atom{1,2,3,4,5}, Atom{3, 2, 1}}, 9))
assert.Equal(t, []Atom{Atom{1,2,3,4,5}, Atom{}}, Trim([]Atom{Atom{1,2,3,4,5}, Atom{3, 2, 1}}, 8))
assert.Equal(t, []Atom{Atom{1,2,3,4,5}, Atom{}}, Trim([]Atom{Atom{1,2,3,4,5}, Atom{3, 2, 1}}, 7))
assert.Equal(t, []Atom{Atom{}}, Trim([]Atom{Atom{1,2,3,4,5}, Atom{3, 2, 1}}, 6))
assert.Equal(t, []Atom{Atom{}}, Trim([]Atom{Atom{1,2,3,4,5}, Atom{3, 2, 1}}, 5))
assert.Equal(t, []Atom{Atom{}}, Trim([]Atom{Atom{1,2,3,4,5}, Atom{3, 2, 1}}, 4))
assert.Equal(t, []Atom{Atom{}}, Trim([]Atom{Atom{1,2,3,4,5}, Atom{3, 2, 1}}, 3))
assert.Equal(t, []Atom{Atom{}}, Trim([]Atom{Atom{1,2,3,4,5}, Atom{3, 2, 1}}, 2))
assert.Equal(t, []Atom{Atom{}}, Trim([]Atom{Atom{1,2,3,4,5}, Atom{3, 2, 1}}, 1))
assert.Equal(t, []Atom{Atom{}}, Trim([]Atom{Atom{1,2,3,4,5}, Atom{3, 2, 1}}, 0))
}
\ No newline at end of file
......@@ -6,19 +6,17 @@ import (
"bytes"
)
type reader struct {
type Reader struct {
next atomlayer.Atom
currentPath []atomlayer.Atom
remaining atomlayer.BaggageContext
skipped atomlayer.BaggageContext
remaining []atomlayer.Atom
Skipped []atomlayer.Atom
level int
overflowed bool
err error
Overflowed bool
Err error
}
type Reader *reader
func Read(baggage atomlayer.BaggageContext) (r reader) {
func Read(baggage []atomlayer.Atom) (r Reader) {
r.remaining = baggage
r.level = -1
r.advance()
......@@ -26,11 +24,11 @@ func Read(baggage atomlayer.BaggageContext) (r reader) {
}
// Reads data from the specified bag, only tracking skipped atoms from this bag.
func Open(baggage atomlayer.BaggageContext, bagIndex uint64) (r reader) {
func Open(baggage []atomlayer.Atom, bagIndex uint64) (r Reader) {
target := MakeIndexedHeader(0, bagIndex)
exists, overflowed, i := find(baggage, 0, target)
r.overflowed = overflowed
r.Overflowed = overflowed
r.level = 0
if exists {
......@@ -42,19 +40,19 @@ func Open(baggage atomlayer.BaggageContext, bagIndex uint64) (r reader) {
return
}
// Closes the reader, treating all remaining atoms as skipped
func (r *reader) Close() {
// Closes the Reader, treating all remaining atoms as skipped
func (r *Reader) Close() {
// Exit any current bags
for r.level >= 0 { r.Exit() }
for len(r.currentPath) > 0 { r.Exit() }
// Make sure we're not at data atoms
r.advanceToNextHeader()
// Remaining are skipped
if r.next != nil {
r.skipped = append(r.skipped, r.next)
r.Skipped = append(r.Skipped, r.next)
if len(r.remaining) > 0 {
r.skipped = append(r.skipped, r.remaining...)
r.Skipped = append(r.Skipped, r.remaining...)
r.remaining = nil
}
r.next = nil
......@@ -63,11 +61,11 @@ func (r *reader) Close() {
// Advances r.next zero or more atoms, until it's a header atom. If it's already a header atom, does nothing.
// Returns the header atom and its level.
func (r *reader) advanceToNextHeader() (atomlayer.Atom, int) {
func (r *Reader) advanceToNextHeader() (atomlayer.Atom, int) {
for {
switch {
case r.next == nil: goto noheader // End of baggage or error
case atomlayer.IsTrimMarker(r.next): r.overflowed = true; goto nextatom // Handle overflow marker
case atomlayer.IsTrimMarker(r.next): r.Overflowed = true; goto nextatom // Handle overflow marker
case IsHeader(r.next): goto foundheader // Found the next header atom
case IsData(r.next): goto nextatom // Skip any data atoms
}
......@@ -87,7 +85,7 @@ func (r *reader) advanceToNextHeader() (atomlayer.Atom, int) {
}
// Advance into the next child bag of the next bag, if there is one; if there isn't, does nothing, and returns nil
func (r *reader) Enter() atomlayer.Atom {
func (r *Reader) Enter() atomlayer.Atom {
header, level := r.advanceToNextHeader()
switch {
......@@ -108,17 +106,17 @@ func (r *reader) Enter() atomlayer.Atom {
}
// Advance to the specified child bag, ignoring all preceding child bags, and stopping if we reach the end of bag
func (r *reader) EnterIndexed(index uint64) bool {
func (r *Reader) EnterIndexed(index uint64) bool {
return r.enter(MakeIndexedHeader(r.level + 1, index))
}
// Advance to the specified child bag, ignoring all preceding child bags, and stopping if we reach the end of bag
func (r *reader) EnterKeyed(key []byte) bool {
func (r *Reader) EnterKeyed(key []byte) bool {
return r.enter(MakeKeyedHeader(r.level + 1, key))
}
// Advance to provided header atom, ignoring all preceding child bags, and stopping if we reach the end of bag
func (r *reader) enter(target []byte) bool {
func (r *Reader) enter(target []byte) bool {
for {
header, level := r.advanceToNextHeader()
......@@ -152,7 +150,7 @@ func (r *reader) enter(target []byte) bool {
}
// Skips bags, treating them as unprocessed, until we reach a bag at or below the specified level
func (r *reader) skipuntil(stopAtLevel int) {
func (r *Reader) skipuntil(stopAtLevel int) {
skippedAtoms := append(append([]atomlayer.Atom(nil), r.currentPath...), r.next)
r.advance()
for {
......@@ -171,9 +169,9 @@ func (r *reader) skipuntil(stopAtLevel int) {
}
trimmarker:
switch r.overflowed {
switch r.Overflowed {
case true: goto nextatom // Ignore redundant trim marker
case false: r.overflowed = true; goto skipatom // First trim marker seen
case false: r.Overflowed = true; goto skipatom // First trim marker seen
}
skipatom:
......@@ -184,11 +182,11 @@ func (r *reader) skipuntil(stopAtLevel int) {
}
finish:
r.skipped = atomlayer.Merge(r.skipped, skippedAtoms);
r.Skipped = atomlayer.Merge(r.Skipped, skippedAtoms);
}
// Advance to the end of the next bag and pop back up to the parent
func (r *reader) Exit() {
func (r *Reader) Exit() {
for {
switch header, level := r.advanceToNextHeader(); {
case len(r.currentPath) == 0: r.seterror(invalidExit()); return // Called exit too many times
......@@ -208,12 +206,12 @@ func (r *reader) Exit() {
}
// Reads the payload of the next data atom from the next bag. Returns nil if there are no data atoms remaining
func (r *reader) Next() []byte {
func (r *Reader) Next() []byte {
for {
// Non-data atoms
switch {
case r.next == nil: goto nodata // End of baggage or an error
case atomlayer.IsTrimMarker(r.next): r.overflowed = true; goto nextatom // Trim marker, continue
case atomlayer.IsTrimMarker(r.next): r.Overflowed = true; goto nextatom // Trim marker, continue
case !IsData(r.next): goto nodata // Not a data atom
}
......@@ -232,21 +230,21 @@ func (r *reader) Next() []byte {
}
// Returns the error if one occurred. All operations stop after an error occurs
func (r *reader) Error() error {
return r.err
func (r *Reader) Error() error {
return r.Err
}
func (r *reader) seterror(err error) error {
func (r *Reader) seterror(err error) error {
if err != nil {
r.err = err
r.Err = err
r.next = nil
}
return r.err
return r.Err
}
func (r *reader) advance() {
func (r *Reader) advance() {
switch {
case r.err != nil: goto exhausted // Error occurred - stop
case r.Err != nil: goto exhausted // Error occurred - stop
case len(r.remaining) == 0: goto exhausted // No atoms remaining
default: goto advance // Advance to next atom
}
......@@ -267,22 +265,4 @@ func invalidGrandchild(currentLevel, childLevel int) error {
func invalidExit() error {
return fmt.Errorf("Exit called too many times without corresponding bag entries")
}
// Finds the specified atom in the baggage, stopping at the first atom lexicographically larger than it.
// Returns:
// exists - true if the atom was found, false otherwise
// overflowed - true if the overflow marker was found between startat and i, false otherwise
// i - the index of the match, or insertion index if not found
func find(baggage atomlayer.BaggageContext, startat int, target atomlayer.Atom) (exists bool, overflowed bool, i int) {
for i=startat; i<len(baggage); i++ {
overflowed = overflowed || atomlayer.IsTrimMarker(baggage[i])
switch bytes.Compare(baggage[i], target) {
case -1: continue // Haven't encountered yet
case 0: exists = true; return // Found it
case 1: exists = false; return // Went past it
}
}
return
}
\ No newline at end of file
......@@ -9,16 +9,6 @@ import (
"github.com/gogo/protobuf/proto"
)
func TestSliceEqual(t *testing.T) {
assert.NotEqual(t, make([]byte, 0), nil)
assert.NotEqual(t, nil, make([]byte, 0))
assert.False(t, make([]byte, 0) == nil)
arr := []byte{0}
assert.NotEqual(t, arr[1:], nil)
}
func TestSimpleEnter1(t *testing.T) {
baggage := []byte{}
atoms, err := atomlayer.Deserialize(baggage);
......@@ -38,7 +28,7 @@ func TestSimpleEnter2(t *testing.T) {
func TestSimpleReadData(t *testing.T) {
header := atomlayer.Atom{ 248, 5 }
r := Read(atomlayer.BaggageContext{header})
r := Read([]atomlayer.Atom{header})
entered := r.Enter()
assert.NotNil(t, entered)
assert.Equal(t, header, entered)
......@@ -46,7 +36,7 @@ func TestSimpleReadData(t *testing.T) {
assert.Equal(t, 0, r.level)
assert.Nil(t, r.next)
assert.Empty(t, r.remaining)
assert.Empty(t, r.skipped)
assert.Empty(t, r.Skipped)
assert.Equal(t, []atomlayer.Atom{header}, r.currentPath)
assert.Nil(t, r.Enter())
......@@ -64,7 +54,7 @@ func TestSimpleReadData(t *testing.T) {
}
func TestValidLevelJump(t *testing.T) {
baggage := atomlayer.BaggageContext{
baggage := []atomlayer.Atom{
[]byte{248, 5},
[]byte{0, 185, 124, 187, 14, 103, 240, 88, 153},
[]byte{240, 0},
......@@ -72,15 +62,15 @@ func TestValidLevelJump(t *testing.T) {
}
r := Read(baggage)
assert.Nil(t, r.err)
assert.Nil(t, r.Err)
header := r.Enter()
assert.NotNil(t, header)
assert.Nil(t, r.err)
assert.Nil(t, r.Err)
}
func TestInvalidLevelJump(t *testing.T) {
baggage := atomlayer.BaggageContext{
baggage := []atomlayer.Atom{
[]byte{240, 0},
[]byte{0, 131, 154, 212, 173, 65, 53, 70, 55},
[]byte{248, 5},
......@@ -88,36 +78,36 @@ func TestInvalidLevelJump(t *testing.T) {
}
r := Read(baggage)
assert.Nil(t, r.err)
assert.Nil(t, r.Err)
header := r.Enter()
assert.Nil(t, header)
assert.NotNil(t, r.err)
assert.NotNil(t, r.Err)
}
func TestInvalidHeaderAtom(t *testing.T) {
baggage := atomlayer.BaggageContext{
baggage := []atomlayer.Atom{
[]byte{240},
[]byte{0, 131, 154, 212, 173, 65, 53, 70, 55},
}
r := Read(baggage)
assert.Nil(t, r.err)
assert.Nil(t, r.Err)
header := r.Enter()
assert.Nil(t, header)
assert.NotNil(t, r.err)
assert.NotNil(t, r.Err)
}
func TestMultipleDataAtoms(t *testing.T) {
baggage := atomlayer.BaggageContext{
baggage := []atomlayer.Atom{
[]byte{0, 0},
[]byte{0, 1},
[]byte{0, 2},
}
r := Read(baggage)
assert.Nil(t, r.err)
assert.Nil(t, r.Err)
assert.NotNil(t, r.Next())
assert.NotNil(t, r.Next())
......@@ -126,7 +116,7 @@ func TestMultipleDataAtoms(t *testing.T) {
}
func TestEnterSkipsBags(t *testing.T) {
baggage := atomlayer.BaggageContext{
baggage := []atomlayer.Atom{
[]byte{248, 3},
[]byte{0, 6},
[]byte{248, 5},
......@@ -145,7 +135,7 @@ func TestEnterSkipsBags(t *testing.T) {
}
func TestSkippedAtomsSimple(t *testing.T) {
baggage := atomlayer.BaggageContext{
baggage := []atomlayer.Atom{
[]byte{248, 3},
[]byte{0, 6},
[]byte{248, 5},
......@@ -155,15 +145,15 @@ func TestSkippedAtomsSimple(t *testing.T) {
r := Read(baggage)
assert.True(t, r.EnterIndexed(5))