001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tc.net.protocol.transport;
006:
007: import com.tc.logging.TCLogging;
008: import com.tc.net.core.MockTCConnection;
009: import com.tc.net.core.TestTCConnection;
010: import com.tc.net.protocol.IllegalReconnectException;
011: import com.tc.net.protocol.StackNotFoundException;
012: import com.tc.net.protocol.transport.MockTransportHandshakeMessageFactory.CallContext;
013: import com.tc.test.TCTestCase;
014:
015: import java.util.HashSet;
016: import java.util.Set;
017:
018: public class ServerStackProviderTest extends TCTestCase {
019:
020: private ServerStackProvider provider;
021: private MockStackHarnessFactory harnessFactory;
022: private MockNetworkStackHarness harness;
023: private MockTransportHandshakeMessageFactory transportHandshakeMessageFactory;
024: private ConnectionID connId;
025: private ConnectionIDFactory connectionIdFactory;
026: private TestConnectionPolicy connectionPolicy;
027: private TestWireProtocolAdaptorFactory wpaFactory;
028: private MockMessageTransportFactory transportFactory;
029: private DefaultConnectionIdFactory connectionIDProvider;
030:
031: public ServerStackProviderTest() {
032: super ();
033: }
034:
035: protected void setUp() throws Exception {
036: super .setUp();
037:
038: this .harness = new MockNetworkStackHarness();
039:
040: this .harnessFactory = new MockStackHarnessFactory();
041: this .harnessFactory.harness = this .harness;
042: this .connectionIdFactory = new TestConnectionIDFactory();
043:
044: transportFactory = new MockMessageTransportFactory();
045: transportHandshakeMessageFactory = new MockTransportHandshakeMessageFactory();
046: connectionPolicy = new TestConnectionPolicy();
047: wpaFactory = new TestWireProtocolAdaptorFactory();
048: this .provider = new ServerStackProvider(TCLogging
049: .getLogger(ServerStackProvider.class), new HashSet(),
050: this .harnessFactory, null, transportFactory,
051: transportHandshakeMessageFactory,
052: this .connectionIdFactory, connectionPolicy, wpaFactory);
053: connectionIDProvider = new DefaultConnectionIdFactory();
054: this .connId = connectionIDProvider.nextConnectionId();
055: }
056:
057: protected void tearDown() throws Exception {
058: super .tearDown();
059: }
060:
061: /**
062: * Test to make sure that the connection accounting is done properly.
063: */
064: public void testConnectionPolicyInteraction() throws Exception {
065:
066: assertNull(wpaFactory.newWireProtocolAdaptorCalls.poll(0));
067: // XXX: This is yucky. This has the effect of creating a new TCProtocolAdapter which creates a wire protocol
068: // message sink which is the thing we need to drop messages on.
069: provider.getInstance();
070:
071: WireProtocolMessageSink sink = (WireProtocolMessageSink) wpaFactory.newWireProtocolAdaptorCalls
072: .take();
073: TestSynMessage syn = new TestSynMessage();
074: TestSynAckMessage synAck = new TestSynAckMessage();
075: TestTCConnection connection = new TestTCConnection();
076:
077: this .transportHandshakeMessageFactory.synAck = synAck;
078: syn.connection = connection;
079:
080: MockMessageTransport transport = new MockMessageTransport();
081: transportFactory.transport = transport;
082:
083: // make sure that createSynACk calls in the transport handshake message factory are clear
084: assertNull(transportHandshakeMessageFactory.createSynAckCalls
085: .poll(0));
086: // make sure the send calls in the transport are clear
087: assertNull(transport.sendToConnectionCalls.poll(0));
088: connectionPolicy.maxConnections = 13;
089: connectionPolicy.maxConnectionsExceeded = true;
090: // Send SYN message
091: sink.putMessage(syn);
092: // the client should have sent the SYN_ACK message
093: assertSame(synAck, transport.sendToConnectionCalls.take());
094:
095: // The connected client count should have been incremented
096: assertEquals(1, connectionPolicy.clientConnected);
097: // make sure that the transport message factory was called with the proper arguments
098: MockTransportHandshakeMessageFactory.CallContext args = (CallContext) transportHandshakeMessageFactory.createSynAckCalls
099: .poll(0);
100: assertEquals(new Boolean(
101: connectionPolicy.maxConnectionsExceeded), args
102: .getIsMaxConnectionsExceeded());
103: assertEquals(new Integer(connectionPolicy.maxConnections), args
104: .getMaxConnections());
105:
106: assertEquals(0, connectionPolicy.clientDisconnected);
107: // XXX: This is yucky. THis is the connection id that the stack provider assigns to the transport (via the
108: // connection id factory)
109: transport.connectionId = this .connId;
110: provider.notifyTransportClosed(transport);
111: assertEquals(1, connectionPolicy.clientConnected);
112:
113: }
114:
115: public void testRebuildStack() throws Exception {
116: ConnectionID connectionID1 = connectionIDProvider
117: .nextConnectionId();
118: ConnectionID connectionID2 = connectionIDProvider
119: .nextConnectionId();
120: Set rebuild = new HashSet();
121: rebuild.add(connectionID1);
122:
123: provider = new ServerStackProvider(TCLogging
124: .getLogger(ServerStackProvider.class), rebuild,
125: this .harnessFactory, null, transportFactory, null,
126: this .connectionIdFactory, connectionPolicy,
127: new WireProtocolAdaptorFactoryImpl());
128:
129: MockTCConnection conn = new MockTCConnection();
130: provider.attachNewConnection(connectionID1, conn);
131:
132: // trying to attach a stack that wasn't rebuilt at startup should fail.
133: try {
134: provider.attachNewConnection(connectionID2,
135: new MockTCConnection());
136: fail("Expected StackNotFoundException");
137: } catch (StackNotFoundException e) {
138: // expected.
139: }
140: }
141:
142: public void testNotifyTransportDisconnected() throws Exception {
143: TestTCConnection conn = new TestTCConnection();
144: provider.attachNewConnection(ConnectionID.NULL_ID, conn);
145:
146: // send a transport disconnected event
147: MockMessageTransport transport = new MockMessageTransport();
148: transport.connectionId = this .connId;
149: assertEquals(0, connectionPolicy.clientDisconnected);
150: provider.notifyTransportDisconnected(transport);
151:
152: // transport disconnect event doesnt close client
153: assertEquals(0, connectionPolicy.clientDisconnected);
154:
155: // send transport close event
156: provider.notifyTransportClosed(transport);
157:
158: // make sure that the connection policy is decremented
159: assertEquals(1, connectionPolicy.clientDisconnected);
160:
161: }
162:
163: public void testNotifyTransportClose() throws Exception {
164: TestTCConnection conn = new TestTCConnection();
165: provider.attachNewConnection(ConnectionID.NULL_ID, conn);
166:
167: // try looking it up again. Make sure it found what it was looking for.
168: provider.attachNewConnection(connId, conn);
169:
170: // send it a transport closed event.
171: MockMessageTransport transport = new MockMessageTransport();
172: transport.connectionId = this .connId;
173: provider.notifyTransportClosed(transport);
174:
175: // make sure that a future lookup throws a StackNotFoundException
176: try {
177: provider.attachNewConnection(this .connId, conn);
178: fail("Expected StackNotFoundException.");
179: } catch (StackNotFoundException e) {
180: // expected
181: }
182: }
183:
184: /**
185: * Makes sure that removeNetworkStack(String) removes the the expected stack.
186: */
187: public void testRemoveNetworkStack() throws Exception {
188: MockTCConnection conn = new MockTCConnection();
189: provider.attachNewConnection(ConnectionID.NULL_ID, conn);
190:
191: assertEquals(harness, provider.removeNetworkStack(this .connId));
192: assertTrue(provider.removeNetworkStack(this .connId) == null);
193:
194: try {
195: // try looking it up again. Make sure it throws an exception
196: provider.attachNewConnection(this .connId, conn);
197: fail("Should have thrown an exception.");
198: } catch (StackNotFoundException e) {
199: // expected
200: }
201:
202: // trying to remove it again should return null.
203: assertTrue(provider.removeNetworkStack(this .connId) == null);
204: }
205:
206: public void testAttachNewConnection() {
207: assertFalse(harness.wasAttachNewConnectionCalled);
208: assertFalse(harness.wasFinalizeStackCalled);
209:
210: MockTCConnection conn = new MockTCConnection();
211: try {
212: provider.attachNewConnection(ConnectionID.NULL_ID, conn);
213: } catch (StackNotFoundException e) {
214: fail("was virgin, should not throw exception");
215: } catch (IllegalReconnectException e) {
216: fail("was virgin, should not throw exception");
217: }
218:
219: assertFalse(harness.wasAttachNewConnectionCalled);
220: assertTrue(harness.wasFinalizeStackCalled);
221:
222: // test look up of existing connection ID
223: harness.wasAttachNewConnectionCalled = false;
224: harness.wasFinalizeStackCalled = false;
225:
226: try {
227: provider.attachNewConnection(this .connId, conn);
228: } catch (StackNotFoundException e) {
229: fail("was virgin, should not throw exception");
230: } catch (IllegalReconnectException e) {
231: fail("was virgin, should not throw exception");
232: }
233:
234: assertTrue(harness.wasAttachNewConnectionCalled);
235: assertFalse(harness.wasFinalizeStackCalled);
236:
237: // cause lookup failure
238: ConnectionID differentConnId = connectionIDProvider
239: .nextConnectionId();
240: harness.wasAttachNewConnectionCalled = false;
241: harness.wasFinalizeStackCalled = false;
242:
243: try {
244: provider.attachNewConnection(differentConnId, conn);
245: fail("was not virgin and had connId, but should not exist in provider");
246: } catch (StackNotFoundException e) {
247: // expected
248: } catch (IllegalReconnectException e) {
249: fail("unexpected exception: " + e);
250: }
251: }
252:
253: private class TestConnectionIDFactory extends
254: DefaultConnectionIdFactory {
255:
256: public synchronized ConnectionID nextConnectionId() {
257: connId = super.nextConnectionId();
258: return connId;
259: }
260: }
261:
262: }
|