Additional tests for DuplicateAdminRepair, remove old DupAdminRepair.

Project: http://git-wip-us.apache.org/repos/asf/usergrid/repo
Commit: http://git-wip-us.apache.org/repos/asf/usergrid/commit/ceb81076
Tree: http://git-wip-us.apache.org/repos/asf/usergrid/tree/ceb81076
Diff: http://git-wip-us.apache.org/repos/asf/usergrid/diff/ceb81076

Branch: refs/heads/1.x
Commit: ceb81076520db67e88f6c7a0e0934e39703309e7
Parents: e525f4f
Author: Dave Johnson <[email protected]>
Authored: Mon Jan 11 18:08:54 2016 -0500
Committer: Dave Johnson <[email protected]>
Committed: Mon Jan 11 18:08:54 2016 -0500

----------------------------------------------------------------------
 .../apache/usergrid/tools/DupAdminRepair.java   | 311 -------------------
 .../usergrid/tools/DuplicateAdminRepair.java    | 289 +++++++++++++++++
 .../tools/DuplicateAdminUserRepair.java         | 289 -----------------
 .../tools/DuplicateAdminRepairTest.java         | 301 ++++++++++++++++++
 .../tools/DuplicateAdminUserRepairTest.java     | 301 ------------------
 .../usergrid/tools/MockUserOrgManager.java      |   2 +-
 6 files changed, 591 insertions(+), 902 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/usergrid/blob/ceb81076/stack/tools/src/main/java/org/apache/usergrid/tools/DupAdminRepair.java
