From a677b171adae6e936fbe64b5eec3839bbacde84e Mon Sep 17 00:00:00 2001 From: Virgil Date: Sat, 4 Apr 2026 09:34:08 +0000 Subject: [PATCH] test(ax): add filename-stem Good/Bad/Ugly triads Co-Authored-By: Virgil --- internal/nameutil/name_test.go | 23 +++++++++++++ lns_test.go | 35 +++++++++++++++++++ pkg/covenant/blind_test.go | 47 ++++++++++++++++++++++++++ pkg/covenant/covenant_test.go | 33 ++++++++++++++++++ pkg/covenant/locked_lookup_test.go | 35 +++++++++++++++++++ pkg/covenant/name_test.go | 38 +++++++++++++++++++++ pkg/covenant/rules_extra_test.go | 41 ++++++++++++++++++++++ pkg/dns/common_test.go | 30 ++++++++++++++++ pkg/dns/nsec_test.go | 31 +++++++++++++++++ pkg/dns/resolve_test.go | 28 +++++++++++++++ pkg/dns/resource_test.go | 39 +++++++++++++++++++++ pkg/primitives/claim_test.go | 34 +++++++++++++++++++ pkg/primitives/covenant_binary_test.go | 46 +++++++++++++++++++++++++ pkg/primitives/covenant_items_test.go | 36 ++++++++++++++++++++ pkg/primitives/invitem_test.go | 34 +++++++++++++++++++ pkg/primitives/namedelta_test.go | 25 ++++++++++++++ pkg/primitives/namestate_state_test.go | 23 +++++++++++++ pkg/primitives/namestate_test.go | 22 ++++++++++++ pkg/primitives/types_test.go | 25 ++++++++++++++ pkg/primitives/view_test.go | 45 ++++++++++++++++++++++++ 20 files changed, 670 insertions(+) diff --git a/internal/nameutil/name_test.go b/internal/nameutil/name_test.go index 48f3f27..a209671 100644 --- a/internal/nameutil/name_test.go +++ b/internal/nameutil/name_test.go @@ -32,3 +32,26 @@ func TestNameUtil_Function_Ugly(t *testing.T) { } } +func TestName_Function_Good(t *testing.T) { + got, ok := Canonicalize("Example.lthn.") + if !ok || got != "example" { + t.Fatalf("Canonicalize() = %q, %v, want %q, true", got, ok, "example") + } +} + +func TestName_Function_Bad(t *testing.T) { + if got, ok := Canonicalize(42); ok || got != "" { + t.Fatalf("Canonicalize() = %q, %v, want empty false", got, ok) + } +} + +func TestName_Function_Ugly(t *testing.T) { + got, ok := CatalogLabel([]byte("MiXeD")) + if !ok { + t.Fatal("CatalogLabel should accept raw byte labels") + } + + if got != "MiXeD" { + t.Fatalf("CatalogLabel() = %q, want %q", got, "MiXeD") + } +} diff --git a/lns_test.go b/lns_test.go index e2dc9cb..9b02a6a 100644 --- a/lns_test.go +++ b/lns_test.go @@ -2172,3 +2172,38 @@ func TestServiceVerifyCovenants(t *testing.T) { t.Fatalf("GetVerifyCovenants returned %d for an invalid finalize address, want -1", got) } } + +func TestLns_Function_Good(t *testing.T) { + if got := GetServiceName(); got != ServiceName { + t.Fatalf("GetServiceName() = %q, want %q", got, ServiceName) + } + + if svc := GetNewService(nil); svc == nil { + t.Fatal("GetNewService should return a service") + } + + if svc := GetNewServiceWithOptions(nil); svc == nil { + t.Fatal("GetNewServiceWithOptions should return a service") + } +} + +func TestLns_Function_Bad(t *testing.T) { + if got := Register(nil); got.OK { + t.Fatalf("Register(nil) = %#v, want failure", got) + } + + if got := GetRegister(nil); got.OK { + t.Fatalf("GetRegister(nil) = %#v, want failure", got) + } +} + +func TestLns_Function_Ugly(t *testing.T) { + svc := NewServiceWithOptions(nil) + if svc == nil { + t.Fatal("NewServiceWithOptions(nil) should return a service") + } + + if svc.reservedCatalogOverride != nil || svc.lockedCatalogOverride != nil { + t.Fatalf("nil options should not populate catalog overrides: %#v", svc) + } +} diff --git a/pkg/covenant/blind_test.go b/pkg/covenant/blind_test.go index a6a4d62..7f323d4 100644 --- a/pkg/covenant/blind_test.go +++ b/pkg/covenant/blind_test.go @@ -52,3 +52,50 @@ func TestGetBlind(t *testing.T) { t.Fatalf("GetBlind returned %x, want %x", got, want) } } + +func TestBlind_Function_Good(t *testing.T) { + var nonce primitives.Hash + for i := range nonce { + nonce[i] = byte(i) + } + + got, err := Blind(0, nonce) + if err != nil { + t.Fatalf("Blind returned error: %v", err) + } + + want, err := GetBlind(0, nonce) + if err != nil { + t.Fatalf("GetBlind returned error: %v", err) + } + + if got != want { + t.Fatalf("Blind() = %x, want %x", got, want) + } +} + +func TestBlind_Function_Bad(t *testing.T) { + var nonce primitives.Hash + got, err := Blind(1, nonce) + if err != nil { + t.Fatalf("Blind returned error: %v", err) + } + + if got == (primitives.Hash{}) { + t.Fatal("Blind should return a non-zero commitment for non-zero value") + } +} + +func TestBlind_Function_Ugly(t *testing.T) { + var nonce primitives.Hash + nonce[0] = 1 + + got, err := Blind(0, nonce) + if err != nil { + t.Fatalf("Blind returned error: %v", err) + } + + if got == (primitives.Hash{}) { + t.Fatal("Blind should produce a digest for arbitrary nonces") + } +} diff --git a/pkg/covenant/covenant_test.go b/pkg/covenant/covenant_test.go index 9f0ac0c..46c61fe 100644 --- a/pkg/covenant/covenant_test.go +++ b/pkg/covenant/covenant_test.go @@ -42,3 +42,36 @@ func TestCovenantTypePredicates(t *testing.T) { } } +func TestCovenant_Function_Good(t *testing.T) { + if got := GetTypeName(TypeRegister); got != "REGISTER" { + t.Fatalf("GetTypeName(TypeRegister) = %q, want %q", got, "REGISTER") + } + + if got := GetTypes()["BID"]; got != TypeBid { + t.Fatalf("GetTypes()[BID] = %d, want %d", got, TypeBid) + } + + if got := TypeFinalize.String(); got != "FINALIZE" { + t.Fatalf("String() = %q, want %q", got, "FINALIZE") + } +} + +func TestCovenant_Function_Bad(t *testing.T) { + if got := TypeName(CovenantType(99)); got != "UNKNOWN" { + t.Fatalf("TypeName(99) = %q, want %q", got, "UNKNOWN") + } + + if TypeNone.IsName() || TypeNone.IsLinked() || !TypeNone.IsKnown() { + t.Fatal("TypeNone predicate invariants failed") + } +} + +func TestCovenant_Function_Ugly(t *testing.T) { + if got := GetTypesByVal()[TypeRevoke]; got != "REVOKE" { + t.Fatalf("GetTypesByVal()[TypeRevoke] = %q, want %q", got, "REVOKE") + } + + if !TypeReveal.IsLinked() || !TypeRevoke.IsLinked() { + t.Fatal("linked covenant boundary checks failed") + } +} diff --git a/pkg/covenant/locked_lookup_test.go b/pkg/covenant/locked_lookup_test.go index 3ed6fcd..8a7693d 100644 --- a/pkg/covenant/locked_lookup_test.go +++ b/pkg/covenant/locked_lookup_test.go @@ -353,3 +353,38 @@ func TestLockedCatalogGetByNameRejectsNonASCII(t *testing.T) { t.Fatal("GetByName should reject non-ASCII labels") } } + +func TestLockedLookup_Function_Good(t *testing.T) { + item, ok := GetLockedName("NEC") + if !ok { + t.Fatal("GetLockedName should find the locked reference entry") + } + + if item.Name != "nec" { + t.Fatalf("item.Name = %q, want %q", item.Name, "nec") + } + + if !HasLockedHash(item.Hash) { + t.Fatal("HasLockedHash should report the locked reference entry") + } +} + +func TestLockedLookup_Function_Bad(t *testing.T) { + if HasLockedName("does-not-exist") { + t.Fatal("unknown names should not be reported as locked") + } + + if _, ok := GetLockedName("does-not-exist"); ok { + t.Fatal("GetLockedName should return false for unknown names") + } +} + +func TestLockedLookup_Function_Ugly(t *testing.T) { + if !GetHasLockedName("nec.lthn") { + t.Fatal("GetHasLockedName should accept canonical .lthn names") + } + + if _, ok := GetLockedByBinary([]byte("NEC")); !ok { + t.Fatal("GetLockedByBinary should find the locked reference entry") + } +} diff --git a/pkg/covenant/name_test.go b/pkg/covenant/name_test.go index e7451ec..38cb67e 100644 --- a/pkg/covenant/name_test.go +++ b/pkg/covenant/name_test.go @@ -363,3 +363,41 @@ func TestHashRejectsInvalidName(t *testing.T) { t.Fatal("HashName should reject unsupported input types") } } + +func TestName_Function_Good(t *testing.T) { + if !VerifyString("example-1") { + t.Fatal("VerifyString should accept a valid non-blacklisted name") + } + + if _, err := HashString("example-1"); err != nil { + t.Fatalf("HashString returned error: %v", err) + } +} + +func TestName_Function_Bad(t *testing.T) { + if VerifyString("Example") { + t.Fatal("VerifyString should reject uppercase labels") + } + + if _, err := HashString("Example"); err == nil { + t.Fatal("HashString should reject invalid names") + } + + if VerifyName(123) { + t.Fatal("VerifyName should reject unsupported input types") + } +} + +func TestName_Function_Ugly(t *testing.T) { + if VerifyBinary([]byte("abc-")) { + t.Fatal("VerifyBinary should reject trailing hyphens") + } + + if VerifyBinary([]byte("ab\x80")) { + t.Fatal("VerifyBinary should reject non-ASCII input") + } + + if _, ok := GetBlacklist()["example"]; !ok { + t.Fatal("GetBlacklist should expose the blacklist map") + } +} diff --git a/pkg/covenant/rules_extra_test.go b/pkg/covenant/rules_extra_test.go index 416b98f..a6ba7b4 100644 --- a/pkg/covenant/rules_extra_test.go +++ b/pkg/covenant/rules_extra_test.go @@ -781,3 +781,44 @@ func TestCoinbaseClaimConjureOverflow(t *testing.T) { t.Fatalf("VerifyCovenants returned %d for overflowing coinbase claim outputs, want -1", got) } } + +func TestRulesExtra_Function_Good(t *testing.T) { + tx := primitives.Transaction{ + Outputs: []primitives.Output{ + {Covenant: primitives.Covenant{Type: uint8(TypeOpen)}}, + {Covenant: primitives.Covenant{Type: uint8(TypeUpdate)}}, + }, + } + + if got := CountOpens(tx); got != 1 { + t.Fatalf("CountOpens() = %d, want 1", got) + } + + if got := GetCountUpdates(tx); got != 2 { + t.Fatalf("GetCountUpdates() = %d, want 2", got) + } +} + +func TestRulesExtra_Function_Bad(t *testing.T) { + if _, err := GrindName(0, 0, NameRules{}); err == nil { + t.Fatal("GrindName should reject zero-sized names") + } +} + +func TestRulesExtra_Function_Ugly(t *testing.T) { + tx := primitives.Transaction{ + Outputs: []primitives.Output{ + {Covenant: primitives.Covenant{Type: uint8(TypeClaim)}}, + {Covenant: primitives.Covenant{Type: uint8(TypeRenew)}}, + {Covenant: primitives.Covenant{Type: uint8(TypeFinalize)}}, + }, + } + + if got := CountRenewals(tx); got != 2 { + t.Fatalf("CountRenewals() = %d, want 2", got) + } + + if got := GetCountRenewals(tx); got != 2 { + t.Fatalf("GetCountRenewals() = %d, want 2", got) + } +} diff --git a/pkg/dns/common_test.go b/pkg/dns/common_test.go index b666871..e6f4804 100644 --- a/pkg/dns/common_test.go +++ b/pkg/dns/common_test.go @@ -118,3 +118,33 @@ func TestHSTypesTables(t *testing.T) { } } } + +func TestCommon_Function_Good(t *testing.T) { + if got := GetDefaultTTL(); got != DEFAULT_TTL { + t.Fatalf("GetDefaultTTL() = %d, want %d", got, DEFAULT_TTL) + } + + if len(GetDummy()) != 0 { + t.Fatalf("GetDummy() length = %d, want 0", len(GetDummy())) + } +} + +func TestCommon_Function_Bad(t *testing.T) { + if _, ok := GetHSTypes()["NOPE"]; ok { + t.Fatal("GetHSTypes should not contain unknown keys") + } + + if _, ok := GetHSTypesByVal()[HSType(99)]; ok { + t.Fatal("GetHSTypesByVal should not contain unknown values") + } +} + +func TestCommon_Function_Ugly(t *testing.T) { + if !bytes.Equal(GetTypeMapAAAA(), TYPE_MAP_AAAA) { + t.Fatal("GetTypeMapAAAA should alias TYPE_MAP_AAAA") + } + + if reflect.ValueOf(GetHSTypes()).Pointer() != reflect.ValueOf(HSTypes).Pointer() { + t.Fatal("GetHSTypes should alias HSTypes") + } +} diff --git a/pkg/dns/nsec_test.go b/pkg/dns/nsec_test.go index 19cc47b..262ade1 100644 --- a/pkg/dns/nsec_test.go +++ b/pkg/dns/nsec_test.go @@ -114,3 +114,34 @@ func TestPrevNameRejectsEmptyName(t *testing.T) { _ = PrevName(".") } + +func TestNsec_Function_Good(t *testing.T) { + rr := GetCreate("Example", NextName("Example"), []byte{0x01, 0x02}) + if rr.Name != "Example." { + t.Fatalf("GetCreate name = %q, want %q", rr.Name, "Example.") + } + + if rr.TTL != DEFAULT_TTL { + t.Fatalf("GetCreate TTL = %d, want %d", rr.TTL, DEFAULT_TTL) + } +} + +func TestNsec_Function_Bad(t *testing.T) { + defer func() { + if recover() == nil { + t.Fatal("PrevName should panic for an empty trimmed name") + } + }() + + _ = PrevName(".") +} + +func TestNsec_Function_Ugly(t *testing.T) { + if got := GetNextName("Example"); got != "example\x00." { + t.Fatalf("GetNextName() = %q, want %q", got, "example\x00.") + } + + if got := GetPrevName("Example"); got != "exampld\xff." { + t.Fatalf("GetPrevName() = %q, want %q", got, "exampld\xff.") + } +} diff --git a/pkg/dns/resolve_test.go b/pkg/dns/resolve_test.go index 2b88ce4..89116ba 100644 --- a/pkg/dns/resolve_test.go +++ b/pkg/dns/resolve_test.go @@ -560,3 +560,31 @@ func TestPackageLevelResolveAndVerifyAliases(t *testing.T) { } } } + +func TestResolve_Function_Good(t *testing.T) { + got, err := Resolve("Foo-Bar.lthn") + if err != nil { + t.Fatalf("Resolve returned error: %v", err) + } + + want := sha3.Sum256([]byte("foo-bar")) + if got != want { + t.Fatalf("Resolve() = %x, want %x", got, want) + } +} + +func TestResolve_Function_Bad(t *testing.T) { + if _, err := Resolve(123); err == nil { + t.Fatal("Resolve should reject unsupported input types") + } +} + +func TestResolve_Function_Ugly(t *testing.T) { + if !VerifyByString("Foo-Bar.lthn") { + t.Fatal("VerifyByString should accept canonical names after normalization") + } + + if !GetVerifyBinary([]byte("Foo-Bar.lthn")) { + t.Fatal("GetVerifyBinary should accept canonical byte names") + } +} diff --git a/pkg/dns/resource_test.go b/pkg/dns/resource_test.go index 3cb7528..bb838c4 100644 --- a/pkg/dns/resource_test.go +++ b/pkg/dns/resource_test.go @@ -832,3 +832,42 @@ func TestResourceDecodeRejectsInvalidPayloads(t *testing.T) { t.Fatal("Decode should reject truncated TXT entries") } } + +func TestResource_Function_Good(t *testing.T) { + resource := NewResource() + if resource == nil { + t.Fatal("NewResource should return a resource") + } + + if resource.TTL != DEFAULT_TTL { + t.Fatalf("NewResource TTL = %d, want %d", resource.TTL, DEFAULT_TTL) + } +} + +func TestResource_Function_Bad(t *testing.T) { + if _, err := DecodeResource([]byte{1}); err == nil { + t.Fatal("DecodeResource should reject unsupported versions") + } + + var resource *Resource + if got := resource.GetSize(); got != 0 { + t.Fatalf("nil resource GetSize() = %d, want 0", got) + } +} + +func TestResource_Function_Ugly(t *testing.T) { + resource := &Resource{ + Records: []ResourceRecord{ + NSRecord{NS: "ns1.example."}, + TXTRecord{Entries: []string{"hello"}}, + }, + } + + if !resource.HasNS() || !resource.GetHasNS() { + t.Fatal("resource should report NS-capable records") + } + + if got := resource.ToNS("example"); len(got) != 1 || got[0].NS != "ns1.example." { + t.Fatalf("ToNS() = %#v, want one NS record", got) + } +} diff --git a/pkg/primitives/claim_test.go b/pkg/primitives/claim_test.go index 5399170..1f478c3 100644 --- a/pkg/primitives/claim_test.go +++ b/pkg/primitives/claim_test.go @@ -100,3 +100,37 @@ func TestClaimHelpers(t *testing.T) { t.Fatal("NewClaim helpers should return a claim wrapper") } } + +func TestClaim_Function_Good(t *testing.T) { + if NewClaim() == nil || GetNewClaim() == nil { + t.Fatal("NewClaim helpers should return a claim wrapper") + } +} + +func TestClaim_Function_Bad(t *testing.T) { + var claim *Claim + if claim.FromBlob([]byte("proof")) != nil { + t.Fatal("nil claim receiver should stay nil") + } + + if _, err := (Claim{Blob: make([]byte, maxClaimSize + 1)}).MarshalBinary(); err == nil { + t.Fatal("MarshalBinary should reject oversized claims") + } +} + +func TestClaim_Function_Ugly(t *testing.T) { + claim := Claim{Blob: []byte("ownership-proof")} + raw, err := claim.MarshalBinary() + if err != nil { + t.Fatalf("MarshalBinary returned error: %v", err) + } + + var decoded Claim + if err := decoded.UnmarshalBinary(raw); err != nil { + t.Fatalf("UnmarshalBinary returned error: %v", err) + } + + if got := decoded.GetBlob(); string(got) != "ownership-proof" { + t.Fatalf("decoded blob = %q, want %q", got, "ownership-proof") + } +} diff --git a/pkg/primitives/covenant_binary_test.go b/pkg/primitives/covenant_binary_test.go index a7b5349..6286888 100644 --- a/pkg/primitives/covenant_binary_test.go +++ b/pkg/primitives/covenant_binary_test.go @@ -66,3 +66,49 @@ func TestCovenantBinaryZeroValue(t *testing.T) { t.Fatalf("decoded zero value = %+v, want zero value", decoded) } } + +func TestCovenantBinary_Function_Good(t *testing.T) { + cov := Covenant{} + cov.SetFinalize( + Hash{43, 44, 45}, + 188, + []byte("final"), + 12, + 21, + 34, + Hash{46, 47, 48}, + ) + + raw, err := cov.MarshalBinary() + if err != nil { + t.Fatalf("MarshalBinary returned error: %v", err) + } + + var decoded Covenant + if err := decoded.UnmarshalBinary(raw); err != nil { + t.Fatalf("UnmarshalBinary returned error: %v", err) + } + + if decoded.Type != cov.Type || decoded.Len() != cov.Len() { + t.Fatalf("decoded covenant = %+v, want %+v", decoded, cov) + } +} + +func TestCovenantBinary_Function_Bad(t *testing.T) { + var cov Covenant + if err := cov.UnmarshalBinary(nil); err == nil { + t.Fatal("UnmarshalBinary should reject short buffers") + } +} + +func TestCovenantBinary_Function_Ugly(t *testing.T) { + var cov Covenant + raw, err := cov.MarshalBinary() + if err != nil { + t.Fatalf("MarshalBinary returned error: %v", err) + } + + if len(raw) == 0 { + t.Fatal("MarshalBinary should produce a compact encoding") + } +} diff --git a/pkg/primitives/covenant_items_test.go b/pkg/primitives/covenant_items_test.go index 91c6f06..b224966 100644 --- a/pkg/primitives/covenant_items_test.go +++ b/pkg/primitives/covenant_items_test.go @@ -643,3 +643,39 @@ func TestCovenantJSONRejectsInvalidEncoding(t *testing.T) { t.Fatal("FromJSON should reject invalid hex data") } } + +func TestCovenantItems_Function_Good(t *testing.T) { + var cov Covenant + cov.SetOpen(Hash{1, 2, 3}, []byte("example")) + + if cov.Len() != 3 { + t.Fatalf("SetOpen should populate three covenant items, got %d", cov.Len()) + } + + if got := cov.IndexOf([]byte("example")); got != 2 { + t.Fatalf("IndexOf() = %d, want 2", got) + } +} + +func TestCovenantItems_Function_Bad(t *testing.T) { + var cov Covenant + if _, err := cov.Get(0); err == nil { + t.Fatal("Get should reject empty covenants") + } + + if err := cov.Set(1, []byte("x")); err == nil { + t.Fatal("Set should reject out-of-range indexes") + } +} + +func TestCovenantItems_Function_Ugly(t *testing.T) { + cov := Covenant{Items: [][]byte{[]byte("a"), []byte("b")}} + + if item, err := cov.Get(-1); err != nil || string(item) != "b" { + t.Fatalf("Get(-1) = %q, %v, want %q, nil", item, err, "b") + } + + if got := cov.Clone(); got.Len() != cov.Len() { + t.Fatalf("Clone() length = %d, want %d", got.Len(), cov.Len()) + } +} diff --git a/pkg/primitives/invitem_test.go b/pkg/primitives/invitem_test.go index 96e0cfd..e7d7e42 100644 --- a/pkg/primitives/invitem_test.go +++ b/pkg/primitives/invitem_test.go @@ -43,3 +43,37 @@ func TestInvItemHelpers(t *testing.T) { t.Fatalf("decoded inventory item = %+v, want %+v", decoded, item) } } + +func TestInvItem_Function_Good(t *testing.T) { + item := NewInvItem(InvTypeClaim, Hash{}) + if item == nil { + t.Fatal("NewInvItem should return a value") + } + + if !item.IsClaim() || item.IsTX() || item.IsBlock() || item.IsAirdrop() { + t.Fatal("inventory type predicates should match the claim type") + } +} + +func TestInvItem_Function_Bad(t *testing.T) { + var item InvItem + if err := item.UnmarshalBinary([]byte{1, 2}); err == nil { + t.Fatal("UnmarshalBinary should reject invalid lengths") + } +} + +func TestInvItem_Function_Ugly(t *testing.T) { + item := InvItem{Type: InvTypeCompactBlock} + if !item.IsBlock() { + t.Fatal("compact block should count as a block") + } + + raw, err := item.MarshalBinary() + if err != nil { + t.Fatalf("MarshalBinary returned error: %v", err) + } + + if len(raw) != item.GetSize() { + t.Fatalf("MarshalBinary length = %d, want %d", len(raw), item.GetSize()) + } +} diff --git a/pkg/primitives/namedelta_test.go b/pkg/primitives/namedelta_test.go index 13dc090..7e3de65 100644 --- a/pkg/primitives/namedelta_test.go +++ b/pkg/primitives/namedelta_test.go @@ -172,3 +172,28 @@ func assertNameDeltaEqual(t *testing.T, got, want NameDelta) { assertBoolPtr("Expired", got.Expired, want.Expired) assertBoolPtr("Weak", got.Weak, want.Weak) } + +func TestNameDelta_Function_Good(t *testing.T) { + if got := (NameDelta{}).IsNull(); !got { + t.Fatal("zero delta should be null") + } +} + +func TestNameDelta_Function_Bad(t *testing.T) { + var delta NameDelta + if err := delta.UnmarshalBinary([]byte{1, 2, 3}); err == nil { + t.Fatal("UnmarshalBinary should reject short buffers") + } +} + +func TestNameDelta_Function_Ugly(t *testing.T) { + height := uint32(7) + delta := NameDelta{Height: &height} + if got := delta.GetField(); got != 1 { + t.Fatalf("GetField() = %d, want 1", got) + } + + if got := delta.GetSize(); got <= 4 { + t.Fatalf("GetSize() = %d, want greater than 4", got) + } +} diff --git a/pkg/primitives/namestate_state_test.go b/pkg/primitives/namestate_state_test.go index 0d13ca7..241a4fc 100644 --- a/pkg/primitives/namestate_state_test.go +++ b/pkg/primitives/namestate_state_test.go @@ -151,3 +151,26 @@ func TestNameStateClaimableAndExpired(t *testing.T) { t.Fatal("closed names without an owner should expire once the renewal window ends") } } + +func TestNameStateState_Function_Good(t *testing.T) { + ns := NameState{Height: 10} + rules := NameStateRules{TreeInterval: 1, BiddingPeriod: 1, RevealPeriod: 1} + + if got := ns.State(10, rules); got != NameStateOpening { + t.Fatalf("State() = %s, want %s", got, NameStateOpening) + } +} + +func TestNameStateState_Function_Bad(t *testing.T) { + var ns NameState + if ns.IsClaimable(0, NameStateRules{}) { + t.Fatal("zero state should not be claimable") + } +} + +func TestNameStateState_Function_Ugly(t *testing.T) { + ns := NameState{Revoked: 12} + if got := ns.State(13, NameStateRules{}); got != NameStateRevoked { + t.Fatalf("State() = %s, want %s", got, NameStateRevoked) + } +} diff --git a/pkg/primitives/namestate_test.go b/pkg/primitives/namestate_test.go index 13d6cda..7b30e0b 100644 --- a/pkg/primitives/namestate_test.go +++ b/pkg/primitives/namestate_test.go @@ -571,3 +571,25 @@ func TestNameStateBinaryZeroValue(t *testing.T) { t.Fatalf("decoded zero value = %+v, want zero value", decoded) } } + +func TestNameState_Function_Good(t *testing.T) { + var ns NameState + if ns.Delta() == nil || ns.GetDelta() == nil { + t.Fatal("Delta helpers should allocate a sparse delta") + } +} + +func TestNameState_Function_Bad(t *testing.T) { + ns := NameState{Name: []byte("foo"), Height: 1} + if got := ns.MaybeExpire(1, NameStateRules{}); got { + t.Fatal("MaybeExpire should stay false when the name is not expired") + } +} + +func TestNameState_Function_Ugly(t *testing.T) { + ns := NameState{Name: []byte("foo"), Height: 10} + clone := ns.Clone() + if clone.NameHash != ns.NameHash || !bytes.Equal(clone.Name, ns.Name) { + t.Fatalf("Clone() = %+v, want %+v", clone, ns) + } +} diff --git a/pkg/primitives/types_test.go b/pkg/primitives/types_test.go index c42533d..c73dd31 100644 --- a/pkg/primitives/types_test.go +++ b/pkg/primitives/types_test.go @@ -367,3 +367,28 @@ func TestOutputIsUnspendable(t *testing.T) { t.Fatal("revoke covenant output should be unspendable") } } + +func TestTypes_Function_Good(t *testing.T) { + addr := Address{Version: 0, Hash: bytes.Repeat([]byte{0x01}, 20)} + if !addr.IsValid() || !addr.IsPubkeyHash() { + t.Fatalf("valid pubkey hash address should be accepted: %#v", addr) + } +} + +func TestTypes_Function_Bad(t *testing.T) { + addr := Address{Version: 32, Hash: bytes.Repeat([]byte{0x01}, 1)} + if addr.IsValid() { + t.Fatalf("invalid address should not be valid: %#v", addr) + } +} + +func TestTypes_Function_Ugly(t *testing.T) { + cov := Covenant{Type: covenantTypeRevoke} + if !cov.IsUnspendable() || !cov.IsRevoke() { + t.Fatalf("revoke covenant should be unspendable and revoke: %#v", cov) + } + + if !(Covenant{Type: covenantTypeOpen}).IsName() { + t.Fatal("open covenant should be a name covenant") + } +} diff --git a/pkg/primitives/view_test.go b/pkg/primitives/view_test.go index b64c92a..49960ba 100644 --- a/pkg/primitives/view_test.go +++ b/pkg/primitives/view_test.go @@ -4,6 +4,7 @@ package primitives import ( "bytes" + "errors" "testing" ) @@ -154,3 +155,47 @@ func (d NameDelta) MarshalMust(t *testing.T) []byte { return data } + +func TestView_Function_Good(t *testing.T) { + view := NewNameView() + if view == nil { + t.Fatal("NewNameView should return a view") + } + + var hash Hash + ns, err := view.GetNameStateSync(nil, hash) + if err != nil { + t.Fatalf("GetNameStateSync returned error: %v", err) + } + + if ns == nil || ns.NameHash != hash { + t.Fatalf("GetNameStateSync returned %#v, want zero state keyed by hash", ns) + } +} + +func TestView_Function_Bad(t *testing.T) { + view := NewNameView() + wantErr := errors.New("db failure") + if _, err := view.GetNameStateSync(stubNameStateDB{err: wantErr}, Hash{}); err != wantErr { + t.Fatalf("GetNameStateSync should propagate db errors, got %v", err) + } +} + +func TestView_Function_Ugly(t *testing.T) { + var view NameView + firstHash := Hash{1} + secondHash := Hash{2} + + view.names = map[Hash]*NameState{ + firstHash: &NameState{NameHash: firstHash}, + secondHash: &NameState{NameHash: secondHash}, + } + view.order = []Hash{secondHash, firstHash} + view.names[firstHash].setHeight(1) + view.names[secondHash].setHeight(2) + + undo := view.ToNameUndo() + if len(undo.Names) != 2 { + t.Fatalf("ToNameUndo() = %d entries, want 2", len(undo.Names)) + } +}