- 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
114 lines
2.8 KiB
Go
114 lines
2.8 KiB
Go
package tce_test
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"git.n1ko.dev/Niko/niko_trust/pkg/tce"
|
|
)
|
|
|
|
func TestIDAccessors(t *testing.T) {
|
|
// ComputeID is SHA-256 over the canonical bytes.
|
|
id := tce.ComputeID([]byte("trust.n1ko.dev/tce/1"))
|
|
if id.IsZero() {
|
|
t.Fatal("a computed ID must not be zero")
|
|
}
|
|
if !id.Equal(id) {
|
|
t.Fatal("an ID must equal itself")
|
|
}
|
|
if len(id.String()) != 64 {
|
|
t.Fatalf("ID hex must be 64 chars, got %d", len(id.String()))
|
|
}
|
|
if len(id.Bytes()) != 32 {
|
|
t.Fatalf("ID bytes must be 32, got %d", len(id.Bytes()))
|
|
}
|
|
// Bytes is a copy: mutating it must not change the ID.
|
|
raw := id.Bytes()
|
|
raw[0] ^= 0xff
|
|
if id.Bytes()[0] == raw[0] {
|
|
t.Fatal("Bytes did not return an independent copy")
|
|
}
|
|
|
|
zero := tce.ID{}
|
|
if !zero.IsZero() {
|
|
t.Fatal("zero ID must report IsZero")
|
|
}
|
|
if id.IsZero() {
|
|
t.Fatal("non-zero ID must not report IsZero")
|
|
}
|
|
}
|
|
|
|
func TestParseID(t *testing.T) {
|
|
// accurate 64-char lowercase hex
|
|
good := "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
|
|
id, err := tce.ParseID(good)
|
|
if err != nil {
|
|
t.Fatalf("ParseID good: %v", err)
|
|
}
|
|
if id.String() != good {
|
|
t.Fatalf("round-trip mismatch: %s != %s", id.String(), good)
|
|
}
|
|
|
|
bad := []string{
|
|
good[:63], // too short
|
|
good + "0", // too long
|
|
good[:63] + "G", // non-hex
|
|
good[:63] + "A", // uppercase rejected
|
|
}
|
|
for _, b := range bad {
|
|
if _, err := tce.ParseID(b); err == nil {
|
|
t.Errorf("ParseID(%q): expected error", b)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestIDFromBytes(t *testing.T) {
|
|
b := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
|
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}
|
|
id, err := tce.IDFromBytes(b)
|
|
if err != nil {
|
|
t.Fatalf("IDFromBytes: %v", err)
|
|
}
|
|
if id.Bytes()[0] != 0 || id.Bytes()[31] != 31 {
|
|
t.Fatal("IDFromBytes copied incorrectly")
|
|
}
|
|
if _, err := tce.IDFromBytes(b[:31]); err == nil {
|
|
t.Fatal("IDFromBytes wrong length must error")
|
|
}
|
|
}
|
|
|
|
func TestIDText(t *testing.T) {
|
|
good := "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
|
|
id, err := tce.ParseID(good)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
text, err := id.MarshalText()
|
|
if err != nil {
|
|
t.Fatalf("MarshalText: %v", err)
|
|
}
|
|
if string(text) != good {
|
|
t.Fatalf("MarshalText = %q, want %q", text, good)
|
|
}
|
|
var back tce.ID
|
|
if err := back.UnmarshalText(text); err != nil {
|
|
t.Fatalf("UnmarshalText: %v", err)
|
|
}
|
|
if !back.Equal(id) {
|
|
t.Fatal("UnmarshalText did not reconstruct the ID")
|
|
}
|
|
if err := back.UnmarshalText([]byte("zz")); err == nil {
|
|
t.Fatal("UnmarshalText must reject bad hex")
|
|
}
|
|
}
|
|
|
|
func TestComputeIDStable(t *testing.T) {
|
|
a := tce.ComputeID([]byte("abc"))
|
|
b := tce.ComputeID([]byte("abc"))
|
|
c := tce.ComputeID([]byte("abd"))
|
|
if !a.Equal(b) {
|
|
t.Fatal("same input must yield equal IDs")
|
|
}
|
|
if a.Equal(c) {
|
|
t.Fatal("different input must yield different IDs")
|
|
}
|
|
}
|