@@ -74,46 +74,209 @@ TEST_F(ServiceEndpointsConfigFileLoaderTest, TestServiceSpecificEndpointsOnly)
7474 TempFile configFile (std::ios_base::out | std::ios_base::trunc);
7575 ASSERT_TRUE (configFile.good ());
7676
77- configFile << " [profile test]\n " ;
78- configFile << " region = us-east-1\n " ;
79- configFile << " services = testservices\n " ;
80- configFile << " \n [services testservices]\n " ;
77+ configFile << " [services s3-minio]\n " ;
8178 configFile << " s3 =\n " ;
82- configFile << " endpoint_url = http://localhost:9000\n " ;
79+ configFile << " endpoint_url = https://play.min.io:9000\n " ;
80+ configFile << " \n [profile dev-minio]\n " ;
81+ configFile << " services = s3-minio\n " ;
8382 configFile.flush ();
8483
8584 AWSConfigFileProfileConfigLoader loader (configFile.GetFileName (), true );
8685 ASSERT_TRUE (loader.Load ());
8786
8887 // Test that global endpoint is null when not set
89- auto globalEndpoint = loader.GetGlobalEndpointUrl (" test " );
88+ auto globalEndpoint = loader.GetGlobalEndpointUrl (" dev-minio " );
9089 ASSERT_EQ (nullptr , globalEndpoint);
9190
92- // Test service-specific endpoint still works
93- auto s3Endpoint = loader.GetServiceEndpointUrl (" test " , " s3" );
91+ // Test service-specific endpoint
92+ auto s3Endpoint = loader.GetServiceEndpointUrl (" dev-minio " , " s3" );
9493 ASSERT_NE (nullptr , s3Endpoint);
95- ASSERT_STREQ (" http://localhost:9000" , s3Endpoint->c_str ());
94+ ASSERT_STREQ (" https://play.min.io:9000" , s3Endpoint->c_str ());
95+
96+ // Test case insensitive lookup
97+ auto s3EndpointUpper = loader.GetServiceEndpointUrl (" dev-minio" , " S3" );
98+ ASSERT_NE (nullptr , s3EndpointUpper);
99+ ASSERT_STREQ (" https://play.min.io:9000" , s3EndpointUpper->c_str ());
96100}
97101
98102TEST_F (ServiceEndpointsConfigFileLoaderTest, TestGlobalEndpointOnly)
99103{
100104 TempFile configFile (std::ios_base::out | std::ios_base::trunc);
101105 ASSERT_TRUE (configFile.good ());
102106
103- configFile << " [profile test ]\n " ;
104- configFile << " endpoint_url = https://global.example.com \n " ;
107+ configFile << " [profile dev-global ]\n " ;
108+ configFile << " endpoint_url = https://play.min.io:9000 \n " ;
105109 configFile.flush ();
106110
107111 AWSConfigFileProfileConfigLoader loader (configFile.GetFileName (), true );
108112 ASSERT_TRUE (loader.Load ());
109113
110114 // Test global endpoint
111- auto globalEndpoint = loader.GetGlobalEndpointUrl (" test " );
115+ auto globalEndpoint = loader.GetGlobalEndpointUrl (" dev-global " );
112116 ASSERT_NE (nullptr , globalEndpoint);
113- ASSERT_STREQ (" https://global.example.com " , globalEndpoint->c_str ());
117+ ASSERT_STREQ (" https://play.min.io:9000 " , globalEndpoint->c_str ());
114118
115119 // Test that service-specific endpoint is null when not set
116- auto s3Endpoint = loader.GetServiceEndpointUrl (" test " , " s3" );
120+ auto s3Endpoint = loader.GetServiceEndpointUrl (" dev-global " , " s3" );
117121 ASSERT_EQ (nullptr , s3Endpoint);
118122}
119123
124+ TEST_F (ServiceEndpointsConfigFileLoaderTest, TestServiceSpecificAndGlobalEndpoints)
125+ {
126+ TempFile configFile (std::ios_base::out | std::ios_base::trunc);
127+ ASSERT_TRUE (configFile.good ());
128+
129+ configFile << " [services s3-specific-and-global]\n " ;
130+ configFile << " s3 =\n " ;
131+ configFile << " endpoint_url = https://play.min.io:9000\n " ;
132+ configFile << " \n [profile dev-s3-specific-and-global]\n " ;
133+ configFile << " endpoint_url = http://localhost:1234\n " ;
134+ configFile << " services = s3-specific-and-global\n " ;
135+ configFile.flush ();
136+
137+ AWSConfigFileProfileConfigLoader loader (configFile.GetFileName (), true );
138+ ASSERT_TRUE (loader.Load ());
139+
140+ // Test service-specific S3 endpoint
141+ auto s3Endpoint = loader.GetServiceEndpointUrl (" dev-s3-specific-and-global" , " s3" );
142+ ASSERT_NE (nullptr , s3Endpoint);
143+ ASSERT_STREQ (" https://play.min.io:9000" , s3Endpoint->c_str ());
144+
145+ // Test global endpoint for other services
146+ auto globalEndpoint = loader.GetGlobalEndpointUrl (" dev-s3-specific-and-global" );
147+ ASSERT_NE (nullptr , globalEndpoint);
148+ ASSERT_STREQ (" http://localhost:1234" , globalEndpoint->c_str ());
149+
150+ // Test that non-configured service returns null (would fall back to global)
151+ auto dynamoEndpoint = loader.GetServiceEndpointUrl (" dev-s3-specific-and-global" , " dynamodb" );
152+ ASSERT_EQ (nullptr , dynamoEndpoint);
153+ }
154+
155+ TEST_F (ServiceEndpointsConfigFileLoaderTest, TestMultipleServicesInDefinition)
156+ {
157+ TempFile configFile (std::ios_base::out | std::ios_base::trunc);
158+ ASSERT_TRUE (configFile.good ());
159+
160+ configFile << " [services testing-s3-and-eb]\n " ;
161+ configFile << " s3 =\n " ;
162+ configFile << " endpoint_url = http://localhost:4567\n " ;
163+ configFile << " elastic_beanstalk =\n " ;
164+ configFile << " endpoint_url = http://localhost:8000\n " ;
165+ configFile << " \n [profile dev]\n " ;
166+ configFile << " services = testing-s3-and-eb\n " ;
167+ configFile.flush ();
168+
169+ AWSConfigFileProfileConfigLoader loader (configFile.GetFileName (), true );
170+ ASSERT_TRUE (loader.Load ());
171+
172+ // Test S3 endpoint
173+ auto s3Endpoint = loader.GetServiceEndpointUrl (" dev" , " s3" );
174+ ASSERT_NE (nullptr , s3Endpoint);
175+ ASSERT_STREQ (" http://localhost:4567" , s3Endpoint->c_str ());
176+
177+ // Test Elastic Beanstalk endpoint with normalized service ID
178+ auto ebEndpoint = loader.GetServiceEndpointUrl (" dev" , " Elastic Beanstalk" );
179+ ASSERT_NE (nullptr , ebEndpoint);
180+ ASSERT_STREQ (" http://localhost:8000" , ebEndpoint->c_str ());
181+
182+ // Test direct normalized lookup
183+ auto ebEndpointDirect = loader.GetServiceEndpointUrl (" dev" , " elastic_beanstalk" );
184+ ASSERT_NE (nullptr , ebEndpointDirect);
185+ ASSERT_STREQ (" http://localhost:8000" , ebEndpointDirect->c_str ());
186+ }
187+
188+ TEST_F (ServiceEndpointsConfigFileLoaderTest, TestIgnoreGlobalEndpointInServicesSection)
189+ {
190+ TempFile configFile (std::ios_base::out | std::ios_base::trunc);
191+ ASSERT_TRUE (configFile.good ());
192+
193+ configFile << " [profile testing]\n " ;
194+ configFile << " services = bad-service-definition\n " ;
195+ configFile << " \n [services bad-service-definition]\n " ;
196+ configFile << " endpoint_url = http://do-not-use.aws/\n " ;
197+ configFile.flush ();
198+
199+ AWSConfigFileProfileConfigLoader loader (configFile.GetFileName (), true );
200+ ASSERT_TRUE (loader.Load ());
201+
202+ // Test that global endpoint in services section is ignored
203+ auto globalEndpoint = loader.GetGlobalEndpointUrl (" testing" );
204+ ASSERT_EQ (nullptr , globalEndpoint);
205+
206+ // Test that service-specific endpoints return null (no services configured)
207+ auto s3Endpoint = loader.GetServiceEndpointUrl (" testing" , " s3" );
208+ ASSERT_EQ (nullptr , s3Endpoint);
209+ }
210+
211+ TEST_F (ServiceEndpointsConfigFileLoaderTest, TestSourceProfileEndpointIsolation)
212+ {
213+ TempFile configFile (std::ios_base::out | std::ios_base::trunc);
214+ ASSERT_TRUE (configFile.good ());
215+
216+ configFile << " [profile A]\n " ;
217+ configFile << " credential_source = Ec2InstanceMetadata\n " ;
218+ configFile << " endpoint_url = https://profile-a-endpoint.aws/\n " ;
219+ configFile << " \n [profile B]\n " ;
220+ configFile << " source_profile = A\n " ;
221+ configFile << " role_arn = arn:aws:iam::123456789012:role/roleB\n " ;
222+ configFile << " services = profileB\n " ;
223+ configFile << " \n [services profileB]\n " ;
224+ configFile << " ec2 =\n " ;
225+ configFile << " endpoint_url = https://profile-b-ec2-endpoint.aws\n " ;
226+ configFile.flush ();
227+
228+ AWSConfigFileProfileConfigLoader loader (configFile.GetFileName (), true );
229+ ASSERT_TRUE (loader.Load ());
230+
231+ // Test that profile B gets EC2 endpoint from its own services definition
232+ auto ec2Endpoint = loader.GetServiceEndpointUrl (" B" , " ec2" );
233+ ASSERT_NE (nullptr , ec2Endpoint);
234+ ASSERT_STREQ (" https://profile-b-ec2-endpoint.aws" , ec2Endpoint->c_str ());
235+
236+ // Test that profile B has no global endpoint (doesn't inherit from profile A)
237+ auto globalEndpointB = loader.GetGlobalEndpointUrl (" B" );
238+ ASSERT_EQ (nullptr , globalEndpointB);
239+
240+ // Test that profile A still has its own global endpoint
241+ auto globalEndpointA = loader.GetGlobalEndpointUrl (" A" );
242+ ASSERT_NE (nullptr , globalEndpointA);
243+ ASSERT_STREQ (" https://profile-a-endpoint.aws/" , globalEndpointA->c_str ());
244+
245+ // Test that other services in profile B return null (no chaining to profile A)
246+ auto s3Endpoint = loader.GetServiceEndpointUrl (" B" , " s3" );
247+ ASSERT_EQ (nullptr , s3Endpoint);
248+ }
249+ TEST_F (ServiceEndpointsConfigFileLoaderTest, TestIgnoreConfiguredEndpointUrls)
250+ {
251+ TempFile configFile (std::ios_base::out | std::ios_base::trunc);
252+ ASSERT_TRUE (configFile.good ());
253+
254+ configFile << " [profile default]\n " ;
255+ configFile << " ignore_configured_endpoint_urls = true\n " ;
256+ configFile << " endpoint_url = https://should-be-ignored.com\n " ;
257+ configFile << " \n [profile test]\n " ;
258+ configFile << " ignore_configured_endpoint_urls = TRUE\n " ;
259+ configFile << " \n [profile empty]\n " ;
260+ configFile << " ignore_configured_endpoint_urls =\n " ;
261+ configFile.flush ();
262+
263+ AWSConfigFileProfileConfigLoader loader (configFile.GetFileName (), true );
264+ ASSERT_TRUE (loader.Load ());
265+ auto profiles = loader.GetProfiles ();
266+
267+ // Test flag is parsed and stored
268+ ASSERT_STREQ (" true" , profiles[" default" ].GetValue (" ignore_configured_endpoint_urls" ).c_str ());
269+ ASSERT_STREQ (" TRUE" , profiles[" test" ].GetValue (" ignore_configured_endpoint_urls" ).c_str ());
270+ ASSERT_STREQ (" " , profiles[" empty" ].GetValue (" ignore_configured_endpoint_urls" ).c_str ());
271+
272+ // Test absent key returns empty string
273+ TempFile configFile2 (std::ios_base::out | std::ios_base::trunc);
274+ configFile2 << " [profile absent]\n " ;
275+ configFile2 << " region = us-east-1\n " ;
276+ configFile2.flush ();
277+
278+ AWSConfigFileProfileConfigLoader loader2 (configFile2.GetFileName (), true );
279+ ASSERT_TRUE (loader2.Load ());
280+ auto profiles2 = loader2.GetProfiles ();
281+ ASSERT_STREQ (" " , profiles2[" absent" ].GetValue (" ignore_configured_endpoint_urls" ).c_str ());
282+ }
0 commit comments