@@ -2,9 +2,11 @@ package godump
22
33import (
44 "fmt"
5+ "github.com/stretchr/testify/require"
56 "os"
67 "reflect"
78 "regexp"
9+ "runtime"
810 "strings"
911 "testing"
1012 "text/tabwriter"
@@ -603,3 +605,138 @@ func TestTheKitchenSink(t *testing.T) {
603605 assert .Contains (t , out , "Everything" ) // middle-ground
604606
605607}
608+
609+ func TestAnsiColorize_Disabled (t * testing.T ) {
610+ orig := enableColor
611+ enableColor = false
612+ defer func () { enableColor = orig }()
613+
614+ out := ansiColorize (colorYellow , "test" )
615+ assert .Equal (t , "test" , out )
616+ }
617+
618+ func TestForceExportedFallback (t * testing.T ) {
619+ type s struct { val string }
620+ v := reflect .ValueOf (s {"hidden" }).Field (0 ) // not addressable
621+ out := forceExported (v )
622+ assert .Equal (t , "hidden" , out .String ())
623+ }
624+
625+ func TestAnsiColorize_DisabledBranch (t * testing.T ) {
626+ orig := enableColor
627+ enableColor = false
628+ defer func () { enableColor = orig }()
629+
630+ out := ansiColorize (colorLime , "xyz" )
631+ assert .Equal (t , "xyz" , out )
632+ }
633+
634+ func TestFindFirstNonInternalFrame_FallbackBranch (t * testing.T ) {
635+ orig := callerFn
636+ defer func () { callerFn = orig }()
637+
638+ // Always fail to simulate 10 bad frames
639+ callerFn = func (i int ) (uintptr , string , int , bool ) {
640+ return 0 , "" , 0 , false
641+ }
642+
643+ file , line := findFirstNonInternalFrame ()
644+ assert .Equal (t , "" , file )
645+ assert .Equal (t , 0 , line )
646+ }
647+
648+ func TestForceExported_NoInterfaceNoAddr (t * testing.T ) {
649+ v := reflect .ValueOf (struct { a string }{"x" }).Field (0 )
650+ if v .CanAddr () {
651+ t .Skip ("Field unexpectedly addressable; cannot hit fallback branch" )
652+ }
653+ out := forceExported (v )
654+ assert .Equal (t , "x" , out .String ())
655+ }
656+
657+ func TestPrintDumpHeader_SkipWhenNoFrame (t * testing.T ) {
658+ orig := callerFn
659+ defer func () { callerFn = orig }()
660+
661+ callerFn = func (skip int ) (uintptr , string , int , bool ) {
662+ return 0 , "" , 0 , false
663+ }
664+
665+ var b strings.Builder
666+ printDumpHeader (& b , 3 )
667+ assert .Equal (t , "" , b .String ()) // nothing should be written
668+ }
669+
670+ var runtimeCaller = runtime .Caller
671+
672+ func TestCallerLocation_Fallback (t * testing.T ) {
673+ // Override runtime.Caller behavior
674+ orig := runtimeCaller
675+ defer func () { runtimeCaller = orig }()
676+ runtimeCaller = func (skip int ) (uintptr , string , int , bool ) {
677+ return 0 , "" , 0 , false
678+ }
679+
680+ file , line := callerLocation (5 )
681+ assert .Equal (t , "" , file )
682+ assert .Equal (t , 0 , line )
683+ }
684+
685+ type customChan chan int
686+
687+ func TestPrintValue_ChanNilBranch_Hardforce (t * testing.T ) {
688+ var buf strings.Builder
689+ tw := tabwriter .NewWriter (& buf , 0 , 0 , 1 , ' ' , 0 )
690+
691+ var ch customChan
692+ v := reflect .ValueOf (ch )
693+
694+ assert .True (t , v .IsNil ())
695+ assert .Equal (t , reflect .Chan , v .Kind ())
696+
697+ printValue (tw , v , 0 , map [uintptr ]bool {})
698+ tw .Flush ()
699+
700+ out := stripANSI (buf .String ())
701+ assert .Contains (t , out , "customChan(nil)" )
702+ }
703+
704+ type secretString string
705+
706+ func (s secretString ) String () string {
707+ return "👻 hidden stringer"
708+ }
709+
710+ type hidden struct {
711+ secret secretString // unexported
712+ }
713+
714+ func TestAsStringer_ForceExported (t * testing.T ) {
715+ h := & hidden {secret : "boo" } // pointer makes fields addressable
716+ v := reflect .ValueOf (h ).Elem ().FieldByName ("secret" ) // now v.CanAddr() is true, but v.CanInterface() is false
717+
718+ assert .False (t , v .CanInterface (), "field must not be interfaceable" )
719+ str := asStringer (v )
720+
721+ assert .Contains (t , str , "👻 hidden stringer" )
722+ }
723+
724+ func TestForceExported_Interfaceable (t * testing.T ) {
725+ v := reflect .ValueOf ("already ok" )
726+ require .True (t , v .CanInterface ())
727+
728+ out := forceExported (v )
729+
730+ assert .Equal (t , "already ok" , out .Interface ())
731+ }
732+
733+ func TestMakeAddressable_CanAddr (t * testing.T ) {
734+ s := "hello"
735+ v := reflect .ValueOf (& s ).Elem () // addressable string
736+
737+ require .True (t , v .CanAddr ())
738+
739+ out := makeAddressable (v )
740+
741+ assert .Equal (t , v .Interface (), out .Interface ()) // compare by value
742+ }
0 commit comments