/*
* Copyright 2009 Martin Grotzke
*
* 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 de.javakaffee.web.msm;
import static de.javakaffee.web.msm.integration.TestUtils.assertDeepEquals;
import static de.javakaffee.web.msm.integration.TestUtils.createSession;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.security.Principal;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.servlet.http.HttpServletRequest;
import org.apache.catalina.Context;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.Manager;
import org.apache.catalina.authenticator.Constants;
import org.apache.catalina.authenticator.SavedRequest;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.realm.GenericPrincipal;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import de.javakaffee.web.msm.MemcachedSessionService.SessionManager;
/**
* Test the {@link TranscoderService}.
*
* @author <a href="mailto:martin.grotzke@javakaffee.de">Martin Grotzke</a>
*/
public abstract class TranscoderServiceTest {
protected static SessionManager _manager;
private static boolean _managerHasGetContainer;
static {
try {
Manager.class.getDeclaredMethod("getContainer");
_managerHasGetContainer = true;
} catch (NoSuchMethodException e) { }
}
@BeforeMethod
public void setup() throws LifecycleException, ClassNotFoundException, IOException {
_manager = mock( SessionManager.class );
final Context context = new StandardContext();
when( _manager.getContext() ).thenReturn( context ); // needed for createSession
// Manager.getContainer no longer available in tc 8.5+
if(_managerHasGetContainer) {
when( _manager.getContainer() ).thenReturn( context );
}
when( _manager.newMemcachedBackupSession() ).thenAnswer(new Answer<MemcachedBackupSession>() {
@Override
public MemcachedBackupSession answer(final InvocationOnMock invocation) throws Throwable {
return newMemcachedBackupSession( _manager );
}
});
final MemcachedSessionService service = new DummyMemcachedSessionService<SessionManager>( _manager );
when( _manager.createSession( anyString() ) ).thenAnswer(new Answer<MemcachedBackupSession>() {
@Override
public MemcachedBackupSession answer(final InvocationOnMock invocation) throws Throwable {
return createSession(service);
}
});
when( _manager.readPrincipal( (ObjectInputStream)any() ) ).thenReturn( createPrincipal() );
when( _manager.getMemcachedSessionService() ).thenReturn( service );
when( _manager.willAttributeDistribute(anyString(), any())).thenReturn(true);
}
@Nonnull
protected MemcachedBackupSession newMemcachedBackupSession( @Nullable final SessionManager manager ) {
return new MemcachedBackupSession( manager );
}
@Test
public void testSerializeSessionFieldsIncludesFormPrincipalNote() {
final MemcachedBackupSession session = (MemcachedBackupSession) _manager.createSession( null );
final Principal saved = createPrincipal();
session.setNote(Constants.FORM_PRINCIPAL_NOTE, saved);
final byte[] data = TranscoderService.serializeSessionFields( session );
final MemcachedBackupSession deserialized = TranscoderService.deserializeSessionFields(data, _manager ).getSession();
final Principal actual = (Principal) deserialized.getNote(Constants.FORM_PRINCIPAL_NOTE);
assertNotNull(actual);
assertDeepEquals(actual, saved);
}
@Test
public void testSerializeSessionFieldsIncludesFormRequestNote() {
final MemcachedBackupSession session = (MemcachedBackupSession) _manager.createSession( null );
final SavedRequest saved = new SavedRequest();
saved.setQueryString("foo=bar");
saved.setRequestURI("http://www.foo.org");
session.setNote(Constants.FORM_REQUEST_NOTE, saved);
final byte[] data = TranscoderService.serializeSessionFields( session );
final MemcachedBackupSession deserialized = TranscoderService.deserializeSessionFields(data, _manager ).getSession();
final SavedRequest actual = (SavedRequest) deserialized.getNote(Constants.FORM_REQUEST_NOTE);
assertNotNull(actual);
assertDeepEquals(actual, saved);
}
@Test
public void testVersionUpgrade() {
final MemcachedBackupSession session = (MemcachedBackupSession) _manager.createSession( null );
final byte[] data = TranscoderService.serializeSessionFields( session, TranscoderService.VERSION_1 );
final byte[] attributesData = TranscoderService.deserializeSessionFields(data, _manager ).getAttributesData();
// we just check that data is read (w/o) bounds issues and no data
// is left (we just passed data in, w/o added attributesData appended)
assertEquals(attributesData.length, 0);
}
@Test
public void testSerializeSessionFields() {
final MemcachedBackupSession session = (MemcachedBackupSession) _manager.createSession( null );
session.setLastBackupTime( System.currentTimeMillis() );
final byte[] data = TranscoderService.serializeSessionFields( session );
final MemcachedBackupSession deserialized = TranscoderService.deserializeSessionFields(data, _manager ).getSession();
assertSessionFields( session, deserialized );
}
@Test
public void testSerializeSessionFieldsWithAuthenticatedPrincipal() {
final MemcachedBackupSession session = (MemcachedBackupSession) _manager.createSession( null );
session.setAuthType( HttpServletRequest.FORM_AUTH );
session.setPrincipal( createPrincipal() );
session.setLastBackupTime( System.currentTimeMillis() );
final byte[] data = TranscoderService.serializeSessionFields( session );
final MemcachedBackupSession deserialized = TranscoderService.deserializeSessionFields( data, _manager ).getSession();
assertSessionFields( session, deserialized );
}
@Nonnull
protected abstract GenericPrincipal createPrincipal();
@Test
public void testSerializeSessionWithoutAttributes() {
final MemcachedBackupSession session = (MemcachedBackupSession) _manager.createSession( null );
session.setLastBackupTime( System.currentTimeMillis() );
final TranscoderService transcoderService = new TranscoderService( new JavaSerializationTranscoder( _manager ) );
final byte[] data = transcoderService.serialize( session );
final MemcachedBackupSession deserialized = transcoderService.deserialize( data, _manager );
assertSessionFields( session, deserialized );
}
@Test
public void testSerializeSessionWithAttributes() {
final MemcachedBackupSession session = (MemcachedBackupSession) _manager.createSession( null );
final TranscoderService transcoderService = new TranscoderService( new JavaSerializationTranscoder( _manager ) );
final String value = "bar";
session.setAttribute( "foo", value );
session.setLastBackupTime( System.currentTimeMillis() );
final byte[] data = transcoderService.serialize( session );
final MemcachedBackupSession deserialized = transcoderService.deserialize( data, _manager );
assertSessionFields( session, deserialized );
Assert.assertEquals( value, deserialized.getAttribute( "foo" ) );
}
private void assertSessionFields( final MemcachedBackupSession session, final MemcachedBackupSession deserialized ) {
Assert.assertEquals( session.getCreationTimeInternal(), deserialized.getCreationTimeInternal() );
Assert.assertEquals( session.getLastAccessedTimeInternal(), deserialized.getLastAccessedTimeInternal() );
Assert.assertEquals( session.getMaxInactiveInterval(), deserialized.getMaxInactiveInterval() );
Assert.assertEquals( session.isNewInternal(), deserialized.isNewInternal() );
Assert.assertEquals( session.isValidInternal(), deserialized.isValidInternal() );
Assert.assertEquals( session.getThisAccessedTimeInternal(), deserialized.getThisAccessedTimeInternal() );
Assert.assertEquals( session.getLastBackupTime(), deserialized.getLastBackupTime() );
Assert.assertEquals( session.getIdInternal(), deserialized.getIdInternal() );
Assert.assertEquals( session.getAuthType(), deserialized.getAuthType() );
assertDeepEquals( session.getPrincipal(), deserialized.getPrincipal() );
}
}