001/*-------------------------------------------------------------------------+ 002| | 003| Copyright (c) 2005-2018 The ConQAT Project | 004| | 005| Licensed under the Apache License, Version 2.0 (the "License"); | 006| you may not use this file except in compliance with the License. | 007| You may obtain a copy of the License at | 008| | 009| http://www.apache.org/licenses/LICENSE-2.0 | 010| | 011| Unless required by applicable law or agreed to in writing, software | 012| distributed under the License is distributed on an "AS IS" BASIS, | 013| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 014| See the License for the specific language governing permissions and | 015| limitations under the License. | 016| | 017+-------------------------------------------------------------------------*/ 018package org.conqat.lib.commons.test; 019 020import java.io.File; 021import java.io.IOException; 022import java.util.Arrays; 023import java.util.List; 024import java.util.Optional; 025import java.util.function.Predicate; 026 027import org.conqat.lib.commons.collections.CollectionUtils; 028import org.conqat.lib.commons.resources.Resource; 029import org.conqat.lib.commons.resources.ResourceException; 030 031/** 032 * A test helper that provides access to a test-specific resources. Backed by a 033 * {@link TestDataManager}. 034 */ 035public class ManagedTestData { 036 037 /** Test data manager for this test case. */ 038 private final TestDataManager testDataManager; 039 040 /** 041 * @param contextClass 042 * The (test) class using the managed test data. The package of the 043 * class determines the root folder that is used for resource 044 * lookups. 045 */ 046 public ManagedTestData(Class<?> contextClass) { 047 testDataManager = TestDataManager.getInstance(contextClass); 048 } 049 050 /** 051 * Returns the given resource. The resource must be placed in the test-data 052 * folder under the package name of the contextClass. The path may also contain 053 * forward slashes to address sub-resources. The test-data directory is, for 054 * example, 055 * "engine/com.teamscale.index/test-data/com/teamscale/index/code_clones" for 056 * the context class 057 * com.teamscale.index.code_clones.TeamscaleCloneDetectionTest. 058 */ 059 public Resource getResource(String path) { 060 return testDataManager.getResource(path); 061 } 062 063 /** 064 * Returns the given resource or an empty optional if no resource with the given 065 * path exists. The resource must be placed in the test-data folder under the 066 * package name of the contextClass. The path may also contain forward slashes 067 * to address sub-resources. The test-data directory is, for example, 068 * "engine/com.teamscale.index/test-data/com/teamscale/index/code_clones" for * 069 * the context class com.teamscale.index.code_clones.TeamscaleCloneDetectionTest 070 * (does not include the name of the test). 071 */ 072 public Optional<Resource> getResourceIfExists(String path) { 073 if (testDataManager.hasResource(path)) { 074 return Optional.of(testDataManager.getResource(path)); 075 } else { 076 return Optional.empty(); 077 } 078 } 079 080 /** 081 * Returns the content of given resource. The content is expected to be UTF-8 082 * encoded and line separators are normalized. The resource must be placed in 083 * the test-data folder under the package name of the contextClass. The path may 084 * also contain forward slashes to address sub-resources. The test-data 085 * directory is, for example, 086 * "engine/com.teamscale.index/test-data/com/teamscale/index/code_clones" for 087 * the context class com.teamscale.index.code_clones.TeamscaleCloneDetectionTest 088 * (does not include the name of the test). 089 * 090 * In case you need to load the non-normalized content use 091 * {@link #getResource(String)} and {@link Resource#getContentAsRawString()} or 092 * {@link Resource#getAsByteArray()} instead. 093 */ 094 public String getDataContent(String path) { 095 return testDataManager.getResource(path).getContent(); 096 } 097 098 /** 099 * Returns a copy of the given resource as temporary file. The original resource 100 * must be placed in the test-data folder under the package name of the 101 * contextClass. The path may also contain forward slashes to address 102 * sub-resources. The test-data directory is, for example, 103 * "engine/com.teamscale.index/test-data/com/teamscale/index/code_clones" for 104 * the context class com.teamscale.index.code_clones.TeamscaleCloneDetectionTest 105 * (does not include the name of the test). 106 * 107 * In case your test relies on the exact file name use 108 * {@link #getDataFile(String, File)} instead, which allows you to copy into a 109 * given temporary directory under the original file name. 110 */ 111 public File getDataFile(String fileName) { 112 Resource resource = testDataManager.getResource(fileName); 113 try { 114 return resource.getAsTmpFile(); 115 } catch (IOException e) { 116 throw ResourceException.newLoadFailed(resource, e); 117 } 118 } 119 120 /** 121 * Returns a copy of the given resource as temporary file. The temporary copy is 122 * stored directly in the given tempDir. The original resource must be placed in 123 * the test-data folder under the package name of the contextClass. The path may 124 * also contain forward slashes to address sub-resources. The test-data 125 * directory is, for example, 126 * "engine/com.teamscale.index/test-data/com/teamscale/index/code_clones" for 127 * the context class com.teamscale.index.code_clones.TeamscaleCloneDetectionTest 128 * (does not include the name of the test). 129 */ 130 public File getDataFile(String fileName, File tempDir) { 131 Resource resource = testDataManager.getResource(fileName); 132 File newFile = new File(tempDir, fileName); 133 try { 134 resource.copyTo(newFile); 135 } catch (IOException e) { 136 throw ResourceException.newLoadFailed(resource, e); 137 } 138 return newFile; 139 } 140 141 /** 142 * Creates a copy of the given resource directory in the given tempDir. The 143 * original resource must be placed in the test-data folder under the package 144 * name of the contextClass. The path may also contain forward slashes to 145 * address sub-resources. The test-data directory is, for example, 146 * "engine/com.teamscale.index/test-data/com/teamscale/index/code_clones" for 147 * the context class com.teamscale.index.code_clones.TeamscaleCloneDetectionTest 148 * (does not include the name of the test). 149 * 150 * @return The root of the directory in the temporary location. 151 */ 152 public File copyDataDirectory(String directoryName, File tempDir) { 153 List<Resource> resources = testDataManager.listResourcesRecursively(directoryName); 154 for (Resource resource : resources) { 155 try { 156 resource.copyTo(new File(tempDir, resource.getPath())); 157 } catch (IOException e) { 158 throw ResourceException.newLoadFailed(resource, e); 159 } 160 } 161 return new File(tempDir, directoryName); 162 } 163 164 /** 165 * Lists all resources contained in the given subfolder. If fileExtensions are 166 * given the resources that do not match any of them are filtered out. 167 */ 168 public List<Resource> listResources(String subfolder, String... fileExtensions) { 169 return listResources(subfolder, filterByExtension(fileExtensions)); 170 } 171 172 /** 173 * Lists all resources contained in the given subfolder matching the given 174 * predicate. 175 */ 176 public List<Resource> listResources(String subfolder, Predicate<Resource> filter) { 177 return CollectionUtils.filter(testDataManager.listResources(subfolder), filter); 178 } 179 180 /** 181 * Lists all resources contained in the given subfolder recursively. If 182 * fileExtensions are given the resources that do not match any of them are 183 * filtered out. 184 */ 185 public List<Resource> listResourcesRecursively(String subfolder, String... fileExtensions) { 186 return listResourcesRecursively(subfolder, filterByExtension(fileExtensions)); 187 } 188 189 /** 190 * Lists all resources contained in the given subfolder recursively matching the 191 * given predicate. 192 */ 193 public List<Resource> listResourcesRecursively(String subfolder, Predicate<Resource> filter) { 194 return CollectionUtils.filter(testDataManager.listResourcesRecursively(subfolder), filter); 195 } 196 197 private static Predicate<Resource> filterByExtension(String... fileExtensions) { 198 if (fileExtensions.length == 0) { 199 return (resource) -> true; 200 } 201 return (resource) -> Arrays.stream(fileExtensions).anyMatch(resource::hasExtension); 202 } 203}