----------------------------------------------------------------------
diff --git 
a/stack/tools/src/main/java/org/apache/usergrid/tools/DupAdminRepair.java 
b/stack/tools/src/main/java/org/apache/usergrid/tools/DupAdminRepair.java
deleted file mode 100644
index 45929e8..0000000
--- a/stack/tools/src/main/java/org/apache/usergrid/tools/DupAdminRepair.java
+++ /dev/null
@@ -1,311 +0,0 @@
-/*
- * 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.tools;
-
-
-import java.io.FileWriter;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.apache.usergrid.management.OrganizationInfo;
-import org.apache.usergrid.management.UserInfo;
-import org.apache.usergrid.persistence.Entity;
-import org.apache.usergrid.persistence.EntityManager;
-import org.apache.usergrid.persistence.Query;
-import org.apache.usergrid.persistence.Results;
-import org.apache.usergrid.persistence.SimpleEntityRef;
-import org.apache.usergrid.persistence.cassandra.CassandraService;
-import org.apache.usergrid.persistence.entities.Application;
-import org.apache.usergrid.persistence.entities.User;
-import 
org.apache.usergrid.persistence.exceptions.DuplicateUniquePropertyExistsException;
-import org.apache.usergrid.utils.JsonUtils;
-
-import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.Option;
-import org.apache.commons.cli.OptionBuilder;
-import org.apache.commons.cli.Options;
-
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimap;
-
-import static 
org.apache.usergrid.persistence.cassandra.CassandraService.MANAGEMENT_APPLICATION_ID;
-
-
-/**
- * This is a utility to load all entities in an application and re-save them, 
this forces the secondary indexing to be
- * updated.
- *
- * @author tnine
- */
-public class DupAdminRepair extends ExportingToolBase {
-
-    /**
-     *
-     */
-    private static final int PAGE_SIZE = 100;
-
-    private static final Logger logger = LoggerFactory.getLogger( 
DupAdminRepair.class );
-
-
-    @Override
-    @SuppressWarnings("static-access")
-    public Options createOptions() {
-
-        Option hostOption =
-                OptionBuilder.withArgName( "host" ).hasArg().isRequired( true 
).withDescription( "Cassandra host" )
-                             .create( "host" );
-
-        Option outputOption =
-                OptionBuilder.withArgName( "output" ).hasArg().isRequired( 
true ).withDescription( "Cassandra host" )
-                             .create( "output" );
-
-        Options options = new Options();
-        options.addOption( hostOption );
-        options.addOption( outputOption );
-
-        return options;
-    }
-
-
-    /*
-     * (non-Javadoc)
-     *
-     * @see
-     * 
org.apache.usergrid.tools.ToolBase#runTool(org.apache.commons.cli.CommandLine)
-     */
-    @Override
-    public void runTool( CommandLine line ) throws Exception {
-        String outputDir = line.getOptionValue( "output" );
-
-        String emailsDir = String.format( "%s/emails", outputDir );
-        String usernamesDir = String.format( "%s/usernames", outputDir );
-        createDir( emailsDir );
-        createDir( usernamesDir );
-
-        startSpring();
-
-        logger.info( "Starting crawl of all admins" );
-
-        EntityManager em = emf.getEntityManager( 
CassandraService.MANAGEMENT_APPLICATION_ID );
-        Application app = em.getApplication();
-
-        // search for all orgs
-
-        Query query = new Query();
-        query.setLimit( PAGE_SIZE );
-        Results r = null;
-
-        Multimap<String, UUID> emails = HashMultimap.create();
-        Multimap<String, UUID> usernames = HashMultimap.create();
-        do {
-
-            r = em.searchCollection( app, "users", query );
-
-            for ( Entity entity : r.getEntities() ) {
-                emails.put( entity.getProperty( "email" 
).toString().toLowerCase(), entity.getUuid() );
-                usernames.put( entity.getProperty( "username" 
).toString().toLowerCase(), entity.getUuid() );
-            }
-
-            query.setCursor( r.getCursor() );
-
-            logger.info( "Searching next page" );
-        }
-        while ( r != null && r.size() == PAGE_SIZE );
-
-        // now go through and print out duplicate emails
-
-        for ( String username : usernames.keySet() ) {
-            Collection<UUID> ids = usernames.get( username );
-
-            if ( ids.size() > 1 ) {
-                logger.info( "Found multiple users with the username {}", 
username );
-
-                // force the username to be reset to the user's email
-                resolveUsernameConflicts( usernamesDir, username, ids );
-            }
-        }
-
-        for ( String email : emails.keySet() ) {
-            Collection<UUID> ids = emails.get( email );
-
-            if ( ids.size() > 1 ) {
-                // get the admin the same way as the rest tier, this way the 
OTHER
-                // admins will be removed
-                UserInfo targetUser = managementService.getAdminUserByEmail( 
email );
-
-                if ( targetUser == null ) {
-
-                    List<UUID> tempIds = new ArrayList<UUID>( ids );
-                    Collections.sort( tempIds );
-
-                    UUID toLoad = tempIds.get( 0 );
-
-                    logger.warn( "Could not load target user by email {}, 
loading by UUID {} instead", email, toLoad );
-                    targetUser = managementService.getAdminUserByUuid( toLoad 
);
-
-                    ids.remove( toLoad );
-                }
-
-                UUID targetId = targetUser.getUuid();
-
-                ids.remove( targetId );
-
-                logger.warn( "Found multiple admins with the email {}.  
Retaining uuid {}", email, targetId );
-
-                FileWriter file = new FileWriter( String.format( "%s/%s.all", 
emailsDir, email ) );
-
-                Map<String, Object> userOrganizationData = 
managementService.getAdminUserOrganizationData( targetId );
-
-                file.write( JsonUtils.mapToFormattedJsonString( 
userOrganizationData ) );
-
-                for ( UUID id : ids ) {
-
-                    userOrganizationData = 
managementService.getAdminUserOrganizationData( id );
-
-                    file.write( JsonUtils.mapToFormattedJsonString( 
userOrganizationData ) );
-
-                    file.write( "\n\n" );
-
-                    mergeAdmins( emailsDir, id, targetId );
-                }
-
-                file.flush();
-                file.close();
-
-                // force the index update after all other admins have been 
merged
-                logger.info( "Forcing re-index of admin with email {} and id 
{}", email, targetId );
-                User targetUserEntity = em.get( targetUser.getUuid(), 
User.class );
-                em.update( targetUserEntity );
-
-                FileWriter merged = new FileWriter( String.format( 
"%s/%s.merged", emailsDir, email ) );
-
-                userOrganizationData = 
managementService.getAdminUserOrganizationData( targetUser.getUuid() );
-
-                merged.write( JsonUtils.mapToFormattedJsonString( 
userOrganizationData ) );
-                merged.flush();
-                merged.close();
-            }
-        }
-
-        logger.info( "Repair complete" );
-    }
-
-
-    /**
-     * When our usernames are equal, we need to check if our emails are equal. 
If they're not, we need to change the one
-     * that DOES NOT get returned on a lookup by username
-     */
-    private void resolveUsernameConflicts( String targetDir, String userName, 
Collection<UUID> ids ) throws Exception {
-        // lookup the admin id
-        UserInfo existing = managementService.getAdminUserByUsername( userName 
);
-
-        if ( existing == null ) {
-            logger.warn( "Could not determine an admin for colliding username 
'{}'.  Skipping", userName );
-            return;
-        }
-
-        ids.remove( existing.getUuid() );
-
-        boolean collision = false;
-
-        EntityManager em = emf.getEntityManager( MANAGEMENT_APPLICATION_ID );
-
-        for ( UUID id : ids ) {
-            UserInfo other = managementService.getAdminUserByUuid( id );
-
-            // same username and email, these will be merged later in the 
process,
-            // skip it
-            if ( other != null && other.getEmail() != null && 
other.getEmail().equals( existing.getEmail() ) ) {
-                logger.info(
-                        "Users with the same username '{}' have the same email 
'{}'. This will be resolved later in "
-                                + "the process, skipping", userName, 
existing.getEmail() );
-                continue;
-            }
-
-            // if we get here, the emails do not match, but the usernames do. 
Force
-            // both usernames to emails
-            collision = true;
-
-            setUserName( em, other, other.getEmail() );
-        }
-
-        if ( collision ) {
-            setUserName( em, existing, existing.getEmail() );
-        }
-    }
-
-
-    /** Set the username to the one provided, if we can't due to duplicate 
property issues, we fall back to user+uuid */
-    private void setUserName( EntityManager em, UserInfo other, String 
newUserName ) throws Exception {
-        logger.info( "Setting username to {} for user with username {} and id 
{}", new Object[] {
-                newUserName, other.getUsername(), other.getUuid()
-        } );
-
-        try {
-            em.setProperty( new SimpleEntityRef( "user", other.getUuid() ), 
"username", newUserName, true );
-        }
-        catch ( DuplicateUniquePropertyExistsException e ) {
-            logger.warn( "More than 1 user has the username of {}.  Setting 
the username to their username+UUID as a "
-                    + "fallback", newUserName );
-
-            setUserName( em, other, String.format( "%s-%s", 
other.getUsername(), other.getUuid() ) );
-        }
-    }
-
-
-    /** Merge the source admin to the target admin by copying oranizations. 
Then deletes the source admin */
-    private void mergeAdmins( String targetDir, UUID sourceId, UUID targetId ) 
throws Exception {
-
-        EntityManager em = emf.getEntityManager( MANAGEMENT_APPLICATION_ID );
-
-        User sourceUser = em.get( sourceId, User.class );
-
-        // may have already been deleted, do nothing
-        if ( sourceUser == null ) {
-            logger.warn( "Source admin with uuid {} does not exist in 
cassandra", sourceId );
-            return;
-        }
-
-        UserInfo targetUserInfo = managementService.getAdminUserByUuid( 
targetId );
-
-        @SuppressWarnings("unchecked") Map<String, Map<String, UUID>> 
sourceOrgs =
-                ( Map<String, Map<String, UUID>> ) 
managementService.getAdminUserOrganizationData( sourceId )
-                                                                    .get( 
"organizations" );
-
-        for ( String orgName : sourceOrgs.keySet() ) {
-            UUID orgId = sourceOrgs.get( orgName ).get( "uuid" );
-
-            OrganizationInfo org = managementService.getOrganizationByUuid( 
orgId );
-
-            logger.info( "Adding organization {} to admin with email {} and id 
{}",
-                    new Object[] { org.getName(), sourceUser.getEmail(), 
sourceUser.getUuid() } );
-
-            // copy it over to the target admin
-            managementService.addAdminUserToOrganization( targetUserInfo, org, 
false );
-        }
-
-        logger.info( "Deleting admin with email {} and id {}", 
sourceUser.getEmail(), sourceUser.getUuid() );
-
-        em.delete( sourceUser );
-    }
-}

http://git-wip-us.apache.org/repos/asf/usergrid/blob/ceb81076/stack/tools/src/main/java/org/apache/usergrid/tools/DuplicateAdminRepair.java
----------------------------------------------------------------------
diff --git 
a/stack/tools/src/main/java/org/apache/usergrid/tools/DuplicateAdminRepair.java 
b/stack/tools/src/main/java/org/apache/usergrid/tools/DuplicateAdminRepair.java
new file mode 100644
index 0000000..f38e3d6
--- /dev/null
+++ 
b/stack/tools/src/main/java/org/apache/usergrid/tools/DuplicateAdminRepair.java
@@ -0,0 +1,289 @@
+/*
+ * 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.tools;
+
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.OptionBuilder;
+import org.apache.commons.cli.Options;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.usergrid.management.ManagementService;
+import org.apache.usergrid.persistence.EntityManagerFactory;
+import rx.functions.Action1;
+
+import java.util.*;
+
+import static org.apache.usergrid.tools.UserOrgInterface.Org;
+import static org.apache.usergrid.tools.UserOrgInterface.OrgUser;
+
+
+/**
+ * Find duplicate admin users, delete the one that is not indexed.
+ */
+public class DuplicateAdminRepair extends ToolBase {
+
+    UserOrgInterface           manager = null;
+    
+    static final String        THREADS_ARG_NAME = "threads"; 
+    
+    int                        threadCount = 5;
+
+    static final String        DRYRUN_ARG_NAME = "dryrun";
+
+    boolean                    dryRun = false;
+
+    Multimap<String, OrgUser>  emails = HashMultimap.create();
+    
+    Multimap<String, OrgUser>  usernames = HashMultimap.create();
+
+    boolean                    testing = false;
+
+
+    DuplicateAdminRepair() {
+        super();
+    }
+
+    DuplicateAdminRepair(EntityManagerFactory emf, ManagementService 
managementService ) {
+        this();
+        this.emf = emf;
+        this.managementService = managementService;
+    }
+    
+    
+    @Override
+    @SuppressWarnings("static-access")
+    public Options createOptions() {
+
+        Options options = super.createOptions();
+
+        Option dryRunOption = OptionBuilder.hasArg()
+            .withType(Boolean.TRUE)
+            .withDescription( "-" + DRYRUN_ARG_NAME + " true to print what 
tool would do and do not alter data.")
+            .create( DRYRUN_ARG_NAME );
+        options.addOption( dryRunOption );
+        
+        Option writeThreadsOption = OptionBuilder.hasArg()
+            .withType(0)
+            .withDescription( "Write Threads -" + THREADS_ARG_NAME )
+            .create(THREADS_ARG_NAME);
+        options.addOption( writeThreadsOption );        
+        
+        return options;
+    }
+
+    
+    public UserOrgManager createNewRepairManager() {
+        return new UserOrgManager( emf, managementService );
+    }
+   
+    
+    @Override
+    public void runTool(CommandLine line) throws Exception {
+
+        startSpring();
+        setVerbose( line );
+
+        if (StringUtils.isNotEmpty( line.getOptionValue( THREADS_ARG_NAME ) )) 
{
+            try {
+                threadCount = Integer.parseInt( line.getOptionValue( 
THREADS_ARG_NAME ) );
+            } catch (NumberFormatException nfe) {
+                logger.error( "-" + THREADS_ARG_NAME + " must be specified as 
an integer. Aborting..." );
+                return;
+            }
+        }
+
+        if ( StringUtils.isNotEmpty( line.getOptionValue( DRYRUN_ARG_NAME ) )) 
{
+            dryRun = Boolean.parseBoolean( line.getOptionValue( 
DRYRUN_ARG_NAME ));
+        }
+
+        if ( manager == null ) { // we use a special manager when mockTesting
+            if (dryRun) {
+                manager = new DryRunUserOrgManager( emf, managementService );
+            } else {
+                manager = new UserOrgManager( emf, managementService );
+            }
+        } 
+
+        logger.info( "DuplicateAdminUserRepair tool starting up... manager: " 
+ manager.getClass().getSimpleName() );
+       
+        // build multi-map of users by email and users by name
+        
+        manager.getUsers().doOnNext( new Action1<OrgUser>() {
+            @Override
+            public void call( OrgUser user ) {
+
+                if (user.getUsername() == null) {
+                    logger.warn( "User {} has no username", user.getId() );
+                    return;
+                }
+                if (user.getEmail() == null) {
+                    logger.warn( "User {} has no email", user.getId() );
+                    return;
+                }
+                emails.put( user.getEmail(), user );
+                usernames.put( user.getEmail(), user );
+                
+            }
+        } ).toBlocking().lastOrDefault( null );
+
+        for ( String username : usernames.keySet() ) {
+            Collection<OrgUser> users = usernames.get( username );
+
+            if ( users.size() > 1 ) {
+                logger.info( "Found multiple users with the username {}", 
username );
+
+                // force the username to be reset to the user's email
+                resolveUsernameConflicts( username, users );
+            }
+        }
+
+        for ( String email : emails.keySet() ) {
+            
+            Collection<OrgUser> users = emails.get( email );
+
+            if ( users.size() > 1 ) {
+                // get the admin the same way as the rest tier, this way the 
OTHER
+                // admins will be removed
+                OrgUser targetUser = manager.lookupOrgUserByEmail( email );
+
+                if ( targetUser == null ) {
+
+                    List<OrgUser> tempUsers = new ArrayList<OrgUser>( users );
+                    Collections.sort( tempUsers );
+
+                    OrgUser toLoad = tempUsers.get( 0 );
+
+                    logger.warn( "Could not load target user by email {}, 
loading by UUID {} instead", email, toLoad );
+                    targetUser = toLoad;
+
+                    users.remove( toLoad );
+                }
+
+                users.remove( targetUser );
+
+                logger.warn( "Found multiple admins with the email {}.  
Retaining uuid {}", email, targetUser.getId() );
+
+                for ( OrgUser orgUser : users ) {
+                    mergeAdmins( orgUser, targetUser );
+                }
+
+                // force the index update after all other admins have been 
merged
+                if ( dryRun ) {
+                    logger.info("Would force re-index of 'keeper' user {}:{}", 
+                            targetUser.getUsername(), targetUser.getId());
+                } else {
+                    logger.info( "Forcing re-index of admin with email {} and 
id {}", email, targetUser.getId());
+                    manager.updateOrgUser( targetUser );
+                }
+            }
+        }
+
+        logger.info( "Repair complete" );
+    }
+
+
+    /**
+     * When our usernames are equal, we need to check if our emails are equal. 
If they're not, we need to change the one
+     * that DOES NOT get returned on a lookup by username
+     */
+    private void resolveUsernameConflicts( String userName, 
Collection<OrgUser> users ) throws Exception {
+        
+        // lookup the admin id
+        OrgUser existing = manager.lookupOrgUserByUsername( userName );
+
+        if ( existing == null ) {
+            logger.warn( "Could not determine an admin for colliding username 
'{}'.  Skipping", userName );
+            return;
+        }
+
+        users.remove( existing );
+
+        boolean collision = false;
+
+        for ( OrgUser other : users ) {
+
+            // same username and email, these will be merged later in the 
process,
+            // skip it
+            if ( other != null && other.getEmail() != null && 
other.getEmail().equals( existing.getEmail() ) ) {
+                logger.info(
+                        "Users with the same username '{}' have the same email 
'{}'. This will be resolved later in "
+                                + "the process, skipping", userName, 
existing.getEmail() );
+                continue;
+            }
+
+            // if we get here, the emails do not match, but the usernames do. 
Force
+            // both usernames to emails
+            collision = true;
+
+            setUserName(other, other.getEmail() );
+        }
+
+        if ( collision ) {
+            setUserName(existing, existing.getEmail() );
+        }
+    }
+
+
+    /** Set the username to the one provided, if we can't due to duplicate 
property issues, we fall back to user+uuid */
+    private void setUserName( OrgUser other, String newUserName ) throws 
Exception {
+
+        if ( dryRun ) {
+            logger.info("Would rename user {}:{} to {}", new Object[] { 
+                    other.getUsername(), other.getId(), newUserName });
+        } else {
+            logger.info( "Setting username to {} for user {}:{}", new Object[] 
{
+                    newUserName, other.getUsername(), other.getId() } );
+            
+            manager.setOrgUserName( other, newUserName );
+        }
+    }
+
+
+    /** Merge the source admin to the target admin by copying oranizations. 
Then deletes the source admin */
+    private void mergeAdmins( OrgUser sourceUser, OrgUser targetUser ) throws 
Exception {
+
+        Set<Org> sourceOrgs = manager.getUsersOrgs( sourceUser ); 
+
+        for ( Org org : sourceOrgs ) {
+
+            if ( dryRun ) {
+                logger.info("Would add org {}:{} to user {}:{}", new Object[] {
+                        org.getName(), org.getId(), targetUser.getUsername(), 
targetUser.getId(), });
+
+            } else {
+                logger.info( "Adding organization {}:{} to admin with email {} 
and id {}",
+                    new Object[] { org.getName(), org.getId(), 
targetUser.getEmail(), targetUser.getId() } );
+
+                // copy it over to the target admin
+                manager.addUserToOrg( targetUser, org );
+            }
+        }
+
+        logger.info( "Deleting admin with email {} and id {}", 
sourceUser.getEmail(), sourceUser.getId() );
+
+        if ( dryRun ) {
+            logger.info( "Would remove user {}:{}", new Object[]{
+                    sourceUser.getUsername(), sourceUser.getId() } );
+            
+        } else {
+            manager.removeOrgUser( sourceUser );
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/usergrid/blob/ceb81076/stack/tools/src/main/java/org/apache/usergrid/tools/DuplicateAdminUserRepair.java
----------------------------------------------------------------------
diff --git 
a/stack/tools/src/main/java/org/apache/usergrid/tools/DuplicateAdminUserRepair.java
 
b/stack/tools/src/main/java/org/apache/usergrid/tools/DuplicateAdminUserRepair.java
deleted file mode 100644
index 902eefa..0000000
--- 
a/stack/tools/src/main/java/org/apache/usergrid/tools/DuplicateAdminUserRepair.java
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- * 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.tools;
-
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimap;
-import org.apache.commons.cli.CommandLine;
-import org.apache.commons.cli.Option;
-import org.apache.commons.cli.OptionBuilder;
-import org.apache.commons.cli.Options;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.usergrid.management.ManagementService;
-import org.apache.usergrid.persistence.EntityManagerFactory;
-import rx.functions.Action1;
-
-import java.util.*;
-
-import static org.apache.usergrid.tools.UserOrgInterface.Org;
-import static org.apache.usergrid.tools.UserOrgInterface.OrgUser;
-
-
-/**
- * Find duplicate admin users, delete the one that is not indexed.
- */
-public class DuplicateAdminUserRepair extends ToolBase {
-
-    UserOrgInterface           manager = null;
-    
-    static final String        THREADS_ARG_NAME = "threads"; 
-    
-    int                        threadCount = 5;
-
-    static final String        DRYRUN_ARG_NAME = "dryrun";
-
-    boolean                    dryRun = false;
-
-    Multimap<String, OrgUser>  emails = HashMultimap.create();
-    
-    Multimap<String, OrgUser>  usernames = HashMultimap.create();
-
-    boolean                    testing = false;
-
-
-    DuplicateAdminUserRepair() {
-        super();
-    }
-
-    DuplicateAdminUserRepair(EntityManagerFactory emf, ManagementService 
managementService ) {
-        this();
-        this.emf = emf;
-        this.managementService = managementService;
-    }
-    
-    
-    @Override
-    @SuppressWarnings("static-access")
-    public Options createOptions() {
-
-        Options options = super.createOptions();
-
-        Option dryRunOption = OptionBuilder.hasArg()
-            .withType(Boolean.TRUE)
-            .withDescription( "-" + DRYRUN_ARG_NAME + " true to print what 
tool would do and do not alter data.")
-            .create( DRYRUN_ARG_NAME );
-        options.addOption( dryRunOption );
-        
-        Option writeThreadsOption = OptionBuilder.hasArg()
-            .withType(0)
-            .withDescription( "Write Threads -" + THREADS_ARG_NAME )
-            .create(THREADS_ARG_NAME);
-        options.addOption( writeThreadsOption );        
-        
-        return options;
-    }
-
-    
-    public UserOrgManager createNewRepairManager() {
-        return new UserOrgManager( emf, managementService );
-    }
-   
-    
-    @Override
-    public void runTool(CommandLine line) throws Exception {
-
-        startSpring();
-        setVerbose( line );
-
-        if (StringUtils.isNotEmpty( line.getOptionValue( THREADS_ARG_NAME ) )) 
{
-            try {
-                threadCount = Integer.parseInt( line.getOptionValue( 
THREADS_ARG_NAME ) );
-            } catch (NumberFormatException nfe) {
-                logger.error( "-" + THREADS_ARG_NAME + " must be specified as 
an integer. Aborting..." );
-                return;
-            }
-        }
-
-        if ( StringUtils.isNotEmpty( line.getOptionValue( DRYRUN_ARG_NAME ) )) 
{
-            dryRun = Boolean.parseBoolean( line.getOptionValue( 
DRYRUN_ARG_NAME ));
-        }
-
-        if ( manager == null ) { // we use a special manager when mockTesting
-            if (dryRun) {
-                manager = new DryRunUserOrgManager( emf, managementService );
-            } else {
-                manager = new UserOrgManager( emf, managementService );
-            }
-        } 
-
-        logger.info( "DuplicateAdminUserRepair tool starting up... manager: " 
+ manager.getClass().getSimpleName() );
-       
-        // build multi-map of users by email and users by name
-        
-        manager.getUsers().doOnNext( new Action1<OrgUser>() {
-            @Override
-            public void call( OrgUser user ) {
-
-                if (user.getUsername() == null) {
-                    logger.warn( "User {} has no username", user.getId() );
-                    return;
-                }
-                if (user.getEmail() == null) {
-                    logger.warn( "User {} has no email", user.getId() );
-                    return;
-                }
-                emails.put( user.getEmail(), user );
-                usernames.put( user.getEmail(), user );
-                
-            }
-        } ).toBlocking().lastOrDefault( null );
-
-        for ( String username : usernames.keySet() ) {
-            Collection<OrgUser> users = usernames.get( username );
-
-            if ( users.size() > 1 ) {
-                logger.info( "Found multiple users with the username {}", 
username );
-
-                // force the username to be reset to the user's email
-                resolveUsernameConflicts( username, users );
-            }
-        }
-
-        for ( String email : emails.keySet() ) {
-            
-            Collection<OrgUser> users = emails.get( email );
-
-            if ( users.size() > 1 ) {
-                // get the admin the same way as the rest tier, this way the 
OTHER
-                // admins will be removed
-                OrgUser targetUser = manager.lookupOrgUserByEmail( email );
-
-                if ( targetUser == null ) {
-
-                    List<OrgUser> tempUsers = new ArrayList<OrgUser>( users );
-                    Collections.sort( tempUsers );
-
-                    OrgUser toLoad = tempUsers.get( 0 );
-
-                    logger.warn( "Could not load target user by email {}, 
loading by UUID {} instead", email, toLoad );
-                    targetUser = toLoad;
-
-                    users.remove( toLoad );
-                }
-
-                users.remove( targetUser );
-
-                logger.warn( "Found multiple admins with the email {}.  
Retaining uuid {}", email, targetUser.getId() );
-
-                for ( OrgUser orgUser : users ) {
-                    mergeAdmins( orgUser, targetUser );
-                }
-
-                // force the index update after all other admins have been 
merged
-                if ( dryRun ) {
-                    logger.info("Would force re-index of 'keeper' user {}:{}", 
-                            targetUser.getUsername(), targetUser.getId());
-                } else {
-                    logger.info( "Forcing re-index of admin with email {} and 
id {}", email, targetUser.getId());
-                    manager.updateOrgUser( targetUser );
-                }
-            }
-        }
-
-        logger.info( "Repair complete" );
-    }
-
-
-    /**
-     * When our usernames are equal, we need to check if our emails are equal. 
If they're not, we need to change the one
-     * that DOES NOT get returned on a lookup by username
-     */
-    private void resolveUsernameConflicts( String userName, 
Collection<OrgUser> users ) throws Exception {
-        
-        // lookup the admin id
-        OrgUser existing = manager.lookupOrgUserByUsername( userName );
-
-        if ( existing == null ) {
-            logger.warn( "Could not determine an admin for colliding username 
'{}'.  Skipping", userName );
-            return;
-        }
-
-        users.remove( existing );
-
-        boolean collision = false;
-
-        for ( OrgUser other : users ) {
-
-            // same username and email, these will be merged later in the 
process,
-            // skip it
-            if ( other != null && other.getEmail() != null && 
other.getEmail().equals( existing.getEmail() ) ) {
-                logger.info(
-                        "Users with the same username '{}' have the same email 
'{}'. This will be resolved later in "
-                                + "the process, skipping", userName, 
existing.getEmail() );
-                continue;
-            }
-
-            // if we get here, the emails do not match, but the usernames do. 
Force
-            // both usernames to emails
-            collision = true;
-
-            setUserName(other, other.getEmail() );
-        }
-
-        if ( collision ) {
-            setUserName(existing, existing.getEmail() );
-        }
-    }
-
-
-    /** Set the username to the one provided, if we can't due to duplicate 
property issues, we fall back to user+uuid */
-    private void setUserName( OrgUser other, String newUserName ) throws 
Exception {
-
-        if ( dryRun ) {
-            logger.info("Would rename user {}:{} to {}", new Object[] { 
-                    other.getUsername(), other.getId(), newUserName });
-        } else {
-            logger.info( "Setting username to {} for user with username {} and 
id {}", new Object[] {
-                    newUserName, other.getUsername(), other.getId() } );
-            
-            manager.setOrgUserName( other, newUserName );
-        }
-    }
-
-
-    /** Merge the source admin to the target admin by copying oranizations. 
Then deletes the source admin */
-    private void mergeAdmins( OrgUser sourceUser, OrgUser targetUser ) throws 
Exception {
-
-        Set<Org> sourceOrgs = manager.getUsersOrgs( sourceUser ); 
-
-        for ( Org org : sourceOrgs ) {
-
-            if ( dryRun ) {
-                logger.info("Would add org {}:{} to user {}:{}", new Object[] {
-                        org.getName(), org.getId(), targetUser.getUsername(), 
targetUser.getId(), });
-
-            } else {
-                logger.info( "Adding organization {}:{} to admin with email {} 
and id {}",
-                    new Object[] { org.getName(), org.getId(), 
targetUser.getEmail(), targetUser.getId() } );
-
-                // copy it over to the target admin
-                manager.addUserToOrg( targetUser, org );
-            }
-        }
-
-        logger.info( "Deleting admin with email {} and id {}", 
sourceUser.getEmail(), sourceUser.getId() );
-
-        if ( dryRun ) {
-            logger.info( "Would remove user {}:{}", new Object[]{
-                    sourceUser.getUsername(), sourceUser.getId() } );
-            
-        } else {
-            manager.removeOrgUser( sourceUser );
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/usergrid/blob/ceb81076/stack/tools/src/test/java/org/apache/usergrid/tools/DuplicateAdminRepairTest.java
----------------------------------------------------------------------
diff --git 
a/stack/tools/src/test/java/org/apache/usergrid/tools/DuplicateAdminRepairTest.java
 
b/stack/tools/src/test/java/org/apache/usergrid/tools/DuplicateAdminRepairTest.java
new file mode 100644
index 0000000..e5e9d43
--- /dev/null
+++ 
b/stack/tools/src/test/java/org/apache/usergrid/tools/DuplicateAdminRepairTest.java
@@ -0,0 +1,301 @@
+/*
+ * 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.tools;
+
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.usergrid.ServiceITSetup;
+import org.apache.usergrid.ServiceITSetupImpl;
+import org.apache.usergrid.ServiceITSuite;
+import org.apache.usergrid.management.OrganizationOwnerInfo;
+import org.apache.usergrid.management.UserInfo;
+import org.junit.ClassRule;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.UUID;
+
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.TestCase.assertNotNull;
+import static org.apache.usergrid.tools.UserOrgInterface.OrgUser;
+import static org.junit.Assert.assertEquals;
+
+
+/**
+ * Test duplicate admin repair.
+ */
+public class DuplicateAdminRepairTest {
+    
+    static final Logger logger = LoggerFactory.getLogger( 
DuplicateAdminRepairTest.class );
+    
+    @ClassRule
+    public static ServiceITSetup setup = new ServiceITSetupImpl( 
ServiceITSuite.cassandraResource );
+
+    
+    /**
+     * Test tool logic with mock manager that returns duplicates
+     */
+    @org.junit.Test
+    public void testMockWithDups() throws Exception {
+
+        DuplicateAdminRepair dor = new DuplicateAdminRepair();
+        MockManager mockManager = new MockManager();
+        dor.manager = mockManager;
+        dor.testing = true;
+
+        // the MockManager creates 2 pairs of duplicate orgs
+        assertNotNull( "user1_a", mockManager.getOrgUser( 
mockManager.user1_a.getId() ));
+        assertNotNull( "user1_b", mockManager.getOrgUser( 
mockManager.user1_b.getId() ));
+        assertNotNull( "user2_a", mockManager.getOrgUser( 
mockManager.user2_a.getId() ));
+        assertNotNull( "user2_b", mockManager.getOrgUser( 
mockManager.user2_b.getId() ));
+
+        // verify that correct users indexed
+        assertUsersIndexed( mockManager );
+        
+        dor.startTool( new String[] {}, false ); // false means do not call 
System.exit()
+
+        // verify that correct users indexed
+        assertUsersIndexed( mockManager );
+
+        // verify that duplicate users are gone (the "a" users were the first 
ones created)
+        assertNull( "must remove user1_a", mockManager.getOrgUser( 
mockManager.user1_a.getId() ));
+        assertNull( "must remove user2_a", mockManager.getOrgUser( 
mockManager.user2_a.getId() ));
+
+        // and keepers survived
+        assertNotNull( "user1_b survived", mockManager.getOrgUser( 
mockManager.user1_b.getId() ));
+        assertNotNull( "user2_b survived", mockManager.getOrgUser( 
mockManager.user2_b.getId() ));
+    }
+
+    
+    private void assertUsersIndexed(MockManager mockManager ) {
+        assertEquals("user1_b is in the index",
+                
mockManager.lookupOrgUserByUsername(mockManager.user1_b.getUsername()).getId(),
+                mockManager.user1_b.getId() );
+
+        assertEquals("user1_b is in the index",
+                
mockManager.lookupOrgUserByEmail(mockManager.user1_b.getEmail()).getId(),
+                mockManager.user1_b.getId() );
+
+        assertEquals("user2_b is in the index",
+                
mockManager.lookupOrgUserByUsername(mockManager.user2_b.getUsername()).getId(),
+                mockManager.user2_b.getId() );
+
+        assertEquals("user2_b is in the index",
+                
mockManager.lookupOrgUserByEmail(mockManager.user2_b.getEmail()).getId(),
+                mockManager.user2_b.getId() ); 
+    }
+    
+
+    @org.junit.Test
+    public void testDryRun() throws Exception {
+
+        DuplicateAdminRepair dor = new DuplicateAdminRepair();
+        MockManager mockManager = new MockManager();
+        dor.manager = mockManager;
+        dor.testing = true;
+
+        // the MockManager creates 2 pairs of duplicate orgs
+        assertNotNull( "user1_a", mockManager.getOrgUser( 
mockManager.user1_a.getId() ));
+        assertNotNull( "user1_b", mockManager.getOrgUser( 
mockManager.user1_b.getId() ));
+        assertNotNull( "user2_a", mockManager.getOrgUser( 
mockManager.user2_a.getId() ));
+        assertNotNull( "user2_b", mockManager.getOrgUser( 
mockManager.user2_b.getId() ));
+
+        // verify that correct users indexed
+        assertUsersIndexed( mockManager );
+
+        dor.startTool( new String[] { "-dryrun", "true" }, false ); // false 
means do not call System.exit()
+
+        // verify that correct users indexed
+        assertUsersIndexed( mockManager );
+        
+        // insure nothng was deleted by dry-run
+        assertNotNull( "dryrun should not delete user1_a", 
mockManager.getOrgUser( mockManager.user1_a.getId() ));
+        assertNotNull( "dryrun should not delete user1_b", 
mockManager.getOrgUser( mockManager.user1_b.getId() ));
+        assertNotNull( "dryrun should not delete user2_a", 
mockManager.getOrgUser( mockManager.user2_a.getId() ));
+        assertNotNull( "dryrun should not delete user2_b", 
mockManager.getOrgUser( mockManager.user2_b.getId() ));  
+    }
+
+    
+    /**
+     * Smoke test: does "real" manager run without throwing exceptions?
+     */
+    @org.junit.Test
+    public void testManagerNoDups() throws Exception {
+
+        // create two orgs each with owning user
+
+        final String random1 = 
org.apache.commons.lang.RandomStringUtils.randomAlphanumeric( 10 );
+        final OrganizationOwnerInfo orgOwnerInfo1 = 
setup.getMgmtSvc().createOwnerAndOrganization(
+                "org_" + random1, "user_" + random1, "user_" + random1,
+                "user_" + random1 + "@example.com", "password" );
+
+        final String random2 = 
org.apache.commons.lang.RandomStringUtils.randomAlphanumeric( 10 );
+        final OrganizationOwnerInfo orgOwnerInfo2 = 
setup.getMgmtSvc().createOwnerAndOrganization(
+                "org_" + random2, "user_" + random2, "user_" + random2,
+                "user_" + random2 + "@example.com", "password" );
+
+        // Add user1 to org2
+
+        setup.getMgmtSvc().addAdminUserToOrganization(
+                orgOwnerInfo1.getOwner(), orgOwnerInfo2.getOrganization(), 
false );
+
+        DuplicateAdminRepair dor = new DuplicateAdminRepair();
+
+        dor.startTool( new String[]{}, false );  // false means do not call 
System.exit()
+
+        assertTrue( true ); // we're happy if we get to this point
+    }
+
+    
+    @org.junit.Test
+    public void testManagerLookupMethods() throws Exception {
+        
+        // create two orgs each with owning user
+
+        final String random1 = 
org.apache.commons.lang.RandomStringUtils.randomAlphanumeric( 10 );
+        final OrganizationOwnerInfo orgOwnerInfo1 = 
setup.getMgmtSvc().createOwnerAndOrganization(
+                "org_" + random1, "user_" + random1, "user_" + random1,
+                "user_" + random1 + "@example.com", "password" );
+
+        final String random2 = 
org.apache.commons.lang.RandomStringUtils.randomAlphanumeric( 10 );
+        final OrganizationOwnerInfo orgOwnerInfo2 = 
setup.getMgmtSvc().createOwnerAndOrganization(
+                "org_" + random2, "user_" + random2, "user_" + random2,
+                "user_" + random2 + "@example.com", "password" );
+
+        DuplicateAdminRepair dor = new DuplicateAdminRepair(setup.getEmf(), 
setup.getMgmtSvc());
+        dor.manager = dor.createNewRepairManager(); // test the real manager 
+
+        // start the tool so that Spring, Cassandra, etc/ gets initialized
+        dor.startTool( new String[]{"-dryrun", "true"}, false ); // false 
means do not call System.exit()
+
+        testManagerLookupMethods( dor, orgOwnerInfo1, orgOwnerInfo2, true );
+        
+        dor.manager.removeOrgUser( dor.manager.getOrgUser( 
orgOwnerInfo1.getOwner().getUuid() )); 
+        dor.manager.removeOrgUser( dor.manager.getOrgUser( 
orgOwnerInfo2.getOwner().getUuid() ));
+
+        testManagerLookupMethods( dor, orgOwnerInfo1, orgOwnerInfo2, false );
+    }
+    
+    
+    private void testManagerLookupMethods( DuplicateAdminRepair dor, 
+                                    OrganizationOwnerInfo info1, 
+                                    OrganizationOwnerInfo info2,
+                                    boolean usersExist ) throws Exception {
+        if ( usersExist ) {
+            
+            assertNotNull( dor.manager.getOrgUser( info1.getOwner().getUuid() 
));
+            assertNotNull( dor.manager.getOrgUser( info2.getOwner().getUuid() 
));
+
+            assertNotNull( dor.manager.lookupOrgUserByEmail( 
info1.getOwner().getEmail() ));
+            assertNotNull( dor.manager.lookupOrgUserByEmail( 
info2.getOwner().getEmail() ));
+
+            assertNotNull( dor.manager.lookupOrgUserByUsername( 
info1.getOwner().getUsername() ));
+            assertNotNull( dor.manager.lookupOrgUserByUsername( 
info2.getOwner().getUsername() )); 
+            
+        } else {
+
+            assertNull( dor.manager.getOrgUser( info1.getOwner().getUuid() ) );
+            assertNull( dor.manager.getOrgUser( info2.getOwner().getUuid() ) );
+
+            assertNull( dor.manager.lookupOrgUserByEmail( 
info1.getOwner().getEmail() ) );
+            assertNull( dor.manager.lookupOrgUserByEmail( 
info2.getOwner().getEmail() ) );
+
+            assertNull( dor.manager.lookupOrgUserByUsername( 
info1.getOwner().getUsername() ) );
+            assertNull( dor.manager.lookupOrgUserByUsername( 
info2.getOwner().getUsername() ) );
+        }
+    }
+
+
+    @org.junit.Test
+    public void testManagerOrgUserUpdateMethod() throws Exception {
+
+        // create an org with an admin user
+        final String random1 = 
org.apache.commons.lang.RandomStringUtils.randomAlphanumeric( 10 );
+        final OrganizationOwnerInfo orgOwnerInfo1 = 
setup.getMgmtSvc().createOwnerAndOrganization(
+                "org_" + random1, "user_" + random1, "user_" + random1,
+                "user_" + random1 + "@example.com", "password" );
+
+        DuplicateAdminRepair dor = new DuplicateAdminRepair(setup.getEmf(), 
setup.getMgmtSvc());
+        dor.manager = dor.createNewRepairManager(); // test the real manager 
+
+        // start the tool so that Spring, Cassandra, etc/ gets initialized
+        dor.startTool( new String[]{"-dryrun", "true"}, false ); // false 
means do not call System.exit()
+
+        UserInfo userInfo = setup.getMgmtSvc().getAdminUserByUuid( 
orgOwnerInfo1.getOwner().getUuid() );
+        OrgUser user = dor.manager.getOrgUser( 
orgOwnerInfo1.getOwner().getUuid() );
+        assertEquals( userInfo.getUsername(), user.getUsername());
+        assertEquals( userInfo.getEmail(), user.getEmail());
+
+        // change user's username using updateOrgUser()
+        String newUsername = "boom_" + random1;
+        user.setUsername(newUsername);
+        dor.manager.updateOrgUser( user );
+        user = dor.manager.getOrgUser( orgOwnerInfo1.getOwner().getUuid() );
+        assertEquals( newUsername, user.getUsername());
+        
+        // change user's username using setOrgUserName()
+        newUsername = "blammo_" + random1;
+        dor.manager.setOrgUserName( user, newUsername );
+        user = dor.manager.getOrgUser( orgOwnerInfo1.getOwner().getUuid() );
+        assertEquals( newUsername, user.getUsername());
+    }
+    
+
+    /**
+     * Extend mock manager to add a pair of duplicate users.
+     */
+    static class MockManager extends MockUserOrgManager {
+
+        OrgUser user1_a;
+        OrgUser user1_b;
+        OrgUser user2_a;
+        OrgUser user2_b;
+        
+        public MockManager() throws Exception {
+            
+            super(1); // ask parent to create one pair of duplicate orgs
+            
+            Org org = orgsById.values().iterator().next();
+          
+            String sfx = RandomStringUtils.randomAlphanumeric(10);
+
+            // user1 a and b have duplicate usernames AND DUPLICATE EMAIL 
ADDRESSES
+            
+            user1_a = createOrgUser( UUID.randomUUID(), "UserName_"+sfx, 
"UserName_"+sfx+"@example.com" );
+            addUserToOrg( user1_a, org );
+            pause(100);
+
+            user1_b = createOrgUser( UUID.randomUUID(), "Username_"+sfx, 
"Username_"+sfx+"@example.com" );
+            addUserToOrg( user1_b, org );
+            pause(100);
+
+            // user2 a and b have duplicate usernames AND DIFFERENT EMAIL 
ADDRESSES 
+            
+            user2_a = createOrgUser( UUID.randomUUID(), "UserName_"+sfx, 
"UserName_"+sfx+"@example.com" );
+            addUserToOrg( user2_a, org );
+            pause(100);
+
+            user2_b = createOrgUser( UUID.randomUUID(), "UserName_"+sfx, 
"UserName_"+sfx+"@example.com" );
+            addUserToOrg( user2_b, org );
+            pause(100);
+
+        }
+        
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/usergrid/blob/ceb81076/stack/tools/src/test/java/org/apache/usergrid/tools/DuplicateAdminUserRepairTest.java
----------------------------------------------------------------------
diff --git 
a/stack/tools/src/test/java/org/apache/usergrid/tools/DuplicateAdminUserRepairTest.java
 
b/stack/tools/src/test/java/org/apache/usergrid/tools/DuplicateAdminUserRepairTest.java
deleted file mode 100644
index 6676b87..0000000
--- 
a/stack/tools/src/test/java/org/apache/usergrid/tools/DuplicateAdminUserRepairTest.java
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
- * 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.tools;
-
-
-import org.apache.commons.lang3.RandomStringUtils;
-import org.apache.usergrid.ServiceITSetup;
-import org.apache.usergrid.ServiceITSetupImpl;
-import org.apache.usergrid.ServiceITSuite;
-import org.apache.usergrid.management.OrganizationOwnerInfo;
-import org.apache.usergrid.management.UserInfo;
-import org.junit.ClassRule;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.UUID;
-
-import static junit.framework.Assert.assertNull;
-import static junit.framework.Assert.assertTrue;
-import static junit.framework.TestCase.assertNotNull;
-import static org.apache.usergrid.tools.UserOrgInterface.OrgUser;
-import static org.junit.Assert.assertEquals;
-
-
-/**
- * Test duplicate admin repair.
- */
-public class DuplicateAdminUserRepairTest {
-    
-    static final Logger logger = LoggerFactory.getLogger( 
DuplicateAdminUserRepairTest.class );
-    
-    @ClassRule
-    public static ServiceITSetup setup = new ServiceITSetupImpl( 
ServiceITSuite.cassandraResource );
-
-    
-    /**
-     * Test tool logic with mock manager that returns duplicates
-     */
-    @org.junit.Test
-    public void testMockWithDups() throws Exception {
-
-        DuplicateAdminUserRepair dor = new DuplicateAdminUserRepair();
-        MockManager mockManager = new MockManager();
-        dor.manager = mockManager;
-        dor.testing = true;
-
-        // the MockManager creates 2 pairs of duplicate orgs
-        assertNotNull( "user1_a", mockManager.getOrgUser( 
mockManager.user1_a.getId() ));
-        assertNotNull( "user1_b", mockManager.getOrgUser( 
mockManager.user1_b.getId() ));
-        assertNotNull( "user2_a", mockManager.getOrgUser( 
mockManager.user2_a.getId() ));
-        assertNotNull( "user2_b", mockManager.getOrgUser( 
mockManager.user2_b.getId() ));
-
-        // verify that correct users indexed
-        assertUsersIndexed( mockManager );
-        
-        dor.startTool( new String[] {}, false ); // false means do not call 
System.exit()
-
-        // verify that correct users indexed
-        assertUsersIndexed( mockManager );
-
-        // verify that duplicate users are gone (the "a" users were the first 
ones created)
-        assertNull( "must remove user1_a", mockManager.getOrgUser( 
mockManager.user1_a.getId() ));
-        assertNull( "must remove user2_a", mockManager.getOrgUser( 
mockManager.user2_a.getId() ));
-
-        // and keepers survived
-        assertNotNull( "user1_b survived", mockManager.getOrgUser( 
mockManager.user1_b.getId() ));
-        assertNotNull( "user2_b survived", mockManager.getOrgUser( 
mockManager.user2_b.getId() ));
-    }
-
-    
-    private void assertUsersIndexed(MockManager mockManager ) {
-        assertEquals("user1_b is in the index",
-                
mockManager.lookupOrgUserByUsername(mockManager.user1_b.getUsername()).getId(),
-                mockManager.user1_b.getId() );
-
-        assertEquals("user1_b is in the index",
-                
mockManager.lookupOrgUserByEmail(mockManager.user1_b.getEmail()).getId(),
-                mockManager.user1_b.getId() );
-
-        assertEquals("user2_b is in the index",
-                
mockManager.lookupOrgUserByUsername(mockManager.user2_b.getUsername()).getId(),
-                mockManager.user2_b.getId() );
-
-        assertEquals("user2_b is in the index",
-                
mockManager.lookupOrgUserByEmail(mockManager.user2_b.getEmail()).getId(),
-                mockManager.user2_b.getId() ); 
-    }
-    
-
-    @org.junit.Test
-    public void testDryRun() throws Exception {
-
-        DuplicateAdminUserRepair dor = new DuplicateAdminUserRepair();
-        MockManager mockManager = new MockManager();
-        dor.manager = mockManager;
-        dor.testing = true;
-
-        // the MockManager creates 2 pairs of duplicate orgs
-        assertNotNull( "user1_a", mockManager.getOrgUser( 
mockManager.user1_a.getId() ));
-        assertNotNull( "user1_b", mockManager.getOrgUser( 
mockManager.user1_b.getId() ));
-        assertNotNull( "user2_a", mockManager.getOrgUser( 
mockManager.user2_a.getId() ));
-        assertNotNull( "user2_b", mockManager.getOrgUser( 
mockManager.user2_b.getId() ));
-
-        // verify that correct users indexed
-        assertUsersIndexed( mockManager );
-
-        dor.startTool( new String[] { "-dryrun", "true" }, false ); // false 
means do not call System.exit()
-
-        // verify that correct users indexed
-        assertUsersIndexed( mockManager );
-        
-        // insure nothng was deleted by dry-run
-        assertNotNull( "dryrun should not delete user1_a", 
mockManager.getOrgUser( mockManager.user1_a.getId() ));
-        assertNotNull( "dryrun should not delete user1_b", 
mockManager.getOrgUser( mockManager.user1_b.getId() ));
-        assertNotNull( "dryrun should not delete user2_a", 
mockManager.getOrgUser( mockManager.user2_a.getId() ));
-        assertNotNull( "dryrun should not delete user2_b", 
mockManager.getOrgUser( mockManager.user2_b.getId() ));  
-    }
-
-    
-    /**
-     * Smoke test: does "real" manager run without throwing exceptions?
-     */
-    @org.junit.Test
-    public void testManagerNoDups() throws Exception {
-
-        // create two orgs each with owning user
-
-        final String random1 = 
org.apache.commons.lang.RandomStringUtils.randomAlphanumeric( 10 );
-        final OrganizationOwnerInfo orgOwnerInfo1 = 
setup.getMgmtSvc().createOwnerAndOrganization(
-                "org_" + random1, "user_" + random1, "user_" + random1,
-                "user_" + random1 + "@example.com", "password" );
-
-        final String random2 = 
org.apache.commons.lang.RandomStringUtils.randomAlphanumeric( 10 );
-        final OrganizationOwnerInfo orgOwnerInfo2 = 
setup.getMgmtSvc().createOwnerAndOrganization(
-                "org_" + random2, "user_" + random2, "user_" + random2,
-                "user_" + random2 + "@example.com", "password" );
-
-        // Add user1 to org2
-
-        setup.getMgmtSvc().addAdminUserToOrganization(
-                orgOwnerInfo1.getOwner(), orgOwnerInfo2.getOrganization(), 
false );
-
-        DuplicateAdminUserRepair dor = new DuplicateAdminUserRepair();
-
-        dor.startTool( new String[]{}, false );  // false means do not call 
System.exit()
-
-        assertTrue( true ); // we're happy if we get to this point
-    }
-
-    
-    @org.junit.Test
-    public void testManagerLookupMethods() throws Exception {
-        
-        // create two orgs each with owning user
-
-        final String random1 = 
org.apache.commons.lang.RandomStringUtils.randomAlphanumeric( 10 );
-        final OrganizationOwnerInfo orgOwnerInfo1 = 
setup.getMgmtSvc().createOwnerAndOrganization(
-                "org_" + random1, "user_" + random1, "user_" + random1,
-                "user_" + random1 + "@example.com", "password" );
-
-        final String random2 = 
org.apache.commons.lang.RandomStringUtils.randomAlphanumeric( 10 );
-        final OrganizationOwnerInfo orgOwnerInfo2 = 
setup.getMgmtSvc().createOwnerAndOrganization(
-                "org_" + random2, "user_" + random2, "user_" + random2,
-                "user_" + random2 + "@example.com", "password" );
-
-        DuplicateAdminUserRepair dor = new 
DuplicateAdminUserRepair(setup.getEmf(), setup.getMgmtSvc());
-        dor.manager = dor.createNewRepairManager(); // test the real manager 
-
-        // start the tool so that Spring, Cassandra, etc/ gets initialized
-        dor.startTool( new String[]{"-dryrun", "true"}, false ); // false 
means do not call System.exit()
-
-        testManagerLookupMethods( dor, orgOwnerInfo1, orgOwnerInfo2, true );
-        
-        dor.manager.removeOrgUser( dor.manager.getOrgUser( 
orgOwnerInfo1.getOwner().getUuid() )); 
-        dor.manager.removeOrgUser( dor.manager.getOrgUser( 
orgOwnerInfo2.getOwner().getUuid() ));
-
-        testManagerLookupMethods( dor, orgOwnerInfo1, orgOwnerInfo2, false );
-    }
-    
-    
-    private void testManagerLookupMethods( DuplicateAdminUserRepair dor, 
-                                    OrganizationOwnerInfo info1, 
-                                    OrganizationOwnerInfo info2,
-                                    boolean usersExist ) throws Exception {
-        if ( usersExist ) {
-            
-            assertNotNull( dor.manager.getOrgUser( info1.getOwner().getUuid() 
));
-            assertNotNull( dor.manager.getOrgUser( info2.getOwner().getUuid() 
));
-
-            assertNotNull( dor.manager.lookupOrgUserByEmail( 
info1.getOwner().getEmail() ));
-            assertNotNull( dor.manager.lookupOrgUserByEmail( 
info2.getOwner().getEmail() ));
-
-            assertNotNull( dor.manager.lookupOrgUserByUsername( 
info1.getOwner().getUsername() ));
-            assertNotNull( dor.manager.lookupOrgUserByUsername( 
info2.getOwner().getUsername() )); 
-            
-        } else {
-
-            assertNull( dor.manager.getOrgUser( info1.getOwner().getUuid() ) );
-            assertNull( dor.manager.getOrgUser( info2.getOwner().getUuid() ) );
-
-            assertNull( dor.manager.lookupOrgUserByEmail( 
info1.getOwner().getEmail() ) );
-            assertNull( dor.manager.lookupOrgUserByEmail( 
info2.getOwner().getEmail() ) );
-
-            assertNull( dor.manager.lookupOrgUserByUsername( 
info1.getOwner().getUsername() ) );
-            assertNull( dor.manager.lookupOrgUserByUsername( 
info2.getOwner().getUsername() ) );
-        }
-    }
-
-
-    @org.junit.Test
-    public void testManagerOrgUserUpdateMethod() throws Exception {
-
-        // create an org with an admin user
-        final String random1 = 
org.apache.commons.lang.RandomStringUtils.randomAlphanumeric( 10 );
-        final OrganizationOwnerInfo orgOwnerInfo1 = 
setup.getMgmtSvc().createOwnerAndOrganization(
-                "org_" + random1, "user_" + random1, "user_" + random1,
-                "user_" + random1 + "@example.com", "password" );
-
-        DuplicateAdminUserRepair dor = new 
DuplicateAdminUserRepair(setup.getEmf(), setup.getMgmtSvc());
-        dor.manager = dor.createNewRepairManager(); // test the real manager 
-
-        // start the tool so that Spring, Cassandra, etc/ gets initialized
-        dor.startTool( new String[]{"-dryrun", "true"}, false ); // false 
means do not call System.exit()
-
-        UserInfo userInfo = setup.getMgmtSvc().getAdminUserByUuid( 
orgOwnerInfo1.getOwner().getUuid() );
-        OrgUser user = dor.manager.getOrgUser( 
orgOwnerInfo1.getOwner().getUuid() );
-        assertEquals( userInfo.getUsername(), user.getUsername());
-        assertEquals( userInfo.getEmail(), user.getEmail());
-
-        // change user's username using updateOrgUser()
-        String newUsername = "boom_" + random1;
-        user.setUsername(newUsername);
-        dor.manager.updateOrgUser( user );
-        user = dor.manager.getOrgUser( orgOwnerInfo1.getOwner().getUuid() );
-        assertEquals( newUsername, user.getUsername());
-        
-        // change user's username using setOrgUserName()
-        newUsername = "blammo_" + random1;
-        dor.manager.setOrgUserName( user, newUsername );
-        user = dor.manager.getOrgUser( orgOwnerInfo1.getOwner().getUuid() );
-        assertEquals( newUsername, user.getUsername());
-    }
-    
-
-    /**
-     * Extend mock manager to add a pair of duplicate users.
-     */
-    static class MockManager extends MockUserOrgManager {
-
-        OrgUser user1_a;
-        OrgUser user1_b;
-        OrgUser user2_a;
-        OrgUser user2_b;
-        
-        public MockManager() throws Exception {
-            
-            super(1); // ask parent to create one pair of duplicate orgs
-            
-            Org org = orgsById.values().iterator().next();
-          
-            String sfx = RandomStringUtils.randomAlphanumeric(10);
-
-            // user1 a and b have duplicate usernames AND DUPLICATE EMAIL 
ADDRESSES
-            
-            user1_a = createOrgUser( UUID.randomUUID(), "UserName_"+sfx, 
"UserName_"+sfx+"@example.com" );
-            addUserToOrg( user1_a, org );
-            pause(100);
-
-            user1_b = createOrgUser( UUID.randomUUID(), "Username_"+sfx, 
"Username_"+sfx+"@example.com" );
-            addUserToOrg( user1_b, org );
-            pause(100);
-
-            // user2 a and b have duplicate usernames AND DIFFERENT EMAIL 
ADDRESSES 
-            
-            user2_a = createOrgUser( UUID.randomUUID(), "UserName_"+sfx, 
"UserName_"+sfx+"@example.com" );
-            addUserToOrg( user2_a, org );
-            pause(100);
-
-            user2_b = createOrgUser( UUID.randomUUID(), "UserName_"+sfx, 
"UserName_"+sfx+"@example.com" );
-            addUserToOrg( user2_b, org );
-            pause(100);
-
-        }
-        
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/usergrid/blob/ceb81076/stack/tools/src/test/java/org/apache/usergrid/tools/MockUserOrgManager.java
----------------------------------------------------------------------
diff --git 
a/stack/tools/src/test/java/org/apache/usergrid/tools/MockUserOrgManager.java 
b/stack/tools/src/test/java/org/apache/usergrid/tools/MockUserOrgManager.java
index 4b50f43..818c1b8 100644
--- 
a/stack/tools/src/test/java/org/apache/usergrid/tools/MockUserOrgManager.java
+++ 
b/stack/tools/src/test/java/org/apache/usergrid/tools/MockUserOrgManager.java
@@ -169,7 +169,7 @@ class MockUserOrgManager implements UserOrgInterface {
         for (String orgName : duplicatesByName.keySet()) {
             Set<Org> orgs = duplicatesByName.get( orgName );
             for (Org org : orgs) {
-                DuplicateAdminUserRepairTest.logger.info( "Duplicate org 
{}:{}", orgName, org.getId() );
+                DuplicateAdminRepairTest.logger.info( "Duplicate org {}:{}", 
orgName, org.getId() );
             }
         }
     }

Reply via email to