/* * Copyright 2013, The Sporting Exchange Limited * * 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 com.betfair.cougar.testing.concurrency; import com.betfair.testing.utils.cougar.beans.BatchedRequestBean; import com.betfair.testing.utils.cougar.beans.HttpCallBean; import com.betfair.testing.utils.cougar.beans.HttpResponseBean; import com.betfair.testing.utils.cougar.enums.CougarMessageContentTypeEnum; import com.betfair.testing.utils.cougar.enums.CougarMessageProtocolRequestTypeEnum; import com.betfair.testing.utils.cougar.enums.CougarMessageProtocolResponseTypeEnum; import com.betfair.testing.utils.cougar.helpers.CougarHelpers; import com.betfair.testing.utils.cougar.manager.CougarManager; import org.json.JSONException; import java.sql.Timestamp; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; public class RPCConcurrentBatchedRequestsAcrossMultipleOperations{ private List<Thread> threads = new ArrayList<Thread>(); private List<Executor> executors = new ArrayList<Executor>(); private static final String OK_STATUS_CODE = "200"; public List<Thread> getThreads() { return threads; } public void setThreads(List<Thread> threads) { this.threads = threads; } public List<Executor> getExecutors() { return executors; } public void setExecutors(List<Executor> executors) { this.executors = executors; } public RPCConcurrentBatchedRequestsMultipleOsResponseBean executeTest(Integer numberOfThreads, Integer numberOfCallsPerThread) throws InterruptedException, JSONException{ //Build required calls and executors, and thread them for (int i = 0; i < numberOfThreads; i++) { SimpleExecutor simpleExecutor = new SimpleExecutor("simpleExecutor"+i); ComplexExecutor complexExecutor = new ComplexExecutor("complexExecutor"+i); executors.add(simpleExecutor); executors.add(complexExecutor); Thread thread1 = new Thread(simpleExecutor); Thread thread2 = new Thread(complexExecutor); threads.add(thread1); threads.add(thread2); simpleExecutor.setNumberOfRequests(numberOfCallsPerThread); simpleExecutor.buildCalls(); complexExecutor.setNumberOfRequests(numberOfCallsPerThread); complexExecutor.buildCalls(); } //Start the threads for (Thread thread: threads) { thread.start(); } //Wait until all threads finished for (Thread thread: threads) { thread.join(); } //Create maps to hold responses to assert Map<String, Map<String,Object>> expectedResponses = new LinkedHashMap<String, Map<String,Object>>(); Map<String, Map<String,Object>> actualResponses = new LinkedHashMap<String, Map<String,Object>>(); //Populate response maps for (Executor executor: executors) { Map<String, Map<String,Object>> executorExpectedResponses = executor.getExpectedResponses(); expectedResponses.putAll(executorExpectedResponses); Map<String, Map<String,Object>> executorActualResponses = executor.getActualResponses(); actualResponses.putAll(executorActualResponses); } //Put maps into bean and return RPCConcurrentBatchedRequestsMultipleOsResponseBean returnBean = new RPCConcurrentBatchedRequestsMultipleOsResponseBean(); returnBean.setActualResponses(actualResponses); returnBean.setExpectedResponses(expectedResponses); return returnBean; } public abstract class Executor implements Runnable { protected Map<String, Map<String,Object>> expectedResponses = new LinkedHashMap<String, Map<String,Object>>(); protected Map<String, Map<String,Object>> actualResponses = new LinkedHashMap<String, Map<String,Object>>(); protected List<HttpCallBean> httpCallBeans = new ArrayList<HttpCallBean>(); protected Map<String, Timestamp> expectedRequestTimes = new LinkedHashMap<String, Timestamp>(); protected String identifier; protected int numberOfRequests; protected CougarManager cougarManager = CougarManager.getInstance(); protected CougarHelpers cougarHelpers = new CougarHelpers(); public Map<String, Map<String,Object>> getExpectedResponses(){ return expectedResponses; } public Map<String, Map<String,Object>> getActualResponses(){ return actualResponses; } public void setActualResponses(Map<String, Map<String,Object>> actualResponses) { this.actualResponses = actualResponses; } public void setExpectedResponses(Map<String, Map<String,Object>> expectedResponses) { this.expectedResponses = expectedResponses; } public int getNumberOfRequests() { return numberOfRequests; } public void setNumberOfRequests(int numberOfRequests) { this.numberOfRequests = numberOfRequests; } public abstract void buildCalls() throws JSONException; public void run() { try { this.makeCalls(); } catch (JSONException e) { e.printStackTrace(); } } public void makeCalls() throws JSONException { //Make the calls int loopCounter = 0; for(HttpCallBean callBean: httpCallBeans) { Date time = new Date(); //System.out.println("Making call: " + identifier + "-" + "Response " + loopCounter + " at: " + time.getTime()) ; expectedRequestTimes.put(identifier + "Response " + loopCounter, new Timestamp(time.getTime())); cougarManager.makeRestCougarHTTPCall(callBean, CougarMessageProtocolRequestTypeEnum.RESTJSON, CougarMessageContentTypeEnum.JSON); loopCounter++; } //Get actual responses loopCounter=0; for (HttpCallBean httpCallBean: httpCallBeans) { HttpResponseBean responseBean = httpCallBean.getResponseObjectsByEnum(CougarMessageProtocolResponseTypeEnum.RESTJSONJSON); responseBean.clearResponseHeaders(); Map<String,Object> responseMap = cougarHelpers.convertBatchedResponseToMap(responseBean); actualResponses.put(identifier + "Response " + loopCounter, responseMap); loopCounter++; } //Set the expected response time for (String keyString: expectedResponses.keySet()) { Map<String,Object> responseMap = expectedResponses.get(keyString); Timestamp requestTime = expectedRequestTimes.get(keyString); responseMap.put("requestTime", requestTime); responseMap.put("responseTime", requestTime); } } }; public class SimpleExecutor extends Executor { public SimpleExecutor(String identifier) { this.identifier = identifier; } public void buildCalls() throws JSONException { for (int i = 0; i < numberOfRequests+1; i++) { //Setup call beans HttpCallBean callBean = new HttpCallBean(); BatchedRequestBean request1 = new BatchedRequestBean(); request1.setMethod("testSimpleGet"); request1.setId("1"); request1.setParams("[\"foo\"]"); request1.setVersion("2.0"); request1.setService("Baseline"); BatchedRequestBean request2 = new BatchedRequestBean(); request2.setMethod("testSimpleGet"); request2.setId("2"); request2.setParams("[\"foo\"]"); request2.setVersion("2.0"); request2.setService("Baseline"); List<BatchedRequestBean> requests = new ArrayList<BatchedRequestBean>(); requests.add(request1); requests.add(request2); callBean.setJSONRPC(true); callBean.setBatchedRequestsDirect(requests); httpCallBeans.add(callBean); //Store expected responses Map<String,Object> responseMap = new HashMap<String,Object>(); String response1 = "{\"id\":1,\"result\":{\"message\":\"foo\"},\"jsonrpc\":\"2.0\"}"; String response2 = "{\"id\":2,\"result\":{\"message\":\"foo\"},\"jsonrpc\":\"2.0\"}"; responseMap.put("response1", response1); responseMap.put("response2", response2); responseMap.put("httpStatusCode", OK_STATUS_CODE); responseMap.put("httpStatusText", "OK"); expectedResponses.put(identifier + "Response " + i, responseMap); } } } public class ComplexExecutor extends Executor { public ComplexExecutor(String identifier) { this.identifier = identifier; } public void buildCalls() throws JSONException { for (int i = 0; i < numberOfRequests+1; i++) { //Setup call beans HttpCallBean callBean = new HttpCallBean(); BatchedRequestBean request1 = new BatchedRequestBean(); request1.setMethod("testComplexMutator"); request1.setId("1"); request1.setParams("[{\"name\":\"sum1\",\"value1\":7,\"value2\":55}]"); request1.setVersion("2.0"); request1.setService("Baseline"); BatchedRequestBean request2 = new BatchedRequestBean(); request2.setMethod("testComplexMutator"); request2.setId("2"); request2.setParams("[{\"name\":\"sum2\",\"value1\":8,\"value2\":55}]"); request2.setVersion("2.0"); request2.setService("Baseline"); List<BatchedRequestBean> requests = new ArrayList<BatchedRequestBean>(); requests.add(request1); requests.add(request2); callBean.setJSONRPC(true); callBean.setBatchedRequestsDirect(requests); httpCallBeans.add(callBean); //Store expected responses Map<String,Object> responseMap = new HashMap<String,Object>(); String response1 = "{\"id\":1,\"result\":{\"message\":\"sum1 = 62\"},\"jsonrpc\":\"2.0\"}"; String response2 = "{\"id\":2,\"result\":{\"message\":\"sum2 = 63\"},\"jsonrpc\":\"2.0\"}"; responseMap.put("response1", response1); responseMap.put("response2", response2); responseMap.put("httpStatusCode", OK_STATUS_CODE); responseMap.put("httpStatusText", "OK"); expectedResponses.put(identifier + "Response " + i, responseMap); } } } public static class RPCConcurrentBatchedRequestsMultipleOsResponseBean { private Map<String, Map<String,Object>> expectedResponses = new LinkedHashMap<String, Map<String,Object>>(); private Map<String, Map<String,Object>> actualResponses = new LinkedHashMap<String, Map<String,Object>>(); public Map<String, Map<String,Object>> getActualResponses() { return actualResponses; } public void setActualResponses(Map<String, Map<String,Object>> actualResponses) { this.actualResponses = actualResponses; } public Map<String, Map<String,Object>> getExpectedResponses() { return expectedResponses; } public void setExpectedResponses(Map<String, Map<String,Object>> expectedResponses) { this.expectedResponses = expectedResponses; } } }