1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 package org.openoffice.test.common;
23 
24 import java.io.BufferedReader;
25 import java.io.File;
26 import java.io.FileReader;
27 import java.lang.annotation.Annotation;
28 import java.lang.annotation.ElementType;
29 import java.lang.annotation.Retention;
30 import java.lang.annotation.RetentionPolicy;
31 import java.lang.annotation.Target;
32 import java.lang.reflect.Field;
33 import java.util.ArrayList;
34 import java.util.Arrays;
35 import java.util.Collections;
36 import java.util.List;
37 
38 import org.junit.runner.Runner;
39 import org.junit.runner.notification.RunNotifier;
40 import org.junit.runners.BlockJUnit4ClassRunner;
41 import org.junit.runners.Suite;
42 import org.junit.runners.model.FrameworkMethod;
43 import org.junit.runners.model.InitializationError;
44 import org.junit.runners.model.Statement;
45 
46 public class FileProvider extends Suite {
47 
48 	private static final List<Runner> NO_RUNNERS = Collections.<Runner> emptyList();
49 
50 	private final ArrayList<Runner> runners = new ArrayList<Runner>();
51 
52 	private class TestClassRunnerForParameters extends BlockJUnit4ClassRunner {
53 
54 		private final Object[] parameters;
55 
56 		private int index;
57 
TestClassRunnerForParameters(Class<?> type, Object[] parameters, int index)58 		TestClassRunnerForParameters(Class<?> type, Object[] parameters, int index) throws InitializationError {
59 			super(type);
60 			this.parameters = parameters;
61 			this.index = index;
62 		}
63 
64 		@Override
createTest()65 		public Object createTest() throws Exception {
66 			return getTestClass().getOnlyConstructor().newInstance(parameters);
67 		}
68 
69 		@Override
getName()70 		protected String getName() {
71 			return getTestClass().getJavaClass().getSimpleName() + "[" + index + "]" +  Arrays.toString(parameters);
72 		}
73 
74 		@Override
testName(FrameworkMethod method)75 		protected String testName(FrameworkMethod method) {
76 			return method.getName() + "[" + index + "]" + Arrays.toString(parameters);
77 		}
78 
79 		@Override
validateConstructor(List<Throwable> errors)80 		protected void validateConstructor(List<Throwable> errors) {
81 			validateOnlyOneConstructor(errors);
82 		}
83 
84 		@Override
classBlock(RunNotifier notifier)85 		protected Statement classBlock(RunNotifier notifier) {
86 			return childrenInvoker(notifier);
87 		}
88 
89 		@Override
getRunnerAnnotations()90 		protected Annotation[] getRunnerAnnotations() {
91 			return new Annotation[0];
92 		}
93 	}
94 
95 	@Retention(RetentionPolicy.RUNTIME)
96 	@Target(ElementType.FIELD)
97 	public static @interface FileRepos {
98 	}
99 
100 	@Retention(RetentionPolicy.RUNTIME)
101 	@Target(ElementType.FIELD)
102 	public static @interface FileFilter {
103 
104 	}
105 
106 	@Retention(RetentionPolicy.RUNTIME)
107 	@Target(ElementType.FIELD)
108 	public static @interface FileRepeat {
109 
110 	}
111 
FileProvider(Class<?> klass)112 	public FileProvider(Class<?> klass) throws Throwable {
113 		super(klass, NO_RUNNERS);
114 
115 		String repos = null;
116 		String filter = null;
117 		int repeat = 1;
118 		Field fs[] = klass.getFields();
119 		for (Field f : fs) {
120 			Annotation a = f.getAnnotation(FileRepos.class);
121 			if (a != null) {
122 				Object v = f.get(null);
123 				if (!(v instanceof String))
124 					throw new InitializationError(String.format("Field annotated FileRepos '%s' must be String.", f.getName()));
125 
126 				repos = (String) v;
127 			}
128 
129 			a = f.getAnnotation(FileFilter.class);
130 			if (a != null) {
131 				Object v = f.get(null);
132 				if (v != null && !(v instanceof String))
133 					throw new InitializationError(String.format("Field annotated FileFilter '%s' must be String.", f.getName()));
134 				filter = (String) v;
135 			}
136 
137 			a = f.getAnnotation(FileRepeat.class);
138 			if (a != null) {
139 				Object v = f.get(null);
140 				if (v != null && !(v instanceof Integer))
141 					throw new InitializationError(String.format("Field annotated FileFilter '%s' must be Integer.", f.getName()));
142 				repeat = (Integer) v;
143 			}
144 
145 		}
146 
147 		File reposFile = new File(repos);
148 //		if (!reposFile.exists())
149 //
150 //			throw new InitializationError(String.format("repos '%s' does not exists ", repos));
151 
152 		if(reposFile.exists()){
153 			ArrayList<ArrayList<String>> filterItems = new ArrayList<ArrayList<String>>();
154 			if (filter != null) {
155 				String[] args = SystemUtil.parseCommandLine(filter);
156 				ArrayList<String> filterItem = new ArrayList<String>();
157 				for (int i = 0; i < args.length; i++) {
158 					String a = args[i];
159 					if (a.equals("-f")) {
160 						if (filterItem.size() > 0)
161 							filterItems.add(filterItem);
162 						filterItem = new ArrayList<String>();
163 					} else {
164 						filterItem.add(a);
165 					}
166 				}
167 
168 				if (filterItem.size() > 0)
169 					filterItems.add(filterItem);
170 			}
171 
172 
173 			ArrayList<Object[]> list = new ArrayList<Object[]>();
174 			if (!collectFromFile(reposFile, list, filterItems))
175 				if (!collectFromFiles(reposFile, list, filterItems))
176 					collectFromDir(reposFile, list, filterItems);
177 
178 			for (int i = 0; i < list.size(); i++) {
179 				Object[] t = list.get(i);
180 				for  (int j = 0; j < repeat; j++) {
181 					TestClassRunnerForParameters runner = new TestClassRunnerForParameters(getTestClass().getJavaClass(), t, i * repeat + j);
182 					runners.add(runner);
183 				}
184 			}
185 		}
186 
187 	}
188 
collectFromFiles(File dir, ArrayList<Object[]> list, ArrayList<ArrayList<String>> filterItems)189 	private static boolean collectFromFiles(File dir, ArrayList<Object[]> list, ArrayList<ArrayList<String>> filterItems) {
190 		if (!dir.isDirectory())
191 			return false;
192 
193 		boolean hasListFile = false;
194 		File[] files = dir.listFiles();
195 		for (File f : files) {
196 			if (f.isFile() && f.getName().endsWith(".files")) {
197 				hasListFile = true;
198 				collectFromFile(f, list, filterItems);
199 			}
200 		}
201 
202 		return hasListFile;
203 	}
204 
collectFromDir(File dir, ArrayList<Object[]> list, ArrayList<ArrayList<String>> filterItems)205 	private static boolean collectFromDir(File dir, ArrayList<Object[]> list, ArrayList<ArrayList<String>> filterItems) {
206 		if (!dir.isDirectory())
207 			return false;
208 
209 		File[] files = dir.listFiles();
210 		Arrays.sort(files);
211 		for (File file : files) {
212 			if (file.isDirectory()) {
213 				collectFromDir(file, list, filterItems);
214 				continue;
215 			}
216 
217 			filter(file.getAbsolutePath(), list, filterItems);
218 		}
219 
220 		return true;
221 	}
222 
collectFromFile(File file, ArrayList<Object[]> list, ArrayList<ArrayList<String>> filterItems)223 	private static boolean collectFromFile(File file, ArrayList<Object[]> list, ArrayList<ArrayList<String>> filterItems) {
224 		if (!file.isFile())
225 			return false;
226 
227 		BufferedReader reader = null;
228 		try{
229 			reader = new BufferedReader(new FileReader(file));
230 			String line = null;
231 			while((line = reader.readLine()) != null){
232 				filter(line, list, filterItems);
233 			}
234 		}catch(Exception e){
235 			//ignore
236 		}finally{
237 			try{
238 				if(reader != null){
239 					reader.close();
240 					reader = null;
241 				}
242 
243 			}catch(Exception io){
244 				//ignore;
245 			}
246 		}
247 
248 		return true;
249 	}
250 
filter(String filePath, ArrayList<Object[]> list, ArrayList<ArrayList<String>> filterItems)251 	private static void filter(String filePath, ArrayList<Object[]> list, ArrayList<ArrayList<String>> filterItems) {
252 		if (filterItems.size() == 0) {
253 			Object[] data = { filePath};
254 			list.add(data);
255 			return;
256 		}
257 
258 		for (int i = 0; i < filterItems.size(); i++) {
259 			ArrayList<String> filterItem = filterItems.get(i);
260 			String pattern = filterItem.get(0);
261 			if (pattern != null && filePath.matches(pattern)) {
262 				Object[] data = new Object[filterItem.size()];
263 				data[0] = filePath;
264 				for (int j = 1; j < filterItem.size(); j++)
265 					data[j] = filterItem.get(j);
266 
267 				list.add(data);
268 			}
269 		}
270 	}
271 
272 
273 	@Override
getChildren()274 	protected List<Runner> getChildren() {
275 		return runners;
276 	}
277 }
278