/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.wicket.model;
import static org.hamcrest.core.Is.is;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import org.apache.wicket.util.tester.WicketTestCase;
import org.junit.Test;
/**
* Tests the states of a LoadableDetachableModel
*/
@SuppressWarnings("javadoc")
public class LoadableDetachableModelTest extends WicketTestCase
{
/**
* Checks whether the LDM can escape recursive calls.
*/
@Test
public void recursiveGetObjectDoesntCauseInfiteLoop()
{
class RecursiveLoad extends LoadableDetachableModel<Integer>
{
private static final long serialVersionUID = 1L;
private int count = 0;
@Override
protected Integer load()
{
count++;
getObject();
return count;
}
}
RecursiveLoad ldm = new RecursiveLoad();
assertThat(ldm.isAttached(), is(false));
assertThat(ldm.getObject(), is(1));
assertThat(ldm.isAttached(), is(true));
}
@Test
public void onAttachCalled()
{
class AttachingLoadableModel extends LoadableDetachableModel<Integer>
{
private static final long serialVersionUID = 1L;
private boolean attachCalled = false;
@Override
protected Integer load()
{
return null;
}
@Override
protected void onAttach()
{
attachCalled = true;
}
}
AttachingLoadableModel m = new AttachingLoadableModel();
m.getObject();
assertThat(m.isAttached(), is(true));
assertThat(m.attachCalled, is(true));
}
/**
* Checks whether the LDM can escape recursive calls.
*/
@Test
public void exceptionDuringLoadKeepsLDMDetached()
{
class ExceptionalLoad extends LoadableDetachableModel<Integer>
{
private static final long serialVersionUID = 1L;
private boolean detachCalled = false;
@Override
protected Integer load()
{
throw new RuntimeException();
}
@Override
protected void onDetach()
{
detachCalled = true;
}
}
ExceptionalLoad ldm = new ExceptionalLoad();
assertThat(ldm.isAttached(), is(false));
try
{
assertThat(ldm.getObject(), is(1));
fail("shouldn't get here");
}
catch (RuntimeException e)
{
}
ldm.detach();
assertThat(ldm.isAttached(), is(false));
assertThat(ldm.detachCalled, is(true));
}
private static class SerializedLoad extends LoadableDetachableModel<Integer>
{
private static final long serialVersionUID = 1L;
private int count = 0;
@Override
protected Integer load()
{
return ++count;
}
}
/**
* Tests serialization/deserialization of LDM retaining the correct state.
*
* @throws Exception
*/
@Test
public void serializationDeserializationRetainsInternalState() throws Exception
{
SerializedLoad ldm = new SerializedLoad();
assertThat(ldm.getObject(), is(1));
ldm.detach();
byte[] serialized = serialize(ldm);
LoadableDetachableModel<Integer> deserialized = deserialize(serialized);
assertThat(deserialized.isAttached(), is(false));
assertThat(deserialized.getObject(), is(2));
assertThat(deserialized.isAttached(), is(true));
deserialized.detach();
assertThat(deserialized.isAttached(), is(false));
}
/** Serialization helper */
@SuppressWarnings("unchecked")
private <T> LoadableDetachableModel<T> deserialize(byte[] serialized)
throws IOException, ClassNotFoundException
{
LoadableDetachableModel<T> deserialized = null;
try (ByteArrayInputStream bais = new ByteArrayInputStream(serialized);
ObjectInputStream ois = new ObjectInputStream(bais);)
{
deserialized = (LoadableDetachableModel<T>)ois.readObject();
}
return deserialized;
}
/** Deserialization helper */
private byte[] serialize(Serializable ldm) throws IOException
{
byte[] stream = { };
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);)
{
oos.writeObject(ldm);
stream = baos.toByteArray();
}
return stream;
}
}