blob: 4f569328d099bc99c3cae110f896a1a498484500 [file] [log] [blame]
/*
* 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.sling.jcr.contentloader.internal;
import java.text.ParseException;
import java.util.*;
import javax.jcr.*;
import javax.jcr.nodetype.NodeType;
import junitx.util.PrivateAccessor;
import org.apache.sling.commons.testing.jcr.RepositoryProvider;
import org.apache.sling.jcr.api.SlingRepository;
import org.apache.sling.jcr.contentloader.ContentImportListener;
import org.apache.sling.jcr.contentloader.ContentReader;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import static org.junit.Assert.*;
public class DefaultContentCreatorTest {
static final String DEFAULT_NAME = "default-name";
final Mockery mockery = new JUnit4Mockery();
DefaultContentCreator contentCreator;
Session session;
Node parentNode;
Property prop;
@Rule
public ExpectedException thrown = ExpectedException.none();
@Before
public void setup() throws Exception {
final SlingRepository repo = RepositoryProvider.instance().getRepository();
session = repo.loginAdministrative(null);
contentCreator = new DefaultContentCreator(null);
contentCreator.init(ImportOptionsFactory.createImportOptions(true, true, true, false, false),
new HashMap<String, ContentReader>(), null, null);
parentNode = session.getRootNode().addNode(getClass().getSimpleName()).addNode(uniqueId());
}
@After
public void cleanup() throws RepositoryException {
if(session != null) {
session.save();
session.logout();
session = null;
}
}
@Test
public void willRewriteUndefinedPropertyType() throws RepositoryException {
parentNode = mockery.mock(Node.class);
prop = mockery.mock(Property.class);
contentCreator.init(ImportOptionsFactory.createImportOptions(true, true, true, false, false),
new HashMap<String, ContentReader>(), null, null);
contentCreator.prepareParsing(parentNode, null);
this.mockery.checking(new Expectations() {{
allowing(parentNode).isNodeType("mix:versionable"); will(returnValue(Boolean.FALSE));
allowing(parentNode).getParent(); will(returnValue(null));
oneOf (parentNode).hasProperty("foo"); will(returnValue(Boolean.TRUE));
oneOf (parentNode).setProperty(with(equal("foo")), with(equal("bar")));
}});
contentCreator.createProperty("foo", PropertyType.UNDEFINED, "bar");
}
@Test
public void willNotRewriteUndefinedPropertyType() throws RepositoryException {
parentNode = mockery.mock(Node.class);
prop = mockery.mock(Property.class);
contentCreator.init(ImportOptionsFactory.createImportOptions(false, false, true, false, false),
new HashMap<String, ContentReader>(), null, null);
contentCreator.prepareParsing(parentNode, null);
this.mockery.checking(new Expectations() {{
oneOf (parentNode).hasProperty("foo"); will(returnValue(Boolean.TRUE));
oneOf (parentNode).getProperty("foo"); will(returnValue(prop));
oneOf (prop).isNew(); will(returnValue(Boolean.FALSE));
}});
contentCreator.createProperty("foo", PropertyType.UNDEFINED, "bar");
}
@Test
public void testDoesNotCreateProperty() throws RepositoryException {
final String propertyName = "foo";
prop = mockery.mock(Property.class);
parentNode = mockery.mock(Node.class);
this.mockery.checking(new Expectations(){{
oneOf(parentNode).hasProperty(propertyName); will(returnValue(true));
oneOf(parentNode).getProperty(propertyName); will(returnValue(prop));
oneOf(prop).isNew(); will(returnValue(false));
}});
contentCreator.init(ImportOptionsFactory.createImportOptions(false, false, false, false, false),
new HashMap<String, ContentReader>(), null, null);
contentCreator.prepareParsing(parentNode, null);
//By calling this method we expect that it will returns on first if-statement
contentCreator.createProperty("foo", PropertyType.REFERENCE, "bar");
//Checking that
mockery.assertIsSatisfied();
}
@Test
public void testCreateReferenceProperty() throws RepositoryException {
final String propertyName = "foo";
final String propertyValue = "bar";
final String rootNodeName = uniqueId();
final String uuid = "1b8c88d37f0000020084433d3af4941f";
final Session session = mockery.mock(Session.class);
final ContentImportListener listener = mockery.mock(ContentImportListener.class);
parentNode = mockery.mock(Node.class);
prop = mockery.mock(Property.class);
this.mockery.checking(new Expectations(){{
oneOf(session).itemExists(with(any(String.class))); will(returnValue(true));
oneOf(session).getItem(with(any(String.class))); will(returnValue(parentNode));
exactly(2).of(parentNode).getPath(); will(returnValue("/" + rootNodeName));
oneOf(parentNode).isNode(); will(returnValue(true));
oneOf(parentNode).isNodeType("mix:referenceable"); will(returnValue(true));
oneOf(parentNode).getIdentifier(); will(returnValue(uuid));
oneOf(parentNode).getSession(); will(returnValue(session));
oneOf(parentNode).hasProperty(with(any(String.class)));
oneOf(parentNode).setProperty(propertyName, uuid, PropertyType.REFERENCE);
oneOf(parentNode).getProperty(with(any(String.class)));
oneOf(listener).onCreate(with(any(String.class)));
}});
contentCreator.init(ImportOptionsFactory.createImportOptions(false, false, false, false, false),
new HashMap<String, ContentReader>(), null, listener);
contentCreator.prepareParsing(parentNode,null);
contentCreator.createProperty(propertyName, PropertyType.REFERENCE, propertyValue);
//The only way I found how to test this method is to check numbers of methods calls
mockery.assertIsSatisfied();
}
@Test
public void testCreateFalseCheckedOutPreperty() throws RepositoryException {
parentNode = mockery.mock(Node.class);
this.mockery.checking(new Expectations(){{
oneOf(parentNode).hasProperty(with(any(String.class)));
}});
contentCreator.init(ImportOptionsFactory.createImportOptions(false, false, false, false, false),
new HashMap<String, ContentReader>(), null, null);
contentCreator.prepareParsing(parentNode, null);
int numberOfVersionablesNodes = contentCreator.getVersionables().size();
contentCreator.createProperty("jcr:isCheckedOut", PropertyType.UNDEFINED, "false");
//Checking that list of versionables was changed
assertEquals(numberOfVersionablesNodes + 1, contentCreator.getVersionables().size());
mockery.assertIsSatisfied();
}
@Test
public void testCreateTrueCheckedOutPreperty() throws RepositoryException {
parentNode = mockery.mock(Node.class);
this.mockery.checking(new Expectations(){{
oneOf(parentNode).hasProperty(with(any(String.class)));
}});
contentCreator.init(ImportOptionsFactory.createImportOptions(false, false, false, false, false),
new HashMap<String, ContentReader>(), null, null);
contentCreator.prepareParsing(parentNode, null);
int numberOfVersionablesNodes = contentCreator.getVersionables().size();
contentCreator.createProperty("jcr:isCheckedOut", PropertyType.UNDEFINED, "true");
//Checking that list of versionables doesn't changed
assertEquals(numberOfVersionablesNodes, contentCreator.getVersionables().size());
mockery.assertIsSatisfied();
}
@Test
public void testCreateDateProperty() throws RepositoryException, ParseException {
final String propertyName = "dateProp";
final String propertyValue = "2012-10-01T09:45:00.000+02:00";
final ContentImportListener listener = mockery.mock(ContentImportListener.class);
parentNode = mockery.mock(Node.class);
prop = mockery.mock(Property.class);
this.mockery.checking(new Expectations(){{
oneOf(parentNode).hasProperty(with(any(String.class)));
oneOf(parentNode).setProperty(with(any(String.class)), with(any(Calendar.class)));
oneOf(parentNode).getProperty(with(any(String.class))); will(returnValue(prop));
oneOf(prop).getPath(); will(returnValue(""));
oneOf(listener).onCreate(with(any(String.class)));
}});
contentCreator.init(ImportOptionsFactory.createImportOptions(false, false, false, false, false),
new HashMap<String, ContentReader>(), null, listener);
contentCreator.prepareParsing(parentNode, null);
contentCreator.createProperty(propertyName, PropertyType.DATE, propertyValue);
mockery.assertIsSatisfied();
}
@Test
public void testCreatePropertyWithNewPropertyType() throws RepositoryException, ParseException {
final String propertyName = "foo";
final String propertyValue = "bar";
final Integer propertyType = -1;
final ContentImportListener listener = mockery.mock(ContentImportListener.class);
parentNode = mockery.mock(Node.class);
prop = mockery.mock(Property.class);
this.mockery.checking(new Expectations(){{
oneOf(parentNode).hasProperty(with(any(String.class)));
oneOf(parentNode).getProperty(propertyName); will(returnValue(prop));
oneOf(parentNode).setProperty(propertyName, propertyValue, propertyType);
oneOf(prop).getPath(); will(returnValue(""));
oneOf(listener).onCreate(with(any(String.class)));
}});
contentCreator.init(ImportOptionsFactory.createImportOptions(false, false, false, false, false),
new HashMap<String, ContentReader>(), null, listener);
contentCreator.prepareParsing(parentNode, null);
contentCreator.createProperty(propertyName, propertyType, propertyValue);
mockery.assertIsSatisfied();
}
//----- DefaultContentCreator#createNode(String name, String primaryNodeType, String[] mixinNodeTypes)-------//
@Test
public void createNodeWithoutNameAndTwoInStack() throws RepositoryException {
contentCreator.init(ImportOptionsFactory.createImportOptions(true, true, true, false, false),
new HashMap<String, ContentReader>(), null, null);
//Making parentNodeStack.size() == 1
contentCreator.prepareParsing(parentNode, DEFAULT_NAME);
//Making parentNodeStack.size() == 2
contentCreator.createNode(uniqueId(), null, null);
thrown.expect(RepositoryException.class);
contentCreator.createNode(null, null, null);
}
@Test
public void createNodeWithoutProvidedNames() throws RepositoryException, NoSuchFieldException {
@SuppressWarnings("unchecked")
Stack<Node> nodesStack = (Stack<Node>)PrivateAccessor.getField(contentCreator, "parentNodeStack");
contentCreator.init(ImportOptionsFactory.createImportOptions(true, true, true, false, false),
new HashMap<String, ContentReader>(), null, null);
contentCreator.prepareParsing(parentNode, null);
//Contains parentNode only
assertEquals(1, nodesStack.size());
contentCreator.createNode(null, null, null);
//Node has not been created since any name not provided
assertEquals(1, nodesStack.size());
}
@Test
public void createNodeWithOverwrite() throws RepositoryException {
final String newNodeName = uniqueId();
final String propertyName = uniqueId();
final String propertyValue = uniqueId();
final ContentImportListener listener = mockery.mock(ContentImportListener.class);
this.mockery.checking(new Expectations(){{
oneOf(listener).onCreate(with(any(String.class)));
}});
contentCreator.init(ImportOptionsFactory.createImportOptions(true, false, true, false, false),
new HashMap<String, ContentReader>(), null, listener);
contentCreator.prepareParsing(parentNode, DEFAULT_NAME);
Node nodeToOverwrite = parentNode.addNode(newNodeName);
nodeToOverwrite.setProperty(propertyName, propertyValue);
assertTrue(parentNode.getNode(newNodeName).hasProperty(propertyName));
contentCreator.createNode(newNodeName, null, null);
//If node was overwritten(as we expect) it will not contain this property
assertFalse(parentNode.getNode(newNodeName).hasProperty(propertyName));
mockery.assertIsSatisfied();
}
@Test
public void addMixinsToExistingNode() throws RepositoryException, NoSuchFieldException {
final String newNodeName = uniqueId();
final String[] mixins = {"mix:versionable"};
@SuppressWarnings("unchecked")
final List<Node> versionables = (List<Node>) PrivateAccessor.getField(contentCreator, "versionables");
contentCreator.init(ImportOptionsFactory.createImportOptions(false, false, false, true, false),
new HashMap<String, ContentReader>(), null, null);
contentCreator.prepareParsing(parentNode, DEFAULT_NAME);
Node newNode = parentNode.addNode(newNodeName);
assertEquals(0, versionables.size());
assertFalse(newNode.isNodeType(mixins[0]));
contentCreator.createNode(newNodeName, null, mixins);
assertEquals(1, versionables.size());
assertTrue(newNode.isNodeType(mixins[0]));
}
@Test
public void createNodeWithPrimaryType() throws RepositoryException {
final String newNodeName = uniqueId();
final List<String> createdNodes = new ArrayList<String>();
final ContentImportListener listener = mockery.mock(ContentImportListener.class);
this.mockery.checking(new Expectations(){{
oneOf(listener).onCreate(with(any(String.class)));
}});
contentCreator.init(ImportOptionsFactory.createImportOptions(true, false, true, false, false),
new HashMap<String, ContentReader>(), createdNodes, listener);
contentCreator.prepareParsing(parentNode, DEFAULT_NAME);
int createdNodesSize = createdNodes.size();
contentCreator.createNode(newNodeName, NodeType.NT_UNSTRUCTURED, null);
assertEquals(createdNodesSize + 1, createdNodes.size());
Node createdNode = parentNode.getNode(newNodeName);
assertNotNull(createdNode);
assertTrue(createdNode.getPrimaryNodeType().isNodeType(NodeType.NT_UNSTRUCTURED));
mockery.assertIsSatisfied();
}
//----- DefaultContentCreator#createProperty(String name, int propertyType, String[] values)-------//
@Test
public void propertyDoesntOverwritten() throws RepositoryException {
final String newPropertyName = uniqueId();
final String newPropertyValue = uniqueId();
contentCreator.init(ImportOptionsFactory.createImportOptions(false, false, false, false, false),
new HashMap<String, ContentReader>(), null, null);
contentCreator.prepareParsing(parentNode, DEFAULT_NAME);
parentNode.setProperty(newPropertyName, newPropertyValue);
session.save();
contentCreator.createProperty(newPropertyName, PropertyType.REFERENCE, new String[]{"bar1", "bar2"});
//Checking that property is old
assertTrue(!parentNode.getProperty(newPropertyName).isNew());
assertEquals(newPropertyValue, parentNode.getProperty(newPropertyName).getString());
}
@Test
public void createReferenceProperty() throws RepositoryException, NoSuchFieldException {
final String propName = uniqueId();
final String[] propValues = {uniqueId(), uniqueId()};
final ContentImportListener listener = mockery.mock(ContentImportListener.class);
@SuppressWarnings("unchecked")
final Map<String, String[]> delayedMultipleReferences =
(Map<String, String[]>)PrivateAccessor.getField(contentCreator, "delayedMultipleReferences");
this.mockery.checking(new Expectations(){{
oneOf(listener).onCreate(with(any(String.class)));
}});
contentCreator.init(ImportOptionsFactory.createImportOptions(false, false, false, false, false),
new HashMap<String, ContentReader>(), null, listener);
contentCreator.prepareParsing(parentNode, DEFAULT_NAME);
contentCreator.createProperty(propName, PropertyType.REFERENCE, propValues);
assertTrue(parentNode.hasProperty(propName));
assertTrue(parentNode.getProperty(propName).isNew());
String referencesKey = parentNode.getPath() + "/" + propName;
String[] uuidsOrPaths = delayedMultipleReferences.get(referencesKey);
assertNotNull(uuidsOrPaths);
assertEquals(propValues.length, uuidsOrPaths.length);
mockery.assertIsSatisfied();
}
@Test
public void createDateProperty() throws RepositoryException, ParseException {
final String propName = "dateProp";
final String[] propValues = {"2012-10-01T09:45:00.000+02:00", "2011-02-13T09:45:00.000+02:00"};
final ContentImportListener listener = mockery.mock(ContentImportListener.class);
this.mockery.checking(new Expectations(){{
oneOf(listener).onCreate(with(any(String.class)));
}});
parentNode.addMixin("mix:versionable");
contentCreator.init(ImportOptionsFactory.createImportOptions(false, false, true, false, false),
new HashMap<String, ContentReader>(), null, listener);
contentCreator.prepareParsing(parentNode, null);
assertFalse(parentNode.hasProperty(propName));
contentCreator.createProperty(propName, PropertyType.DATE, propValues);
assertTrue(parentNode.hasProperty(propName));
Property dateProp = parentNode.getProperty(propName);
assertTrue(dateProp.isNew());
assertEquals(propValues.length, dateProp.getValues().length);
mockery.assertIsSatisfied();
}
@Test
public void createUndefinedProperty() throws RepositoryException {
final String propName = uniqueId();
final ContentImportListener listener = mockery.mock(ContentImportListener.class);
this.mockery.checking(new Expectations(){{
oneOf(listener).onCreate(with(any(String.class)));
}});
contentCreator.init(ImportOptionsFactory.createImportOptions(false, false, false, false, false),
new HashMap<String, ContentReader>(), null, listener);
contentCreator.prepareParsing(parentNode, null);
assertFalse(parentNode.hasProperty(propName));
contentCreator.createProperty(propName, PropertyType.UNDEFINED, new String[]{});
assertTrue(parentNode.hasProperty(propName));
mockery.assertIsSatisfied();
}
@Test
public void createOtherProperty() throws RepositoryException {
final String propName = uniqueId();
contentCreator.init(ImportOptionsFactory.createImportOptions(false, false, false, false, false),
new HashMap<String, ContentReader>(), null, null);
contentCreator.prepareParsing(parentNode, null);
assertFalse(parentNode.hasProperty(propName));
contentCreator.createProperty(propName, PropertyType.STRING, new String[]{});
assertTrue(parentNode.hasProperty(propName));
}
//------DefaultContentCreator#finishNode()------//
@Test
public void finishNodeWithMultipleProperty() throws RepositoryException, NoSuchFieldException {
final String propName = uniqueId();
final String underTestNodeName = uniqueId();
@SuppressWarnings("unchecked")
final Map<String, List<String>> delayedMultipleReferences =
(Map<String, List<String>>) PrivateAccessor.getField(contentCreator, "delayedMultipleReferences");
final ContentImportListener listener = mockery.mock(ContentImportListener.class);
this.mockery.checking(new Expectations(){{
exactly(3).of(listener).onCreate(with(any(String.class)));
}});
contentCreator.init(ImportOptionsFactory.createImportOptions(false, false, false, false, false),
new HashMap<String, ContentReader>(), null, listener);
contentCreator.prepareParsing(parentNode, null);
contentCreator.createProperty(propName, PropertyType.REFERENCE, new String[]{underTestNodeName});
contentCreator.createNode(underTestNodeName, null, null);
assertEquals(1, delayedMultipleReferences.size());
Node underTest = parentNode.getNode(underTestNodeName);
underTest.addMixin("mix:referenceable");
contentCreator.finishNode();
assertEquals(0, delayedMultipleReferences.size());
mockery.assertIsSatisfied();
}
@Test
public void finishNodeWithSingleProperty() throws RepositoryException, NoSuchFieldException {
final String propName = uniqueId();
final String underTestNodeName = uniqueId();
final ContentImportListener listener = mockery.mock(ContentImportListener.class);
this.mockery.checking(new Expectations(){{
exactly(2).of(listener).onCreate(with(any(String.class)));
}});
contentCreator.init(ImportOptionsFactory.createImportOptions(false, false, false, false, false),
new HashMap<String, ContentReader>(), null, listener);
contentCreator.prepareParsing(parentNode, null);
contentCreator.createProperty(propName, PropertyType.REFERENCE, underTestNodeName);
contentCreator.createNode(underTestNodeName, null, null);
Node underTest = parentNode.getNode(underTestNodeName);
underTest.addMixin("mix:referenceable");
contentCreator.finishNode();
assertEquals(underTest.getIdentifier(), parentNode.getProperty(propName).getString());
mockery.assertIsSatisfied();
}
@Test
public void finishNodeWithoutProperties() throws RepositoryException, NoSuchFieldException {
final String propName = uniqueId();
final String underTestNodeName = uniqueId();
contentCreator.init(ImportOptionsFactory.createImportOptions(false, false, false, false, false),
new HashMap<String, ContentReader>(), null, null);
contentCreator.prepareParsing(parentNode, null);
contentCreator.createProperty(propName, PropertyType.UNDEFINED, underTestNodeName);
contentCreator.createNode(underTestNodeName, null, null);
contentCreator.finishNode();
assertEquals(underTestNodeName, parentNode.getProperty(propName).getString());
}
@Test
public void finishNotReferenceableNode() throws RepositoryException, NoSuchFieldException {
final String propName = uniqueId();
final String underTestNodeName = uniqueId();
contentCreator.init(ImportOptionsFactory.createImportOptions(false, false, false, false, false),
new HashMap<String, ContentReader>(), null, null);
contentCreator.prepareParsing(parentNode, null);
contentCreator.createProperty(propName, PropertyType.REFERENCE, underTestNodeName);
contentCreator.createNode(underTestNodeName, null, null);
contentCreator.finishNode();
//False since it doesn't have referenceable mixin
assertFalse(parentNode.hasProperty(propName));
}
private final String uniqueId() {
return getClass().getSimpleName() + UUID.randomUUID();
}
}