1- package envconfig_test
1+ package envconfig
22
33import (
4+ "reflect"
5+ "strings"
46 "testing"
57
68 "github.com/stretchr/testify/require"
7- "go.temporal.io/sdk/contrib/envconfig"
89)
910
1011func TestClientConfigTOMLFull (t * testing.T ) {
@@ -28,8 +29,8 @@ server_ca_cert_data = "my-server-ca-cert-data"
2829server_name = "my-server-name"
2930disable_host_verification = true`
3031
31- var conf envconfig. ClientConfig
32- require .NoError (t , conf .FromTOML ([]byte (data ), envconfig. ClientConfigFromTOMLOptions {}))
32+ var conf ClientConfig
33+ require .NoError (t , conf .FromTOML ([]byte (data ), ClientConfigFromTOMLOptions {}))
3334 prof := conf .Profiles ["foo" ]
3435 require .Equal (t , "my-address" , prof .Address )
3536 require .Equal (t , "my-namespace" , prof .Namespace )
@@ -48,10 +49,10 @@ disable_host_verification = true`
4849 require .Equal (t , map [string ]string {"some-header-key" : "some-value" }, prof .GRPCMeta )
4950
5051 // Back to toml and back to structure again, then deep equality check
51- b , err := conf .ToTOML (envconfig. ClientConfigToTOMLOptions {})
52+ b , err := conf .ToTOML (ClientConfigToTOMLOptions {})
5253 require .NoError (t , err )
53- var newConf envconfig. ClientConfig
54- require .NoError (t , newConf .FromTOML (b , envconfig. ClientConfigFromTOMLOptions {}))
54+ var newConf ClientConfig
55+ require .NoError (t , newConf .FromTOML (b , ClientConfigFromTOMLOptions {}))
5556 require .Equal (t , conf , newConf )
5657 // Sanity check that require.Equal actually does deep-equality
5758 newConf .Profiles ["foo" ].Codec .Auth += "-dirty"
@@ -67,8 +68,8 @@ stuff = "does not matter"
6768address = "my-address"
6869some_future_key = "some value"`
6970
70- var conf envconfig. ClientConfig
71- err := conf .FromTOML ([]byte (data ), envconfig. ClientConfigFromTOMLOptions {Strict : true })
71+ var conf ClientConfig
72+ err := conf .FromTOML ([]byte (data ), ClientConfigFromTOMLOptions {Strict : true })
7273 require .ErrorContains (t , err , "unimportant.stuff" )
7374 require .ErrorContains (t , err , "profile.foo.some_future_key" )
7475}
@@ -82,8 +83,8 @@ api_key = "my-api-key"
8283[profile.foo.tls]
8384`
8485
85- var conf envconfig. ClientConfig
86- require .NoError (t , conf .FromTOML ([]byte (data ), envconfig. ClientConfigFromTOMLOptions {}))
86+ var conf ClientConfig
87+ require .NoError (t , conf .FromTOML ([]byte (data ), ClientConfigFromTOMLOptions {}))
8788 prof := conf .Profiles ["foo" ]
8889 require .Empty (t , prof .Address )
8990 require .Empty (t , prof .Namespace )
@@ -93,22 +94,117 @@ api_key = "my-api-key"
9394 require .Zero (t , * prof .TLS )
9495
9596 // Back to toml and back to structure again, then deep equality check
96- b , err := conf .ToTOML (envconfig. ClientConfigToTOMLOptions {})
97+ b , err := conf .ToTOML (ClientConfigToTOMLOptions {})
9798 require .NoError (t , err )
98- var newConf envconfig. ClientConfig
99- require .NoError (t , newConf .FromTOML (b , envconfig. ClientConfigFromTOMLOptions {}))
99+ var newConf ClientConfig
100+ require .NoError (t , newConf .FromTOML (b , ClientConfigFromTOMLOptions {}))
100101 require .Equal (t , conf , newConf )
101102}
102103
103104func TestClientConfigTOMLEmpty (t * testing.T ) {
104- var conf envconfig. ClientConfig
105- require .NoError (t , conf .FromTOML (nil , envconfig. ClientConfigFromTOMLOptions {}))
105+ var conf ClientConfig
106+ require .NoError (t , conf .FromTOML (nil , ClientConfigFromTOMLOptions {}))
106107 require .Empty (t , conf .Profiles )
107108
108109 // Back to toml and back to structure again, then deep equality check
109- b , err := conf .ToTOML (envconfig. ClientConfigToTOMLOptions {})
110+ b , err := conf .ToTOML (ClientConfigToTOMLOptions {})
110111 require .NoError (t , err )
111- var newConf envconfig. ClientConfig
112- require .NoError (t , newConf .FromTOML (b , envconfig. ClientConfigFromTOMLOptions {}))
112+ var newConf ClientConfig
113+ require .NoError (t , newConf .FromTOML (b , ClientConfigFromTOMLOptions {}))
113114 require .Equal (t , conf , newConf )
114115}
116+
117+ func TestClientConfigTOMLAdditionalProfileFields (t * testing.T ) {
118+ data := `
119+ [profile.foo]
120+ address = "my-address"
121+ namespace = "my-namespace"
122+ custom_field = "custom-value"
123+ custom_field2 = 42
124+
125+ [profile.foo.custom_nested]
126+ key1 = "value1"
127+
128+ [profile.foo.custom_nested.deep]
129+ key2 = "value2"
130+
131+ [profile.foo.custom_nested.deep.deeper]
132+ key3 = "value3"
133+
134+ [profile.bar]
135+ address = "bar-address"
136+ custom_field = true`
137+
138+ var conf ClientConfig
139+ additional := make (map [string ]map [string ]any )
140+ require .NoError (t , conf .FromTOML ([]byte (data ), ClientConfigFromTOMLOptions {
141+ AdditionalProfileFields : additional ,
142+ }))
143+
144+ // Verify known fields were parsed
145+ require .Equal (t , "my-address" , conf .Profiles ["foo" ].Address )
146+ require .Equal (t , "my-namespace" , conf .Profiles ["foo" ].Namespace )
147+ require .Equal (t , "bar-address" , conf .Profiles ["bar" ].Address )
148+
149+ // Verify additional fields were captured
150+ require .Equal (t , "custom-value" , additional ["foo" ]["custom_field" ])
151+ require .Equal (t , int64 (42 ), additional ["foo" ]["custom_field2" ])
152+ require .Equal (t , true , additional ["bar" ]["custom_field" ])
153+
154+ // Verify deeply nested additional fields are preserved
155+ customNested , ok := additional ["foo" ]["custom_nested" ].(map [string ]any )
156+ require .True (t , ok , "custom_nested should be a map" )
157+ require .Equal (t , "value1" , customNested ["key1" ])
158+
159+ deep , ok := customNested ["deep" ].(map [string ]any )
160+ require .True (t , ok , "custom_nested.deep should be a map" )
161+ require .Equal (t , "value2" , deep ["key2" ])
162+
163+ deeper , ok := deep ["deeper" ].(map [string ]any )
164+ require .True (t , ok , "custom_nested.deep.deeper should be a map" )
165+ require .Equal (t , "value3" , deeper ["key3" ])
166+
167+ // Back to TOML and back to structure again, then deep equality check
168+ b , err := conf .ToTOML (ClientConfigToTOMLOptions {
169+ AdditionalProfileFields : additional ,
170+ })
171+ require .NoError (t , err )
172+ var newConf ClientConfig
173+ newAdditional := make (map [string ]map [string ]any )
174+ require .NoError (t , newConf .FromTOML (b , ClientConfigFromTOMLOptions {
175+ AdditionalProfileFields : newAdditional ,
176+ }))
177+ require .Equal (t , conf , newConf )
178+ require .Equal (t , additional , newAdditional )
179+ }
180+
181+ func TestClientConfigTOMLAdditionalProfileFieldsConflict (t * testing.T ) {
182+ conf := ClientConfig {
183+ Profiles : map [string ]* ClientConfigProfile {
184+ "foo" : {Address : "my-address" },
185+ },
186+ }
187+
188+ // Attempt to write with an additional field that conflicts with a known field
189+ _ , err := conf .ToTOML (ClientConfigToTOMLOptions {
190+ AdditionalProfileFields : map [string ]map [string ]any {
191+ "foo" : {"address" : "conflict" },
192+ },
193+ })
194+ require .ErrorContains (t , err , "additional field \" address\" in profile \" foo\" conflicts with known profile field" )
195+ }
196+
197+ func TestKnownProfileKeysInSync (t * testing.T ) {
198+ // Extract keys from tomlClientConfigProfile's TOML tags using reflection
199+ expected := make (map [string ]bool )
200+ typ := reflect .TypeFor [tomlClientConfigProfile ]()
201+ for i := range typ .NumField () {
202+ tag := typ .Field (i ).Tag .Get ("toml" )
203+ if key , _ , _ := strings .Cut (tag , "," ); key != "" {
204+ expected [key ] = true
205+ }
206+ }
207+
208+ require .Equal (t , expected , knownProfileKeys ,
209+ "knownProfileKeys must match tomlClientConfigProfile's TOML tags" )
210+ }
0 commit comments