());
        }
        
        assertNotNull(child2);
        this.versionableNodes.put(child2.getId(), child2);
        
        // Create a node that can be associated with the root node
        NodeRef assocNode = this.dbNodeService.createNode(
                rootNodeRef,
                ContentModel.ASSOC_CHILDREN,
                QName.createQName("{test}MyAssocNode"),
                nodeType,
                this.nodeProperties).getChildRef();
        assertNotNull(assocNode);
        this.dbNodeService.createAssociation(nodeRef, assocNode, TEST_ASSOC);
        
        return nodeRef;
    }
    
    /**
     * Creates a new version, checking the properties of the version.
     * 
     * The default test propreties are assigned to the version.
     * 
     * @param versionableNode    the versionable node
     * @return                   the created (and checked) new version
     */
    protected Version createVersion(NodeRef versionableNode)
    {
        return createVersion(versionableNode, this.versionProperties);
    }
    
    /**
     * Creates a new version, checking the properties of the version.
     * 
     * @param versionableNode    the versionable node
     * @param versionProperties  the version properties
     * @return                   the created (and checked) new version
     */
    protected Version createVersion(NodeRef versionableNode, Map versionProperties)
    {
        // Get the next version label
        String nextVersionLabel = peekNextVersionLabel(versionableNode, versionProperties);
        
        // Snap-shot the node created date-time
        long beforeVersionTime = ((Date)nodeService.getProperty(versionableNode, ContentModel.PROP_CREATED)).getTime();
        
        // Now lets create a new version for this node
        Version newVersion = versionService.createVersion(versionableNode, this.versionProperties);
        checkNewVersion(beforeVersionTime, nextVersionLabel, newVersion, versionableNode);
        
        // Return the new version
        return newVersion;
    }
    
    protected Collection createVersion(NodeRef versionableNode, Map versionProperties, boolean versionChildren)
    {
        // Get the next version label
        String nextVersionLabel = peekNextVersionLabel(versionableNode, versionProperties);
        
        // Snap-shot the node created date-time
        long beforeVersionTime = ((Date)nodeService.getProperty(versionableNode, ContentModel.PROP_CREATED)).getTime();
        
        // Now lets create new version for this node (optionally with children)
        Collection versions = versionService.createVersion(versionableNode, this.versionProperties, versionChildren);
        
        // Check the returned versions are correct
        checkVersionCollection(nextVersionLabel, beforeVersionTime, versions);
        
        // Return the new versions
        return versions;
    }
    
    /**
     * Gets the next version label
     */
    protected String peekNextVersionLabel(NodeRef nodeRef, Map versionProperties)
    {
        Version version = this.versionService.getCurrentVersion(nodeRef);
        SerialVersionLabelPolicy policy = new SerialVersionLabelPolicy();
        return policy.calculateVersionLabel(ContentModel.TYPE_CMOBJECT, version, versionProperties);
    }
    
    /**
     * Checkd the validity of a new version
     * 
     * @param beforeVersionTime     the time snap shot before the version was created
     * @param newVersion            the new version
     * @param versionableNode       the versioned node
     */
    protected void checkVersion(long beforeVersionTime, String expectedVersionLabel, Version newVersion, NodeRef versionableNode)
    {
        assertNotNull(newVersion);
        
        // Check the version label
        assertEquals(
                "The expected version label was not used.",
                expectedVersionLabel,
                newVersion.getVersionLabel());
        
        // Check the created date
        long afterVersionTime = System.currentTimeMillis();
        long createdDate = newVersion.getFrozenModifiedDate().getTime();
        if (createdDate < beforeVersionTime || createdDate > afterVersionTime)
        {
            fail("The created date of the version is incorrect.");
        }
        
        // Check the creator
        assertEquals(AuthenticationUtil.getAdminUserName(), newVersion.getFrozenModifier());
        
        // Check the metadata properties of the version
        Map props = newVersion.getVersionProperties();
        assertNotNull("The version properties collection should not be null.", props);
        if (versionProperties != null)
        {
            // TODO sort this out - need to check for the reserved properties too
            //assertEquals(versionProperties.size(), props.size());
            for (String key : versionProperties.keySet())
            {
                assertEquals(
                        versionProperties.get(key),
                        newVersion.getVersionProperty(key));
            }
        }
        
        // Check that the node reference is correct
        NodeRef nodeRef = newVersion.getFrozenStateNodeRef();
        assertNotNull(nodeRef);
        
        // Switch VersionStore depending on configured impl
        if (versionService.getVersionStoreReference().getIdentifier().equals(Version2Model.STORE_ID))
        {
        	// V2 version store (eg. workspace://version2Store)
            assertEquals(
                    Version2Model.STORE_ID,
                    nodeRef.getStoreRef().getIdentifier());
            assertEquals(
                    Version2Model.STORE_PROTOCOL,
                    nodeRef.getStoreRef().getProtocol());
            assertNotNull(nodeRef.getId());
        } 
        else if (versionService.getVersionStoreReference().getIdentifier().equals(VersionModel.STORE_ID))
        {
            // Deprecated V1 version store (eg. workspace://lightWeightVersionStore)
            assertEquals(
                    VersionModel.STORE_ID,
                    nodeRef.getStoreRef().getIdentifier());
            assertEquals(
                    VersionModel.STORE_PROTOCOL,
                    nodeRef.getStoreRef().getProtocol());
            assertNotNull(nodeRef.getId());
        }
    }
    
    protected void checkNewVersion(long beforeVersionTime, String expectedVersionLabel, Version newVersion, NodeRef versionableNode)
    {
        checkVersion(beforeVersionTime, expectedVersionLabel, newVersion, versionableNode);
        
        // TODO: How do we check the frozen attributes ??
        
        // Check the node ref for the current version
        String currentVersionLabel = (String)this.dbNodeService.getProperty(
                versionableNode,
                ContentModel.PROP_VERSION_LABEL);
        assertEquals(newVersion.getVersionLabel(), currentVersionLabel);
    }
    
    /**
     * Helper method to check the validity of the list of newly created versions.
     * 
     * @param beforeVersionTime      the time before the versions where created
     * @param versions               the collection of version objects
     */
    private void checkVersionCollection(String expectedVersionLabel, long beforeVersionTime, Collection versions)
    {
        for (Version version : versions)
        {
            // Get the frozen id from the version
            String frozenNodeId = null;
            
            // Switch VersionStore depending on configured impl
            if (versionService.getVersionStoreReference().getIdentifier().equals(Version2Model.STORE_ID))
            {
                // V2 version store (eg. workspace://version2Store)
                frozenNodeId = ((NodeRef)version.getVersionProperty(Version2Model.PROP_FROZEN_NODE_REF)).getId();
            } 
            else if (versionService.getVersionStoreReference().getIdentifier().equals(VersionModel.STORE_ID))
            {
                // Deprecated V1 version store (eg. workspace://lightWeightVersionStore)
                frozenNodeId = (String)version.getVersionProperty(VersionModel.PROP_FROZEN_NODE_ID);
            }
            
            assertNotNull("Unable to retrieve the frozen node id from the created version.", frozenNodeId);
            
            // Get the original node ref (based on the forzen node)
            NodeRef origionaNodeRef = this.versionableNodes.get(frozenNodeId);
            assertNotNull("The versionable node ref that relates to the frozen node id can not be found.", origionaNodeRef);
            
            // Check the new version
            checkNewVersion(beforeVersionTime, expectedVersionLabel, version, origionaNodeRef);
        }
    }
}