View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.rng.simple;
18  
19  import org.apache.commons.rng.UniformRandomProvider;
20  import org.junit.Assert;
21  import org.junit.BeforeClass;
22  import org.junit.Test;
23  
24  import java.util.EnumSet;
25  import java.util.concurrent.ExecutionException;
26  import java.util.concurrent.ExecutorService;
27  import java.util.concurrent.Executors;
28  import java.util.concurrent.Future;
29  import java.util.concurrent.TimeUnit;
30  import java.util.concurrent.TimeoutException;
31  
32  /**
33   * Tests for {@link ThreadLocalRandomSource}.
34   */
35  public class ThreadLocalRandomSourceTest {
36      /**
37       * A set of all the RandomSource options that requires arguments. This should be
38       * ignored in certain tests since they are not supported.
39       */
40      private static EnumSet<RandomSource> toIgnore;
41  
42      @BeforeClass
43      public static void createToIgnoreSet() {
44          toIgnore = EnumSet.of(RandomSource.TWO_CMRES_SELECT);
45      }
46  
47      @Test(expected = IllegalArgumentException.class)
48      public void testCurrentThrowsForNullRandomSource() {
49          ThreadLocalRandomSource.current(null);
50      }
51  
52      //@Test(expected = IllegalArgumentException.class)
53      public void testCurrentThrowsForRandomSourceWithDataArguments() {
54          ThreadLocalRandomSource.current(RandomSource.TWO_CMRES_SELECT);
55      }
56  
57      @Test
58      public void testCurrentForAllRandomSources()
59              throws InterruptedException, ExecutionException, TimeoutException {
60          final RandomSource[] sources = RandomSource.values();
61          final UniformRandomProvider[] rngs = new UniformRandomProvider[sources.length];
62  
63          for (int i = 0; i < sources.length; i++) {
64              if (toIgnore.contains(sources[i])) {
65                  continue;
66              }
67              final UniformRandomProvider rng = getCurrent(sources[i]);
68              Assert.assertNotNull("Failed to create source: " + sources[i], rng);
69              rngs[i] = rng;
70          }
71          for (int i = 0; i < sources.length; i++) {
72              if (toIgnore.contains(sources[i])) {
73                  continue;
74              }
75              final UniformRandomProvider rng = getCurrent(sources[i]);
76              Assert.assertSame("Failed to return same source: " + sources[i], rngs[i], rng);
77          }
78  
79          // Build on a new thread
80          final UniformRandomProvider[] rngs2 = new UniformRandomProvider[rngs.length];
81          final ExecutorService executor = Executors.newFixedThreadPool(1);
82          final Future<?> future = executor.submit(
83              new Runnable() {
84                  @Override
85                  public void run() {
86                      for (int i = 0; i < sources.length; i++) {
87                          if (toIgnore.contains(sources[i])) {
88                              continue;
89                          }
90                          rngs2[i] = getCurrent(sources[i]);
91                      }
92                  }
93              });
94  
95          // Shutdown and wait for task to end
96          executor.shutdown();
97          future.get(30, TimeUnit.SECONDS);
98  
99          // The RNG from the new thread should be different
100         for (int i = 0; i < sources.length; i++) {
101             if (toIgnore.contains(sources[i])) {
102                 continue;
103             }
104             Assert.assertNotSame("Failed to return different source: " + sources[i], rngs[i], rngs2[i]);
105         }
106     }
107 
108     private static UniformRandomProvider getCurrent(RandomSource source) {
109         try {
110             return ThreadLocalRandomSource.current(source);
111         } catch (final RuntimeException ex) {
112             throw new RuntimeException("Failed to get current: " + source, ex);
113         }
114     }
115 }