/** * See the NOTICE file distributed with this work * for additional information regarding copyright ownership. * Board of Regents of the University of Wisconsin System * 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 com.microsoft.exchange.integration; import java.util.Date; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import org.apache.commons.lang.time.DateUtils; import org.apache.commons.lang.time.StopWatch; import org.apache.commons.math.stat.descriptive.SynchronizedSummaryStatistics; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Value; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.microsoft.exchange.DateHelp; import com.microsoft.exchange.impl.ThreadLocalImpersonationConnectingSIDSourceImpl; import com.microsoft.exchange.messages.FindItem; import com.microsoft.exchange.messages.FindItemResponse; import com.microsoft.exchange.types.ConnectingSIDType; /** * Perform some tests targeted at observing throttling policy and other issues * when using a number of concurrent connections configured with impersonation support. * * @author Nicholas Blair */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations="classpath:/com/microsoft/exchange/exchangeContext-usingImpersonation.xml") public class ImpersonationClientConcurrencyTest extends AbstractIntegrationTest { private int targetConcurrency; /** * @return the targetConcurrency */ public int getTargetConcurrency() { return targetConcurrency; } /** * @param targetConcurrency the targetConcurrency to set */ @Value("${http.maxTotalConnections}") public void setTargetConcurrency(int targetConcurrency) { this.targetConcurrency = targetConcurrency; } /* (non-Javadoc) * @see com.microsoft.exchange.integration.AbstractIntegrationTest#initializeCredentials() */ @Override public void initializeCredentials() { ConnectingSIDType connectingSID = new ConnectingSIDType(); connectingSID.setPrincipalName(emailAddress); ThreadLocalImpersonationConnectingSIDSourceImpl.setConnectingSID(connectingSID); } @Test @Override public void getPrimaryCalendarFolder() { super.getPrimaryCalendarFolder(); } /** * * @throws InterruptedException */ @Test public void testConcurrentFindItems() throws InterruptedException { final int threadCount = targetConcurrency; // setup a latch to stall all threads until ready to run all at once (-1 so the last thread's run invocation triggers the start) final CountDownLatch startLatch = new CountDownLatch(threadCount); final CountDownLatch endLatch = new CountDownLatch(threadCount); ExecutorService executor = Executors.newFixedThreadPool(threadCount); final Date start = DateHelp.makeDate(startDate); final Date end = DateHelp.makeDate(endDate); final SynchronizedSummaryStatistics stats = new SynchronizedSummaryStatistics(); try { for(int i = 0; i < threadCount; i++) { final int index = i; executor.submit(new Runnable() { @Override public void run() { try { initializeCredentials(); FindItem request = constructFindItemRequest(DateUtils.addDays(start, index), DateUtils.addDays(end, index), emailAddress); startLatch.countDown(); try { startLatch.await(); } catch (InterruptedException e) { throw new IllegalStateException("interrupted while waiting to start", e); } for(int j = 0; j < 10; j++) { StopWatch time = new StopWatch(); time.start(); FindItemResponse response = null; try { response = ewsClient.findItem(request); }catch(Exception e) { log.error(e); } time.stop(); String capture = capture(response); log.info(Thread.currentThread().getName() + " response: " + capture); stats.addValue(time.getTime()); } } finally { endLatch.countDown(); } } }); } // now block until everybody is done endLatch.await(); log.info("testConcurrentFindItems complete for " + targetConcurrency + " threads, stats: " + stats); } finally { executor.shutdown(); } } }