- internal/{address,identity,protocol,tce,transport,verify} -> pkg/ so
external Go projects can import the verified core; invariant tests
updated for the new paths
- Config.TrustProxy: key rate limiting by X-Forwarded-For when the relay
sits behind a reverse proxy (off by default, header never trusted
otherwise)
- examples/service + examples/approve: complete passwordless login round
trip (mint request -> wallet approves -> local verify), run live in CI
- docs/SERVICE-GUIDE.md: the integration recipe
127 lines
2.9 KiB
Go
127 lines
2.9 KiB
Go
package tce_test
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"git.n1ko.dev/Niko/niko_trust/pkg/tce"
|
|
)
|
|
|
|
func TestValueConstructorsAndAccessors(t *testing.T) {
|
|
// Null.
|
|
n := tce.Null()
|
|
if !n.IsNull() {
|
|
t.Error("Null must report IsNull")
|
|
}
|
|
if n.Tag() != tce.ValNull {
|
|
t.Error("Null tag")
|
|
}
|
|
if _, ok := n.Bool(); ok {
|
|
t.Error("null is not a bool")
|
|
}
|
|
if _, ok := n.Str(); ok {
|
|
t.Error("null is not a string")
|
|
}
|
|
if _, ok := n.NumberToken(); ok {
|
|
t.Error("null is not a number")
|
|
}
|
|
|
|
// Bool.
|
|
tr := tce.Bool(true)
|
|
fa := tce.Bool(false)
|
|
if b, ok := tr.Bool(); !ok || !b {
|
|
t.Error("Bool(true)")
|
|
}
|
|
if b, ok := fa.Bool(); !ok || b {
|
|
t.Error("Bool(false)")
|
|
}
|
|
if tr.Tag() != tce.ValTrue || fa.Tag() != tce.ValFalse {
|
|
t.Error("bool tags")
|
|
}
|
|
|
|
// String.
|
|
s := tce.String("hello")
|
|
if str, ok := s.Str(); !ok || str != "hello" {
|
|
t.Error("String")
|
|
}
|
|
if s.Tag() != tce.ValString {
|
|
t.Error("string tag")
|
|
}
|
|
|
|
// Number from token and from int.
|
|
nt := tce.Number("1.5")
|
|
tok, ok := nt.NumberToken()
|
|
if !ok || tok != "1.5" {
|
|
t.Error("Number token")
|
|
}
|
|
ni := tce.Int(42)
|
|
if tok, ok := ni.NumberToken(); !ok || tok != "42" {
|
|
t.Errorf("Int token = %q, want 42", tok)
|
|
}
|
|
if ni.Tag() != tce.ValNumber {
|
|
t.Error("number tag")
|
|
}
|
|
|
|
// GoString renders for diagnostics.
|
|
if tr.GoString() != "true" || fa.GoString() != "false" || n.GoString() != "null" {
|
|
t.Error("GoString booleans/null")
|
|
}
|
|
if s.GoString() != "string(hello)" {
|
|
t.Error("GoString string")
|
|
}
|
|
if nt.GoString() != "number(1.5)" {
|
|
t.Error("GoString number")
|
|
}
|
|
}
|
|
|
|
func TestValueEqual(t *testing.T) {
|
|
if !tce.Null().Equal(tce.Null()) {
|
|
t.Error("null == null")
|
|
}
|
|
if !tce.Bool(true).Equal(tce.Bool(true)) {
|
|
t.Error("true == true")
|
|
}
|
|
if tce.Bool(true).Equal(tce.Bool(false)) {
|
|
t.Error("true != false")
|
|
}
|
|
if !tce.String("a").Equal(tce.String("a")) {
|
|
t.Error("string == string")
|
|
}
|
|
if tce.String("a").Equal(tce.String("b")) {
|
|
t.Error("string != string")
|
|
}
|
|
// Numbers compare by canonical form.
|
|
if !tce.Number("1.0").Equal(tce.Number("1")) {
|
|
t.Error("1.0 == 1")
|
|
}
|
|
if !tce.Number("1e1").Equal(tce.Number("10")) {
|
|
t.Error("1e1 == 10")
|
|
}
|
|
if tce.Number("1").Equal(tce.Number("2")) {
|
|
t.Error("1 != 2")
|
|
}
|
|
// Cross-tag never equals.
|
|
if tce.String("1").Equal(tce.Number("1")) {
|
|
t.Error("string(1) != number(1)")
|
|
}
|
|
// A number that cannot canonicalize equals nothing, including itself.
|
|
bad := tce.Number("0x1")
|
|
if bad.Equal(bad) {
|
|
t.Error("un-canonicalizable number must equal nothing")
|
|
}
|
|
}
|
|
|
|
func TestValueIntConstructor(t *testing.T) {
|
|
for _, n := range []int64{0, 1, -1, 42, -42, 123456789, -9223372036854775807, 9223372036854775807} {
|
|
tok, ok := tce.Int(n).NumberToken()
|
|
if !ok {
|
|
t.Fatalf("Int(%d) is not a number", n)
|
|
}
|
|
c, err := tce.CanonicalNumber(tok)
|
|
if err != nil {
|
|
t.Fatalf("Int(%d) token not canonical: %v", n, err)
|
|
}
|
|
if c != tok {
|
|
t.Errorf("Int(%d) token %q not already canonical (%q)", n, tok, c)
|
|
}
|
|
}
|
|
}
|