1 /*
2  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License").
5  * You may not use this file except in compliance with the License.
6  * A copy of the License is located at
7  *
8  *  http://aws.amazon.com/apache2.0
9  *
10  * or in the "license" file accompanying this file. This file is distributed
11  * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12  * express or implied. See the License for the specific language governing
13  * permissions and limitations under the License.
14  */
15 
16 package software.amazon.awssdk.profiles;
17 
18 import static org.assertj.core.api.Assertions.assertThat;
19 import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
20 import static org.assertj.core.api.Assertions.assertThatThrownBy;
21 
22 import java.util.AbstractMap;
23 import java.util.HashMap;
24 import java.util.Map;
25 import java.util.stream.Stream;
26 import org.junit.jupiter.api.Test;
27 import software.amazon.awssdk.utils.StringInputStream;
28 
29 /**
30  * Validate the functionality of {@link ProfileFile}.
31  */
32 public class ProfileFileTest {
33     @Test
emptyFilesHaveNoProfiles()34     public void emptyFilesHaveNoProfiles() {
35         assertThat(configFileProfiles("")).isEmpty();
36     }
37 
38     @Test
emptyProfilesHaveNoProperties()39     public void emptyProfilesHaveNoProperties() {
40         assertThat(configFileProfiles("[profile foo]"))
41             .isEqualTo(profiles(profile("foo")));
42     }
43 
44     @Test
profileDefinitionsMustEndWithBrackets()45     public void profileDefinitionsMustEndWithBrackets() {
46         assertThatThrownBy(() -> configFileProfiles("[profile foo"))
47             .hasMessageContaining("Profile definition must end with ']'");
48     }
49 
50     @Test
profileNamesShouldBeTrimmed()51     public void profileNamesShouldBeTrimmed() {
52         assertThat(configFileProfiles("[profile \tfoo \t]"))
53             .isEqualTo(profiles(profile("foo")));
54     }
55 
56     @Test
tabsCanSeparateProfileNamesFromProfilePrefix()57     public void tabsCanSeparateProfileNamesFromProfilePrefix() {
58         assertThat(configFileProfiles("[profile\tfoo]"))
59             .isEqualTo(profiles(profile("foo")));
60     }
61 
62     @Test
propertiesMustBeDefinedInAProfile()63     public void propertiesMustBeDefinedInAProfile() {
64         assertThatThrownBy(() -> configFileProfiles("name = value"))
65             .hasMessageContaining("Expected a profile definition");
66     }
67 
68     @Test
profilesCanContainProperties()69     public void profilesCanContainProperties() {
70         assertThat(configFileProfiles("[profile foo]\n" +
71                                       "name = value"))
72             .isEqualTo(profiles(profile("foo", property("name", "value"))));
73     }
74 
75     @Test
windowsStyleLineEndingsAreSupported()76     public void windowsStyleLineEndingsAreSupported() {
77         assertThat(configFileProfiles("[profile foo]\r\n" +
78                                       "name = value"))
79             .isEqualTo(profiles(profile("foo", property("name", "value"))));
80     }
81 
82     @Test
equalsSignsAreSupportedInPropertyNames()83     public void equalsSignsAreSupportedInPropertyNames() {
84         assertThat(configFileProfiles("[profile foo]\r\n" +
85                                       "name = val=ue"))
86             .isEqualTo(profiles(profile("foo", property("name", "val=ue"))));
87     }
88 
89     @Test
unicodeCharactersAreSupportedInPropertyValues()90     public void unicodeCharactersAreSupportedInPropertyValues() {
91         assertThat(configFileProfiles("[profile foo]\r\n" +
92                                       "name = \uD83D\uDE02"))
93             .isEqualTo(profiles(profile("foo", property("name", "\uD83D\uDE02"))));
94     }
95 
96     @Test
profilesCanContainMultipleProperties()97     public void profilesCanContainMultipleProperties() {
98         assertThat(configFileProfiles("[profile foo]\n" +
99                                       "name = value\n" +
100                                       "name2 = value2"))
101             .isEqualTo(profiles(profile("foo",
102                                         property("name", "value"),
103                                         property("name2", "value2"))));
104     }
105 
106     @Test
propertyKeysAndValuesAreTrimmed()107     public void propertyKeysAndValuesAreTrimmed() {
108         assertThat(configFileProfiles("[profile foo]\n" +
109                                       "name \t=  \tvalue \t"))
110             .isEqualTo(profiles(profile("foo", property("name", "value"))));
111     }
112 
113     @Test
propertyValuesCanBeEmpty()114     public void propertyValuesCanBeEmpty() {
115         assertThat(configFileProfiles("[profile foo]\n" +
116                                       "name ="))
117             .isEqualTo(profiles(profile("foo", property("name", ""))));
118     }
119 
120     @Test
propertyKeysCannotBeEmpty()121     public void propertyKeysCannotBeEmpty() {
122         assertThatThrownBy(() -> configFileProfiles("[profile foo]\n" +
123                                                     "= value"))
124             .hasMessageContaining("Property did not have a name");
125     }
126 
127     @Test
propertyDefinitionsMustContainAnEqualsSign()128     public void propertyDefinitionsMustContainAnEqualsSign() {
129         assertThatThrownBy(() -> configFileProfiles("[profile foo]\n" +
130                                                     "key : value"))
131             .hasMessageContaining("Expected an '=' sign defining a property");
132     }
133 
134     @Test
multipleProfilesCanBeEmpty()135     public void multipleProfilesCanBeEmpty() {
136         assertThat(configFileProfiles("[profile foo]\n" +
137                                       "[profile bar]"))
138             .isEqualTo(profiles(profile("foo"),
139                                 profile("bar")));
140     }
141 
142     @Test
multipleProfilesCanHaveProperties()143     public void multipleProfilesCanHaveProperties() {
144         assertThat(configFileProfiles("[profile foo]\n" +
145                                       "name = value\n" +
146                                       "[profile bar]\n" +
147                                       "name2 = value2"))
148             .isEqualTo(profiles(profile("foo", property("name", "value")),
149                                 profile("bar", property("name2", "value2"))));
150     }
151 
152     @Test
blankLinesAreIgnored()153     public void blankLinesAreIgnored() {
154         assertThat(configFileProfiles("\t \n" +
155                                       "[profile foo]\n" +
156                                       "\t\n" +
157                                       " \n" +
158                                       "name = value\n" +
159                                       "\t \n" +
160                                       "[profile bar]\n" +
161                                       " \t"))
162             .isEqualTo(profiles(profile("foo", property("name", "value")),
163                                 profile("bar")));
164     }
165 
166     @Test
poundSignCommentsAreIgnored()167     public void poundSignCommentsAreIgnored() {
168         assertThat(configFileProfiles("# Comment\n" +
169                                       "[profile foo] # Comment\n" +
170                                       "name = value # Comment with # sign"))
171             .isEqualTo(profiles(profile("foo", property("name", "value"))));
172     }
173 
174     @Test
semicolonCommentsAreIgnored()175     public void semicolonCommentsAreIgnored() {
176         assertThat(configFileProfiles("; Comment\n" +
177                                       "[profile foo] ; Comment\n" +
178                                       "name = value ; Comment with ; sign"))
179             .isEqualTo(profiles(profile("foo", property("name", "value"))));
180     }
181 
182     @Test
commentTypesCanBeUsedTogether()183     public void commentTypesCanBeUsedTogether() {
184         assertThat(configFileProfiles("# Comment\n" +
185                                       "[profile foo] ; Comment\n" +
186                                       "name = value # Comment with ; sign"))
187             .isEqualTo(profiles(profile("foo", property("name", "value"))));
188     }
189 
190     @Test
commentsCanBeEmpty()191     public void commentsCanBeEmpty() {
192         assertThat(configFileProfiles(";\n" +
193                                       "[profile foo];\n" +
194                                       "name = value ;\n"))
195             .isEqualTo(profiles(profile("foo", property("name", "value"))));
196     }
197 
198     @Test
commentsCanBeAdjacentToProfileNames()199     public void commentsCanBeAdjacentToProfileNames() {
200         assertThat(configFileProfiles("[profile foo]; Adjacent semicolons\n" +
201                                       "[profile bar]# Adjacent pound signs"))
202             .isEqualTo(profiles(profile("foo"),
203                                 profile("bar")));
204     }
205 
206     @Test
commentsAdjacentToValuesAreIncludedInTheValue()207     public void commentsAdjacentToValuesAreIncludedInTheValue() {
208         assertThat(configFileProfiles("[profile foo]\n" +
209                                       "name = value; Adjacent semicolons\n" +
210                                       "name2 = value# Adjacent pound signs"))
211             .isEqualTo(profiles(profile("foo",
212                                         property("name", "value; Adjacent semicolons"),
213                                         property("name2", "value# Adjacent pound signs"))));
214     }
215 
216     @Test
propertyValuesCanBeContinuedOnTheNextLine()217     public void propertyValuesCanBeContinuedOnTheNextLine() {
218         assertThat(configFileProfiles("[profile foo]\n" +
219                                       "name = value\n" +
220                                       " -continued"))
221             .isEqualTo(profiles(profile("foo",
222                                         property("name", "value\n-continued"))));
223     }
224 
225     @Test
propertyValuesCanBeContinuedAcrossMultipleLines()226     public void propertyValuesCanBeContinuedAcrossMultipleLines() {
227         assertThat(configFileProfiles("[profile foo]\n" +
228                                       "name = value\n" +
229                                       " -continued\n" +
230                                       " -and-continued"))
231             .isEqualTo(profiles(profile("foo",
232                                         property("name", "value\n-continued\n-and-continued"))));
233     }
234 
235     @Test
continuationValuesIncludeSemicolonComments()236     public void continuationValuesIncludeSemicolonComments() {
237         assertThat(configFileProfiles("[profile foo]\n" +
238                                       "name = value\n" +
239                                       " -continued ; Comment"))
240             .isEqualTo(profiles(profile("foo",
241                                         property("name", "value\n-continued ; Comment"))));
242     }
243 
244     @Test
continuationsCannotBeUsedOutsideOfAProfile()245     public void continuationsCannotBeUsedOutsideOfAProfile() {
246         assertThatThrownBy(() -> configFileProfiles(" -continued"))
247             .hasMessageContaining("Expected a profile or property definition");
248     }
249 
250     @Test
continuationsCannotBeUsedOutsideOfAProperty()251     public void continuationsCannotBeUsedOutsideOfAProperty() {
252         assertThatThrownBy(() -> configFileProfiles("[profile foo]\n" +
253                                                     " -continued"))
254             .hasMessageContaining("Expected a profile or property definition");
255     }
256 
257     @Test
continuationsResetWithProfileDefinition()258     public void continuationsResetWithProfileDefinition() {
259         assertThatThrownBy(() -> configFileProfiles("[profile foo]\n" +
260                                                     "name = value\n" +
261                                                     "[profile foo]\n" +
262                                                     " -continued"))
263             .hasMessageContaining("Expected a profile or property definition");
264     }
265 
266     @Test
duplicateProfilesInTheSameFileMergeProperties()267     public void duplicateProfilesInTheSameFileMergeProperties() {
268         assertThat(configFileProfiles("[profile foo]\n" +
269                                       "name = value\n" +
270                                       "[profile foo]\n" +
271                                       "name2 = value2"))
272             .isEqualTo(profiles(profile("foo",
273                                         property("name", "value"),
274                                         property("name2", "value2"))));
275     }
276 
277     @Test
duplicatePropertiesInAProfileUseTheLastOneDefined()278     public void duplicatePropertiesInAProfileUseTheLastOneDefined() {
279         assertThat(configFileProfiles("[profile foo]\n" +
280                                       "name = value\n" +
281                                       "name = value2"))
282             .isEqualTo(profiles(profile("foo", property("name", "value2"))));
283     }
284 
285     @Test
duplicatePropertiesInDuplicateProfilesUseTheLastOneDefined()286     public void duplicatePropertiesInDuplicateProfilesUseTheLastOneDefined() {
287         assertThat(configFileProfiles("[profile foo]\n" +
288                                       "name = value\n" +
289                                       "[profile foo]\n" +
290                                       "name = value2"))
291             .isEqualTo(profiles(profile("foo", property("name", "value2"))));
292     }
293 
294     @Test
defaultProfileWithProfilePrefixOverridesDefaultProfileWithoutPrefixWhenPrefixedIsFirst()295     public void defaultProfileWithProfilePrefixOverridesDefaultProfileWithoutPrefixWhenPrefixedIsFirst() {
296         assertThat(configFileProfiles("[profile default]\n" +
297                                       "name = value\n" +
298                                       "[default]\n" +
299                                       "name2 = value2"))
300             .isEqualTo(profiles(profile("default", property("name", "value"))));
301     }
302 
303     @Test
defaultProfileWithProfilePrefixOverridesDefaultProfileWithoutPrefixWhenPrefixedIsLast()304     public void defaultProfileWithProfilePrefixOverridesDefaultProfileWithoutPrefixWhenPrefixedIsLast() {
305         assertThat(configFileProfiles("[default]\n" +
306                                       "name2 = value2\n" +
307                                       "[profile default]\n" +
308                                       "name = value"))
309             .isEqualTo(profiles(profile("default", property("name", "value"))));
310     }
311 
312     @Test
invalidProfilesNamesAreIgnored()313     public void invalidProfilesNamesAreIgnored() {
314         assertThat(aggregateFileProfiles("[profile in valid]\n" +
315                                          "name = value\n",
316                                          "[in valid 2]\n" +
317                                          "name2 = value2"))
318             .isEqualTo(profiles());
319     }
320 
321     @Test
invalidPropertyNamesAreIgnored()322     public void invalidPropertyNamesAreIgnored() {
323         assertThat(configFileProfiles("[profile foo]\n" +
324                                       "in valid = value"))
325             .isEqualTo(profiles(profile("foo")));
326     }
327 
328     @Test
allValidProfileNameCharactersAreSupported()329     public void allValidProfileNameCharactersAreSupported() {
330         assertThat(configFileProfiles("[profile ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_./%@:+]"))
331             .isEqualTo(profiles(profile("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_./%@:+")));
332     }
333 
334     @Test
allValidPropertyNameCharactersAreSupported()335     public void allValidPropertyNameCharactersAreSupported() {
336         assertThat(configFileProfiles("[profile foo]\nABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_./%@:+ = value"))
337             .isEqualTo(profiles(profile("foo", property("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_./%@:+",
338                                                         "value"))));
339     }
340 
341     @Test
propertiesCanHaveSubProperties()342     public void propertiesCanHaveSubProperties() {
343         assertThat(configFileProfiles("[profile foo]\n" +
344                                       "s3 =\n" +
345                                       " name = value"))
346             .isEqualTo(profiles(profile("foo", property("s3", "\nname = value"))));
347     }
348 
349     @Test
invalidSubPropertiesCauseAnError()350     public void invalidSubPropertiesCauseAnError() {
351         assertThatThrownBy(() -> configFileProfiles("[profile foo]\n" +
352                                                     "s3 =\n" +
353                                                     " invalid"))
354             .hasMessageContaining("Expected an '=' sign defining a property");
355     }
356 
357     @Test
subPropertiesCanHaveEmptyValues()358     public void subPropertiesCanHaveEmptyValues() {
359         assertThat(configFileProfiles("[profile foo]\n" +
360                                       "s3 =\n" +
361                                       " name ="))
362             .isEqualTo(profiles(profile("foo", property("s3", "\nname ="))));
363     }
364 
365     @Test
invalidSubPropertiesCannotHaveEmptyNames()366     public void invalidSubPropertiesCannotHaveEmptyNames() {
367         assertThatThrownBy(() -> configFileProfiles("[profile foo]\n" +
368                                                     "s3 =\n" +
369                                                     " = value"))
370             .hasMessageContaining("Property did not have a name");
371     }
372 
373     @Test
subPropertiesCanHaveInvalidNames()374     public void subPropertiesCanHaveInvalidNames() {
375         assertThat(configFileProfiles("[profile foo]\n" +
376                                       "s3 =\n" +
377                                       " in valid = value"))
378             .isEqualTo(profiles(profile("foo", property("s3", "\nin valid = value"))));
379     }
380 
381     @Test
subPropertiesCanHaveBlankLines()382     public void subPropertiesCanHaveBlankLines() {
383         assertThat(configFileProfiles("[profile foo]\n" +
384                                       "s3 =\n" +
385                                       " name = value\n" +
386                                       "\t \n" +
387                                       " name2 = value2"))
388             .isEqualTo(profiles(profile("foo", property("s3", "\nname = value\nname2 = value2"))));
389     }
390 
391     @Test
profilesDuplicatedInMultipleFilesAreMerged()392     public void profilesDuplicatedInMultipleFilesAreMerged() {
393         assertThat(aggregateFileProfiles("[profile foo]\n" +
394                                          "name = value\n",
395                                          "[foo]\n" +
396                                          "name2 = value2"))
397             .isEqualTo(profiles(profile("foo",
398                                         property("name", "value"),
399                                         property("name2", "value2"))));
400     }
401 
402     @Test
defaultProfilesWithMixedPrefixesInConfigFileIgnoreOneWithoutPrefixWhenMerging()403     public void defaultProfilesWithMixedPrefixesInConfigFileIgnoreOneWithoutPrefixWhenMerging() {
404         assertThat(configFileProfiles("[profile default]\n" +
405                                       "name = value\n" +
406                                       "[default]\n" +
407                                       "name2 = value2\n" +
408                                       "[profile default]\n" +
409                                       "name3 = value3"))
410             .isEqualTo(profiles(profile("default",
411                                         property("name", "value"),
412                                         property("name3", "value3"))));
413     }
414 
415     @Test
duplicatePropertiesBetweenFilesUsesCredentialsProperty()416     public void duplicatePropertiesBetweenFilesUsesCredentialsProperty() {
417         assertThat(aggregateFileProfiles("[profile foo]\n" +
418                                          "name = value",
419                                          "[foo]\n" +
420                                          "name = value2"))
421             .isEqualTo(profiles(profile("foo", property("name", "value2"))));
422     }
423 
424     @Test
configProfilesWithoutPrefixAreIgnored()425     public void configProfilesWithoutPrefixAreIgnored() {
426         assertThat(configFileProfiles("[foo]\n" +
427                                       "name = value"))
428             .isEqualTo(profiles());
429     }
430 
431     @Test
credentialsProfilesWithPrefixAreIgnored()432     public void credentialsProfilesWithPrefixAreIgnored() {
433         assertThat(credentialFileProfiles("[profile foo]\n" +
434                                           "name = value"))
435             .isEqualTo(profiles());
436     }
437 
438     @Test
sectionsInCredentialsFilesIsIgnored()439     public void sectionsInCredentialsFilesIsIgnored() {
440 
441         String ASSUME_ROLE_PROFILE =
442             "[test]\n"
443             + "region = us-west-1\n"
444             + "credential_source = Environment\n"
445             + "sso_session = session\n"
446             + "role_arn = some_Arn\n"
447             + "[sso-session session]\n"
448             + "sso_region = us-west-1\n"
449             + "start_url = someUrl\n";
450 
451         ProfileFile profileFile = credentialFile(ASSUME_ROLE_PROFILE);
452         Map<String, Profile> profileMap = profileFile.profiles();
453         assertThat(profileMap)
454             .isEqualTo(profiles(profile("test", property("region", "us-west-1")
455                 , property("credential_source", "Environment")
456                 , property("sso_session", "session"),
457                                         property("role_arn", "some_Arn"))));
458 
459         ;
460         assertThat(profileFile.getSection("sso-session", "session")).isNotPresent();
461     }
462 
463     @Test
invalidSectionNamesAreNotAddedInSectionListOfProfileFiles()464     public void invalidSectionNamesAreNotAddedInSectionListOfProfileFiles() {
465 
466         ProfileFile aggregatedProfileFiles = ProfileFile.aggregator()
467                                                         .addFile(credentialFile("[in valid 2]\n"
468                                                                                 + "name2 = value2"))
469                                                         .addFile(configFile("[profile validSection]\n"
470                                                                             + "sso_session = validSso\n"
471                                                                             + "[sso-session validSso]\n"
472                                                                             + "start_url = Valid-url\n"))
473                                                         .addFile(configFile("[profile section]\n"
474                                                                             + "sso_session = sso invalid\n"
475                                                                             + "[sso-session sso invalid]\n"
476                                                                             + "start_url = url\n"))
477                                                         .build();
478 
479         assertThat(aggregatedProfileFiles.profiles())
480             .isEqualTo(profiles(profile("section", property("sso_session", "sso invalid")),
481                        profile("validSection", property("sso_session", "validSso"))));
482 
483         assertThat(aggregatedProfileFiles.getSection("sso-session", "sso")).isNotPresent();
484         assertThat(aggregatedProfileFiles.getSection("sso-session", "sso invalid")).isNotPresent();
485         assertThat(aggregatedProfileFiles.getSection("sso-session", "validSso").get())
486             .isEqualTo(profile("validSso", property("start_url", "Valid-url")));
487     }
488 
489     @Test
defaultSessionNameIsNotSupported_when_session_doesNot_exist()490     public void defaultSessionNameIsNotSupported_when_session_doesNot_exist() {
491 
492         String nonExistentSessionName = "nonExistentSession";
493         ProfileFile aggregatedProfileFiles = ProfileFile.aggregator()
494                                                         .addFile(configFile("[profile validSection]\n"
495                                                                             + "sso_session = " + nonExistentSessionName + "\n"
496                                                                             + "[profile " + nonExistentSessionName + "]\n"
497                                                                             + "start_url = Valid-url-2\n"
498                                                                             + "[sso-session default]\n"
499                                                                             + "start_url = Valid-url\n"))
500                                                         .build();
501 
502         assertThat(aggregatedProfileFiles.profiles())
503             .isEqualTo(profiles(profile("validSection", property("sso_session",  nonExistentSessionName)),
504                                 profile(nonExistentSessionName, property("start_url", "Valid-url-2"))));
505 
506         assertThat(aggregatedProfileFiles.getSection("sso-session", nonExistentSessionName)).isNotPresent();
507     }
508 
509     @Test
sessionIsNotAdjacentToProfile()510     public void sessionIsNotAdjacentToProfile() {
511 
512         ProfileFile aggregatedProfileFiles = ProfileFile.aggregator()
513                                                         .addFile(configFile("[profile profile1]\n"
514                                                                             + "sso_session = sso-token1\n"
515                                                                             + "[profile profile2]\n"
516                                                                             + "region  = us-west-2\n"
517                                                                             + "[default]\n"
518                                                                             + "default_property = property1\n"))
519                                                         .addFile(configFile("[sso-session sso-token1]\n"
520                                                                             + "start_url = startUrl1\n"
521                                                                             + "[profile profile3]\n"
522                                                                             + "region = us-east-1\n")
523                                                         ).build();
524 
525         assertThat(aggregatedProfileFiles.profiles())
526             .isEqualTo(profiles(profile("profile1", property("sso_session",  "sso-token1")),
527                                 profile("default", property("default_property", "property1")),
528                                 profile("profile2", property("region", "us-west-2")),
529                                 profile("profile3", property("region", "us-east-1"))
530 
531             ));
532 
533         assertThat(aggregatedProfileFiles.getSection("sso-session", "sso-token1")).isPresent();
534         assertThat(aggregatedProfileFiles.getSection("sso-session", "sso-token1").get()).isEqualTo(
535             profile("sso-token1", property("start_url", "startUrl1"))         );
536     }
537 
538     @Test
exceptionIsThrown_when_sectionDoesnotHaveASquareBracket()539     public void exceptionIsThrown_when_sectionDoesnotHaveASquareBracket() {
540 
541 
542         assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(
543             () -> ProfileFile.aggregator()
544                              .addFile(configFile("[profile profile1]\n"
545                                                  + "sso_session = sso-token1\n"
546                                                  + "[sso-session sso-token1\n"
547                                                  + "start_url = startUrl1\n")
548                              ).build()).withMessageContaining("Section definition must end with ']' on line 3");
549 
550     }
551 
552     @Test
loadingDefaultProfileFileWorks()553     public void loadingDefaultProfileFileWorks() {
554         ProfileFile.defaultProfileFile();
555     }
556 
557     @Test
returnsEmptyMap_when_AwsFilesDoNotExist()558     public void returnsEmptyMap_when_AwsFilesDoNotExist() {
559         ProfileFile missingProfile = ProfileFile.aggregator()
560                                                 .build();
561 
562         assertThat(missingProfile.profiles()).isEmpty();
563         assertThat(missingProfile.profiles()).isInstanceOf(Map.class);
564     }
565 
configFile(String configFile)566     private ProfileFile configFile(String configFile) {
567         return ProfileFile.builder()
568                           .content(new StringInputStream(configFile))
569                           .type(ProfileFile.Type.CONFIGURATION)
570                           .build();
571     }
572 
configFileProfiles(String configFile)573     private Map<String, Profile> configFileProfiles(String configFile) {
574         return configFile(configFile).profiles();
575     }
576 
credentialFile(String credentialFile)577     private ProfileFile credentialFile(String credentialFile) {
578         return ProfileFile.builder()
579                           .content(new StringInputStream(credentialFile))
580                           .type(ProfileFile.Type.CREDENTIALS)
581                           .build();
582     }
583 
credentialFileProfiles(String credentialFile)584     private Map<String, Profile> credentialFileProfiles(String credentialFile) {
585         return credentialFile(credentialFile).profiles();
586     }
587 
aggregateFileProfiles(String configFile, String credentialFile)588     private Map<String, Profile> aggregateFileProfiles(String configFile, String credentialFile) {
589         return ProfileFile.aggregator()
590                           .addFile(credentialFile(credentialFile))
591                           .addFile(configFile(configFile))
592                           .build()
593                           .profiles();
594     }
595 
profiles(Profile... profiles)596     private Map<String, Profile> profiles(Profile... profiles) {
597         Map<String, Profile> result = new HashMap<>();
598         Stream.of(profiles).forEach(p -> result.put(p.name(), p));
599         return result;
600     }
601 
602     @SafeVarargs
profile(String name, Map.Entry<String, String>... properties)603     private final Profile profile(String name, Map.Entry<String, String>... properties) {
604         Map<String, String> propertiesMap = new HashMap<>();
605         Stream.of(properties).forEach(p -> propertiesMap.put(p.getKey(), p.getValue()));
606         return Profile.builder().name(name).properties(propertiesMap).build();
607     }
608 
property(String name, String value)609     private Map.Entry<String, String> property(String name, String value) {
610         return new AbstractMap.SimpleImmutableEntry<>(name, value);
611     }
612 }
613