View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.shared.filtering;
20  
21  import java.io.IOException;
22  import java.io.Writer;
23  import java.nio.file.Files;
24  import java.nio.file.Path;
25  import java.nio.file.Paths;
26  import java.util.List;
27  import java.util.Properties;
28  
29  import org.apache.maven.api.di.testing.MavenDITest;
30  import org.junit.jupiter.api.Test;
31  import org.mockito.ArgumentCaptor;
32  import org.slf4j.Logger;
33  
34  import static org.apache.maven.api.di.testing.MavenDIExtension.getBasedir;
35  import static org.junit.jupiter.api.Assertions.assertEquals;
36  import static org.junit.jupiter.api.Assertions.assertFalse;
37  import static org.junit.jupiter.api.Assertions.assertThrows;
38  import static org.junit.jupiter.api.Assertions.assertTrue;
39  import static org.mockito.Mockito.mock;
40  import static org.mockito.Mockito.times;
41  import static org.mockito.Mockito.verify;
42  
43  /**
44   * @author Olivier Lamy
45   * @since 1.0-beta-1
46   */
47  @MavenDITest
48  public class PropertyUtilsTest {
49      private static Path testDirectory = Paths.get(getBasedir(), "target/test-classes/");
50  
51      @Test
52      public void testBasic() throws Exception {
53          Path basicProp = testDirectory.resolve("basic.properties");
54  
55          Files.deleteIfExists(basicProp);
56  
57          try (Writer writer = Files.newBufferedWriter(basicProp)) {
58              writer.write("ghost=${non_existent}\n");
59              writer.write("key=${untat_na_damgo}\n");
60              writer.write("untat_na_damgo=gani_man\n");
61              writer.flush();
62          }
63  
64          Properties prop = PropertyUtils.loadPropertyFile(basicProp, false, false);
65          assertEquals("gani_man", prop.getProperty("key"));
66          assertEquals("${non_existent}", prop.getProperty("ghost"));
67      }
68  
69      @Test
70      public void testSystemProperties() throws Exception {
71          Path systemProp = testDirectory.resolve("system.properties");
72  
73          Files.deleteIfExists(systemProp);
74  
75          try (Writer writer = Files.newBufferedWriter(systemProp)) {
76              writer.write("key=${user.dir}");
77              writer.flush();
78          }
79  
80          Properties prop = PropertyUtils.loadPropertyFile(systemProp, false, true);
81          assertEquals(prop.getProperty("key"), System.getProperty("user.dir"));
82      }
83  
84      @Test
85      public void testException() throws Exception {
86          Path nonExistent = testDirectory.resolve("not_existent_file");
87  
88          assertFalse(Files.exists(nonExistent), "property file exist: " + nonExistent);
89  
90          assertThrows(Exception.class, () -> PropertyUtils.loadPropertyFile(nonExistent, true, false));
91      }
92  
93      @Test
94      public void testloadpropertiesFile() throws Exception {
95          Path propertyFile = Paths.get(getBasedir() + "/src/test/units-files/propertyutils-test.properties");
96          Properties baseProps = new Properties();
97          baseProps.put("pom.version", "realVersion");
98  
99          Properties interpolated = PropertyUtils.loadPropertyFile(propertyFile, baseProps);
100         assertEquals("realVersion", interpolated.get("version"));
101         assertEquals("${foo}", interpolated.get("foo"));
102         assertEquals("realVersion", interpolated.get("bar"));
103         assertEquals("none filtered", interpolated.get("none"));
104     }
105 
106     /**
107      * Test case to reproduce MSHARED-417
108      *
109      * @throws IOException if problem writing file
110      */
111     @Test
112     public void testCircularReferences() throws IOException {
113         Path basicProp = testDirectory.resolve("circular.properties");
114 
115         Files.deleteIfExists(basicProp);
116 
117         try (Writer writer = Files.newBufferedWriter(basicProp)) {
118             writer.write("test=${test2}\n");
119             writer.write("test2=${test2}\n");
120             writer.flush();
121         }
122 
123         Logger logger = mock(Logger.class);
124 
125         Properties prop = PropertyUtils.loadPropertyFile(basicProp, null, logger);
126         assertEquals("${test2}", prop.getProperty("test"));
127         assertEquals("${test2}", prop.getProperty("test2"));
128         assertWarn(
129                 logger,
130                 "Circular reference between properties detected: test2 => test2",
131                 "Circular reference between properties detected: test => test2 => test2");
132     }
133 
134     /**
135      * Test case to reproduce MSHARED-417
136      *
137      * @throws IOException if problem writing file
138      */
139     @Test
140     public void testCircularReferences3Vars() throws IOException {
141         Path basicProp = testDirectory.resolve("circular.properties");
142 
143         Files.deleteIfExists(basicProp);
144 
145         try (Writer writer = Files.newBufferedWriter(basicProp)) {
146             writer.write("test=${test2}\n");
147             writer.write("test2=${test3}\n");
148             writer.write("test3=${test}\n");
149             writer.flush();
150         }
151 
152         Logger logger = mock(Logger.class);
153 
154         Properties prop = PropertyUtils.loadPropertyFile(basicProp, null, logger);
155         assertEquals("${test2}", prop.getProperty("test"));
156         assertEquals("${test3}", prop.getProperty("test2"));
157         assertEquals("${test}", prop.getProperty("test3"));
158         assertWarn(
159                 logger,
160                 "Circular reference between properties detected: test3 => test => test2 => test3",
161                 "Circular reference between properties detected: test2 => test3 => test => test2",
162                 "Circular reference between properties detected: test => test2 => test3 => test");
163     }
164 
165     private void assertWarn(Logger mock, String... expected) {
166         ArgumentCaptor<String> argument = ArgumentCaptor.forClass(String.class);
167         verify(mock, times(expected.length)).warn(argument.capture());
168         List<String> messages = argument.getAllValues();
169         for (String str : expected) {
170             assertTrue(messages.contains(str));
171         }
172     }
173 }