001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.junit;
043:
044: import java.util.LinkedList;
045: import java.util.List;
046:
047: /**
048: * A helper class, which holds informatino about filtered tests
049: */
050: public class Filter {
051: private IncludeExclude inc[] = new IncludeExclude[] {};
052: private IncludeExclude exc[] = new IncludeExclude[] {};
053:
054: /** Creates new Filter */
055: public Filter() {
056: }
057:
058: public void setIncludes(IncludeExclude includes[]) {
059: inc = arrayCopy(includes);
060: }
061:
062: public void setExcludes(IncludeExclude excludes[]) {
063: exc = arrayCopy(excludes);
064: }
065:
066: public IncludeExclude[] getIncludes() {
067: return arrayCopy(inc);
068: }
069:
070: public IncludeExclude[] getExcludes() {
071: return arrayCopy(exc);
072: }
073:
074: public boolean isIncluded(String name) {
075: int i;
076: for (i = 0; i < inc.length; i++)
077: if (inc[i].getName() == null
078: || match(inc[i].getName(), name))
079: break;
080:
081: if (0 < inc.length && i == inc.length) {
082: return false;
083: }
084:
085: for (i = 0; i < exc.length; i++)
086: if (match(exc[i].getName(), name))
087: break;
088:
089: return i == exc.length;
090: }
091:
092: public String getExpectedFail(String name) {
093: StringBuffer sb = new StringBuffer();
094: for (int i = 0; i < inc.length; i++) {
095: if (inc[i].getName() == null
096: || match(inc[i].getName(), name)) {
097: if (inc[i].getExpectedFail() != null) {
098: if (sb.length() != 0)
099: sb.append("; ");
100: sb.append(inc[i].getExpectedFail());
101: }
102: }
103: }
104: if (sb.length() == 0)
105: return null;
106: else
107: return sb.toString();
108: }
109:
110: /**
111: * Matches a string against a pattern. The pattern contains two special
112: * characters:
113: * '*' which means zero or more characters,
114: * '?' which means one and only one character.
115: *
116: * This code was stolen from Ant's DirectoryScanner.match(String, String) function.
117: *
118: * @param pattern the (non-null) pattern to match against
119: * @param str the (non-null) string that must be matched against the
120: * pattern
121: *
122: * @return <code>true</code> when the string matches against the pattern,
123: * <code>false</code> otherwise.
124: */
125: public static boolean match(String pattern, String str) {
126:
127: if (null == pattern && null == str)
128: return true;
129:
130: if (null == pattern || null == str)
131: return false;
132:
133: char[] patArr = pattern.toCharArray();
134: char[] strArr = str.toCharArray();
135: int patIdxStart = 0;
136: int patIdxEnd = patArr.length - 1;
137: int strIdxStart = 0;
138: int strIdxEnd = strArr.length - 1;
139: char ch;
140:
141: boolean containsStar = false;
142: for (int i = 0; i < patArr.length; i++) {
143: if (patArr[i] == '*') {
144: containsStar = true;
145: break;
146: }
147: }
148:
149: if (!containsStar) {
150: // No '*'s, so we make a shortcut
151: if (patIdxEnd != strIdxEnd) {
152: return false; // Pattern and string do not have the same size
153: }
154: for (int i = 0; i <= patIdxEnd; i++) {
155: ch = patArr[i];
156: if (ch != '?' && ch != strArr[i]) {
157: return false; // Character mismatch
158: }
159: }
160: return true; // String matches against pattern
161: }
162:
163: if (patIdxEnd == 0) {
164: return true; // Pattern contains only '*', which matches anything
165: }
166:
167: // Process characters before first star
168: while ((ch = patArr[patIdxStart]) != '*'
169: && strIdxStart <= strIdxEnd) {
170: if (ch != '?' && ch != strArr[strIdxStart]) {
171: return false;
172: }
173: patIdxStart++;
174: strIdxStart++;
175: }
176: if (strIdxStart > strIdxEnd) {
177: // All characters in the string are used. Check if only '*'s are
178: // left in the pattern. If so, we succeeded. Otherwise failure.
179: for (int i = patIdxStart; i <= patIdxEnd; i++) {
180: if (patArr[i] != '*') {
181: return false;
182: }
183: }
184: return true;
185: }
186:
187: // Process characters after last star
188: while ((ch = patArr[patIdxEnd]) != '*'
189: && strIdxStart <= strIdxEnd) {
190: if (ch != '?' && ch != strArr[strIdxEnd]) {
191: return false;
192: }
193: patIdxEnd--;
194: strIdxEnd--;
195: }
196: if (strIdxStart > strIdxEnd) {
197: // All characters in the string are used. Check if only '*'s are
198: // left in the pattern. If so, we succeeded. Otherwise failure.
199: for (int i = patIdxStart; i <= patIdxEnd; i++) {
200: if (patArr[i] != '*') {
201: return false;
202: }
203: }
204: return true;
205: }
206:
207: // process pattern between stars. padIdxStart and patIdxEnd point
208: // always to a '*'.
209: while (patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd) {
210: int patIdxTmp = -1;
211: for (int i = patIdxStart + 1; i <= patIdxEnd; i++) {
212: if (patArr[i] == '*') {
213: patIdxTmp = i;
214: break;
215: }
216: }
217: if (patIdxTmp == patIdxStart + 1) {
218: // Two stars next to each other, skip the first one.
219: patIdxStart++;
220: continue;
221: }
222: // Find the pattern between padIdxStart & padIdxTmp in str between
223: // strIdxStart & strIdxEnd
224: int patLength = (patIdxTmp - patIdxStart - 1);
225: int strLength = (strIdxEnd - strIdxStart + 1);
226: int foundIdx = -1;
227: strLoop: for (int i = 0; i <= strLength - patLength; i++) {
228: for (int j = 0; j < patLength; j++) {
229: ch = patArr[patIdxStart + j + 1];
230: if (ch != '?' && ch != strArr[strIdxStart + i + j]) {
231: continue strLoop;
232: }
233: }
234:
235: foundIdx = strIdxStart + i;
236: break;
237: }
238:
239: if (foundIdx == -1) {
240: return false;
241: }
242:
243: patIdxStart = patIdxTmp;
244: strIdxStart = foundIdx + patLength;
245: }
246:
247: // All characters in the string are used. Check if only '*'s are left
248: // in the pattern. If so, we succeeded. Otherwise failure.
249: for (int i = patIdxStart; i <= patIdxEnd; i++) {
250: if (patArr[i] != '*') {
251: return false;
252: }
253: }
254: return true;
255: }
256:
257: public String toString() {
258: StringBuffer b = new StringBuffer();
259:
260: if (0 < inc.length) {
261: b.append("-i ");
262: for (int i = 0; i < inc.length; i++) {
263: b.append(inc[i]);
264: b.append(' ');
265: }
266: }
267:
268: if (0 < exc.length) {
269: b.append("-e ");
270: for (int i = 0; i < exc.length; i++) {
271: b.append(exc[i]);
272: b.append(' ');
273: }
274: }
275:
276: return b.toString();
277: }
278:
279: private IncludeExclude[] arrayCopy(IncludeExclude[] orig) {
280: List<IncludeExclude> lst = new LinkedList<IncludeExclude>();
281: for (int i = 0; i < orig.length; i++)
282: if (null != orig[i]
283: && !(orig[i].getName() == null && orig[i]
284: .getExpectedFail() == null)) {
285: lst.add(orig[i]);
286: }
287:
288: return lst.toArray(new IncludeExclude[0]);
289: }
290:
291: public static class IncludeExclude {
292: private String name;
293: private String expectedFail;
294:
295: public IncludeExclude() {
296: }
297:
298: public IncludeExclude(String name, String expectedFail) {
299: this .name = name;
300: this .expectedFail = expectedFail;
301: }
302:
303: public String getName() {
304: return name;
305: }
306:
307: public String getExpectedFail() {
308: return expectedFail;
309: }
310:
311: public void setName(String name) {
312: this .name = name;
313: }
314:
315: public void setExpectedFail(String expectedFail) {
316: this .expectedFail = expectedFail;
317: }
318:
319: public String toString() {
320: return name + ":" + expectedFail;
321: }
322: }
323: }
|