3636import org .json .JSONException ;
3737import org .json .JSONObject ;
3838import org .junit .Assert ;
39+ import org .junit .Assume ;
3940import org .junit .experimental .categories .Category ;
4041import org .labkey .remoteapi .CommandException ;
4142import org .labkey .remoteapi .CommandResponse ;
6970import java .util .List ;
7071import java .util .Map ;
7172import java .util .Set ;
73+ import java .util .concurrent .atomic .AtomicInteger ;
7274import java .util .function .Predicate ;
7375
7476@ Category ({BVT .class , UnitTests .class })
@@ -318,6 +320,7 @@ else if (responseBody.contains("<title>Upgrade Status</title>") ||
318320 boolean addedHeader = false ;
319321 for (String key : json .keySet ())
320322 {
323+ AtomicInteger ioeCounter = new AtomicInteger (0 );
321324 TestSuite testsuite = new TestSuite (key );
322325 JSONArray testClassArray = json .getJSONArray (key );
323326 // Individual tests include both the class name and the requested timeout
@@ -331,7 +334,7 @@ else if (responseBody.contains("<title>Upgrade Status</title>") ||
331334 // Timeout is represented in seconds
332335 int timeout = testClass .getInt ("timeout" );
333336 if (accept .test (testClass .toMap ()))
334- testsuite .addTest (new RemoteTest (className , timeout ));
337+ testsuite .addTest (new RemoteTest (className , timeout , ioeCounter ));
335338 }
336339
337340 }
@@ -370,23 +373,27 @@ else if (responseBody.contains("<title>Upgrade Status</title>") ||
370373 @ SuppressWarnings ("JUnitMalformedDeclaration" )
371374 public static class RemoteTest extends TestCase
372375 {
373- String _remoteClass ;
376+ private final String _remoteClass ;
374377 /** Timeout in seconds to wait for the whole testcase to finish on the server */
375378 private final int _timeout ;
379+ // Skip tests after a certain number of IOExceptions
380+ private final AtomicInteger _ioeCounter ;
376381
377382 /** Stash and reuse so that we can keep using the same session instead of re-authenticating with every request */
378383 private static final Connection connection = WebTestHelper .getRemoteApiConnection ();
379384
380- public RemoteTest (String remoteClass , int timeout )
385+ public RemoteTest (String remoteClass , int timeout , AtomicInteger ioeCounter )
381386 {
382387 super (remoteClass );
383388 _remoteClass = remoteClass ;
384389 _timeout = timeout ;
390+ _ioeCounter = ioeCounter ;
385391 }
386392
387393 @ Override
388394 protected void runTest ()
389395 {
396+ Assume .assumeTrue ("Too many consecutive test timeouts" , _ioeCounter .get () < 5 );
390397 long startTime = System .currentTimeMillis ();
391398 try
392399 {
@@ -405,16 +412,19 @@ else if (resultJson.get("wasSuccessful") != Boolean.TRUE)
405412 WebTestHelper .logToServer (getLogTestString ("successful" , startTime ) + ", " + dump (resultJson , false ), connection );
406413 LOG .info (getLogTestString ("successful" , startTime ));
407414 LOG .info (dump (resultJson , true ));
415+ _ioeCounter .set (0 );
408416 }
409417 catch (SocketTimeoutException ste )
410418 {
419+ _ioeCounter .incrementAndGet ();
411420 String timed_out = getLogTestString ("timed out" , startTime );
412421 LOG .error (timed_out );
413422 ArtifactCollector .dumpThreads ();
414423 throw new RuntimeException (timed_out , ste );
415424 }
416425 catch (IOException ioe )
417426 {
427+ _ioeCounter .incrementAndGet ();
418428 String message = getLogTestString ("failed: " + ioe .getMessage (), startTime );
419429 LOG .error (message );
420430 throw new RuntimeException (message , ioe );
0 commit comments