1818import java .util .concurrent .Executors ;
1919import java .util .concurrent .Future ;
2020import java .util .concurrent .TimeUnit ;
21- import java .util .concurrent .TimeoutException ;
2221import java .util .regex .Pattern ;
2322import java .util .stream .Collectors ;
2423import org .junit .jupiter .api .Assertions ;
@@ -49,7 +48,7 @@ private static List<String> discoverProblemNames() {
4948
5049 if ("jar" .equals (resource .getProtocol ())) {
5150 System .err .println (
52- "Cannot discover problems dynamically from within a JAR file. Please ensure 'src/main/java' is accessible on the file system during testing." );
51+ "Cannot discover problems dynamically from within a JAR file. Please ensure 'src/main/java' is accessible on the file system during testing." );
5352 return Collections .emptyList ();
5453 }
5554
@@ -70,7 +69,7 @@ private static List<String> discoverProblemNames() {
7069 @ Override
7170 public boolean accept (File current , String name ) {
7271 return new File (current , name ).isDirectory ()
73- && PROBLEM_DIR_PATTERN .matcher (name ).matches ();
72+ && PROBLEM_DIR_PATTERN .matcher (name ).matches ();
7473 }
7574 });
7675
@@ -79,10 +78,25 @@ public boolean accept(File current, String name) {
7978 return Collections .emptyList ();
8079 }
8180
82- List <String > problems = Arrays .stream (problemDirs )
83- .map (File ::getName )
84- .sorted ()
85- .collect (Collectors .toList ());
81+ List <String > problems =
82+ Arrays .stream (problemDirs ).map (File ::getName ).sorted ().collect (Collectors .toList ());
83+
84+ // Read maxproblems system property
85+ String maxProblemsStr = System .getProperty ("maxproblems" );
86+ if (maxProblemsStr != null ) {
87+ try {
88+ int maxProblems = Integer .parseInt (maxProblemsStr );
89+ if (maxProblems > 0 && maxProblems < problems .size ()) {
90+ problems = problems .subList (0 , maxProblems );
91+ System .out .println ("Limiting to " + maxProblems + " problems: " + problems );
92+ } else if (maxProblems <= 0 ) {
93+ System .err .println ("Invalid maxproblems value: " + maxProblems + ". Using all problems." );
94+ }
95+ // If maxProblems >= problems.size(), use all problems
96+ } catch (NumberFormatException e ) {
97+ System .err .println ("Invalid maxproblems format: " + maxProblemsStr + ". Using all problems." );
98+ }
99+ }
86100
87101 System .out .println ("Discovered problems: " + problems );
88102 return problems ;
@@ -96,125 +110,128 @@ Collection<DynamicTest> runMavenExecTests() {
96110 final ExecutorService executor = Executors .newFixedThreadPool (MAX_THREADS );
97111
98112 List <Future <TestResult >> futures = PROBLEMS .stream ()
99- .map (problem -> {
100- Callable <TestResult > task = () -> {
101- Thread .currentThread ().setName ("Problem-Runner-" + problem );
102- String command = String .format ("mvn exec:exec -Dproblem=%s" , problem );
103- System .out .println (Thread .currentThread ().getName () + ": Executing command for " + problem
104- + ": " + command );
105-
106- Process process ;
107- try {
108- process = Runtime .getRuntime ().exec (command );
109- } catch (Exception e ) {
110- return new TestResult (
111- problem , false , "" , "Failed to execute command: " + e .getMessage (), e );
112- }
113-
114- StringBuilder output = new StringBuilder ();
115- StringBuilder errorOutput = new StringBuilder ();
116-
117- Thread outputGobbler = new Thread (() -> {
118- try (BufferedReader reader =
119- new BufferedReader (new InputStreamReader (process .getInputStream ()))) {
120- String line ;
121- while ((line = reader .readLine ()) != null ) {
122- output .append (line ).append ("\n " );
123- }
113+ .map (problem -> {
114+ Callable <TestResult > task = () -> {
115+ Thread .currentThread ().setName ("Problem-Runner-" + problem );
116+ String command = String .format ("mvn exec:exec -Dproblem=%s" , problem );
117+ System .out .println (Thread .currentThread ().getName () + ": Executing command for " + problem
118+ + ": " + command );
119+
120+ Process process ;
121+ try {
122+ process = Runtime .getRuntime ().exec (command );
124123 } catch (Exception e ) {
125- System . err . println ( Thread . currentThread (). getName () + ": Error reading output for "
126- + problem + " : " + e .getMessage ());
124+ return new TestResult (
125+ problem , false , "" , "Failed to execute command : " + e .getMessage (), e );
127126 }
128- });
129-
130- Thread errorGobbler = new Thread (() -> {
131- try (BufferedReader errorReader =
132- new BufferedReader (new InputStreamReader (process .getErrorStream ()))) {
133- String line ;
134- while ((line = errorReader .readLine ()) != null ) {
135- errorOutput .append (line ).append ("\n " );
127+
128+ StringBuilder output = new StringBuilder ();
129+ StringBuilder errorOutput = new StringBuilder ();
130+
131+ Thread outputGobbler = new Thread (() -> {
132+ try (BufferedReader reader =
133+ new BufferedReader (new InputStreamReader (process .getInputStream ()))) {
134+ String line ;
135+ while ((line = reader .readLine ()) != null ) {
136+ output .append (line ).append ("\n " );
137+ }
138+ } catch (Exception e ) {
139+ System .err .println (Thread .currentThread ().getName () + ": Error reading output for "
140+ + problem + ": " + e .getMessage ());
136141 }
137- } catch (Exception e ) {
138- System .err .println (Thread .currentThread ().getName ()
139- + ": Error reading error output for " + problem + ": " + e .getMessage ());
140- }
141- });
142+ });
143+
144+ Thread errorGobbler = new Thread (() -> {
145+ try (BufferedReader errorReader =
146+ new BufferedReader (new InputStreamReader (process .getErrorStream ()))) {
147+ String line ;
148+ while ((line = errorReader .readLine ()) != null ) {
149+ errorOutput .append (line ).append ("\n " );
150+ }
151+ } catch (Exception e ) {
152+ System .err .println (Thread .currentThread ().getName ()
153+ + ": Error reading error output for " + problem + ": " + e .getMessage ());
154+ }
155+ });
142156
143- outputGobbler .start ();
144- errorGobbler .start ();
157+ outputGobbler .start ();
158+ errorGobbler .start ();
145159
146- boolean completed ;
147- try {
148- completed = process .waitFor (TEST_TIMEOUT .toSeconds (), TimeUnit .SECONDS );
149- outputGobbler .join (100 );
150- errorGobbler .join (100 );
151- } catch (InterruptedException e ) {
152- process .destroyForcibly ();
153- outputGobbler .join (100 );
154- errorGobbler .join (100 );
155- Thread .currentThread ().interrupt ();
156- return new TestResult (
157- problem , false , output .toString (), "Test interrupted" , e );
158- }
160+ boolean completed ;
161+ try {
162+ completed = process .waitFor (TEST_TIMEOUT .toSeconds (), TimeUnit .SECONDS );
163+ outputGobbler .join (100 );
164+ errorGobbler .join (100 );
165+ } catch (InterruptedException e ) {
166+ process .destroyForcibly ();
167+ outputGobbler .join (100 );
168+ errorGobbler .join (100 );
169+ Thread .currentThread ().interrupt ();
170+ return new TestResult (problem , false , output .toString (), "Test interrupted" , e );
171+ }
172+
173+ if (!completed ) {
174+ process .destroy ();
175+ if (process .isAlive ()) {
176+ process .destroyForcibly ();
177+ }
178+ outputGobbler .join (100 );
179+ errorGobbler .join (100 );
180+ return new TestResult (
181+ problem ,
182+ false ,
183+ output .toString (),
184+ "Process timed out after " + TEST_TIMEOUT .toSeconds () + " seconds" ,
185+ null );
186+ }
159187
160- if (!completed ) {
161- process .destroy ();
162- if (process .isAlive ()) {
188+ int exitCode ;
189+ try {
190+ exitCode = process .exitValue ();
191+ } catch (IllegalThreadStateException e ) {
163192 process .destroyForcibly ();
193+ return new TestResult (
194+ problem , false , output .toString (), "Process did not terminate properly" , e );
164195 }
165- outputGobbler .join (100 );
166- errorGobbler .join (100 );
167- return new TestResult (
168- problem , false , output .toString (), "Process timed out after " + TEST_TIMEOUT .toSeconds () + " seconds" , null );
169- }
170196
171- int exitCode ;
197+ boolean success = (exitCode == 0 );
198+ return new TestResult (problem , success , output .toString (), errorOutput .toString (), null );
199+ };
200+ return executor .submit (task );
201+ })
202+ .collect (Collectors .toList ());
203+
204+ Collection <DynamicTest > dynamicTests = futures .stream ()
205+ .map (future -> DynamicTest .dynamicTest ("Test problem: " + future .toString (), () -> {
206+ TestResult result = null ;
172207 try {
173- exitCode = process .exitValue ();
174- } catch (IllegalThreadStateException e ) {
175- process .destroyForcibly ();
176- return new TestResult (
177- problem , false , output .toString (), "Process did not terminate properly" , e );
178- }
208+ result = future .get ();
179209
180- boolean success = (exitCode == 0 );
181- return new TestResult (problem , success , output .toString (), errorOutput .toString (), null );
182- };
183- return executor .submit (task );
184- })
185- .collect (Collectors .toList ());
210+ System .out .println ("Test " + result .problemName + " completed. Output:\n " + result .output );
211+ if (!result .errorOutput .isEmpty ()) {
212+ System .err .println ("Test " + result .problemName + " error output:\n " + result .errorOutput );
213+ }
186214
187- Collection <DynamicTest > dynamicTests = futures .stream ()
188- .map (future -> DynamicTest .dynamicTest ("Test problem: " + future .toString (), () -> {
189- TestResult result = null ;
190- try {
191- result = future .get ();
192-
193- System .out .println ("Test " + result .problemName + " completed. Output:\n " + result .output );
194- if (!result .errorOutput .isEmpty ()) {
195- System .err .println ("Test " + result .problemName + " error output:\n " + result .errorOutput );
196- }
215+ Assertions .assertTrue (
216+ result .success ,
217+ "Maven command failed for problem: " + result .problemName + "\n Error output:\n "
218+ + result .errorOutput );
197219
198- Assertions .assertTrue (
199- result .success ,
200- "Maven command failed for problem: " + result .problemName + "\n Error output:\n "
201- + result .errorOutput );
202-
203- } catch (InterruptedException e ) {
204- Thread .currentThread ().interrupt ();
205- Assertions .fail (
206- "Test for problem " + (result != null ? result .problemName : "unknown" )
207- + " was interrupted." ,
208- e );
209- } catch (ExecutionException e ) {
210- Throwable cause = e .getCause ();
211- Assertions .fail (
212- "An error occurred during execution for problem "
213- + (result != null ? result .problemName : "unknown" ) + ": " + cause .getMessage (),
214- cause );
215- }
216- }))
217- .collect (Collectors .toList ());
220+ } catch (InterruptedException e ) {
221+ Thread .currentThread ().interrupt ();
222+ Assertions .fail (
223+ "Test for problem " + (result != null ? result .problemName : "unknown" )
224+ + " was interrupted." ,
225+ e );
226+ } catch (ExecutionException e ) {
227+ Throwable cause = e .getCause ();
228+ Assertions .fail (
229+ "An error occurred during execution for problem "
230+ + (result != null ? result .problemName : "unknown" ) + ": " + cause .getMessage (),
231+ cause );
232+ }
233+ }))
234+ .collect (Collectors .toList ());
218235
219236 executor .shutdown ();
220237 try {
@@ -249,4 +266,4 @@ public String toString() {
249266 return problemName ;
250267 }
251268 }
252- }
269+ }
0 commit comments