|  | @@ -17,6 +17,7 @@ import com.carrotsearch.randomizedtesting.annotations.Timeout;
 | 
	
		
			
				|  |  |  import org.apache.logging.log4j.LogManager;
 | 
	
		
			
				|  |  |  import org.apache.logging.log4j.Logger;
 | 
	
		
			
				|  |  |  import org.elasticsearch.common.CheckedConsumer;
 | 
	
		
			
				|  |  | +import org.elasticsearch.common.CheckedRunnable;
 | 
	
		
			
				|  |  |  import org.elasticsearch.core.internal.io.IOUtils;
 | 
	
		
			
				|  |  |  import org.elasticsearch.packaging.util.Archives;
 | 
	
		
			
				|  |  |  import org.elasticsearch.packaging.util.Distribution;
 | 
	
	
		
			
				|  | @@ -51,9 +52,11 @@ import java.nio.file.StandardCopyOption;
 | 
	
		
			
				|  |  |  import java.nio.file.StandardOpenOption;
 | 
	
		
			
				|  |  |  import java.nio.file.attribute.FileAttribute;
 | 
	
		
			
				|  |  |  import java.nio.file.attribute.PosixFilePermissions;
 | 
	
		
			
				|  |  | +import java.util.ArrayList;
 | 
	
		
			
				|  |  |  import java.util.Collections;
 | 
	
		
			
				|  |  |  import java.util.List;
 | 
	
		
			
				|  |  |  import java.util.Locale;
 | 
	
		
			
				|  |  | +import java.util.concurrent.TimeUnit;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  import static org.elasticsearch.packaging.util.Cleanup.cleanEverything;
 | 
	
		
			
				|  |  |  import static org.elasticsearch.packaging.util.Docker.ensureImageIsLoaded;
 | 
	
	
		
			
				|  | @@ -467,4 +470,44 @@ public abstract class PackagingTestCase extends Assert {
 | 
	
		
			
				|  |  |              );
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * Runs the code block for 10 seconds waiting for no assertion to trip.
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public static void assertBusy(CheckedRunnable<Exception> codeBlock) throws Exception {
 | 
	
		
			
				|  |  | +        assertBusy(codeBlock, 10, TimeUnit.SECONDS);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * Runs the code block for the provided interval, waiting for no assertions to trip.
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    public static void assertBusy(CheckedRunnable<Exception> codeBlock, long maxWaitTime, TimeUnit unit) throws Exception {
 | 
	
		
			
				|  |  | +        long maxTimeInMillis = TimeUnit.MILLISECONDS.convert(maxWaitTime, unit);
 | 
	
		
			
				|  |  | +        // In case you've forgotten your high-school studies, log10(x) / log10(y) == log y(x)
 | 
	
		
			
				|  |  | +        long iterations = Math.max(Math.round(Math.log10(maxTimeInMillis) / Math.log10(2)), 1);
 | 
	
		
			
				|  |  | +        long timeInMillis = 1;
 | 
	
		
			
				|  |  | +        long sum = 0;
 | 
	
		
			
				|  |  | +        List<AssertionError> failures = new ArrayList<>();
 | 
	
		
			
				|  |  | +        for (int i = 0; i < iterations; i++) {
 | 
	
		
			
				|  |  | +            try {
 | 
	
		
			
				|  |  | +                codeBlock.run();
 | 
	
		
			
				|  |  | +                return;
 | 
	
		
			
				|  |  | +            } catch (AssertionError e) {
 | 
	
		
			
				|  |  | +                failures.add(e);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            sum += timeInMillis;
 | 
	
		
			
				|  |  | +            Thread.sleep(timeInMillis);
 | 
	
		
			
				|  |  | +            timeInMillis *= 2;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        timeInMillis = maxTimeInMillis - sum;
 | 
	
		
			
				|  |  | +        Thread.sleep(Math.max(timeInMillis, 0));
 | 
	
		
			
				|  |  | +        try {
 | 
	
		
			
				|  |  | +            codeBlock.run();
 | 
	
		
			
				|  |  | +        } catch (AssertionError e) {
 | 
	
		
			
				|  |  | +            for (AssertionError failure : failures) {
 | 
	
		
			
				|  |  | +                e.addSuppressed(failure);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            throw e;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  }
 |