View Javadoc
1   package com.atlassian.plugin.util.zip;
2   
3   import com.atlassian.plugin.test.PluginTestUtils;
4   import org.apache.commons.io.FileUtils;
5   import org.apache.commons.io.IOUtils;
6   import org.junit.Before;
7   import org.junit.Test;
8   
9   import java.io.File;
10  import java.io.FileInputStream;
11  import java.io.FileOutputStream;
12  import java.io.IOException;
13  import java.util.zip.ZipEntry;
14  import java.util.zip.ZipOutputStream;
15  
16  import static org.junit.Assert.assertEquals;
17  import static org.mockito.Mockito.mock;
18  import static org.mockito.Mockito.when;
19  
20  public class TestUrlUnzipper {
21      private File basedir;
22      private File destdir;
23      private File zip;
24      private File sourcedir;
25      private File source1;
26  
27      @Before
28      public void setUp() throws Exception {
29          basedir = PluginTestUtils.createTempDirectory(TestUrlUnzipper.class);
30          FileUtils.cleanDirectory(basedir);
31          destdir = new File(basedir, "dest");
32          destdir.mkdir();
33          zip = new File(basedir, "test.zip");
34          sourcedir = new File(basedir, "source");
35          sourcedir.mkdir();
36          source1 = new File(sourcedir, "source1.jar");
37          FileUtils.writeStringToFile(source1, "source1");
38          source1.setLastModified(source1.lastModified() - 100000);
39      }
40  
41      @Test
42      public void testConditionalUnzip() throws IOException, InterruptedException {
43          zip(sourcedir, zip);
44          UrlUnzipper unzipper = new UrlUnzipper(zip.toURI().toURL(), destdir);
45          unzipper.conditionalUnzip();
46  
47          assertEquals(1, destdir.listFiles().length);
48          File dest1 = destdir.listFiles()[0];
49          assertEquals(source1.lastModified(), dest1.lastModified());
50          assertEquals("source1", FileUtils.readFileToString(dest1));
51  
52          FileUtils.writeStringToFile(source1, "source1-modified");
53          zip(sourcedir, zip);
54          unzipper = new UrlUnzipper(zip.toURI().toURL(), destdir);
55          unzipper.conditionalUnzip();
56  
57          assertEquals(1, destdir.listFiles().length);
58          dest1 = destdir.listFiles()[0];
59          assertEquals(source1.lastModified(), dest1.lastModified());
60          assertEquals("source1-modified", FileUtils.readFileToString(dest1));
61  
62      }
63  
64      @Test
65      public void testConditionalUnzipCleansZipDirectory() throws IOException, InterruptedException {
66          File f = new File(destdir, "bogusfile.txt");
67          zip(sourcedir, zip);
68          UrlUnzipper unzipper = new UrlUnzipper(zip.toURI().toURL(), destdir);
69          unzipper.conditionalUnzip();
70          assertEquals(1, destdir.listFiles().length); // there's only one..
71          assertEquals("source1.jar", destdir.listFiles()[0].getName()); // ..and it's not randomfile.txt
72      }
73  
74      @Test
75      public void testConditionalUnzipWithNoUnzipIfNoFileMod() throws IOException, InterruptedException {
76          zip(sourcedir, zip);
77          UrlUnzipper unzipper = new UrlUnzipper(zip.toURI().toURL(), destdir);
78          unzipper.conditionalUnzip();
79  
80          assertEquals(1, destdir.listFiles().length);
81          File dest1 = destdir.listFiles()[0];
82          assertEquals(source1.lastModified(), dest1.lastModified());
83          assertEquals("source1", FileUtils.readFileToString(dest1));
84  
85          long ts = source1.lastModified();
86          FileUtils.writeStringToFile(source1, "source1-modified");
87          source1.setLastModified(ts);
88          zip(sourcedir, zip);
89          unzipper = new UrlUnzipper(zip.toURI().toURL(), destdir);
90          unzipper.conditionalUnzip();
91  
92          assertEquals(1, destdir.listFiles().length);
93          dest1 = destdir.listFiles()[0];
94          assertEquals(source1.lastModified(), dest1.lastModified());
95          assertEquals("source1", FileUtils.readFileToString(dest1));
96      }
97  
98      @Test
99      public void testSaveEntryLegalRelativePath() throws IOException {
100         zip(sourcedir, zip);
101         final UrlUnzipper unzipper = new UrlUnzipper(zip.toURI().toURL(), destdir);
102         final ZipEntry entry = mock(ZipEntry.class);
103 
104         when(entry.getName()).thenReturn("something/.././test-relative.txt");
105         when(entry.isDirectory()).thenReturn(false);
106         when(entry.getTime()).thenReturn(source1.lastModified());
107         unzipper.saveEntry(new FileInputStream(source1), entry);
108 
109         assertEquals(1, destdir.listFiles().length);
110         final File dest1 = destdir.listFiles()[0];
111         assertEquals("test-relative.txt", dest1.getName());
112         assertEquals(source1.lastModified(), dest1.lastModified());
113         assertEquals("source1", FileUtils.readFileToString(dest1));
114     }
115 
116     private void zip(File basedir, File destfile) throws IOException {
117         ZipOutputStream zout = new ZipOutputStream(new FileOutputStream(destfile));
118         for (File child : basedir.listFiles()) {
119             // Zip files have a time granularity of 2 seconds.
120             long ZIP_FILE_GRAIN = 2000;
121             // Since we want to check that the unzipper restores modification times from the zip, we
122             // ensure all our files have exactly representable modification times.
123             child.setLastModified((child.lastModified() / ZIP_FILE_GRAIN) * ZIP_FILE_GRAIN);
124 
125             ZipEntry entry = new ZipEntry(child.getName());
126             entry.setTime(child.lastModified());
127             zout.putNextEntry(entry);
128             FileInputStream input = new FileInputStream(child);
129             IOUtils.copy(input, zout);
130             input.close();
131         }
132         zout.close();
133     }
134 }