|
Java example source code file (EventCountCircuitBreakerTest.java)
The EventCountCircuitBreakerTest.java Java example source code/* * 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.commons.lang3.concurrent; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import org.junit.Test; /** * Test class for {@code EventCountCircuitBreaker}. */ public class EventCountCircuitBreakerTest { /** Constant for the opening threshold. */ private static final int OPENING_THRESHOLD = 10; /** Constant for the closing threshold. */ private static final int CLOSING_THRESHOLD = 5; /** Constant for the factor for converting nanoseconds. */ private static final long NANO_FACTOR = 1000L * 1000L * 1000L; /** * Tests that time units are correctly taken into account by constructors. */ @Test public void testIntervalCalculation() { EventCountCircuitBreaker breaker = new EventCountCircuitBreaker(OPENING_THRESHOLD, 1, TimeUnit.SECONDS, CLOSING_THRESHOLD, 2, TimeUnit.MILLISECONDS); assertEquals("Wrong opening interval", NANO_FACTOR, breaker.getOpeningInterval()); assertEquals("Wrong closing interval", 2 * NANO_FACTOR / 1000, breaker.getClosingInterval()); } /** * Tests that the closing interval is the same as the opening interval if it is not * specified. */ @Test public void testDefaultClosingInterval() { EventCountCircuitBreaker breaker = new EventCountCircuitBreaker(OPENING_THRESHOLD, 1, TimeUnit.SECONDS, CLOSING_THRESHOLD); assertEquals("Wrong closing interval", NANO_FACTOR, breaker.getClosingInterval()); } /** * Tests that the closing threshold is the same as the opening threshold if not * specified otherwise. */ @Test public void testDefaultClosingThreshold() { EventCountCircuitBreaker breaker = new EventCountCircuitBreaker(OPENING_THRESHOLD, 1, TimeUnit.SECONDS); assertEquals("Wrong closing interval", NANO_FACTOR, breaker.getClosingInterval()); assertEquals("Wrong closing threshold", OPENING_THRESHOLD, breaker.getClosingThreshold()); } /** * Tests that a circuit breaker is closed after its creation. */ @Test public void testInitiallyClosed() { EventCountCircuitBreaker breaker = new EventCountCircuitBreaker(OPENING_THRESHOLD, 1, TimeUnit.SECONDS); assertFalse("Open", breaker.isOpen()); assertTrue("Not closed", breaker.isClosed()); } /** * Tests whether the current time is correctly determined. */ @Test public void testNow() { EventCountCircuitBreaker breaker = new EventCountCircuitBreaker(OPENING_THRESHOLD, 1, TimeUnit.SECONDS); long now = breaker.now(); long delta = Math.abs(System.nanoTime() - now); assertTrue("Delta to current time too large", delta < 100000); } /** * Tests that the circuit breaker stays closed if the number of received events stays * below the threshold. */ @Test public void testNotOpeningUnderThreshold() { long startTime = 1000; EventCountCircuitBreakerTestImpl breaker = new EventCountCircuitBreakerTestImpl(OPENING_THRESHOLD, 1, TimeUnit.SECONDS, CLOSING_THRESHOLD, 1, TimeUnit.SECONDS); for (int i = 0; i < OPENING_THRESHOLD - 1; i++) { assertTrue("In open state", breaker.at(startTime).incrementAndCheckState()); startTime++; } assertTrue("Not closed", breaker.isClosed()); } /** * Tests that the circuit breaker stays closed if there are a number of received * events, but not in a single check interval. */ @Test public void testNotOpeningCheckIntervalExceeded() { long startTime = 0L; long timeIncrement = 3 * NANO_FACTOR / (2 * OPENING_THRESHOLD); EventCountCircuitBreakerTestImpl breaker = new EventCountCircuitBreakerTestImpl(OPENING_THRESHOLD, 1, TimeUnit.SECONDS, CLOSING_THRESHOLD, 1, TimeUnit.SECONDS); for (int i = 0; i < 5 * OPENING_THRESHOLD; i++) { assertTrue("In open state", breaker.at(startTime).incrementAndCheckState()); startTime += timeIncrement; } assertTrue("Not closed", breaker.isClosed()); } /** * Tests that the circuit breaker opens if all conditions are met. */ @Test public void testOpeningWhenThresholdReached() { long startTime = 0; long timeIncrement = NANO_FACTOR / OPENING_THRESHOLD - 1; EventCountCircuitBreakerTestImpl breaker = new EventCountCircuitBreakerTestImpl(OPENING_THRESHOLD, 1, TimeUnit.SECONDS, CLOSING_THRESHOLD, 1, TimeUnit.SECONDS); boolean open = false; for (int i = 0; i < OPENING_THRESHOLD + 1; i++) { open = !breaker.at(startTime).incrementAndCheckState(); startTime += timeIncrement; } assertTrue("Not open", open); assertFalse("Closed", breaker.isClosed()); } /** * Tests that an open circuit breaker does not close itself when the number of events * received is over the threshold. */ @Test public void testNotClosingOverThreshold() { EventCountCircuitBreakerTestImpl breaker = new EventCountCircuitBreakerTestImpl(OPENING_THRESHOLD, 10, TimeUnit.SECONDS, CLOSING_THRESHOLD, 1, TimeUnit.SECONDS); long startTime = 0; breaker.open(); for (int i = 0; i <= CLOSING_THRESHOLD; i++) { assertFalse("Not open", breaker.at(startTime).incrementAndCheckState()); startTime += 1000; } assertFalse("Closed in new interval", breaker.at(startTime + NANO_FACTOR) .incrementAndCheckState()); assertTrue("Not open at end", breaker.isOpen()); } /** * Tests that the circuit breaker closes automatically if the number of events * received goes under the closing threshold. */ @Test public void testClosingWhenThresholdReached() { EventCountCircuitBreakerTestImpl breaker = new EventCountCircuitBreakerTestImpl(OPENING_THRESHOLD, 10, TimeUnit.SECONDS, CLOSING_THRESHOLD, 1, TimeUnit.SECONDS); breaker.open(); breaker.at(1000).incrementAndCheckState(); assertFalse("Already closed", breaker.at(2000).checkState()); assertFalse("Closed at interval end", breaker.at(NANO_FACTOR).checkState()); assertTrue("Not closed after interval end", breaker.at(NANO_FACTOR + 1) .checkState()); assertTrue("Not closed at end", breaker.isClosed()); } /** * Tests whether an explicit open operation fully initializes the internal check data * object. Otherwise, the circuit breaker may close itself directly afterwards. */ @Test public void testOpenStartsNewCheckInterval() { EventCountCircuitBreakerTestImpl breaker = new EventCountCircuitBreakerTestImpl(OPENING_THRESHOLD, 2, TimeUnit.SECONDS, CLOSING_THRESHOLD, 1, TimeUnit.SECONDS); breaker.at(NANO_FACTOR - 1000).open(); assertTrue("Not open", breaker.isOpen()); assertFalse("Already closed", breaker.at(NANO_FACTOR + 100).checkState()); } /** * Tests whether a new check interval is started if the circuit breaker has a * transition to open state. */ @Test public void testAutomaticOpenStartsNewCheckInterval() { EventCountCircuitBreakerTestImpl breaker = new EventCountCircuitBreakerTestImpl(OPENING_THRESHOLD, 2, TimeUnit.SECONDS, CLOSING_THRESHOLD, 1, TimeUnit.SECONDS); long time = 10 * NANO_FACTOR; for (int i = 0; i <= OPENING_THRESHOLD; i++) { breaker.at(time++).incrementAndCheckState(); } assertTrue("Not open", breaker.isOpen()); time += NANO_FACTOR - 1000; assertFalse("Already closed", breaker.at(time).incrementAndCheckState()); time += 1001; assertTrue("Not closed in time interval", breaker.at(time).checkState()); } /** * Tests whether the circuit breaker can be closed explicitly. */ @Test public void testClose() { EventCountCircuitBreakerTestImpl breaker = new EventCountCircuitBreakerTestImpl(OPENING_THRESHOLD, 2, TimeUnit.SECONDS, CLOSING_THRESHOLD, 1, TimeUnit.SECONDS); long time = 0; for (int i = 0; i <= OPENING_THRESHOLD; i++, time += 1000) { breaker.at(time).incrementAndCheckState(); } assertTrue("Not open", breaker.isOpen()); breaker.close(); assertTrue("Not closed", breaker.isClosed()); assertTrue("Open again", breaker.at(time + 1000).incrementAndCheckState()); } /** * Tests whether events are generated when the state is changed. */ @Test public void testChangeEvents() { EventCountCircuitBreaker breaker = new EventCountCircuitBreaker(OPENING_THRESHOLD, 1, TimeUnit.SECONDS); ChangeListener listener = new ChangeListener(breaker); breaker.addChangeListener(listener); breaker.open(); breaker.close(); listener.verify(Boolean.TRUE, Boolean.FALSE); } /** * Tests whether a change listener can be removed. */ @Test public void testRemoveChangeListener() { EventCountCircuitBreaker breaker = new EventCountCircuitBreaker(OPENING_THRESHOLD, 1, TimeUnit.SECONDS); ChangeListener listener = new ChangeListener(breaker); breaker.addChangeListener(listener); breaker.open(); breaker.removeChangeListener(listener); breaker.close(); listener.verify(Boolean.TRUE); } /** * Tests that a state transition triggered by multiple threads is handled correctly. * Only the first transition should cause an event to be sent. */ @Test public void testStateTransitionGuarded() throws InterruptedException { final EventCountCircuitBreaker breaker = new EventCountCircuitBreaker(OPENING_THRESHOLD, 1, TimeUnit.SECONDS); ChangeListener listener = new ChangeListener(breaker); breaker.addChangeListener(listener); final int threadCount = 128; final CountDownLatch latch = new CountDownLatch(1); Thread[] threads = new Thread[threadCount]; for (int i = 0; i < threadCount; i++) { threads[i] = new Thread() { @Override public void run() { try { latch.await(); } catch (InterruptedException iex) { // ignore } breaker.open(); } }; threads[i].start(); } latch.countDown(); for (Thread thread : threads) { thread.join(); } listener.verify(Boolean.TRUE); } /** * Tests that automatic state transitions generate change events as well. */ @Test public void testChangeEventsGeneratedByAutomaticTransitions() { EventCountCircuitBreakerTestImpl breaker = new EventCountCircuitBreakerTestImpl(OPENING_THRESHOLD, 2, TimeUnit.SECONDS, CLOSING_THRESHOLD, 1, TimeUnit.SECONDS); ChangeListener listener = new ChangeListener(breaker); breaker.addChangeListener(listener); long time = 0; for (int i = 0; i <= OPENING_THRESHOLD; i++, time += 1000) { breaker.at(time).incrementAndCheckState(); } breaker.at(NANO_FACTOR + 1).checkState(); breaker.at(3 * NANO_FACTOR).checkState(); listener.verify(Boolean.TRUE, Boolean.FALSE); } /** * A test implementation of {@code EventCountCircuitBreaker} which supports mocking the timer. * This is useful for the creation of deterministic tests for switching the circuit * breaker's state. */ private static class EventCountCircuitBreakerTestImpl extends EventCountCircuitBreaker { /** The current time in nanoseconds. */ private long currentTime; public EventCountCircuitBreakerTestImpl(int openingThreshold, long openingInterval, TimeUnit openingUnit, int closingThreshold, long closingInterval, TimeUnit closingUnit) { super(openingThreshold, openingInterval, openingUnit, closingThreshold, closingInterval, closingUnit); } /** * Sets the current time to be used by this test object for the next operation. * * @param time the time to set * @return a reference to this object */ public EventCountCircuitBreakerTestImpl at(long time) { currentTime = time; return this; } /** * {@inheritDoc} This implementation returns the value passed to the {@code at()} * method. */ @Override long now() { return currentTime; } } /** * A test change listener for checking whether correct change events are generated. */ private static class ChangeListener implements PropertyChangeListener { /** The expected event source. */ private final Object expectedSource; /** A list with the updated values extracted from received change events. */ private final List<Boolean> changedValues; /** * Creates a new instance of {@code ChangeListener} and sets the expected event * source. * * @param source the expected event source */ public ChangeListener(Object source) { expectedSource = source; changedValues = new ArrayList<Boolean>(); } public void propertyChange(PropertyChangeEvent evt) { assertEquals("Wrong event source", expectedSource, evt.getSource()); assertEquals("Wrong property name", "open", evt.getPropertyName()); Boolean newValue = (Boolean) evt.getNewValue(); Boolean oldValue = (Boolean) evt.getOldValue(); assertNotEquals("Old and new value are equal", newValue, oldValue); changedValues.add(newValue); } /** * Verifies that change events for the expected values have been received. * * @param values the expected values */ public void verify(Boolean... values) { assertArrayEquals(values, changedValues.toArray(new Boolean[changedValues.size()])); } } } Other Java examples (source code examples)Here is a short list of links related to this Java EventCountCircuitBreakerTest.java source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.