/* * Copyright 2000-2013 Enonic AS * http://www.enonic.com/license */ package com.enonic.cms.core.portal.livetrace; import org.junit.Test; import java.security.SecureRandom; import java.util.*; import java.util.concurrent.atomic.AtomicLong; import static org.junit.Assert.*; public class CurrentPortalRequestsTest { private final static Random RANDOM_WHEEL = new SecureRandom(); private AtomicLong atomicRequestNumber = new AtomicLong( 0 ); @Test public void size_returns_1_after_one_trace_is_added() { CurrentPortalRequests currentPortalRequests = new CurrentPortalRequests(); PortalRequestTrace trace = new PortalRequestTrace( 1, "http://locahost:8080/site/0/home" ); currentPortalRequests.add( trace ); assertEquals( 1, currentPortalRequests.getSize() ); } @Test public void getList_returns_1_item_after_trace_is_added() { CurrentPortalRequests currentPortalRequests = new CurrentPortalRequests(); PortalRequestTrace trace = new PortalRequestTrace( 1, "http://locahost:8080/site/0/home" ); currentPortalRequests.add( trace ); List<PortalRequestTrace> actualList = currentPortalRequests.getList(); assertSame( 1, actualList.size() ); assertSame( trace, actualList.get( 0 ) ); } @Test public void getList_returns_items_in_order_as_they_where_inserted() { CurrentPortalRequests currentPortalRequests = new CurrentPortalRequests(); PortalRequestTrace trace1 = new PortalRequestTrace( 1, "http://locahost:8080/site/0/home" ); currentPortalRequests.add( trace1 ); PortalRequestTrace trace2 = new PortalRequestTrace( 1, "http://locahost:8080/site/0/home" ); currentPortalRequests.add( trace2 ); List<PortalRequestTrace> actualList = currentPortalRequests.getList(); assertSame( 2, actualList.size() ); assertSame( trace1, actualList.get( 0 ) ); assertSame( trace2, actualList.get( 1 ) ); } @Test public void concurrent_100_threads_adding_random_requests() { final int numberOfThreadsToStart = 100; final CurrentPortalRequests currentPortalRequests = new CurrentPortalRequests(); List<RequestSimulator> requestSimulators = new ArrayList<RequestSimulator>(); for ( int i = 0; i < numberOfThreadsToStart; i++ ) { requestSimulators.add( new RequestSimulator( currentPortalRequests, random( 10, 100 ), false ) ); } List<Thread> threads = createThreadsForRequestSimulators( requestSimulators ); startThreads( threads ); waitForThreadsToFinish( threads ); assertNoExceptionsThrownForRequestSimulators( requestSimulators ); assertEquals( countTotalNumberOfExecutions( requestSimulators ), currentPortalRequests.getSize() ); assertUniqueRequestNumbers( currentPortalRequests.getList() ); } @Test public void concurrent_100_threads_adding_100_requests() { long startTime = System.currentTimeMillis(); final int numberOfThreadsToStart = 100; final CurrentPortalRequests currentPortalRequests = new CurrentPortalRequests(); List<RequestSimulator> requestSimulators = new ArrayList<RequestSimulator>(); for ( int i = 0; i < numberOfThreadsToStart; i++ ) { requestSimulators.add( new RequestSimulator( currentPortalRequests, 100, false ) ); } List<Thread> threads = createThreadsForRequestSimulators( requestSimulators ); startThreads( threads ); waitForThreadsToFinish( threads ); System.out.println( "concurrent_100_threads_adding_100_requests, time: " + ( System.currentTimeMillis() - startTime ) ); assertNoExceptionsThrownForRequestSimulators( requestSimulators ); assertEquals( countTotalNumberOfExecutions( requestSimulators ), currentPortalRequests.getSize() ); assertUniqueRequestNumbers( currentPortalRequests.getList() ); } @Test public void concurrent_100_threads_adding_100_requests_and_removing_them() { long startTime = System.currentTimeMillis(); final CurrentPortalRequests currentPortalRequests = new CurrentPortalRequests(); final int numberOfRequestSimulatorsToStart = 100; List<RequestSimulator> requestSimulators = new ArrayList<RequestSimulator>(); for ( int i = 0; i < numberOfRequestSimulatorsToStart; i++ ) { requestSimulators.add( new RequestSimulator( currentPortalRequests, random( 10, 100 ), true ) ); } List<Thread> threads = createThreadsForRequestSimulators( requestSimulators ); startThreads( threads ); waitForThreadsToFinish( threads ); System.out.println( "concurrent_100_threads_adding_100_requests_and_removing_them, time: " + ( System.currentTimeMillis() - startTime ) ); assertNoExceptionsThrownForRequestSimulators( requestSimulators ); assertEquals( 0, currentPortalRequests.getSize() ); assertUniqueRequestNumbers( currentPortalRequests.getList() ); } @Test public void concurrent_100_threads_adding_random_requests_and_removing_them() { long startTime = System.currentTimeMillis(); final CurrentPortalRequests currentPortalRequests = new CurrentPortalRequests(); final int numberOfRequestSimulatorsToStart = 100; final List<RequestSimulator> requestSimulators = new ArrayList<RequestSimulator>(); for ( int i = 0; i < numberOfRequestSimulatorsToStart; i++ ) { requestSimulators.add( new RequestSimulator( currentPortalRequests, 100, true ) ); } final List<TraceInfoReaderSimulator> traceInfoReaderSimulators = new ArrayList<TraceInfoReaderSimulator>(); for ( int i = 0; i < 100; i++ ) { traceInfoReaderSimulators.add( new TraceInfoReaderSimulator( currentPortalRequests, 100 ) ); } List<Thread> threads = createThreadsForRequestSimulators( requestSimulators ); threads.addAll( createThreadsForTraceInfoReaderSimulators( traceInfoReaderSimulators ) ); startThreads( threads ); waitForThreadsToFinish( threads ); assertNoExceptionsThrownForRequestSimulators( requestSimulators ); assertNoExceptionsThrownForTraceInfoReaderSimulators( traceInfoReaderSimulators ); assertEquals( 0, currentPortalRequests.getSize() ); assertUniqueRequestNumbers( currentPortalRequests.getList() ); } private void assertNoExceptionsThrownForRequestSimulators( List<RequestSimulator> simulators ) { for ( Simulator simulator : simulators ) { assertTrue( "Simulator have thrown exception!", !simulator.exceptionThrown ); } } private void assertNoExceptionsThrownForTraceInfoReaderSimulators( List<TraceInfoReaderSimulator> simulators ) { for ( Simulator simulator : simulators ) { assertTrue( "Simulator have thrown exception!", !simulator.exceptionThrown ); } } private void assertUniqueRequestNumbers( List<PortalRequestTrace> traces ) { final Set<Long> usedRequestNumbers = new HashSet<Long>(); for ( PortalRequestTrace trace : traces ) { long currentRequestNumber = trace.getRequestNumber(); assertTrue( currentRequestNumber + " duplicate requestNumber found!", !usedRequestNumbers.contains( currentRequestNumber ) ); usedRequestNumbers.add( currentRequestNumber ); } } private PortalRequestTrace createTrace() { long requestNumber = atomicRequestNumber.incrementAndGet(); return new PortalRequestTrace( requestNumber, "http://locahost:8080/site/0/home" ); } private static int random( int low, int high ) { return RANDOM_WHEEL.nextInt( high - low + 1 ) + low; } private List<Thread> createThreadsForRequestSimulators( List<RequestSimulator> simulators ) { List<Thread> threads = new ArrayList<Thread>(); for ( RequestSimulator requestSimulator : simulators ) { threads.add( new Thread( requestSimulator ) ); } return threads; } private List<Thread> createThreadsForTraceInfoReaderSimulators( List<TraceInfoReaderSimulator> simulators ) { List<Thread> threads = new ArrayList<Thread>(); for ( TraceInfoReaderSimulator requestSimulator : simulators ) { threads.add( new Thread( requestSimulator ) ); } return threads; } private void startThreads( Collection<Thread> threads ) { for ( Thread thread : threads ) { thread.start(); } } private void waitForThreadsToFinish( Collection<Thread> threads ) { for ( Thread thread : threads ) { try { thread.join(); } catch ( InterruptedException e ) { e.printStackTrace(); fail(); } } } private int countTotalNumberOfExecutions( Iterable<RequestSimulator> it ) { int sum = 0; for ( RequestSimulator t : it ) { sum += t.numberOfExecutions; } return sum; } private class RequestSimulator extends Simulator implements Runnable { private CurrentPortalRequests currentPortalRequests; final int numberOfExecutions; private boolean remove = false; private int[] sleepsBeforeRemoving; RequestSimulator( CurrentPortalRequests currentPortalRequests, int numberOfExecutions, boolean remove ) { this.currentPortalRequests = currentPortalRequests; this.numberOfExecutions = numberOfExecutions; this.remove = remove; if ( remove ) { sleepsBeforeRemoving = new int[numberOfExecutions]; for ( int i = 0; i < numberOfExecutions; i++ ) { sleepsBeforeRemoving[i] = random( 3, 9 ); } } } public void run() { try { for ( int i = 0; i < numberOfExecutions; i++ ) { PortalRequestTrace trace = createTrace(); currentPortalRequests.add( trace ); if ( remove ) { Thread.sleep( sleepsBeforeRemoving[i] ); currentPortalRequests.remove( trace ); } } } catch ( Exception e ) { e.printStackTrace(); exceptionThrown = true; } } } private class TraceInfoReaderSimulator extends Simulator implements Runnable { private CurrentPortalRequests currentPortalRequests; final int numberOfExecutions; private int[] sleepsBeforeReading; TraceInfoReaderSimulator( CurrentPortalRequests currentPortalRequests, int numberOfExecutions ) { this.currentPortalRequests = currentPortalRequests; this.numberOfExecutions = numberOfExecutions; sleepsBeforeReading = new int[numberOfExecutions]; for ( int i = 0; i < numberOfExecutions; i++ ) { sleepsBeforeReading[i] = random( 3, 9 ); } } public void run() { try { for ( int i = 0; i < numberOfExecutions; i++ ) { currentPortalRequests.getSize(); //noinspection UnusedDeclaration for ( PortalRequestTrace trace : currentPortalRequests.getList() ) { // just simulating iteration } Thread.sleep( sleepsBeforeReading[i] ); } } catch ( Exception e ) { e.printStackTrace(); exceptionThrown = true; } } } private class Simulator { boolean exceptionThrown = false; } }