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.source64;
18  
19  import org.apache.commons.rng.core.util.NumberFactory;
20  import org.junit.jupiter.api.Assertions;
21  import org.junit.jupiter.api.Test;
22  import org.junit.jupiter.params.ParameterizedTest;
23  import org.junit.jupiter.params.provider.CsvSource;
24  
25  /**
26   * The tests the caching of calls to {@link LongProvider#nextLong()} are used as
27   * the source for {@link LongProvider#nextInt()} and
28   * {@link LongProvider#nextBoolean()}.
29   */
30  class LongProviderTest {
31      /**
32       * A simple class to return a fixed value as the source for
33       * {@link LongProvider#next()}.
34       */
35      static final class FixedLongProvider extends LongProvider {
36          /** The value. */
37          private long value;
38  
39          /**
40           * @param value the value
41           */
42          FixedLongProvider(long value) {
43              this.value = value;
44          }
45  
46          @Override
47          public long next() {
48              return value;
49          }
50      }
51  
52      /**
53       * A simple class to flip the bits in a number as the source for
54       * {@link LongProvider#next()}.
55       */
56      static final class FlipLongProvider extends LongProvider {
57          /** The value. */
58          private long value;
59  
60          /**
61           * @param value the value
62           */
63          FlipLongProvider(long value) {
64              // Flip the bits so the first call to next() returns to the same state
65              this.value = ~value;
66          }
67  
68          @Override
69          public long next() {
70              // Flip the bits
71              value = ~value;
72              return value;
73          }
74      }
75  
76      /**
77       * This test ensures that the call to {@link LongProvider#nextInt()} returns the
78       * lower and then upper 32-bits from {@link LongProvider#nextLong()}.
79       */
80      @Test
81      void testNextInt() {
82          final int max = 5;
83          for (int i = 0; i < max; i++) {
84              for (int j = 0; j < max; j++) {
85                  // Pack into lower then upper bits
86                  final long value = NumberFactory.makeLong(j, i);
87                  final LongProvider provider = new FixedLongProvider(value);
88                  Assertions.assertEquals(i, provider.nextInt(), "1st call not the upper 32-bits");
89                  Assertions.assertEquals(j, provider.nextInt(), "2nd call not the lower 32-bits");
90                  Assertions.assertEquals(i, provider.nextInt(), "3rd call not the upper 32-bits");
91                  Assertions.assertEquals(j, provider.nextInt(), "4th call not the lower 32-bits");
92              }
93          }
94      }
95  
96      /**
97       * This test ensures that the call to {@link LongProvider#nextBoolean()} returns
98       * each of the bits from a call to {@link LongProvider#nextLong()}.
99       *
100      * <p>The order should be from the least-significant bit.
101      */
102     @Test
103     void testNextBoolean() {
104         for (int i = 0; i < Long.SIZE; i++) {
105             // Set only a single bit in the source
106             final long value = 1L << i;
107             final LongProvider provider = new FlipLongProvider(value);
108             // Test the result for a single pass over the long
109             for (int j = 0; j < Long.SIZE; j++) {
110                 final boolean expected = i == j;
111                 final int index = j;
112                 Assertions.assertEquals(expected, provider.nextBoolean(), () -> "Pass 1, bit " + index);
113             }
114             // The second pass should use the opposite bits
115             for (int j = 0; j < Long.SIZE; j++) {
116                 final boolean expected = i != j;
117                 final int index = j;
118                 Assertions.assertEquals(expected, provider.nextBoolean(), () -> "Pass 2, bit " + index);
119             }
120         }
121     }
122 
123     @ParameterizedTest
124     @CsvSource({
125         // OK
126         "10, 0, 10",
127         "10, 5, 5",
128         "10, 9, 1",
129         // Allowed edge cases
130         "0, 0, 0",
131         "10, 10, 0",
132         // Bad
133         "10, 0, 11",
134         "10, 10, 1",
135         "10, 10, 2147483647",
136         "10, 0, -1",
137         "10, 5, -1",
138     })
139     void testNextBytesIndices(int size, int start, int len) {
140         final FixedLongProvider rng = new FixedLongProvider(999);
141         final byte[] bytes = new byte[size];
142         // Be consistent with System.arraycopy
143         try {
144             System.arraycopy(bytes, start, bytes, start, len);
145         } catch (IndexOutOfBoundsException ex) {
146             // nextBytes should throw under the same conditions.
147             // Note: This is not ArrayIndexOutOfBoundException to be
148             // future compatible with Objects.checkFromIndexSize.
149             Assertions.assertThrows(IndexOutOfBoundsException.class, () ->
150                 rng.nextBytes(bytes, start, len));
151             return;
152         }
153         rng.nextBytes(bytes, start, len);
154     }
155 }