001: // Copyright 2007 The Apache Software Foundation
002: //
003: // Licensed under the Apache License, Version 2.0 (the "License");
004: // you may not use this file except in compliance with the License.
005: // You may obtain a copy of the License at
006: //
007: // http://www.apache.org/licenses/LICENSE-2.0
008: //
009: // Unless required by applicable law or agreed to in writing, software
010: // distributed under the License is distributed on an "AS IS" BASIS,
011: // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: // See the License for the specific language governing permissions and
013: // limitations under the License.
014:
015: package org.apache.tapestry.integration;
016:
017: import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newList;
018:
019: import java.io.BufferedInputStream;
020: import java.io.InputStream;
021: import java.io.InputStreamReader;
022: import java.net.URL;
023: import java.util.List;
024: import java.util.concurrent.CyclicBarrier;
025:
026: import org.apache.tapestry.ioc.internal.util.InternalUtils;
027: import org.apache.tapestry.test.JettyRunner;
028: import org.testng.Assert;
029: import org.testng.annotations.AfterClass;
030: import org.testng.annotations.BeforeClass;
031: import org.testng.annotations.Test;
032:
033: /**
034: * Tapestry seems least stable at initial startup (all those proxies and generated code). So we're
035: * giving it a crushing just as it starts up.
036: */
037: public class LaunchCrusherTest extends Assert {
038: // Jetty's default thread pool max size is 256. If you push this number too high, you get connection reset by peer
039: // errors (I think Jetty reject requests when there's no available thread, after a short timeout).
040: private static final int THREAD_COUNT = 50;
041:
042: /** The port on which the internal copy of Jetty is executed. */
043: public static final int JETTY_PORT = 9999;
044:
045: private JettyRunner _jetty;
046:
047: private final CyclicBarrier _barrier = new CyclicBarrier(
048: THREAD_COUNT + 1);
049:
050: class Worker implements Runnable {
051: private String _name;
052:
053: private String _content;
054:
055: public synchronized String getContent() {
056: return _content;
057: }
058:
059: public void run() {
060: _name = Thread.currentThread().getName();
061:
062: System.out.printf("[%s] waiting ...\n", _name);
063:
064: try {
065: _barrier.await();
066:
067: URL url = new URL(String.format("http://localhost:%d/",
068: JETTY_PORT));
069:
070: readContent(url);
071:
072: _barrier.await();
073: } catch (Exception ex) {
074: throw new RuntimeException(ex);
075: }
076: }
077:
078: private void readContent(URL url) {
079: System.out.printf("[%s] reading ...\n", _name);
080:
081: try {
082: InputStream is = url.openStream();
083: InputStreamReader reader = new InputStreamReader(
084: new BufferedInputStream(is));
085:
086: StringBuilder builder = new StringBuilder();
087:
088: char[] buffer = new char[10000];
089:
090: while (true) {
091: int length = reader.read(buffer);
092:
093: if (length < 0)
094: break;
095:
096: builder.append(buffer, 0, length);
097: }
098:
099: reader.close();
100:
101: synchronized (this ) {
102: _content = builder.toString();
103: }
104:
105: System.out.printf("[%s] done.\n", _name);
106: } catch (Exception ex) {
107: System.out.printf("[%s] fail: %s.\n", _name, ex
108: .toString());
109:
110: synchronized (this ) {
111: _content = "[" + ex.toString() + "]";
112: }
113: }
114: }
115: }
116:
117: @BeforeClass
118: public void setup() {
119: _jetty = new JettyRunner("/", JETTY_PORT, "src/test/app1");
120: }
121:
122: @AfterClass
123: public void cleanup() {
124: _jetty.stop();
125: }
126:
127: @Test
128: public void crushing_number_of_threads_at_startup()
129: throws Exception {
130: Worker[] workers = new Worker[THREAD_COUNT];
131:
132: for (int i = 0; i < THREAD_COUNT; i++) {
133: workers[i] = new Worker();
134:
135: new Thread(workers[i]).start();
136: }
137:
138: _barrier.await();
139:
140: System.out.printf("%d threads started\n", THREAD_COUNT);
141:
142: _barrier.await();
143:
144: String expected = workers[0].getContent();
145: String failureContent = null;
146: List<Integer> failures = newList();
147:
148: System.out.printf("*****\n%s\n*****\n", expected);
149:
150: for (int i = 1; i < THREAD_COUNT; i++) {
151: String actual = workers[i].getContent();
152:
153: if (!actual.equals(expected)) {
154: failures.add(i);
155:
156: if (failureContent == null)
157: failureContent = actual;
158:
159: }
160: }
161:
162: if (failureContent != null) {
163: System.err.println("Failures in thread(s): "
164: + InternalUtils.join(failures));
165:
166: assertEquals(failureContent, expected);
167: }
168: }
169: }
|