/*
* JBoss, Home of Professional Open Source.
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership. Some portions may be licensed
* to Red Hat, Inc. under one or more contributor license agreements.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*/
/**
*
*/
package org.teiid.net.socket;
import static org.junit.Assert.*;
import java.io.IOException;
import java.io.Serializable;
import java.net.InetAddress;
import java.util.Collection;
import java.util.Properties;
import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.teiid.client.security.ILogon;
import org.teiid.client.security.InvalidSessionException;
import org.teiid.client.security.LogonException;
import org.teiid.client.security.LogonResult;
import org.teiid.client.security.SessionToken;
import org.teiid.client.util.ResultsFuture;
import org.teiid.client.util.ResultsReceiver;
import org.teiid.core.TeiidComponentException;
import org.teiid.core.crypto.NullCryptor;
import org.teiid.net.CommunicationException;
import org.teiid.net.ConnectionException;
import org.teiid.net.HostInfo;
import org.teiid.net.TeiidURL;
/**
* <code>TestCase</case> for <code>SocketServerConnection</code>
* @see SocketServerConnection
*/
@SuppressWarnings("nls")
public class TestSocketServerConnection {
private static final class FakeILogon implements ILogon {
Throwable t;
public FakeILogon(Throwable t) {
this.t = t;
}
@Override
public void assertIdentity(SessionToken sessionId)
throws InvalidSessionException, TeiidComponentException {
}
@Override
public ResultsFuture<?> logoff()
throws InvalidSessionException {
return null;
}
@Override
public LogonResult logon(
Properties connectionProperties)
throws LogonException,
TeiidComponentException {
return new LogonResult(new SessionToken(1, connectionProperties.getProperty(TeiidURL.CONNECTION.USER_NAME, "fooUser")), "foo", "fake"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
@Override
public ResultsFuture<?> ping()
throws TeiidComponentException, CommunicationException {
if (t != null) {
if (t instanceof CommunicationException) {
CommunicationException ce = (CommunicationException)t;
t = null;
throw ce;
}
TeiidComponentException e = new TeiidComponentException(t);
t = null;
throw e;
}
return ResultsFuture.NULL_FUTURE;
}
@Override
public ResultsFuture<?> ping(Collection<String> sessions)
throws TeiidComponentException, CommunicationException {
return ping();
}
@Override
public LogonResult neogitiateGssLogin(Properties connectionProperties,
byte[] serviceToken, boolean createSession) throws LogonException {
return null;
}
}
/**
* Validate that the client host name and IP address property in
* the connection properties object is set after a <code>SocketServerConnection</code>
* is established.
*
* <p>The expected results contains the host name and IP address
* of the local machine as returned by <code>NetUtils</code>.
* These values are not put into the initial connection object
* and it is up to <code>SocketServerConnection</code> to place
* the values into the connection properties object during the
* connection process.</p>
* @throws Throwable
*
* @since Westport
*/
@Test public void testSocketServerConnection_PropertiesClientHost() throws Throwable {
Properties p = new Properties();
SocketServerConnection.updateConnectionProperties(p, InetAddress.getLocalHost(), true);
assertTrue(p.containsKey(TeiidURL.CONNECTION.CLIENT_HOSTNAME));
assertTrue(p.containsKey(TeiidURL.CONNECTION.CLIENT_IP_ADDRESS));
}
@Test public void testLogonFailsWithMultipleHosts() throws Exception {
Properties p = new Properties();
SocketServerInstanceFactory instanceFactory = Mockito.mock(SocketServerInstanceFactory.class);
Mockito.stub(instanceFactory.getServerInstance((HostInfo)Mockito.anyObject())).toThrow(new SingleInstanceCommunicationException());
ServerDiscovery discovery = new UrlServerDiscovery(new TeiidURL("mm://host1:1,host2:2")); //$NON-NLS-1$
try {
new SocketServerConnection(instanceFactory, false, discovery, p);
fail("exception expected"); //$NON-NLS-1$
} catch (CommunicationException e) {
assertEquals("TEIID20021 No valid host available. Attempted connections to: [host1:1, host2:2]", e.getMessage()); //$NON-NLS-1$
}
}
@Test public void testLogon() throws Exception {
SocketServerConnection connection = createConnection(null);
assertEquals(String.valueOf(1), connection.getLogonResult().getSessionID());
}
@Test public void testChangeUser() throws Exception {
Properties p = new Properties();
SocketServerConnection connection = createConnection(null, p);
assertEquals("fooUser", connection.getLogonResult().getUserName());
p.setProperty(TeiidURL.CONNECTION.USER_NAME, "newUser");
connection.authenticate();
assertEquals("newUser", connection.getLogonResult().getUserName());
}
/**
* Since the original instance is still open, this will be a transparent retry
*/
@Test public void testRetry() throws Exception {
SocketServerConnection connection = createConnection(new SingleInstanceCommunicationException());
connection.setFailOver(true);
connection.setFailOverPingInterval(50);
ILogon logon = connection.getService(ILogon.class);
Thread.sleep(70);
logon.ping();
}
@Test(expected=CommunicationException.class) public void testImmediateFail() throws Exception {
SocketServerConnection connection = createConnection(new CommunicationException());
ILogon logon = connection.getService(ILogon.class);
logon.ping();
}
@Test(expected=CommunicationException.class) public void testImmediateFail1() throws Exception {
SocketServerConnection connection = createConnection(new CommunicationException());
connection.setFailOver(true);
ILogon logon = connection.getService(ILogon.class);
logon.ping();
}
private SocketServerConnection createConnection(final Throwable throwException) throws CommunicationException, ConnectionException {
return createConnection(throwException, new Properties());
}
private SocketServerConnection createConnection(final Throwable throwException, Properties p) throws CommunicationException, ConnectionException {
return createConnection(throwException, new HostInfo("0.0.0.2", 1), p); //$NON-NLS-1$
}
private SocketServerConnection createConnection(final Throwable t, final HostInfo hostInfo, Properties p)
throws CommunicationException, ConnectionException {
ServerDiscovery discovery = new UrlServerDiscovery(new TeiidURL(hostInfo.getHostName(), hostInfo.getPortNumber(), false));
SocketServerInstanceFactory instanceFactory = new SocketServerInstanceFactory() {
FakeILogon logon = new FakeILogon(t);
@Override
public SocketServerInstance getServerInstance(HostInfo info)
throws CommunicationException, IOException {
SocketServerInstance instance = Mockito.mock(SocketServerInstance.class);
Mockito.stub(instance.getCryptor()).toReturn(new NullCryptor());
Mockito.stub(instance.getHostInfo()).toReturn(hostInfo);
Mockito.stub(instance.getService(ILogon.class)).toReturn(logon);
Mockito.stub(instance.getServerVersion()).toReturn("07.03");
if (t != null) {
try {
Mockito.doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation)
throws Throwable {
if (logon.t == null) {
return null;
}
throw logon.t;
}
}).when(instance).send((Message)Mockito.anyObject(), (ResultsReceiver<Object>)Mockito.anyObject(), (Serializable)Mockito.anyObject());
} catch (Exception e) {
}
}
Mockito.stub(instance.isOpen()).toReturn(true);
return instance;
}
@Override
public void connected(SocketServerInstance instance,
SessionToken session) {
}
@Override
public void disconnected(SocketServerInstance instance,
SessionToken session) {
}
};
SocketServerConnection connection = new SocketServerConnection(instanceFactory, false, discovery, p);
return connection;
}
@Test public void testIsSameInstance() throws Exception {
SocketServerConnection conn = createConnection(null, new HostInfo("0.0.0.0", 1), new Properties()); //$NON-NLS-1$
SocketServerConnection conn1 = createConnection(null, new HostInfo("0.0.0.1", 1), new Properties()); //$NON-NLS-1$
assertFalse(conn.isSameInstance(conn1));
assertTrue(conn.isSameInstance(conn));
}
}