/*
* Copyright 2003-2017 JetBrains s.r.o.
*
* 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 jetbrains.mps.smodel;
import jetbrains.mps.smodel.ModelUndoTest.TestUndoHandler;
import jetbrains.mps.smodel.TestModelFactory.TestModelAccess;
import jetbrains.mps.smodel.TestModelFactory.TestRepository;
import jetbrains.mps.util.IterableUtil;
import org.jetbrains.mps.openapi.model.SNode;
import org.jetbrains.mps.openapi.model.SNodeId;
import org.jetbrains.mps.openapi.module.SRepository;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import static jetbrains.mps.smodel.TestModelFactory.ourRole;
/**
* Various tests to check SModel, not related to read/change listeners
* @author Artem Tikhomirov
*/
public class ModelImplementationTest {
private final TestModelAccess myTestModelAccess = new TestModelAccess();
private final SRepository myTestRepo = new TestRepository(myTestModelAccess);
@Before
public void setUp() {
TestUndoHandler uh = new TestUndoHandler();
uh.needsUndo(false); // undo is not our focus here, we merely need to avoid NPE from ModelAccess.instance().isInsideCommand()
UndoHelper.getInstance().setUndoHandler(uh);
}
/**
* There's a defect in insertChildBefore, node to insert has been checked for getParent() == null
* which holds true both for detached/free-floating nodes AND for normal roots
* Model m1 with two roots, r1 and r2. Insert r1 under r2 and observe both roots still there, as well as r1 as child of r2
*/
@Test
public void testRootInsertedAsChild_sameModel() {
final TestModelFactory m1f = new TestModelFactory();
org.jetbrains.mps.openapi.model.SModel m1 = m1f.createModel(2, 2);
myTestModelAccess.enterCommand();
m1f.attachTo(myTestRepo);
final org.jetbrains.mps.openapi.model.SNode r1 = m1f.getRoot(1);
final org.jetbrains.mps.openapi.model.SNode r2 = m1f.getRoot(2);
final org.jetbrains.mps.openapi.model.SNodeId r1id = r1.getNodeId();
Assert.assertEquals(2, IterableUtil.asCollection(m1.getRootNodes()).size());
Assert.assertEquals(2, IterableUtil.asCollection(r2.getChildren()).size());
Assert.assertSame(r1, m1.getNode(r1id));
//
//
try {
r2.insertChildBefore(ourRole, r1, null);
Assert.assertEquals(2, IterableUtil.asCollection(m1.getRootNodes()).size());// 2 !!!
Assert.assertEquals(3, IterableUtil.asCollection(r2.getChildren()).size()); // 3 !!!
Assert.assertTrue(IterableUtil.asCollection(r2.getChildren()).contains(r1)); // !!!
Assert.assertNotNull(r2.getParent()); // !!!
Assert.assertSame(r1, m1.getNode(r1id)); // ?!
Assert.fail("Insert of a root not detached from a model shall fail");
} catch (IllegalModelAccessException ignored) {
// expected
}
}
/**
* There's was a left-over from pre-3.0 to clear model of a node being added to free-floating node.
* Only model was cleared, without un-registering node from its model.
*
* Move root from a registered model (m2) to a free-floating node
*/
@Test
public void testRootInsertedAsChild_otherModel() {
final TestModelFactory m1f = new TestModelFactory();
org.jetbrains.mps.openapi.model.SModel m1 = m1f.createModel(2, 2);
myTestModelAccess.enterCommand();
m1f.attachTo(myTestRepo);
final org.jetbrains.mps.openapi.model.SNode r1 = m1f.getRoot(1);
final SNode ffn = m1f.createNode();
final SNodeId r1id = r1.getNodeId();
Assert.assertEquals(2, IterableUtil.asCollection(m1.getRootNodes()).size());
Assert.assertEquals(2, IterableUtil.asCollection(r1.getChildren()).size());
Assert.assertSame(r1, m1.getNode(r1id));
//
//
try {
ffn.insertChildBefore(ourRole, r1, null);
Assert.assertEquals(2, IterableUtil.asCollection(m1.getRootNodes()).size());
Assert.assertTrue(IterableUtil.asCollection(ffn.getChildren()).contains(r1));
Assert.assertSame(r1, m1.getNode(r1id)); // still in the model
Assert.assertNull(m1.getNode(r1id).getModel()); // but got no model assigned
Assert.fail("Insert of a root not detached from a model shall fail");
} catch (IllegalModelAccessException ignored) {
// expected
}
}
}