/*
* 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.usergrid.corepersistence.service;
import java.util.List;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.usergrid.corepersistence.TestCoreModule;
import org.apache.usergrid.corepersistence.util.CpNamingUtils;
import org.apache.usergrid.persistence.core.guice.MigrationManagerRule;
import org.apache.usergrid.persistence.core.scope.ApplicationScope;
import org.apache.usergrid.persistence.core.scope.ApplicationScopeImpl;
import org.apache.usergrid.persistence.core.test.ITRunner;
import org.apache.usergrid.persistence.core.test.UseModules;
import org.apache.usergrid.persistence.graph.Edge;
import org.apache.usergrid.persistence.graph.GraphManager;
import org.apache.usergrid.persistence.graph.GraphManagerFactory;
import org.apache.usergrid.persistence.graph.MarkedEdge;
import org.apache.usergrid.persistence.graph.SearchByEdge;
import org.apache.usergrid.persistence.graph.SearchByEdgeType;
import org.apache.usergrid.persistence.graph.impl.SimpleSearchByEdge;
import org.apache.usergrid.persistence.model.entity.Id;
import org.apache.usergrid.persistence.model.entity.SimpleId;
import com.google.common.base.Optional;
import com.google.inject.Inject;
import rx.Observable;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@RunWith( ITRunner.class )
@UseModules( TestCoreModule.class )
public class ConnectionServiceImplTest {
private static final Logger logger = LoggerFactory.getLogger(ConnectionServiceImplTest.class);
@Inject
private GraphManagerFactory graphManagerFactory;
@Inject
private ConnectionService connectionService;
@Inject
@Rule
public MigrationManagerRule migrationManagerRule;
@Test
public void testSingleConnection() {
final ApplicationScope applicationScope = new ApplicationScopeImpl( new SimpleId( "application" ) );
final GraphManager gm = graphManagerFactory.createEdgeManager( applicationScope );
//now write a single connection
final Id source = new SimpleId( "source" );
//add to a collection
final String collectionName = "testCollection";
final Edge collectionEdge = CpNamingUtils.createCollectionEdge( applicationScope.getApplication(), collectionName, source );
final Edge writtenCollection = gm.writeEdge( collectionEdge ).toBlocking().last();
assertNotNull("Collection edge written", writtenCollection);
final Id target = new SimpleId( "target" );
final String connectionType = "testConnection";
final Edge connectionEdge = CpNamingUtils.createConnectionEdge( source, connectionType, target );
final Edge writtenConnection = gm.writeEdge( connectionEdge ).toBlocking().last();
//now run the cleanup
final int count =
connectionService.deDupeConnections( Observable.just( applicationScope ) ).count().toBlocking().last();
assertEquals( "No edges deleted", 0, count );
//now ensure we can read the edge.
final SearchByEdge simpleSearchByEdge =
new SimpleSearchByEdge( source, connectionEdge.getType(), target, Long.MAX_VALUE,
SearchByEdgeType.Order.DESCENDING, Optional.absent() );
final List<MarkedEdge> edges = gm.loadEdgeVersions( simpleSearchByEdge ).toList().toBlocking().last();
assertEquals( 1, edges.size() );
assertEquals( writtenConnection, edges.get( 0 ) );
}
@Test
public void testDuplicateConnections() {
final ApplicationScope applicationScope = new ApplicationScopeImpl( new SimpleId( "application" ) );
final GraphManager gm = graphManagerFactory.createEdgeManager( applicationScope );
//now write a single connection
final Id source = new SimpleId( "source" );
//add to a collection
final String collectionName = "testCollection";
final Edge collectionEdge = CpNamingUtils.createCollectionEdge( applicationScope.getApplication(), collectionName, source );
final Edge writtenCollection = gm.writeEdge( collectionEdge ).toBlocking().last();
assertNotNull("Collection edge written", writtenCollection);
//now write 3 connections between the same nodes.
final Id target = new SimpleId( "target" );
final String connectionType = "testConnection";
//write our first connection
final Edge connection1 = CpNamingUtils.createConnectionEdge( source, connectionType, target );
final Edge written1 = gm.writeEdge( connection1 ).toBlocking().last();
logger.info( "Wrote edge 1 with edge {}", written1 );
//write the second
final Edge connection2 = CpNamingUtils.createConnectionEdge( source, connectionType, target );
final Edge written2 = gm.writeEdge( connection2 ).toBlocking().last();
logger.info( "Wrote edge 2 with edge {}", written2 );
//write the 3rd
final Edge connection3 = CpNamingUtils.createConnectionEdge( source, connectionType, target );
final Edge written3 = gm.writeEdge( connection3 ).toBlocking().last();
logger.info( "Wrote edge 3 with edge {}", written3 );
assertTrue( "Expected edge timestamp to be in order", written1.getTimestamp() <= written2.getTimestamp() );
assertTrue( "Expected edge timestamp to be in order", written2.getTimestamp() <= written3.getTimestamp() );
//now run the cleanup
final List<ConnectionScope> deletedConnections =
connectionService.deDupeConnections( Observable.just( applicationScope ) ).toList().toBlocking().last();
//check our oldest was deleted first
assertEdgeData( written2, deletedConnections.get( 0 ).getEdge() );
assertEdgeData( written1, deletedConnections.get( 1 ).getEdge() );
assertEquals( "2 edges deleted", 2, deletedConnections.size() );
//now ensure we can read the edge.
final SearchByEdge simpleSearchByEdge =
new SimpleSearchByEdge( source, connection1.getType(), target, Long.MAX_VALUE,
SearchByEdgeType.Order.DESCENDING, Optional.absent() );
//check only 1 exists
final List<MarkedEdge> edges = gm.loadEdgeVersions( simpleSearchByEdge ).toList().toBlocking().last();
assertEquals( 1, edges.size() );
assertEquals( written3, edges.get( 0 ) );
}
/**
* Compares edges based on their sourceId, type, targetId and timestamp. It ignores the deleted flag
* @param expected
* @param asserted
*/
private void assertEdgeData(final Edge expected, final Edge asserted){
assertEquals("SourceId the same", expected.getSourceNode(), asserted.getSourceNode());
assertEquals("TargetId the same", expected.getTargetNode(), asserted.getTargetNode());
assertEquals("Type the same", expected.getType(), asserted.getType());
assertEquals("Timestamp the same", expected.getTimestamp(), asserted.getTimestamp());
}
}