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.plugin.testing.resources;
20  
21  import java.io.File;
22  import java.io.IOException;
23  import java.util.Collection;
24  import java.util.Set;
25  import java.util.TreeSet;
26  
27  import org.codehaus.plexus.util.DirectoryScanner;
28  import org.codehaus.plexus.util.FileUtils;
29  import org.junit.Assert;
30  import org.junit.Rule;
31  import org.junit.rules.TestWatcher;
32  import org.junit.runner.Description;
33  
34  /**
35   * Junit4 test {@link Rule} to extract and assert test resources.
36   *
37   * @since 3.1.0
38   */
39  public class TestResources extends TestWatcher {
40  
41      private final String projectsDir;
42  
43      private final String workDir;
44  
45      public TestResources() {
46          this("src/test/projects", "target/test-projects");
47      }
48  
49      public TestResources(String projectsDir, String workDir) {
50          this.projectsDir = projectsDir;
51          this.workDir = workDir;
52      }
53  
54      private String name;
55  
56      @Override
57      protected void starting(Description d) {
58          String methodName = d.getMethodName();
59          if (methodName != null) {
60              methodName = methodName.replace('/', '_').replace('\\', '_');
61          }
62          name = d.getTestClass().getSimpleName() + "_" + methodName;
63      }
64  
65      /**
66       * Creates new clean copy of test project directory structure. The copy is named after both the test being executed
67       * and test project name, which allows the same test project can be used by multiple tests and by different
68       * instances of the same parametrized tests.
69       * <p>
70       * TODO Provide alternative working directory naming for Windows, which still limits path names to ~250 charecters
71       */
72      public File getBasedir(String project) throws IOException {
73          if (name == null) {
74              throw new IllegalStateException(
75                      getClass().getSimpleName() + " must be a test class field annotated with org.junit.Rule");
76          }
77          File src = new File(projectsDir, project).getCanonicalFile();
78          Assert.assertTrue("Test project directory does not exist: " + src.getPath(), src.isDirectory());
79          File basedir = new File(workDir, name + "_" + project).getCanonicalFile();
80          FileUtils.deleteDirectory(basedir);
81          Assert.assertTrue("Test project working directory created", basedir.mkdirs());
82          FileUtils.copyDirectoryStructure(src, basedir);
83          return basedir;
84      }
85  
86      // static helpers
87  
88      public static void cp(File basedir, String from, String to) throws IOException {
89          // TODO ensure destination lastModified timestamp changes
90          FileUtils.copyFile(new File(basedir, from), new File(basedir, to));
91      }
92  
93      public static void assertFileContents(File basedir, String expectedPath, String actualPath) throws IOException {
94          String expected = FileUtils.fileRead(new File(basedir, expectedPath));
95          String actual = FileUtils.fileRead(new File(basedir, actualPath));
96          Assert.assertEquals(expected, actual);
97      }
98  
99      public static void assertDirectoryContents(File dir, String... expectedPaths) {
100         DirectoryScanner scanner = new DirectoryScanner();
101         scanner.setBasedir(dir);
102         scanner.addDefaultExcludes();
103         scanner.scan();
104 
105         Set<String> actual = new TreeSet<>();
106         for (String path : scanner.getIncludedFiles()) {
107             actual.add(path);
108         }
109         for (String path : scanner.getIncludedDirectories()) {
110             if (path.length() > 0) {
111                 actual.add(path + "/");
112             }
113         }
114 
115         Set<String> expected = new TreeSet<>();
116         if (expectedPaths != null) {
117             for (String path : expectedPaths) {
118                 expected.add(path);
119             }
120         }
121 
122         // compare textual representation to make diff easier to understand
123         Assert.assertEquals(toString(expected), toString(actual));
124     }
125 
126     private static String toString(Collection<String> strings) {
127         StringBuilder sb = new StringBuilder();
128         for (String string : strings) {
129             sb.append(string).append('\n');
130         }
131         return sb.toString();
132     }
133 
134     public static void touch(File basedir, String path) throws InterruptedException {
135         touch(new File(basedir, path));
136     }
137 
138     public static void touch(File file) throws InterruptedException {
139         if (!file.isFile()) {
140             throw new IllegalArgumentException("Not a file " + file);
141         }
142         long lastModified = file.lastModified();
143         file.setLastModified(System.currentTimeMillis());
144 
145         // TODO do modern filesystems still have this silly lastModified resolution?
146         if (lastModified == file.lastModified()) {
147             Thread.sleep(1000L);
148             file.setLastModified(System.currentTimeMillis());
149         }
150     }
151 
152     public static void rm(File basedir, String path) {
153         Assert.assertTrue("delete " + path, new File(basedir, path).delete());
154     }
155 
156     /**
157      * @since 3.2.0
158      */
159     public static void create(File basedir, String... paths) throws IOException {
160         if (paths == null || paths.length == 0) {
161             throw new IllegalArgumentException();
162         }
163         for (String path : paths) {
164             File file = new File(basedir, path);
165             Assert.assertTrue(file.getParentFile().mkdirs());
166             file.createNewFile();
167             Assert.assertTrue(file.isFile() && file.canRead());
168         }
169     }
170 }