/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.activemq.artemis.tests.unit.core.util; import java.util.HashSet; import org.apache.activemq.artemis.tests.util.SpawnedVMSupport; import org.apache.activemq.artemis.utils.RandomUtil; import org.junit.Assert; import org.junit.Test; /** * This test will start many parallel VMs, to make sure each VM would generate a good distribution of random numbers */ public class RandomUtilDistributionTest { public static void main(String[] arg) { long start = Long.parseLong(arg[0]); try { Thread.sleep((start - System.currentTimeMillis()) / 2); } catch (Exception e) { } while (System.currentTimeMillis() < start) { Thread.yield(); } int value; value = RandomUtil.randomInterval(0, 255); System.exit(value); } @Test public void testDistribution() throws Exception { int numberOfStarts = 50; int iterations = 10; int value = 0; for (int i = 0; i < iterations; i++) { int v = internalDistributionTest(numberOfStarts); value += v; } // I'm using an extra parenthesis here to avoid rounding problems. // Be careful removing it (make sure you know what you're doing in case you do so) int minimumExpected = (int) ((iterations * numberOfStarts) * 0.80); System.out.println("value=" + value + ", minimum expected = " + minimumExpected); Assert.assertTrue("The Random distribution is pretty bad. All tries have returned duplicated randoms. value=" + value + ", minimum expected = " + minimumExpected, value > minimumExpected); } private int internalDistributionTest(int numberOfTries) throws Exception { long timeStart = System.currentTimeMillis() + 5000; Process[] process = new Process[numberOfTries]; int[] value = new int[numberOfTries]; try { for (int i = 0; i < numberOfTries; i++) { process[i] = SpawnedVMSupport.spawnVM(RandomUtilDistributionTest.class.getName(), true, "" + timeStart); } HashSet<Integer> valueSet = new HashSet<>(); for (int i = 0; i < numberOfTries; i++) { value[i] = process[i].waitFor(); Assert.assertTrue(value[i] >= 0); valueSet.add(process[i].exitValue()); } System.out.println("Generated " + valueSet.size() + " randoms out of " + numberOfTries + " tries"); return valueSet.size(); } finally { for (Process p : process) { if (p != null) { p.destroy(); } } } } }