/**
* Copyright 2004-2016 Riccardo Solmi. All rights reserved.
* This file is part of the Whole Platform.
*
* The Whole Platform 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 3 of the License, or
* (at your option) any later version.
*
* The Whole Platform 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 the Whole Platform. If not, see <http://www.gnu.org/licenses/>.
*/
package org.whole.lang.lifecycle;
import java.util.List;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.whole.lang.bindings.BindingManagerFactory;
import org.whole.lang.commands.ICommand;
import org.whole.lang.model.IEntity;
import org.whole.lang.model.InternalIEntity;
import org.whole.lang.models.codebase.XmlModel;
import org.whole.lang.models.factories.ModelsEntityFactory;
import org.whole.lang.models.model.Model;
import org.whole.lang.reflect.ReflectionFactory;
/**
* @author Riccardo Solmi
*/
public class LifecycleAPITest {
Model model;
IHistoryManager history;
@BeforeClass
public static void deployWholePlatform() {
ReflectionFactory.deployWholePlatform();
}
@Before
public void setUp() {
model = new XmlModel().create();
history = ReflectionFactory.getHistoryManager(model);
history.setHistoryEnabled(true);
}
@Test
public void testUndoSize() {
assertEquals(0, history.getUndoSize());
model.getName().wSetValue("newLangName");
assertEquals(1, history.getUndoSize());
model.getNamespace().wSetValue("org.whole.lang");
assertEquals(2, history.getUndoSize());
model.getName().wSetValue("newerLangName");
assertEquals(3, history.getUndoSize());
model.getDeclarations().wRemove(1);
assertEquals(4, history.getUndoSize());
model.setName(ModelsEntityFactory.instance.createSimpleName("new data"));
assertEquals(5, history.getUndoSize());
model.getDeclarations().wAdd(ModelsEntityFactory.instance.createDataEntity());
assertEquals(6, history.getUndoSize());
model.getDeclarations().wSet(2, ModelsEntityFactory.instance.createDataEntity());
assertEquals(7, history.getUndoSize());
model.getDeclarations().wAdd(3, ModelsEntityFactory.instance.createDataEntity());
assertEquals(8, history.getUndoSize());
model.wSet(model.getName(), ModelsEntityFactory.instance.createSimpleName("new name"));
assertEquals(9, history.getUndoSize());
}
@Test
public void testUndoCommands() {
IEntity id = model.wGet(0);
id.wSetValue("newLangName");
ICommand lastCommand = ((InternalIEntity) id).wGetLastCommand();
List<ICommand> changes = history.getUndoCommands();
ICommand command = changes.get(changes.size()-1);
assertSame(lastCommand, command);
assertEquals(id, command.getSource());
assertEquals("newLangName", command.getNewObject());
}
@Test
public void testUndo() {
IEntity id = model.wGet(0);
String idVal = id.wStringValue();
id.wSetValue("newLangName");
assertEquals(1, history.getUndoSize());
assertEquals("newLangName", model.wGet(0).wStringValue());
history.undo();
assertEquals(0, history.getUndoSize());
assertEquals(idVal, model.wGet(0).wStringValue());
}
@Test
public void testEnablement() {
assertTrue(history.isHistoryEnabled());
model.getName().setValue("value 1");
history.setHistoryEnabled(true);
model.getName().setValue("value 2");
assertEquals(2, history.getUndoSize());
history.setHistoryEnabled(false);
model.getName().setValue("value 3");
model.getName().setValue("value 4");
assertEquals(2, history.getUndoSize());
history.setHistoryEnabled(true);
assertEquals(0, history.getUndoSize());
model.getName().setValue("value 5");
assertEquals(1, history.getUndoSize());
}
@Test
public void testStatus() {
ITransaction transaction = ReflectionFactory.getTransaction(model);
assertEquals(transaction.getStatus(), Status.NO_TRANSACTION);
}
@Test
public void testIllegalStates() {
ITransaction transaction = ReflectionFactory.getTransaction(model);
try {
transaction.commit();
fail();
} catch (IllegalStateException e) {
}
try {
transaction.rollback();
fail();
} catch (IllegalStateException e) {
}
try {
transaction.setRollbackOnly();
fail();
} catch (IllegalStateException e) {
}
}
@Test
public void testCommit() {
ITransaction transaction = ReflectionFactory.getTransaction(model);
IEntity e1 = model.wGet(0);
IEntity e2 = model.wGet(3);
transaction.begin();
e1.wSetValue("newLangName");
ICommand c1 = ((InternalIEntity) e1).wGetLastCommand();
e2.wSetValue("newNamespace");
ICommand c2 = ((InternalIEntity) e2).wGetLastCommand();
String langName = e1.wStringValue();
int size = history.getUndoSize();
assertTrue(c1.getExecutionTime() <= c2.getExecutionTime());
transaction.commit();
assertEquals(e1.wStringValue(), langName);
assertTrue(history.getUndoSize() < size);
assertEquals(c1.getExecutionTime(), c2.getExecutionTime());
}
@Test
public void testRollback() {
ITransaction transaction = ReflectionFactory.getTransaction(model);
IEntity e1 = model.wGet(0);
IEntity e2 = model.wGet(3);
transaction.begin();
String langName = e1.wStringValue();
int size = history.getUndoSize();
e1.wSetValue("newLangName");
e2.wSetValue("newNamespace");
transaction.rollback();
assertEquals(e1.wStringValue(), langName);
assertEquals(history.getUndoSize(), size);
}
@Test
public void testSetRollbackOnly() {
ITransaction transaction = ReflectionFactory.getTransaction(model);
IEntity e1 = model.wGet(0);
IEntity e2 = model.wGet(3);
transaction.begin();
String langName = e1.wStringValue();
int size = history.getUndoSize();
e1.wSetValue("newLangName");
e2.wSetValue("newNamespace");
int size1 = history.getUndoSize();
transaction.setRollbackOnly();
assertEquals(e1.wStringValue(), "newLangName");
assertEquals(history.getUndoSize(), size1);
try {
transaction.commit();
fail();
} catch (RollbackException e) {
}
assertEquals(e1.wStringValue(), langName);
assertEquals(history.getUndoSize(), size);
}
@Test
public void testUndoRedoTransactionBoundary() {
ITransaction transaction = ReflectionFactory.getTransaction(model);
IEntity e1 = model.wGet(0);
IEntity e2 = model.wGet(3);
String langName1 = e1.wStringValue();
String rootName1 = e2.wStringValue();
int size = history.getUndoSize();
transaction.begin();
e1.wSetValue("newLangName");
e2.wSetValue("newNamespace");
transaction.commit();
String langName2 = e1.wStringValue();
String rootName2 = e2.wStringValue();
int size2 = history.getUndoSize();
assertEquals(e1.wStringValue(), langName2);
assertEquals(e2.wStringValue(), rootName2);
history.undo();
assertEquals(e1.wStringValue(), langName1);
assertEquals(e2.wStringValue(), rootName1);
assertEquals(history.getUndoSize(), size);
history.redo();
assertEquals(e1.wStringValue(), langName2);
assertEquals(e2.wStringValue(), rootName2);
assertEquals(history.getUndoSize(), size2);
}
@Test
public void testMultipleModelsUndoSingleTransactionBoundary() {
IEntity tuple = BindingManagerFactory.instance.createTuple(true);
tuple.wGetModel().getCompoundModel().setHistoryManager(history, false);
ITransaction transaction = ReflectionFactory.getTransaction(model);
transaction.begin();
IEntity declarations = model.getDeclarations();
int declarationsSize = declarations.wSize();
IEntity declaration = declarations.wGet(0);
declarations.wRemove(0);
tuple.wAdd(declaration);
transaction.commit();
history.undo();
assertEquals(declarationsSize, declarations.wSize());
assertEquals(0, tuple.wSize());
}
@Test
public void testMultipleModelsUndoCrossTransactionBoundary() {
IEntity tuple = BindingManagerFactory.instance.createTuple(true);
//with a different history manger
ITransaction transaction = ReflectionFactory.getTransaction(model);
transaction.begin();
IEntity declarations = model.getDeclarations();
IEntity declaration = declarations.wGet(0);
declarations.wRemove(0);
tuple.wAdd(declaration);
transaction.commit();
try {
history.undo();
fail();
} catch (Exception e) {
}
}
}