@@ -42,7 +42,7 @@ TEST_F(ServiceEndpointsConfigFileLoaderTest, TestServiceSpecificEndpoints)
4242 auto profileIt = profiles.find (" default" );
4343 ASSERT_NE (profiles.end (), profileIt);
4444 const auto & profile = profileIt->second ;
45- auto globalEndpoint = profile.GetEndpointUrl ();
45+ auto globalEndpoint = profile.GetGlobalEndpointUrl ();
4646 ASSERT_TRUE (globalEndpoint.has_value ());
4747 ASSERT_STREQ (" https://global.example.com" , globalEndpoint->c_str ());
4848
@@ -75,7 +75,7 @@ TEST_F(ServiceEndpointsConfigFileLoaderTest, TestServiceSpecificEndpointsOnly)
7575 const auto & profile = profileIt->second ;
7676
7777 // Test that global endpoint is null when not set
78- auto globalEndpoint = profile.GetEndpointUrl ();
78+ auto globalEndpoint = profile.GetGlobalEndpointUrl ();
7979 ASSERT_FALSE (globalEndpoint.has_value ());
8080
8181 // Test services endpoints are parsed correctly
@@ -103,7 +103,7 @@ TEST_F(ServiceEndpointsConfigFileLoaderTest, TestGlobalEndpointOnly)
103103 const auto & profile = profileIt->second ;
104104
105105 // Test global endpoint
106- auto globalEndpoint = profile.GetEndpointUrl ();
106+ auto globalEndpoint = profile.GetGlobalEndpointUrl ();
107107 ASSERT_TRUE (globalEndpoint.has_value ());
108108 ASSERT_STREQ (" https://play.min.io:9000" , globalEndpoint->c_str ());
109109
@@ -140,7 +140,7 @@ TEST_F(ServiceEndpointsConfigFileLoaderTest, TestServiceSpecificAndGlobalEndpoin
140140 ASSERT_EQ (" https://play.min.io:9000" , endpoints.at (" S3" ));
141141
142142 // Test global endpoint
143- auto globalEndpoint = profile.GetEndpointUrl ();
143+ auto globalEndpoint = profile.GetGlobalEndpointUrl ();
144144 ASSERT_TRUE (globalEndpoint.has_value ());
145145 ASSERT_STREQ (" http://localhost:1234" , globalEndpoint->c_str ());
146146}
@@ -194,7 +194,7 @@ TEST_F(ServiceEndpointsConfigFileLoaderTest, TestIgnoreGlobalEndpointInServicesS
194194 const auto & profile = profileIt->second ;
195195
196196 // Test that global endpoint in services section is ignored
197- auto globalEndpoint = profile.GetEndpointUrl ();
197+ auto globalEndpoint = profile.GetGlobalEndpointUrl ();
198198 ASSERT_FALSE (globalEndpoint.has_value ());
199199
200200 // Test that services endpoints are empty (global endpoint_url ignored)
@@ -239,11 +239,11 @@ TEST_F(ServiceEndpointsConfigFileLoaderTest, TestSourceProfileEndpointIsolation)
239239 ASSERT_EQ (" https://profile-b-ec2-endpoint.aws" , endpointsB.at (" EC2" ));
240240
241241 // Test that profile B has no global endpoint (doesn't inherit from profile A)
242- auto globalEndpointB = profileB.GetEndpointUrl ();
242+ auto globalEndpointB = profileB.GetGlobalEndpointUrl ();
243243 ASSERT_FALSE (globalEndpointB.has_value ());
244244
245245 // Test that profile A still has its own global endpoint
246- auto globalEndpointA = profileA.GetEndpointUrl ();
246+ auto globalEndpointA = profileA.GetGlobalEndpointUrl ();
247247 ASSERT_TRUE (globalEndpointA.has_value ());
248248 ASSERT_STREQ (" https://profile-a-endpoint.aws/" , globalEndpointA->c_str ());
249249
@@ -304,4 +304,95 @@ TEST_F(ServiceEndpointsConfigFileLoaderTest, TestMultipleServicesDefinitions)
304304 const auto & endpoints = services.GetEndpoints ();
305305 ASSERT_EQ (1u , endpoints.size ());
306306 ASSERT_EQ (" http://foo.com" , endpoints.at (" S3" ));
307+ }
308+
309+ TEST_F (ServiceEndpointsConfigFileLoaderTest, TestDuplicateGlobalEndpointUrl)
310+ {
311+ TempFile configFile (std::ios_base::out | std::ios_base::trunc);
312+ ASSERT_TRUE (configFile.good ());
313+
314+ configFile << " [profile dev-global]\n " ;
315+ configFile << " endpoint_url = https://play.min.io:9000\n " ;
316+ configFile << " endpoint_url = https://play2.min.io:9000\n " ;
317+ configFile.flush ();
318+
319+ AWSConfigFileProfileConfigLoader loader (configFile.GetFileName (), true );
320+ ASSERT_TRUE (loader.Load ());
321+ auto profiles = loader.GetProfiles ();
322+ auto profileIt = profiles.find (" dev-global" );
323+ ASSERT_NE (profiles.end (), profileIt);
324+ const auto & profile = profileIt->second ;
325+
326+ // Test that last value wins for duplicate global endpoint_url
327+ auto globalEndpoint = profile.GetGlobalEndpointUrl ();
328+ ASSERT_TRUE (globalEndpoint.has_value ());
329+ ASSERT_STREQ (" https://play2.min.io:9000" , globalEndpoint->c_str ());
330+ }
331+
332+ TEST_F (ServiceEndpointsConfigFileLoaderTest, TestDuplicateServiceEndpointUrl)
333+ {
334+ TempFile configFile (std::ios_base::out | std::ios_base::trunc);
335+ ASSERT_TRUE (configFile.good ());
336+
337+ configFile << " [services s3test]\n " ;
338+ configFile << " s3 =\n " ;
339+ configFile << " endpoint_url = https://play.min.io:9000\n " ;
340+ configFile << " s3 =\n " ;
341+ configFile << " endpoint_url = https://play2.min.io:9000\n " ;
342+ configFile << " \n [profile dev]\n " ;
343+ configFile << " services = s3test\n " ;
344+ configFile.flush ();
345+
346+ AWSConfigFileProfileConfigLoader loader (configFile.GetFileName (), true );
347+ ASSERT_TRUE (loader.Load ());
348+ auto profiles = loader.GetProfiles ();
349+ auto profileIt = profiles.find (" dev" );
350+ ASSERT_NE (profiles.end (), profileIt);
351+ const auto & profile = profileIt->second ;
352+
353+ // Test that last value wins for duplicate service endpoint_url
354+ const auto & services = profile.GetServices ();
355+ ASSERT_TRUE (services.IsSet ());
356+ const auto & endpoints = services.GetEndpoints ();
357+ ASSERT_EQ (1u , endpoints.size ());
358+ ASSERT_EQ (" https://play2.min.io:9000" , endpoints.at (" S3" ));
359+ }
360+
361+ TEST_F (ServiceEndpointsConfigFileLoaderTest, TestMixedDuplicateEndpoints)
362+ {
363+ TempFile configFile (std::ios_base::out | std::ios_base::trunc);
364+ ASSERT_TRUE (configFile.good ());
365+
366+ configFile << " [profile dev-mixed]\n " ;
367+ configFile << " endpoint_url = https://global1.example.com\n " ;
368+ configFile << " services = mixed-services\n " ;
369+ configFile << " endpoint_url = https://global2.example.com\n " ;
370+ configFile << " \n [services mixed-services]\n " ;
371+ configFile << " s3 =\n " ;
372+ configFile << " endpoint_url = https://s3-first.example.com\n " ;
373+ configFile << " dynamodb =\n " ;
374+ configFile << " endpoint_url = https://dynamo.example.com\n " ;
375+ configFile << " s3 =\n " ;
376+ configFile << " endpoint_url = https://s3-last.example.com\n " ;
377+ configFile.flush ();
378+
379+ AWSConfigFileProfileConfigLoader loader (configFile.GetFileName (), true );
380+ ASSERT_TRUE (loader.Load ());
381+ auto profiles = loader.GetProfiles ();
382+ auto profileIt = profiles.find (" dev-mixed" );
383+ ASSERT_NE (profiles.end (), profileIt);
384+ const auto & profile = profileIt->second ;
385+
386+ // Test that last global endpoint_url wins
387+ auto globalEndpoint = profile.GetGlobalEndpointUrl ();
388+ ASSERT_TRUE (globalEndpoint.has_value ());
389+ ASSERT_STREQ (" https://global2.example.com" , globalEndpoint->c_str ());
390+
391+ // Test that last service endpoint_url wins, but other services remain
392+ const auto & services = profile.GetServices ();
393+ ASSERT_TRUE (services.IsSet ());
394+ const auto & endpoints = services.GetEndpoints ();
395+ ASSERT_EQ (2u , endpoints.size ());
396+ ASSERT_EQ (" https://s3-last.example.com" , endpoints.at (" S3" ));
397+ ASSERT_EQ (" https://dynamo.example.com" , endpoints.at (" DYNAMODB" ));
307398}
0 commit comments