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.core.source32;
18  
19  import org.junit.jupiter.api.Assertions;
20  import org.junit.jupiter.api.Test;
21  import org.junit.jupiter.params.ParameterizedTest;
22  import org.junit.jupiter.params.provider.CsvSource;
23  
24  /**
25   * The tests the caching of calls to {@link IntProvider#nextInt()} are used as
26   * the source for {@link IntProvider#nextInt()} and
27   * {@link IntProvider#nextBoolean()}.
28   */
29  class IntProviderTest {
30      /**
31       * A simple class to flip the bits in a number as the source for
32       * {@link IntProvider#next()}.
33       */
34      static final class FlipIntProvider extends IntProvider {
35          /** The value. */
36          private int value;
37  
38          /**
39           * @param value the value
40           */
41          FlipIntProvider(int value) {
42              // Flip the bits so the first call to next() returns to the same state
43              this.value = ~value;
44          }
45  
46          @Override
47          public int next() {
48              // Flip the bits
49              value = ~value;
50              return value;
51          }
52      }
53  
54      /**
55       * This test ensures that the call to {@link IntProvider#nextBoolean()} returns
56       * each of the bits from a call to {@link IntProvider#nextInt()}.
57       *
58       * <p>The order should be from the least-significant bit.
59       */
60      @Test
61      void testNextBoolean() {
62          for (int i = 0; i < Integer.SIZE; i++) {
63              // Set only a single bit in the source
64              final int value = 1 << i;
65              final IntProvider provider = new FlipIntProvider(value);
66              // Test the result for a single pass over the long
67              for (int j = 0; j < Integer.SIZE; j++) {
68                  final boolean expected = i == j;
69                  final int index = j;
70                  Assertions.assertEquals(expected, provider.nextBoolean(), () -> "Pass 1, bit " + index);
71              }
72              // The second pass should use the opposite bits
73              for (int j = 0; j < Integer.SIZE; j++) {
74                  final boolean expected = i != j;
75                  final int index = j;
76                  Assertions.assertEquals(expected, provider.nextBoolean(), () -> "Pass 2, bit " + index);
77              }
78          }
79      }
80  
81      @ParameterizedTest
82      @CsvSource({
83          // OK
84          "10, 0, 10",
85          "10, 5, 5",
86          "10, 9, 1",
87          // Allowed edge cases
88          "0, 0, 0",
89          "10, 10, 0",
90          // Bad
91          "10, 0, 11",
92          "10, 10, 1",
93          "10, 10, 2147483647",
94          "10, 0, -1",
95          "10, 5, -1",
96      })
97      void testNextBytesIndices(int size, int start, int len) {
98          final FlipIntProvider rng = new FlipIntProvider(999);
99          final byte[] bytes = new byte[size];
100         // Be consistent with System.arraycopy
101         try {
102             System.arraycopy(bytes, start, bytes, start, len);
103         } catch (IndexOutOfBoundsException ex) {
104             // nextBytes should throw under the same conditions.
105             // Note: This is not ArrayIndexOutOfBoundException to be
106             // future compatible with Objects.checkFromIndexSize.
107             Assertions.assertThrows(IndexOutOfBoundsException.class, () ->
108                 rng.nextBytes(bytes, start, len));
109             return;
110         }
111         rng.nextBytes(bytes, start, len);
112     }
113 }