1 package org.apache.maven.surefire.api.util;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.Collections;
25 import java.util.Iterator;
26 import java.util.List;
27 import java.util.Set;
28
29 import org.apache.maven.surefire.api.testset.TestSetFailedException;
30
31 import static java.lang.Math.max;
32
33
34
35
36
37
38
39 public class TestsToRun implements Iterable<Class<?>>
40 {
41 private final List<Class<?>> locatedClasses;
42
43 private volatile boolean finished;
44
45 private int iteratedCount;
46
47
48
49
50
51
52 public TestsToRun( Set<Class<?>> locatedClasses )
53 {
54 this.locatedClasses = new ArrayList<>( locatedClasses );
55 }
56
57 public static TestsToRun fromClass( Class<?> clazz )
58 throws TestSetFailedException
59 {
60 return new TestsToRun( Collections.<Class<?>>singleton( clazz ) );
61 }
62
63
64
65
66 public Iterator<Class<?>> iterated()
67 {
68 return newWeakIterator();
69 }
70
71
72
73
74
75
76 @Override
77 public Iterator<Class<?>> iterator()
78 {
79 return new ClassesIterator();
80 }
81
82 private final class ClassesIterator
83 extends CloseableIterator<Class<?>>
84 {
85 private final Iterator<Class<?>> it = TestsToRun.this.locatedClasses.iterator();
86
87 private int iteratedCount;
88
89 @Override
90 protected boolean isClosed()
91 {
92 return TestsToRun.this.isFinished();
93 }
94
95 @Override
96 protected boolean doHasNext()
97 {
98 return it.hasNext();
99 }
100
101 @Override
102 protected Class<?> doNext()
103 {
104 Class<?> nextTest = it.next();
105 TestsToRun.this.iteratedCount = max( ++iteratedCount, TestsToRun.this.iteratedCount );
106 return nextTest;
107 }
108
109 @Override
110 protected void doRemove()
111 {
112 }
113
114 @Override
115 public void remove()
116 {
117 throw new UnsupportedOperationException( "unsupported remove" );
118 }
119 }
120
121 public final void markTestSetFinished()
122 {
123 finished = true;
124 }
125
126 public final boolean isFinished()
127 {
128 return finished;
129 }
130
131 @Override
132 public String toString()
133 {
134 StringBuilder sb = new StringBuilder( "TestsToRun: [" );
135 for ( Class<?> clazz : this )
136 {
137 sb.append( ' ' )
138 .append( clazz.getName() );
139 }
140
141 sb.append( ']' );
142 return sb.toString();
143 }
144
145 public boolean containsAtLeast( int atLeast )
146 {
147 return containsAtLeast( iterator(), atLeast );
148 }
149
150 private boolean containsAtLeast( Iterator<Class<?>> it, int atLeast )
151 {
152 for ( int i = 0; i < atLeast; i++ )
153 {
154 if ( !it.hasNext() )
155 {
156 return false;
157 }
158
159 it.next();
160 }
161
162 return true;
163 }
164
165 public boolean containsExactly( int items )
166 {
167 Iterator<Class<?>> it = iterator();
168 return containsAtLeast( it, items ) && !it.hasNext();
169 }
170
171
172
173
174
175 public boolean allowEagerReading()
176 {
177 return true;
178 }
179
180 public Class<?>[] getLocatedClasses()
181 {
182 if ( !allowEagerReading() )
183 {
184 throw new IllegalStateException( "Cannot eagerly read" );
185 }
186 Collection<Class<?>> result = new ArrayList<>();
187 for ( Class<?> clazz : this )
188 {
189 result.add( clazz );
190 }
191 return result.toArray( new Class<?>[result.size()] );
192 }
193
194
195
196
197
198
199
200 public Class<?> getClassByName( String className )
201 {
202 for ( Class<?> clazz : this )
203 {
204 if ( clazz.getName().equals( className ) )
205 {
206 return clazz;
207 }
208 }
209 return null;
210 }
211
212
213
214
215
216 private Iterator<Class<?>> newWeakIterator()
217 {
218 final Iterator<Class<?>> it = locatedClasses.subList( 0, iteratedCount ).iterator();
219 return new CloseableIterator<Class<?>>()
220 {
221 @Override
222 protected boolean isClosed()
223 {
224 return TestsToRun.this.isFinished();
225 }
226
227 @Override
228 protected boolean doHasNext()
229 {
230 return it.hasNext();
231 }
232
233 @Override
234 protected Class<?> doNext()
235 {
236 return it.next();
237 }
238
239 @Override
240 protected void doRemove()
241 {
242 }
243
244 @Override
245 public void remove()
246 {
247 throw new UnsupportedOperationException( "unsupported remove" );
248 }
249 };
250 }
251 }