1 /*******************************************************************************
2  * Copyright (c) 2014 Moritz Eysholdt and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     Moritz Eysholdt <moritz.eysholdt@itemis.de> - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.jdt.internal.junit4.runner;
15 
16 import java.util.HashSet;
17 import java.util.Set;
18 
19 import org.junit.runner.Description;
20 import org.junit.runner.Runner;
21 import org.junit.runner.manipulation.Filter;
22 import org.junit.runner.manipulation.NoTestsRemainException;
23 
24 /**
25  * This filter keeps all matched {@link Description}s in a tree, including the children and
26  * container of the matched Description.
27  *
28  * It is allowed to match more than one Description.
29  */
30 public class SubForestFilter extends Filter {
31 
32 	private Set<Description> fIncluded= null;
33 
34 	private final DescriptionMatcher fMatcher;
35 
SubForestFilter(DescriptionMatcher matcher)36 	public SubForestFilter(DescriptionMatcher matcher) {
37 		fMatcher= matcher;
38 	}
39 
40 	@Override
apply(Object child)41 	public void apply(Object child) throws NoTestsRemainException {
42 		if (child instanceof Runner && fIncluded == null) {
43 			fIncluded= new HashSet<Description>();
44 			collectIncludedDescriptions(((Runner)child).getDescription());
45 			if (fIncluded.isEmpty())
46 				throw new NoTestsRemainException();
47 		}
48 		super.apply(child);
49 	}
50 
collectIncludedDescriptions(Description description)51 	private boolean collectIncludedDescriptions(Description description) {
52 		if (fMatcher.matches(description)) {
53 			includeWithChildren(description);
54 			return true;
55 		}
56 		boolean hasIncludedChild= false;
57 		for (Description child : description.getChildren()) {
58 			hasIncludedChild|= collectIncludedDescriptions(child);
59 		}
60 		if (hasIncludedChild) {
61 			this.fIncluded.add(description);
62 		}
63 		return hasIncludedChild;
64 	}
65 
66 	@Override
describe()67 	public String describe() {
68 		return fMatcher.toString();
69 	}
70 
getIncludedDescriptions()71 	public Set<Description> getIncludedDescriptions() {
72 		return fIncluded;
73 	}
74 
includeWithChildren(Description description)75 	private void includeWithChildren(Description description) {
76 		fIncluded.add(description);
77 		for (Description child : description.getChildren()) {
78 			includeWithChildren(child);
79 		}
80 	}
81 
82 	@Override
shouldRun(Description description)83 	public boolean shouldRun(Description description) {
84 		return fIncluded.contains(description);
85 	}
86 
87 }
88