stronger kind tests and validation
This commit is contained in:
+11
-5
@@ -7,11 +7,12 @@ const (
|
|||||||
KindBuy
|
KindBuy
|
||||||
KindSell
|
KindSell
|
||||||
KindSplit
|
KindSplit
|
||||||
|
sentinelKind
|
||||||
)
|
)
|
||||||
|
|
||||||
// String returns a human readable value
|
// String returns a unique string value for Kind k
|
||||||
func (d Kind) String() string {
|
func (k Kind) String() string {
|
||||||
switch d {
|
switch k {
|
||||||
case KindBuy:
|
case KindBuy:
|
||||||
return "buy"
|
return "buy"
|
||||||
case KindSell:
|
case KindSell:
|
||||||
@@ -23,8 +24,13 @@ func (d Kind) String() string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is returns true when k equals o
|
// Valid returns true if k is an accepted value for the Kind type
|
||||||
|
func (k Kind) Valid() bool {
|
||||||
|
return k > 0 && k < sentinelKind
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is returns true when k and o are valid and equal.
|
||||||
func (k Kind) Is(o any) bool {
|
func (k Kind) Is(o any) bool {
|
||||||
other, ok := o.(Kind)
|
other, ok := o.(Kind)
|
||||||
return ok && k == other
|
return ok && k.Valid() && k == other
|
||||||
}
|
}
|
||||||
|
|||||||
+75
-40
@@ -1,60 +1,95 @@
|
|||||||
package internal
|
package internal
|
||||||
|
|
||||||
import "testing"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
func TestSide_String(t *testing.T) {
|
func TestSide_String(t *testing.T) {
|
||||||
tests := []struct {
|
const unknown = "unknown"
|
||||||
name string
|
|
||||||
side Kind
|
seen := make(map[string]Kind, sentinelKind)
|
||||||
want string
|
for k := Kind(1); k < sentinelKind; k++ {
|
||||||
}{
|
t.Run(fmt.Sprintf("Kind %d", k), func(t *testing.T) {
|
||||||
{"buy", KindBuy, "buy"},
|
str := k.String()
|
||||||
{"sell", KindSell, "sell"},
|
|
||||||
{"unknown", KindUnknown, "unknown"},
|
if other, ok := seen[str]; ok {
|
||||||
|
t.Errorf("want Kind(%d).String to be unique but was a duplicate of Kind(%d)", k, other)
|
||||||
|
} else {
|
||||||
|
seen[str] = k
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
if len(str) == 0 {
|
||||||
if got := tt.side.String(); got != tt.want {
|
t.Errorf("want Kind(%d).String to be non-empty", k)
|
||||||
t.Errorf("want Side.String() to be %v but got %v", tt.want, got)
|
}
|
||||||
|
|
||||||
|
if str == unknown {
|
||||||
|
t.Errorf("want Kind(%d).String to be a known value", k)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if KindUnknown.String() != unknown {
|
||||||
|
t.Errorf("want Kind(0) to be unknown")
|
||||||
|
}
|
||||||
|
|
||||||
|
if Kind(sentinelKind).String() != unknown {
|
||||||
|
t.Errorf("want Kind(%d) to be unknown", sentinelKind)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSide_IsBuy(t *testing.T) {
|
func TestSide_Valid(t *testing.T) {
|
||||||
tests := []struct {
|
for k := Kind(1); k < sentinelKind; k++ {
|
||||||
name string
|
if !k.Valid() {
|
||||||
side Kind
|
t.Errorf("want %s(%d) to be valid", k, k)
|
||||||
want bool
|
|
||||||
}{
|
|
||||||
{"buy", KindBuy, true},
|
|
||||||
{"sell", KindSell, false},
|
|
||||||
{"unknown", KindUnknown, false},
|
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
if got := tt.side.Is(KindBuy); got != tt.want {
|
|
||||||
t.Errorf("want Side.IsBuy() to be %v but got %v", tt.want, got)
|
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
if KindUnknown.Valid() {
|
||||||
|
t.Errorf("want Kind(0) to be invalid")
|
||||||
|
}
|
||||||
|
|
||||||
|
if Kind(sentinelKind).Valid() {
|
||||||
|
t.Errorf("want Kind(%d) to be invalid", sentinelKind)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSide_IsSell(t *testing.T) {
|
func TestSide_Is(t *testing.T) {
|
||||||
tests := []struct {
|
t.Run("valid is self", func(t *testing.T) {
|
||||||
name string
|
for k := Kind(1); k < sentinelKind; k++ {
|
||||||
side Kind
|
if !k.Is(k) {
|
||||||
want bool
|
t.Errorf("want Kind(%d).Is(%d) to be true", k, k)
|
||||||
}{
|
|
||||||
{"buy", KindBuy, false},
|
|
||||||
{"sell", KindSell, true},
|
|
||||||
{"unknown", KindUnknown, false},
|
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
if got := tt.side.Is(KindSell); got != tt.want {
|
|
||||||
t.Errorf("want Side.IsSell() to be %v but got %v", tt.want, got)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("valid is unknown", func(t *testing.T) {
|
||||||
|
for k := Kind(1); k < sentinelKind; k++ {
|
||||||
|
if k.Is(KindUnknown) {
|
||||||
|
t.Errorf("want Kind(%d).Is(0) to be false", k)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if k.Is(sentinelKind) {
|
||||||
|
t.Errorf("want Kind(%d).Is(%d) to be false", k, sentinelKind)
|
||||||
|
}
|
||||||
|
|
||||||
|
if k.Is(struct{}{}) {
|
||||||
|
t.Errorf("want Kind(%d).Is(other type) to be false", k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("unknown is unknown", func(t *testing.T) {
|
||||||
|
if KindUnknown.Is(KindUnknown) {
|
||||||
|
t.Errorf("want Kind(0).Is(0) to be false")
|
||||||
|
}
|
||||||
|
|
||||||
|
if KindUnknown.Is(sentinelKind) {
|
||||||
|
t.Errorf("want Kind(0).Is(%d) to be false", sentinelKind)
|
||||||
|
}
|
||||||
|
|
||||||
|
if sentinelKind.Is(sentinelKind) {
|
||||||
|
t.Errorf("want Kind(%d).Is(%d) to be false", sentinelKind, sentinelKind)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -132,6 +132,8 @@ func BuildReport(ctx context.Context, reader RecordReader, writer ReportWriter,
|
|||||||
buysCount++
|
buysCount++
|
||||||
} else if rec.Kind().Is(KindSell) {
|
} else if rec.Kind().Is(KindSell) {
|
||||||
sellsCount++
|
sellsCount++
|
||||||
|
} else if !rec.Kind().Valid() {
|
||||||
|
return fmt.Errorf("cannot process Kind(%d)", rec.Kind())
|
||||||
}
|
}
|
||||||
|
|
||||||
lastTimestamp = rec.Timestamp()
|
lastTimestamp = rec.Timestamp()
|
||||||
|
|||||||
Reference in New Issue
Block a user