1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.wrapper;
20
21 import java.io.BufferedWriter;
22 import java.io.File;
23 import java.io.IOException;
24 import java.io.OutputStream;
25 import java.net.URI;
26 import java.net.URISyntaxException;
27 import java.net.URL;
28 import java.nio.charset.StandardCharsets;
29 import java.nio.file.FileVisitResult;
30 import java.nio.file.Files;
31 import java.nio.file.Path;
32 import java.nio.file.Paths;
33 import java.nio.file.SimpleFileVisitor;
34 import java.nio.file.attribute.BasicFileAttributes;
35 import java.nio.file.attribute.FileTime;
36 import java.util.jar.JarOutputStream;
37 import java.util.jar.Manifest;
38 import java.util.zip.ZipEntry;
39 import java.util.zip.ZipException;
40 import java.util.zip.ZipOutputStream;
41
42 import org.junit.jupiter.api.BeforeEach;
43 import org.junit.jupiter.api.Test;
44 import org.junit.jupiter.api.io.TempDir;
45
46 import static org.junit.jupiter.api.Assertions.assertEquals;
47 import static org.junit.jupiter.api.Assertions.assertFalse;
48 import static org.junit.jupiter.api.Assertions.assertTrue;
49 import static org.junit.jupiter.api.Assertions.fail;
50 import static org.mockito.Mockito.mock;
51 import static org.mockito.Mockito.when;
52
53
54
55
56 public class InstallerTest {
57 @TempDir
58 private File tempFolder;
59
60 private Path testDir;
61
62 private Installer install;
63
64 private Path distributionDir;
65
66 private Path zipStore;
67
68 private Path mavenHomeDir;
69
70 private Path zipDestination;
71
72 private WrapperConfiguration configuration = new WrapperConfiguration();
73
74 private Downloader download;
75
76 private Verifier verifier;
77
78 private PathAssembler pathAssembler;
79
80 private PathAssembler.LocalDistribution localDistribution;
81
82 @BeforeEach
83 void setup() throws Exception {
84 testDir = tempFolder.toPath();
85
86 configuration.setZipBase(PathAssembler.PROJECT_STRING);
87 configuration.setZipPath(Paths.get("someZipPath"));
88 configuration.setDistributionBase(PathAssembler.MAVEN_USER_HOME_STRING);
89 configuration.setDistributionPath(Paths.get("someDistPath"));
90 configuration.setDistribution(new URI("http://server/maven-0.9.zip"));
91 configuration.setAlwaysDownload(false);
92 configuration.setAlwaysUnpack(false);
93 configuration.setDistributionSha256Sum("");
94 distributionDir = testDir.resolve("someDistPath");
95 mavenHomeDir = distributionDir.resolve("maven-0.9");
96 zipStore = testDir.resolve("zips");
97 zipDestination = zipStore.resolve("maven-0.9.zip");
98
99 download = mock(Downloader.class);
100 verifier = mock(Verifier.class);
101 pathAssembler = mock(PathAssembler.class);
102 localDistribution = mock(PathAssembler.LocalDistribution.class);
103
104 when(localDistribution.getZipFile()).thenReturn(zipDestination);
105 when(localDistribution.getDistributionDir()).thenReturn(distributionDir);
106 when(pathAssembler.getDistribution(configuration)).thenReturn(localDistribution);
107
108 install = new Installer(download, verifier, pathAssembler);
109 }
110
111 private void createTestZip(Path zipDestination) throws Exception {
112 Path explodedZipDir = testDir.resolve("explodedZip");
113 Files.createDirectories(explodedZipDir);
114 Files.createDirectories(zipDestination.getParent());
115 Path mavenScript = explodedZipDir.resolve("maven-0.9/bin/mvn");
116 Path mavenLib = explodedZipDir.resolve("maven-0.9/lib/maven-core-0.9.jar");
117 Files.createDirectories(mavenScript.getParent());
118 Files.createDirectories(mavenLib.getParent());
119 try (BufferedWriter writer = Files.newBufferedWriter(mavenScript, StandardCharsets.UTF_8)) {
120 writer.write("something");
121 }
122 try (OutputStream os = Files.newOutputStream(mavenLib);
123 JarOutputStream jar = new JarOutputStream(os, new Manifest())) {
124 jar.putNextEntry(new ZipEntry("test"));
125 jar.closeEntry();
126 }
127
128 zipTo(explodedZipDir, zipDestination);
129 }
130
131 public void testCreateDist() throws Exception {
132 Path homeDir = install.createDist(configuration);
133
134 assertEquals(mavenHomeDir, homeDir);
135 assertTrue(Files.isDirectory(homeDir));
136 assertTrue(Files.exists(homeDir.resolve("bin/mvn")));
137 assertTrue(Files.exists(zipDestination));
138
139 assertEquals(localDistribution, pathAssembler.getDistribution(configuration));
140 assertEquals(distributionDir, localDistribution.getDistributionDir());
141 assertEquals(zipDestination, localDistribution.getZipFile());
142
143
144
145 }
146
147 @Test
148 void testCreateDistWithExistingDistribution() throws Exception {
149
150 createTestZip(zipDestination);
151 Files.createDirectories(mavenHomeDir);
152 Path someFile = mavenHomeDir.resolve("some-file");
153 touchFile(someFile);
154
155 Path homeDir = install.createDist(configuration);
156
157 assertEquals(mavenHomeDir, homeDir);
158 assertTrue(Files.isDirectory(mavenHomeDir));
159 assertTrue(Files.exists(homeDir.resolve("some-file")));
160 assertTrue(Files.exists(zipDestination));
161
162 assertEquals(localDistribution, pathAssembler.getDistribution(configuration));
163 assertEquals(distributionDir, localDistribution.getDistributionDir());
164 assertEquals(zipDestination, localDistribution.getZipFile());
165 }
166
167 @Test
168 void testCreateDistWithExistingDistAndZipAndAlwaysUnpackTrue() throws Exception {
169
170 createTestZip(zipDestination);
171 Files.createDirectories(mavenHomeDir);
172 Path garbage = mavenHomeDir.resolve("garbage");
173 touchFile(garbage);
174 configuration.setAlwaysUnpack(true);
175
176 Path homeDir = install.createDist(configuration);
177
178 assertEquals(mavenHomeDir, homeDir);
179 assertTrue(Files.isDirectory(mavenHomeDir));
180 assertFalse(Files.exists(homeDir.resolve("garbage")));
181 assertTrue(Files.exists(zipDestination));
182
183 assertEquals(localDistribution, pathAssembler.getDistribution(configuration));
184 assertEquals(distributionDir, localDistribution.getDistributionDir());
185 assertEquals(zipDestination, localDistribution.getZipFile());
186 }
187
188 @Test
189 void testCreateDistWithExistingZipAndDistAndAlwaysDownloadTrue() throws Exception {
190
191 createTestZip(zipDestination);
192 Path garbage = mavenHomeDir.resolve("garbage");
193 touchFile(garbage);
194 configuration.setAlwaysUnpack(true);
195
196 Path homeDir = install.createDist(configuration);
197
198 assertEquals(mavenHomeDir, homeDir);
199 assertTrue(Files.isDirectory(mavenHomeDir));
200 assertTrue(Files.exists(homeDir.resolve("bin/mvn")));
201 assertFalse(Files.exists(homeDir.resolve("garbage")));
202 assertTrue(Files.exists(zipDestination));
203
204 assertEquals(localDistribution, pathAssembler.getDistribution(configuration));
205 assertEquals(distributionDir, localDistribution.getDistributionDir());
206 assertEquals(zipDestination, localDistribution.getZipFile());
207
208
209
210 }
211
212 @Test
213 void testZipSlip() throws URISyntaxException {
214 URL resource = getClass().getClassLoader().getResource("zip-slip.zip");
215 Path zipSlip = Paths.get(resource.toURI());
216 when(localDistribution.getZipFile()).thenReturn(zipSlip);
217 configuration.setAlwaysUnpack(true);
218
219 try {
220 install.createDist(configuration);
221 fail("Should fail as it contains a zip slip.");
222 } catch (Exception ex) {
223 assertTrue(ex instanceof ZipException);
224 }
225 }
226
227 public void zipTo(final Path directoryToZip, final Path zipFile) throws IOException {
228
229 try (OutputStream fos = Files.newOutputStream(zipFile);
230 ZipOutputStream zos = new ZipOutputStream(fos)) {
231
232 Files.walkFileTree(directoryToZip, new SimpleFileVisitor<Path>() {
233 @Override
234
235 public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attrs)
236 throws IOException {
237
238 if (!directoryToZip.equals(dir)) {
239 zos.putNextEntry(
240 new ZipEntry(directoryToZip.relativize(dir).toString() + "/"));
241 zos.closeEntry();
242 }
243 return FileVisitResult.CONTINUE;
244 }
245
246 @Override
247
248 public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException {
249 zos.putNextEntry(
250 new ZipEntry(directoryToZip.relativize(file).toString()));
251 Files.copy(file, zos);
252 zos.closeEntry();
253 return FileVisitResult.CONTINUE;
254 }
255 });
256 }
257 }
258
259 private void touchFile(Path file) throws IOException {
260 if (Files.notExists(file)) {
261 Files.createDirectories(file.getParent());
262 Files.createFile(file);
263 }
264 Files.setLastModifiedTime(file, FileTime.fromMillis(System.currentTimeMillis()));
265 }
266 }