/* * * Copyright 2016 Robert Winkler and Bohdan Storozhuk * * Licensed 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 io.github.resilience4j.circuitbreaker.internal; import static org.assertj.core.api.Assertions.assertThat; import org.junit.Test; import java.util.concurrent.ThreadLocalRandom; import java.util.stream.IntStream; import java.util.stream.Stream; public class RingBitSetTest { @Test public void testRingBitSet() { RingBitSet ringBitSet = new RingBitSet(4); // The initial index is -1 assertThat(ringBitSet.getIndex()).isEqualTo(-1); assertThat(ringBitSet.setNextBit(true)).isEqualTo(1); assertThat(ringBitSet.getIndex()).isEqualTo(0); assertThat(ringBitSet.setNextBit(false)).isEqualTo(1); assertThat(ringBitSet.getIndex()).isEqualTo(1); assertThat(ringBitSet.setNextBit(true)).isEqualTo(2); assertThat(ringBitSet.getIndex()).isEqualTo(2); assertThat(ringBitSet.setNextBit(true)).isEqualTo(3); assertThat(ringBitSet.getIndex()).isEqualTo(3); assertThat(ringBitSet.setNextBit(false)).isEqualTo(2); // The index has reached the maximum size and is set back to 0 assertThat(ringBitSet.getIndex()).isEqualTo(0); assertThat(ringBitSet.setNextBit(false)).isEqualTo(2); assertThat(ringBitSet.getIndex()).isEqualTo(1); // The cardinality must be 2 because the first true was overwritten by the 5th setNextBit() assertThat(ringBitSet.cardinality()).isEqualTo(2); // The size is 64-bit, because the bits are stored in an array of one long value assertThat(ringBitSet.size()).isEqualTo(64); // The length must be 4, because the ring bit set contains 4 entries assertThat(ringBitSet.length()).isEqualTo(4); } @Test public void testRingBitSetParallel() { System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", "20"); RingBitSet ringBitSet = new RingBitSet(1000); IntStream.range(0, 1000).parallel().forEach((i) -> { if (i < 500) { ringBitSet.setNextBit(true); } else { ringBitSet.setNextBit(false); } }); // The cardinality must be 500 assertThat(ringBitSet.cardinality()).isEqualTo(500); // The size is 1024-bit, because the bits are stored in an array of 16 long values assertThat(ringBitSet.size()).isEqualTo(1024); // The length must be 1000, because the ring bit set contains 1000 entries assertThat(ringBitSet.length()).isEqualTo(1000); } @Test public void testRingBitSetWithSlightlyLessCapacity() { RingBitSet ringBitSet = new RingBitSet(100); long expectedCardinality = Stream.generate(ThreadLocalRandom.current()::nextBoolean) .limit(1000) .peek(ringBitSet::setNextBit) .skip(900) .mapToInt(b -> b ? 1 : 0) .sum(); assertThat(ringBitSet.cardinality()).isEqualTo((int) expectedCardinality); assertThat(ringBitSet.size()).isEqualTo(128); assertThat(ringBitSet.length()).isEqualTo(100); } @Test public void testRingBitSetCopyFromTheSameSize() { RingBitSet sourceSet = new RingBitSet(4); // The initial index is -1 assertThat(sourceSet.getIndex()).isEqualTo(-1); assertThat(sourceSet.toString()).isEqualTo("0000"); assertThat(sourceSet.setNextBit(true)).isEqualTo(1); assertThat(sourceSet.toString()).isEqualTo("1000"); assertThat(sourceSet.getIndex()).isEqualTo(0); assertThat(sourceSet.setNextBit(false)).isEqualTo(1); assertThat(sourceSet.toString()).isEqualTo("1000"); assertThat(sourceSet.getIndex()).isEqualTo(1); assertThat(sourceSet.setNextBit(true)).isEqualTo(2); assertThat(sourceSet.toString()).isEqualTo("1010"); assertThat(sourceSet.getIndex()).isEqualTo(2); assertThat(sourceSet.setNextBit(true)).isEqualTo(3); assertThat(sourceSet.toString()).isEqualTo("1011"); assertThat(sourceSet.getIndex()).isEqualTo(3); assertThat(sourceSet.setNextBit(false)).isEqualTo(2); assertThat(sourceSet.toString()).isEqualTo("0011"); // The index has reached the maximum size and is set back to 0 assertThat(sourceSet.getIndex()).isEqualTo(0); assertThat(sourceSet.setNextBit(false)).isEqualTo(2); assertThat(sourceSet.toString()).isEqualTo("0011"); assertThat(sourceSet.getIndex()).isEqualTo(1); RingBitSet setCopy = new RingBitSet(4, sourceSet); assertThat(setCopy.getIndex()).isEqualTo(3); assertThat(setCopy.toString()).isEqualTo("0011"); assertThat(setCopy.cardinality()).isEqualTo(2); // The size is 64-bit, because the bits are stored in an array of one long value assertThat(setCopy.size()).isEqualTo(64); // The length must be 4, because the ring bit set contains 4 entries assertThat(setCopy.length()).isEqualTo(4); } @Test public void testRingBitSetCopyFromTheLongerSet() { RingBitSet sourceSet = new RingBitSet(5); // The initial index is -1 assertThat(sourceSet.getIndex()).isEqualTo(-1); assertThat(sourceSet.toString()).isEqualTo("00000"); assertThat(sourceSet.setNextBit(true)).isEqualTo(1); assertThat(sourceSet.toString()).isEqualTo("10000"); assertThat(sourceSet.getIndex()).isEqualTo(0); assertThat(sourceSet.setNextBit(false)).isEqualTo(1); assertThat(sourceSet.toString()).isEqualTo("10000"); assertThat(sourceSet.getIndex()).isEqualTo(1); assertThat(sourceSet.setNextBit(true)).isEqualTo(2); assertThat(sourceSet.toString()).isEqualTo("10100"); assertThat(sourceSet.getIndex()).isEqualTo(2); assertThat(sourceSet.setNextBit(true)).isEqualTo(3); assertThat(sourceSet.toString()).isEqualTo("10110"); assertThat(sourceSet.getIndex()).isEqualTo(3); assertThat(sourceSet.setNextBit(false)).isEqualTo(3); assertThat(sourceSet.toString()).isEqualTo("10110"); assertThat(sourceSet.getIndex()).isEqualTo(4); assertThat(sourceSet.setNextBit(false)).isEqualTo(2); assertThat(sourceSet.toString()).isEqualTo("00110"); // The index has reached the maximum size and is set back to 0 assertThat(sourceSet.getIndex()).isEqualTo(0); assertThat(sourceSet.setNextBit(true)).isEqualTo(3); assertThat(sourceSet.toString()).isEqualTo("01110"); assertThat(sourceSet.getIndex()).isEqualTo(1); RingBitSet setCopy = new RingBitSet(4, sourceSet); assertThat(setCopy.getIndex()).isEqualTo(3); assertThat(setCopy.toString()).isEqualTo("1001"); assertThat(setCopy.cardinality()).isEqualTo(2); // The size is 64-bit, because the bits are stored in an array of one long value assertThat(setCopy.size()).isEqualTo(64); // The length must be 4, because the ring bit set contains 4 entries assertThat(setCopy.length()).isEqualTo(4); } @Test public void testRingBitSetCopyFromTheShorterSet() { RingBitSet sourceSet = new RingBitSet(3); // The initial index is -1 assertThat(sourceSet.getIndex()).isEqualTo(-1); assertThat(sourceSet.toString()).isEqualTo("000"); assertThat(sourceSet.setNextBit(true)).isEqualTo(1); assertThat(sourceSet.toString()).isEqualTo("100"); assertThat(sourceSet.getIndex()).isEqualTo(0); assertThat(sourceSet.setNextBit(false)).isEqualTo(1); assertThat(sourceSet.toString()).isEqualTo("100"); assertThat(sourceSet.getIndex()).isEqualTo(1); assertThat(sourceSet.setNextBit(true)).isEqualTo(2); assertThat(sourceSet.toString()).isEqualTo("101"); assertThat(sourceSet.getIndex()).isEqualTo(2); assertThat(sourceSet.setNextBit(true)).isEqualTo(2); assertThat(sourceSet.toString()).isEqualTo("101"); assertThat(sourceSet.getIndex()).isEqualTo(0); assertThat(sourceSet.setNextBit(false)).isEqualTo(2); assertThat(sourceSet.toString()).isEqualTo("101"); assertThat(sourceSet.getIndex()).isEqualTo(1); RingBitSet setCopy = new RingBitSet(4, sourceSet); assertThat(setCopy.getIndex()).isEqualTo(2); assertThat(setCopy.toString()).isEqualTo("0110"); assertThat(setCopy.cardinality()).isEqualTo(2); // The size is 64-bit, because the bits are stored in an array of one long value assertThat(setCopy.size()).isEqualTo(64); // The length must be 3, because the ring bit set contains only 3 entries after copying assertThat(setCopy.length()).isEqualTo(3); } }