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.release.config;
20  
21  import java.io.File;
22  import java.io.FileInputStream;
23  import java.io.IOException;
24  import java.io.InputStream;
25  import java.util.Properties;
26  
27  import org.apache.maven.shared.release.PlexusJUnit4TestCase;
28  import org.apache.maven.shared.release.config.ReleaseDescriptorBuilder.BuilderReleaseDescriptor;
29  import org.apache.maven.shared.release.phase.AbstractReleaseTestCase;
30  import org.apache.maven.shared.release.scm.IdentifiedScm;
31  import org.junit.Test;
32  import org.sonatype.plexus.components.sec.dispatcher.SecDispatcher;
33  
34  import static org.junit.Assert.assertEquals;
35  import static org.junit.Assert.assertFalse;
36  import static org.junit.Assert.assertNotEquals;
37  import static org.junit.Assert.assertNotNull;
38  import static org.junit.Assert.assertNull;
39  import static org.junit.Assert.assertTrue;
40  
41  /**
42   * Test the properties store.
43   *
44   * @author <a href="mailto:brett@apache.org">Brett Porter</a>
45   */
46  public class PropertiesReleaseDescriptorStoreTest extends PlexusJUnit4TestCase {
47      private PropertiesReleaseDescriptorStore store;
48  
49      private SecDispatcher secDispatcher;
50  
51      @Override
52      public void setUp() throws Exception {
53          super.setUp();
54          store = (PropertiesReleaseDescriptorStore) lookup(ReleaseDescriptorStore.class, "properties");
55          secDispatcher = lookup(SecDispatcher.class);
56      }
57  
58      @Test
59      public void testReadFromFile() throws ReleaseDescriptorStoreException {
60          File file = getTestFile("target/test-classes/release.properties");
61  
62          ReleaseDescriptor config = store.read(file).build();
63  
64          ReleaseDescriptor expected = createExpectedReleaseConfiguration().build();
65  
66          assertEquals("check matches", expected, config);
67      }
68  
69      @Test
70      public void testReadFromFileUsingWorkingDirectory() throws Exception {
71          ReleaseDescriptorBuilder builder = new ReleaseDescriptorBuilder();
72          builder.setWorkingDirectory(AbstractReleaseTestCase.getPath(getTestFile("target/test-classes")));
73          ReleaseDescriptor config = store.read(builder).build();
74  
75          ReleaseDescriptorBuilder expected = createExpectedReleaseConfiguration();
76          expected.setWorkingDirectory(builder.build().getWorkingDirectory());
77  
78          assertEquals("check matches", expected.build(), config);
79      }
80  
81      @Test
82      public void testReadFromEmptyFile() throws ReleaseDescriptorStoreException {
83          File file = getTestFile("target/test-classes/empty-release.properties");
84  
85          BuilderReleaseDescriptor config = store.read(file).build();
86  
87          assertDefaultReleaseConfiguration(config);
88      }
89  
90      @Test
91      public void testReadMissingFile() throws ReleaseDescriptorStoreException {
92          File file = getTestFile("target/test-classes/no-release.properties");
93  
94          BuilderReleaseDescriptor config = store.read(file).build();
95  
96          assertDefaultReleaseConfiguration(config);
97      }
98  
99      @Test
100     public void testMergeFromEmptyFile() throws ReleaseDescriptorStoreException, IOException {
101         File file = getTestFile("target/test-classes/empty-release.properties");
102 
103         ReleaseDescriptorBuilder mergeDescriptor = createMergeConfiguration();
104         ReleaseDescriptor config = store.read(mergeDescriptor, file).build();
105 
106         assertEquals("Check configurations merged", mergeDescriptor.build(), config);
107     }
108 
109     @Test
110     public void testMergeFromMissingFile() throws ReleaseDescriptorStoreException, IOException {
111         File file = getTestFile("target/test-classes/no-release.properties");
112 
113         ReleaseDescriptorBuilder mergeDescriptor = createMergeConfiguration();
114         ReleaseDescriptor config = store.read(mergeDescriptor, file).build();
115 
116         assertEquals("Check configurations merged", mergeDescriptor.build(), config);
117     }
118 
119     @Test
120     public void testWriteToNewFile() throws Exception {
121         File file = getTestFile("target/test-classes/new-release.properties");
122         file.delete();
123         assertFalse("Check file doesn't exist", file.exists());
124 
125         ReleaseDescriptorBuilder config = createReleaseConfigurationForWriting();
126 
127         store.write(config.build(), file);
128 
129         ReleaseDescriptor rereadDescriptor = store.read(file).build();
130 
131         assertAndAdjustScmPassword(config, rereadDescriptor);
132         assertAndAdjustScmPrivateKeyPassPhrase(config, rereadDescriptor);
133 
134         assertEquals("compare configuration", config.build(), rereadDescriptor);
135     }
136 
137     @Test
138     public void testWriteToWorkingDirectory() throws Exception {
139         File file = getTestFile("target/test-classes/new/release.properties");
140         file.delete();
141         assertFalse("Check file doesn't exist", file.exists());
142         file.getParentFile().mkdirs();
143 
144         ReleaseDescriptorBuilder config = createReleaseConfigurationForWriting();
145         config.setWorkingDirectory(AbstractReleaseTestCase.getPath(file.getParentFile()));
146 
147         store.write(config.build());
148 
149         ReleaseDescriptorBuilder rereadDescriptorBuilder = store.read(file);
150         rereadDescriptorBuilder.setWorkingDirectory(AbstractReleaseTestCase.getPath(file.getParentFile()));
151 
152         assertAndAdjustScmPassword(config, rereadDescriptorBuilder.build());
153         assertAndAdjustScmPrivateKeyPassPhrase(config, rereadDescriptorBuilder.build());
154 
155         assertEquals("compare configuration", config.build(), rereadDescriptorBuilder.build());
156     }
157 
158     @Test
159     public void testWriteToNewFileRequiredOnly() throws ReleaseDescriptorStoreException {
160         File file = getTestFile("target/test-classes/new-release.properties");
161         file.delete();
162         assertFalse("Check file doesn't exist", file.exists());
163 
164         ReleaseDescriptorBuilder config = new ReleaseDescriptorBuilder();
165         config.setCompletedPhase("completed-phase-write");
166         config.setScmSourceUrl("url-write");
167 
168         store.write(config.build(), file);
169 
170         ReleaseDescriptor rereadDescriptor = store.read(file).build();
171 
172         assertEquals("compare configuration", config.build(), rereadDescriptor);
173     }
174 
175     @Test
176     public void testWriteToNewFileDottedIds() throws ReleaseDescriptorStoreException {
177         File file = getTestFile("target/test-classes/new-release.properties");
178         file.delete();
179         assertFalse("Check file doesn't exist", file.exists());
180 
181         ReleaseDescriptorBuilder config = new ReleaseDescriptorBuilder();
182         config.setCompletedPhase("completed-phase-write");
183         config.setScmSourceUrl("url-write");
184 
185         config.addReleaseVersion("group.id:artifact.id", "1.1");
186         config.addDevelopmentVersion("group.id:artifact.id", "1.2-SNAPSHOT");
187 
188         IdentifiedScm scm = new IdentifiedScm();
189         scm.setId("id");
190         scm.setConnection("connection");
191         scm.setDeveloperConnection("devConnection");
192         scm.setTag("tag");
193         scm.setUrl("url");
194         config.addOriginalScmInfo("group.id:artifact.id", scm);
195 
196         store.write(config.build(), file);
197 
198         ReleaseDescriptor rereadDescriptor = store.read(file).build();
199 
200         assertEquals("compare configuration", config.build(), rereadDescriptor);
201     }
202 
203     @Test
204     public void testWriteToNewFileNullMappedScm() throws ReleaseDescriptorStoreException {
205         File file = getTestFile("target/test-classes/new-release.properties");
206         file.delete();
207         assertFalse("Check file doesn't exist", file.exists());
208 
209         ReleaseDescriptorBuilder builder = new ReleaseDescriptorBuilder();
210         builder.setCompletedPhase("completed-phase-write");
211         builder.setScmSourceUrl("url-write");
212 
213         builder.addReleaseVersion("group.id:artifact.id", "1.1");
214         builder.addDevelopmentVersion("group.id:artifact.id", "1.2-SNAPSHOT");
215 
216         builder.addOriginalScmInfo("group.id:artifact.id", null);
217 
218         store.write(builder.build(), file);
219 
220         ReleaseDescriptor rereadDescriptor = store.read(file).build();
221 
222         assertNull("check null scm is mapped correctly", rereadDescriptor.getOriginalScmInfo("group.id:artifact.id"));
223 
224         assertEquals("compare configuration", builder.build(), rereadDescriptor);
225     }
226 
227     @Test
228     public void testOverwriteFile() throws Exception {
229         File file = getTestFile("target/test-classes/rewrite-release.properties");
230         assertTrue("Check file already exists", file.exists());
231 
232         ReleaseDescriptorBuilder config = createReleaseConfigurationForWriting();
233 
234         store.write(config.build(), file);
235 
236         ReleaseDescriptor rereadDescriptor = store.read(file).build();
237 
238         assertAndAdjustScmPassword(config, rereadDescriptor);
239         assertAndAdjustScmPrivateKeyPassPhrase(config, rereadDescriptor);
240 
241         assertEquals("compare configuration", config.build(), rereadDescriptor);
242     }
243 
244     @Test
245     public void testDeleteFile() throws ReleaseDescriptorStoreException, IOException {
246         File file = getTestFile("target/test-classes/delete/release.properties");
247         file.getParentFile().mkdirs();
248         file.createNewFile();
249         assertTrue("Check file already exists", file.exists());
250 
251         ReleaseDescriptorBuilder config = createReleaseConfigurationForWriting();
252         config.setWorkingDirectory(AbstractReleaseTestCase.getPath(file.getParentFile()));
253 
254         store.delete(config.build());
255 
256         assertFalse("Check file already exists", file.exists());
257     }
258 
259     @Test
260     public void testMissingDeleteFile() throws ReleaseDescriptorStoreException, IOException {
261         File file = getTestFile("target/test-classes/delete/release.properties");
262         file.getParentFile().mkdirs();
263         file.delete();
264         assertFalse("Check file already exists", file.exists());
265 
266         ReleaseDescriptorBuilder config = createReleaseConfigurationForWriting();
267         config.setWorkingDirectory(AbstractReleaseTestCase.getPath(file.getParentFile()));
268 
269         store.delete(config.build());
270 
271         assertFalse("Check file already exists", file.exists());
272     }
273 
274     @Test
275     public void testWriteEncryptedProperties() throws Exception {
276         final String scmPassword = "s3cr3t_SCMPASSWORD";
277         final String scmPassPhrase = "s3cr3t_SCMPASSPHRASE";
278 
279         ReleaseDescriptorBuilder config = new ReleaseDescriptorBuilder();
280         config.setCompletedPhase("completed-phase-write");
281         config.setScmSourceUrl("url-write");
282 
283         config.setScmPassword(scmPassword);
284         config.setScmPrivateKeyPassPhrase(scmPassPhrase);
285 
286         File file = getTestFile("target/test-classes/encrypt/release.properties");
287         file.getParentFile().mkdirs();
288 
289         store.write(config.build(), file);
290 
291         Properties persistedProperties = new Properties();
292         try (InputStream is = new FileInputStream(file)) {
293             persistedProperties.load(is);
294         }
295 
296         String persistedPassword = persistedProperties.getProperty("scm.password");
297         assertNotNull(persistedPassword);
298         assertNotEquals(scmPassword, persistedPassword);
299 
300         String persistedPassPhrase = persistedProperties.getProperty("scm.passphrase");
301         assertNotNull(persistedPassPhrase);
302         assertNotEquals(scmPassPhrase, persistedPassPhrase);
303 
304         ReleaseDescriptorBuilder builder = store.read(file);
305         BuilderReleaseDescriptor descriptor = builder.build();
306         assertEquals(scmPassword, descriptor.getScmPassword());
307         assertEquals(scmPassPhrase, descriptor.getScmPrivateKeyPassPhrase());
308     }
309 
310     private ReleaseDescriptorBuilder createReleaseConfigurationForWriting() {
311         ReleaseDescriptorBuilder builder = new ReleaseDescriptorBuilder();
312         builder.setCompletedPhase("completed-phase-write");
313         builder.setCommitByProject(true);
314         builder.setScmSourceUrl("url-write");
315         builder.setScmId("id-write");
316         builder.setScmUsername("username-write");
317         builder.setScmPassword("password-write");
318         builder.setScmPrivateKey("private-key-write");
319         builder.setScmPrivateKeyPassPhrase("passphrase-write");
320         builder.setScmTagBase("tag-base-write");
321         builder.setScmBranchBase("branch-base-write");
322         builder.setScmReleaseLabel("tag-write");
323         builder.setAdditionalArguments("additional-args-write");
324         builder.setPreparationGoals("preparation-goals-write");
325         builder.setCompletionGoals("completion-goals-write");
326         builder.setPomFileName("pom-file-name-write");
327 
328         builder.addReleaseVersion("groupId:artifactId", "1.0");
329         builder.addDevelopmentVersion("groupId:artifactId", "1.1-SNAPSHOT");
330 
331         // The actual kind of string you will get when setting the projectVersionPolicyConfig
332         builder.setProjectVersionPolicyConfig(
333                 "<projectVersionPolicyConfig><foo>bar</foo></projectVersionPolicyConfig>");
334 
335         IdentifiedScm scm = new IdentifiedScm();
336         scm.setId("id-write");
337         scm.setConnection("connection-write");
338         scm.setDeveloperConnection("developerConnection-write");
339         scm.setUrl("url-write");
340         scm.setTag("tag-write");
341         builder.addOriginalScmInfo("groupId:artifactId", scm);
342 
343         scm = new IdentifiedScm();
344         scm.setConnection("connection-write");
345         // omit optional elements
346         builder.addOriginalScmInfo("groupId:subproject1", scm);
347 
348         return builder;
349     }
350 
351     private static void assertDefaultReleaseConfiguration(BuilderReleaseDescriptor config) {
352         assertNull("Expected no completedPhase", config.getCompletedPhase());
353         assertFalse("Expected no commitPerProject", config.isCommitByProject());
354         assertNull("Expected no id", config.getScmId());
355         assertNull("Expected no url", config.getScmSourceUrl());
356         assertNull("Expected no username", config.getScmUsername());
357         assertNull("Expected no password", config.getScmPassword());
358         assertNull("Expected no privateKey", config.getScmPrivateKey());
359         assertNull("Expected no passphrase", config.getScmPrivateKeyPassPhrase());
360         assertNull("Expected no tagBase", config.getScmTagBase());
361         assertNull("Expected no tag", config.getScmReleaseLabel());
362         assertNull("Expected no additional arguments", config.getAdditionalArguments());
363         assertNull("Expected no preparation goals", config.getPreparationGoals());
364         assertNull("Expected no completion goals", config.getCompletionGoals());
365         assertNull("Expected no pom file name", config.getPomFileName());
366 
367         assertNull("Expected no workingDirectory", config.getWorkingDirectory());
368         assertFalse("Expected no generateReleasePoms", config.isGenerateReleasePoms());
369         assertFalse("Expected no useEditMode", config.isScmUseEditMode());
370         assertTrue("Expected default interactive", config.isInteractive());
371         assertFalse("Expected no addScema", config.isAddSchema());
372 
373         for (ReleaseStageVersions versions : config.getProjectVersions().values()) {
374             assertNull("Expected no release version mappings", versions.getRelease());
375             assertNull("Expected no dev version mappings", versions.getDevelopment());
376         }
377         assertTrue("Expected no scm mappings", config.getOriginalScmInfo().isEmpty());
378         assertNotNull("Expected resolved snapshot dependencies map", config.getResolvedSnapshotDependencies());
379     }
380 
381     public ReleaseDescriptorBuilder createMergeConfiguration() throws IOException {
382         ReleaseDescriptorBuilder releaseDescriptor = new ReleaseDescriptorBuilder();
383 
384         releaseDescriptor.setScmSourceUrl("scm-url");
385         releaseDescriptor.setScmUsername("username");
386         // Not setting other optional SCM settings for brevity
387 
388         File workingDir = getTestFile("target/test-working-directory");
389         if (!workingDir.exists()) {
390             assertTrue(
391                     "Failed to create the directory, along with all necessary parent directories", workingDir.mkdirs());
392         }
393 
394         releaseDescriptor.setWorkingDirectory(AbstractReleaseTestCase.getPath(workingDir));
395         // Not setting non-override setting completedPhase
396 
397         return releaseDescriptor;
398     }
399 
400     private void assertAndAdjustScmPassword(ReleaseDescriptorBuilder expected, ReleaseDescriptor original)
401             throws Exception {
402         String expectedPassword = expected.build().getScmPassword();
403         String originalPassword = original.getScmPassword();
404 
405         // encrypting the same password twice doesn't have to be the same result
406         if (expectedPassword != null ? !expectedPassword.equals(originalPassword) : originalPassword != null) {
407             assertEquals(secDispatcher.decrypt(expectedPassword), secDispatcher.decrypt(originalPassword));
408 
409             expected.setScmPassword(originalPassword);
410         }
411         assertEquals(expected.build().getScmPassword(), original.getScmPassword());
412     }
413 
414     private void assertAndAdjustScmPrivateKeyPassPhrase(ReleaseDescriptorBuilder expected, ReleaseDescriptor original)
415             throws Exception {
416         String expectedPassPhrase = expected.build().getScmPrivateKeyPassPhrase();
417         String originalPassPhrase = original.getScmPrivateKeyPassPhrase();
418 
419         // encrypting the same passphrase twice doesn't have to be the same result
420         if (expectedPassPhrase != null ? !expectedPassPhrase.equals(originalPassPhrase) : originalPassPhrase != null) {
421             assertEquals(secDispatcher.decrypt(expectedPassPhrase), secDispatcher.decrypt(originalPassPhrase));
422 
423             expected.setScmPrivateKeyPassPhrase(originalPassPhrase);
424         }
425         assertEquals(expected.build().getScmPrivateKeyPassPhrase(), original.getScmPrivateKeyPassPhrase());
426     }
427 
428     private ReleaseDescriptorBuilder createExpectedReleaseConfiguration() {
429         ReleaseDescriptorBuilder builder = new ReleaseDescriptorBuilder();
430         builder.setCompletedPhase("step1");
431         builder.setCommitByProject(true);
432         builder.setScmId("scm-id");
433         builder.setScmSourceUrl("scm-url");
434         builder.setScmUsername("username");
435         builder.setScmPassword("password");
436         builder.setScmPrivateKey("private-key");
437         builder.setScmPrivateKeyPassPhrase("passphrase");
438         builder.setScmTagBase("tagBase");
439         builder.setScmTagNameFormat("expectedTagNameFormat");
440         builder.setScmBranchBase("branchBase");
441         builder.setScmReleaseLabel("tag");
442         builder.setAdditionalArguments("additional-arguments");
443         builder.setPreparationGoals("preparation-goals");
444         builder.setCompletionGoals("completion-goals");
445         builder.setPomFileName("pom-file-name");
446         builder.setWorkingDirectory(null);
447         builder.setGenerateReleasePoms(false);
448         builder.setScmUseEditMode(false);
449         builder.setInteractive(true);
450         builder.setAddSchema(false);
451         builder.addReleaseVersion("groupId:artifactId1", "2.0");
452         builder.addReleaseVersion("groupId:artifactId2", "3.0");
453         builder.addDevelopmentVersion("groupId:artifactId1", "2.1-SNAPSHOT");
454         builder.addDevelopmentVersion("groupId:artifactId2", "3.0.1-SNAPSHOT");
455         IdentifiedScm scm = new IdentifiedScm();
456         scm.setId("id");
457         scm.setConnection("connection");
458         scm.setDeveloperConnection("developerConnection");
459         scm.setUrl("url");
460         scm.setTag("tag");
461         builder.addOriginalScmInfo("groupId:artifactId1", scm);
462         scm = new IdentifiedScm();
463         scm.setId(null);
464         scm.setConnection("connection2");
465         scm.setUrl("url2");
466         scm.setTag(null);
467         scm.setDeveloperConnection(null);
468         builder.addOriginalScmInfo("groupId:artifactId2", scm);
469         builder.addDependencyReleaseVersion("external:artifactId", "1.0");
470         builder.addDependencyDevelopmentVersion("external:artifactId", "1.1-SNAPSHOT");
471 
472         return builder;
473     }
474 }