/** * Copyright (c) 2009-2011 VMware, Inc. All Rights Reserved. * * 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.springsource.insight.plugin.socket; import java.io.IOException; import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketAddress; import java.util.concurrent.TimeUnit; import com.springsource.insight.collection.test.AbstractCollectionTestSupport; import com.springsource.insight.intercept.operation.Operation; /** * Note: we do not inherit from OperationCollectionAspectTestSupport due * to connect/accept aspects conflicts */ public abstract class SocketAcceptCollectionAspectTestSupport extends AbstractCollectionTestSupport { protected SocketAcceptCollectionAspectTestSupport() { super(); } protected void runAcceptorTest(String testName, SocketAcceptorHelper<?> acceptor) throws IOException, InterruptedException { SocketOperationCollectionAspectSupport aspectInstance = getAspect(); SocketCollectOperationContext context = aspectInstance.getSocketCollectOperationContext(); TestCollector collector = new TestCollector(context); aspectInstance.setCollector(collector); Thread t = new Thread(acceptor, "t" + testName); t.start(); try { SocketAddress connectAddress = new InetSocketAddress("localhost", acceptor.getListenPort()); Socket socket = new Socket(); socket.connect(connectAddress, 125); socket.close(); // just in case it somehow succeeded t.join(TimeUnit.SECONDS.toMillis(5L)); assertFalse(testName + ": Accepting thread still alive", t.isAlive()); Operation opCollected = collector.getCollectedOperation(); assertNotNull(testName + ": No operation collected", opCollected); assertEquals(testName + ": Mismatched types", SocketDefinitions.TYPE, opCollected.getType()); Operation opAccepted = acceptor.getOperation(); assertNotNull(testName + ": No operation accepted", opAccepted); for (String attrName : new String[]{ SocketDefinitions.ACTION_ATTR, SocketDefinitions.ADDRESS_ATTR, SocketDefinitions.PORT_ATTR }) { Object valCollected = opCollected.get(attrName), valAccepted = opAccepted.get(attrName); assertEquals(testName + ": Mismatched values for " + attrName, valCollected, valAccepted); } } finally { acceptor.close(); } } public abstract SocketOperationCollectionAspectSupport getAspect(); /** * A "poor-man's" replacement for argument-captor since we cannot * use it due to conflicts between the connect and accept aspects which are * invoked both */ static class TestCollector extends SocketAcceptOperationCollector { private volatile Operation collectedOperation; public TestCollector(SocketCollectOperationContext context) { super(context); } public Operation getCollectedOperation() { if ((collectedOperation != null) && collectedOperation.isFinalizable()) { collectedOperation.finalizeConstruction(); } return collectedOperation; } @Override protected void processNormalExit(Operation op, Object returnValue) { if (!SocketDefinitions.ACCEPT_ACTION.equals(op.get(SocketDefinitions.ACTION_ATTR, String.class))) { return; // ignore non-accept operations } if (collectedOperation != null) { throw new IllegalStateException("Multiple calls to processNormalExit"); } super.processNormalExit(op, returnValue); collectedOperation = op; } } }