@@ -412,7 +412,7 @@ foo = "bar"`,
412412 assert : func (t * testing.T , test test ) {
413413 // Despite the documentation:
414414 // Pointer variable equality is determined based on the equality of the
415- // referenced values (as opposed to the memory addresses).
415+ // referenced values (as opposed to the memory addresses).
416416 // assert.Equal does not work properly with maps with pointer keys
417417 // https://github.com/stretchr/testify/issues/1143
418418 expected := make (map [unmarshalTextKey ]string )
@@ -3884,9 +3884,9 @@ func TestUnmarshal_Nil(t *testing.T) {
38843884 {
38853885 desc : "simplest" ,
38863886 input : `
3887- [foo]
3888- [foo.foo]
3889- ` ,
3887+ [foo]
3888+ [foo.foo]
3889+ ` ,
38903890 expected : "[foo]\n [foo.foo]\n " ,
38913891 },
38923892 }
@@ -4040,3 +4040,202 @@ func TestIssue994_OK(t *testing.T) {
40404040 assert .NoError (t , err )
40414041 assert .Equal (t , "bar from unmarshaler" , d .S )
40424042}
4043+
4044+ func TestIssue995 (t * testing.T ) {
4045+ type AllowList struct {
4046+ Description string
4047+ Condition string
4048+ Commits []string
4049+ Paths []string
4050+ RegexTarget string
4051+ Regexes []string
4052+ StopWords []string
4053+ }
4054+
4055+ type Rule struct {
4056+ ID string
4057+ Description string
4058+ Regex string
4059+ SecretGroup int
4060+ Entropy interface {}
4061+ Keywords []string
4062+ Path string
4063+ Tags []string
4064+ AllowList * AllowList
4065+ Allowlists []AllowList
4066+ }
4067+
4068+ type GitleaksConfig struct {
4069+ Description string
4070+ Rules []Rule
4071+ Allowlist struct {
4072+ Commits []string
4073+ Paths []string
4074+ RegexTarget string
4075+ Regexes []string
4076+ StopWords []string
4077+ }
4078+ }
4079+
4080+ doc := `
4081+ [[allowlists]]
4082+ description = "Exception for File "
4083+ files = [ '''app/src''']
4084+
4085+ [[rules.allowlists]]
4086+ description = "policies"
4087+ regexes = [
4088+ '''abc'''
4089+ ]
4090+ `
4091+
4092+ var cfg GitleaksConfig
4093+ err := toml .Unmarshal ([]byte (doc ), & cfg )
4094+ assert .NoError (t , err )
4095+
4096+ // Ensure no panic and that nested array table was created.
4097+ if len (cfg .Rules ) == 0 {
4098+ t .Fatalf ("expected Rules to contain at least one element after unmarshaling nested array table" )
4099+ }
4100+ if len (cfg .Rules [0 ].Allowlists ) != 1 {
4101+ t .Fatalf ("expected first Rule to have exactly one allowlists entry, got %d" , len (cfg .Rules [0 ].Allowlists ))
4102+ }
4103+ assert .Equal (t , "policies" , cfg .Rules [0 ].Allowlists [0 ].Description )
4104+ assert .Equal (t , []string {"abc" }, cfg .Rules [0 ].Allowlists [0 ].Regexes )
4105+ }
4106+
4107+ func TestIssue995_InterfaceSlice_MultiNested (t * testing.T ) {
4108+ type Root struct {
4109+ Rules []interface {}
4110+ }
4111+
4112+ doc := `
4113+ [[rules.allowlists]]
4114+ description = "a"
4115+
4116+ [[rules.allowlists]]
4117+ description = "b"
4118+ `
4119+
4120+ var r Root
4121+ err := toml .Unmarshal ([]byte (doc ), & r )
4122+ assert .NoError (t , err )
4123+
4124+ if len (r .Rules ) != 1 {
4125+ t .Fatalf ("expected one element in Rules, got %d" , len (r .Rules ))
4126+ }
4127+
4128+ m , ok := r .Rules [0 ].(map [string ]interface {})
4129+ if ! ok {
4130+ t .Fatalf ("expected Rules[0] to be a map[string]any, got %T" , r .Rules [0 ])
4131+ }
4132+
4133+ als , ok := m ["allowlists" ].([]interface {})
4134+ if ! ok {
4135+ t .Fatalf ("expected allowlists to be []any, got %T" , m ["allowlists" ])
4136+ }
4137+ if len (als ) != 2 {
4138+ t .Fatalf ("expected 2 allowlists entries, got %d" , len (als ))
4139+ }
4140+
4141+ a0 , ok := als [0 ].(map [string ]interface {})
4142+ if ! ok {
4143+ t .Fatalf ("expected allowlists[0] to be map[string]any, got %T" , als [0 ])
4144+ }
4145+ a1 , ok := als [1 ].(map [string ]interface {})
4146+ if ! ok {
4147+ t .Fatalf ("expected allowlists[1] to be map[string]any, got %T" , als [1 ])
4148+ }
4149+ assert .Equal (t , "a" , a0 ["description" ])
4150+ assert .Equal (t , "b" , a1 ["description" ])
4151+ }
4152+
4153+ func TestIssue995_MultiNestedConcrete (t * testing.T ) {
4154+ type AllowList struct {
4155+ Description string
4156+ }
4157+ type Rule struct {
4158+ Allowlists []AllowList
4159+ }
4160+ type Root struct {
4161+ Rules []Rule
4162+ }
4163+
4164+ doc := `
4165+ [[rules.allowlists]]
4166+ description = "a"
4167+
4168+ [[rules.allowlists]]
4169+ description = "b"
4170+ `
4171+
4172+ var r Root
4173+ err := toml .Unmarshal ([]byte (doc ), & r )
4174+ assert .NoError (t , err )
4175+
4176+ if len (r .Rules ) != 1 {
4177+ t .Fatalf ("expected one element in Rules, got %d" , len (r .Rules ))
4178+ }
4179+ assert .Equal (t , 2 , len (r .Rules [0 ].Allowlists ))
4180+ assert .Equal (t , "a" , r .Rules [0 ].Allowlists [0 ].Description )
4181+ assert .Equal (t , "b" , r .Rules [0 ].Allowlists [1 ].Description )
4182+ }
4183+
4184+ func TestIssue995_PointerToSlice_Rules (t * testing.T ) {
4185+ type AllowList struct { Description string }
4186+ type Rule struct { Allowlists []AllowList }
4187+ type Root struct { Rules * []Rule }
4188+
4189+ doc := `
4190+ [[rules.allowlists]]
4191+ description = "a"
4192+
4193+ [[rules.allowlists]]
4194+ description = "b"
4195+ `
4196+
4197+ var r Root
4198+ err := toml .Unmarshal ([]byte (doc ), & r )
4199+ assert .NoError (t , err )
4200+ if r .Rules == nil {
4201+ t .Fatalf ("expected Rules pointer to be initialized" )
4202+ }
4203+ if len (* r .Rules ) != 1 {
4204+ t .Fatalf ("expected one element in Rules, got %d" , len (* r .Rules ))
4205+ }
4206+ rule := (* r .Rules )[0 ]
4207+ assert .Equal (t , 2 , len (rule .Allowlists ))
4208+ assert .Equal (t , "a" , rule .Allowlists [0 ].Description )
4209+ assert .Equal (t , "b" , rule .Allowlists [1 ].Description )
4210+ }
4211+
4212+ func TestIssue995_SliceNonEmpty_UsesLastElement (t * testing.T ) {
4213+ type AllowList struct { Description string }
4214+ type Rule struct { Allowlists []AllowList }
4215+ type Root struct { Rules []Rule }
4216+
4217+ // Pre-initialize with one Rule; nested array table should populate
4218+ // the last element, not create a new one at this level.
4219+ var r Root
4220+ r .Rules = []Rule {{}}
4221+
4222+ doc := `
4223+ [[rules.allowlists]]
4224+ description = "a"
4225+
4226+ [[rules.allowlists]]
4227+ description = "b"
4228+ `
4229+
4230+ err := toml .Unmarshal ([]byte (doc ), & r )
4231+ assert .NoError (t , err )
4232+ if len (r .Rules ) != 1 {
4233+ t .Fatalf ("expected one element in Rules, got %d" , len (r .Rules ))
4234+ }
4235+ assert .Equal (t , 2 , len (r .Rules [0 ].Allowlists ))
4236+ // Values presence check
4237+ got := []string {r .Rules [0 ].Allowlists [0 ].Description , r .Rules [0 ].Allowlists [1 ].Description }
4238+ if ! (got [0 ] == "a" && got [1 ] == "b" ) && ! (got [0 ] == "b" && got [1 ] == "a" ) {
4239+ t .Fatalf ("unexpected values in allowlists: %v" , got )
4240+ }
4241+ }
0 commit comments