niko_trust/pkg/tce/value_test.go
Niko Marmeladkov 3bf13fa488 Public SDK packages, proxy-aware rate limits, service login recipe
- 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
2026-08-26 12:49:54 +03:00

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)
}
}
}