source: src/test/java/geniusweb/runserver/MaxLoadTest.java@ 40

Last change on this file since 40 was 40, checked in by bart, 3 years ago

Refactor to help reusing partiesserver.

File size: 7.1 KB
Line 
1package geniusweb.runserver;
2
3import java.io.BufferedReader;
4import java.io.File;
5import java.io.FileNotFoundException;
6import java.io.FileReader;
7import java.io.IOException;
8import java.io.InputStream;
9import java.io.InputStreamReader;
10import java.io.OutputStream;
11import java.lang.management.ManagementFactory;
12import java.lang.management.OperatingSystemMXBean;
13import java.net.HttpURLConnection;
14import java.net.MalformedURLException;
15import java.net.ProtocolException;
16import java.net.URISyntaxException;
17import java.net.URL;
18import java.net.URLConnection;
19import java.nio.charset.StandardCharsets;
20import java.util.Arrays;
21import java.util.List;
22
23import org.apache.maven.model.Model;
24import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
25import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
26import org.junit.After;
27import org.junit.Before;
28import org.junit.Test;
29
30import com.fasterxml.jackson.core.JsonProcessingException;
31import com.fasterxml.jackson.databind.ObjectMapper;
32
33import geniusweb.deadline.Deadline;
34import geniusweb.deadline.DeadlineTime;
35import geniusweb.protocol.session.TeamInfo;
36import geniusweb.protocol.session.saop.SAOPSettings;
37import geniusweb.references.Parameters;
38import geniusweb.references.PartyRef;
39import geniusweb.references.PartyWithParameters;
40import geniusweb.references.PartyWithProfile;
41import geniusweb.references.ProfileRef;
42
43/**
44 * End to end test starts server, plus partyserver plus profilesserver, and then
45 * tries to launch large number of parties and keep them busy. Checks and
46 * reports the average CPU loads. Ensure that you have no other background tasks
47 * when you run this test, to avoid incorrect CPU measurements (we can't measure
48 * java-only CPU loads)
49 *
50 *
51 * <h2>Large tests</h2> Tomcat-embed seems very limited in heap space. Best way
52 * to test this with {@link #NUMBER_SESSIONS}>20 is to run all services on
53 * standard tomcat (not embed). To achieve this, disable the @Before and @After.
54 * Additionally, make sure that server.xml has maxThreads="4500" or some large
55 * number sufficient for your test.
56 */
57public class MaxLoadTest {
58 private static final int NUMBER_SESSIONS = 5;
59 private static final int INTER_LAUNCH_DELAY = 20;
60 private static final int PARTY_RESPONSETIME = 1;
61
62 // HACK can we get it from maven?
63 private static final ObjectMapper jackson = new ObjectMapper();
64
65 /**
66 * Test takes average load of last minute. It may take also a minute or two
67 * to launch all sessions to start with. The average should be taken AFTER
68 * all sessions were launched.
69 */
70 private static final long TEST_TIME_MS = 3 * 60 * 1000;
71
72 private static final EmbeddedTomcat tomcat = new EmbeddedTomcat();
73 private static final Parameters parameters = new Parameters().with("delay",
74 PARTY_RESPONSETIME);
75 private static final String PROFILE1 = "ws://localhost:8080/profilesserver/websocket/get/7issues/7issues1";
76 private static final String PROFILE2 = "ws://localhost:8080/profilesserver/websocket/get/7issues/7issues2";
77 private static final Deadline deadline = new DeadlineTime(TEST_TIME_MS);
78
79 private final URL url;
80 private final byte[] startcommand;
81 private final String GENIUSWEB_VERSION;
82 private final String HARDLINER;
83
84
85 public MaxLoadTest() throws URISyntaxException, FileNotFoundException, IOException, XmlPullParserException {
86 MavenXpp3Reader reader = new MavenXpp3Reader();
87 Model model = reader.read(new FileReader("pom.xml"));
88 GENIUSWEB_VERSION = model.getVersion(); // actual geniusweb version in the POM.
89 HARDLINER = "http://localhost:8080/partiesserver/run/hardliner-"
90 + GENIUSWEB_VERSION;
91
92 url = new URL("http://localhost:8080/runserver/run");
93 String startsession = jackson.writeValueAsString(getSettings());
94 startcommand = startsession.toString().getBytes(StandardCharsets.UTF_8);
95 }
96
97 /**
98 * Start up embedded tomcat servers (all: parties-, profile- and run-server)
99 *
100 * @throws InterruptedException
101 *
102 * @throws Throwable
103 */
104 @Before
105 public void before() throws InterruptedException {
106 tomcat.start();
107 tomcat.deploy("runserver");
108 tomcat.deployWar("profilesserver", new File(
109 "target/jars/profilesserver-" + GENIUSWEB_VERSION + ".war"));
110 tomcat.deployWar("partiesserver", new File(
111 "target/jars/partiesserver-" + GENIUSWEB_VERSION + ".war"));
112 System.out.println("waiting for server start");
113 Thread.sleep(1500);// HOW do this properly?
114 System.out.println("server started I hope");
115
116 }
117
118 @After
119 public void after() throws InterruptedException {
120 System.setSecurityManager(null);
121 tomcat.stop();
122 Thread.sleep(2000);
123 }
124
125 @Test
126 public void testRunOneSession()
127 throws URISyntaxException, IOException, InterruptedException {
128
129 for (int n = 0; n < NUMBER_SESSIONS; n++) {
130 startSession();
131 Thread.sleep(INTER_LAUNCH_DELAY);
132 }
133
134 // wait at least 1minute, becaues getLoadAver averages over 1 minute.
135 long testtime = Math.max(TEST_TIME_MS + 100, 60 * 1000);
136 System.out.println("Started session. Waiting termination. This should take about "+testtime/1000+"s");
137 for (int n=0; n<testtime/1000; n++) {
138 System.out.print(n+".");
139 Thread.sleep(1000);
140 }
141 OperatingSystemMXBean operatingSystemMXBean = ManagementFactory
142 .getOperatingSystemMXBean();
143
144 System.out.println("average load in last minute was "
145 + operatingSystemMXBean.getSystemLoadAverage());
146 }
147
148 /**
149 *
150 * @return the response received from the startup request
151 * @throws IOException
152 * @throws ProtocolException
153 * @throws IllegalStateException if party can not be launched.
154 */
155 private void startSession() throws IOException, ProtocolException {
156 URLConnection con = url.openConnection();
157 HttpURLConnection http = (HttpURLConnection) con;
158 http.setRequestMethod("POST"); // PUT is another valid option
159 http.setDoOutput(true);
160
161 http.setFixedLengthStreamingMode(startcommand.length);
162 http.setRequestProperty("Content-Type",
163 "application/json; charset=UTF-8");
164 http.setUseCaches(false);
165 http.setDoOutput(true);
166 http.connect();
167 try (OutputStream os = http.getOutputStream()) {
168 os.write(startcommand);
169 }
170
171 InputStream is = http.getInputStream();
172 BufferedReader rd = new BufferedReader(new InputStreamReader(is));
173 String response = "";
174 String line;
175 while ((line = rd.readLine()) != null) {
176 response += line + "\r";
177 }
178 rd.close();
179 System.out.println("sent request. Response=" + response);
180 if (!(response.startsWith("SAOP")))
181 throw new IllegalStateException(
182 "Failed to start party:" + response);
183 }
184
185 private SAOPSettings getSettings() throws URISyntaxException {
186 PartyRef partyref = new PartyRef(HARDLINER);
187 PartyWithParameters party1 = new PartyWithParameters(partyref,
188 parameters);
189 PartyWithParameters party2 = new PartyWithParameters(partyref,
190 parameters);
191 PartyWithProfile partyprofile1 = new PartyWithProfile(party1,
192 new ProfileRef(PROFILE1));
193 PartyWithProfile partyprofile2 = new PartyWithProfile(party2,
194 new ProfileRef(PROFILE2));
195 TeamInfo team1 = new TeamInfo(Arrays.asList(partyprofile1));
196 TeamInfo team2 = new TeamInfo(Arrays.asList(partyprofile2));
197
198 List<TeamInfo> participants = Arrays.asList(team1, team2);
199 SAOPSettings settings = new SAOPSettings(participants, deadline);
200 return settings;
201 }
202
203}
Note: See TracBrowser for help on using the repository browser.