changeset 2277:a15a2233e4c7

Provide DbUrlCompleterService Reviewed-by: omajid Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2016-April/018584.html
author Andrew Azores <aazores@redhat.com>
date Tue, 26 Apr 2016 10:27:02 -0400
parents 651386629cea
children 21d476af1f0e
files launcher/src/main/java/com/redhat/thermostat/launcher/internal/Activator.java launcher/src/main/java/com/redhat/thermostat/launcher/internal/DbUrlCompleter.java launcher/src/main/java/com/redhat/thermostat/launcher/internal/DbUrlCompleterService.java launcher/src/main/java/com/redhat/thermostat/launcher/internal/DbUrlFinder.java launcher/src/main/java/com/redhat/thermostat/launcher/internal/TabCompletion.java launcher/src/test/java/com/redhat/thermostat/launcher/internal/ActivatorTest.java launcher/src/test/java/com/redhat/thermostat/launcher/internal/DbUrlCompleterTest.java launcher/src/test/java/com/redhat/thermostat/launcher/internal/DbUrlFinderTest.java launcher/src/test/java/com/redhat/thermostat/launcher/internal/ShellCommandTest.java
diffstat 9 files changed, 341 insertions(+), 156 deletions(-) [+]
line wrap: on
line diff
--- a/launcher/src/main/java/com/redhat/thermostat/launcher/internal/Activator.java	Mon Apr 25 17:13:31 2016 -0400
+++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/Activator.java	Tue Apr 26 10:27:02 2016 -0400
@@ -145,6 +145,7 @@
     private MultipleServiceTracker vmIdCompleterDepsTracker;
     private MultipleServiceTracker agentIdCompleterDepsTracker;
     private MultipleServiceTracker pingCommandCompleterDepsTracker;
+    private MultipleServiceTracker dbUrlCompleterDepsTracker;
 
     private CommandRegistry registry;
 
@@ -320,12 +321,29 @@
         });
         pingCommandCompleterDepsTracker.open();
 
+        final DbUrlCompleterService dbUrlCompleterService = new DbUrlCompleterService();
+        final Class<?> [] dbUrlCompleterDeps = new Class<?>[] { CommonPaths.class };
+        dbUrlCompleterDepsTracker = new MultipleServiceTracker(context, dbUrlCompleterDeps, new Action() {
+            @Override
+            public void dependenciesAvailable(Map<String, Object> services) {
+                CommonPaths paths = (CommonPaths) services.get(CommonPaths.class.getName());
+                dbUrlCompleterService.setCommonPaths(paths);
+            }
+
+            @Override
+            public void dependenciesUnavailable() {
+                dbUrlCompleterService.setCommonPaths(null);
+            }
+        });
+        dbUrlCompleterDepsTracker.open();
+
         LogLevelCompleterService logLevelCompleterService = new LogLevelCompleterService();
         context.registerService(CompleterService.class.getName(), logLevelCompleterService, null);
 
         context.registerService(CompleterService.class.getName(), vmIdCompleterService, null);
         context.registerService(CompleterService.class.getName(), agentIdCompleterService, null);
         context.registerService(CompleterService.class.getName(), pingCommandCompleterService, null);
+        context.registerService(CompleterService.class.getName(), dbUrlCompleterService, null);
     }
 
     @Override
@@ -351,6 +369,9 @@
         if (pingCommandCompleterDepsTracker != null) {
             pingCommandCompleterDepsTracker.close();
         }
+        if (dbUrlCompleterDepsTracker != null) {
+            dbUrlCompleterDepsTracker.close();
+        }
         registry.unregisterCommands();
     }
 }
--- a/launcher/src/main/java/com/redhat/thermostat/launcher/internal/DbUrlCompleter.java	Mon Apr 25 17:13:31 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * Copyright 2012-2016 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.launcher.internal;
-
-import com.redhat.thermostat.common.cli.TabCompleter;
-import com.redhat.thermostat.common.config.ClientPreferences;
-import jline.console.completer.StringsCompleter;
-
-import java.util.List;
-
-public class DbUrlCompleter implements TabCompleter {
-
-    private final ClientPreferences prefs;
-
-    public DbUrlCompleter(ClientPreferences preferences) {
-        this.prefs = preferences;
-    }
-
-    @Override
-    public int complete(final String buffer, final int cursor, final List<CharSequence> candidates) {
-        String dbUrl = "";
-        if (prefs.getConnectionUrl() != null) {
-            dbUrl = prefs.getConnectionUrl();
-        }
-        StringsCompleter stringsCompleter = new StringsCompleter(dbUrl);
-        return stringsCompleter.complete(buffer, cursor, candidates);
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/DbUrlCompleterService.java	Tue Apr 26 10:27:02 2016 -0400
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2012-2016 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.launcher.internal;
+
+import com.redhat.thermostat.common.cli.AbstractCompleterService;
+import com.redhat.thermostat.common.cli.CliCommandOption;
+import com.redhat.thermostat.common.cli.CompletionFinderTabCompleter;
+import com.redhat.thermostat.common.cli.TabCompleter;
+import com.redhat.thermostat.shared.config.CommonPaths;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+public class DbUrlCompleterService extends AbstractCompleterService {
+
+    public static final CliCommandOption DB_URL_OPTION = new CliCommandOption("d", "dbUrl", true, "Database URL", false);
+
+    @Override
+    public Set<String> getCommands() {
+        return TabCompletion.ALL_COMMANDS_COMPLETER;
+    }
+
+    @Override
+    public Map<CliCommandOption, ? extends TabCompleter> getOptionCompleters() {
+        TabCompleter completer = new CompletionFinderTabCompleter(new DbUrlFinder(dependencyServices));
+        return Collections.singletonMap(DB_URL_OPTION, completer);
+    }
+
+    public void setCommonPaths(CommonPaths paths) {
+        setService(CommonPaths.class, paths);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/DbUrlFinder.java	Tue Apr 26 10:27:02 2016 -0400
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2012-2016 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.launcher.internal;
+
+import com.redhat.thermostat.common.cli.CompletionFinder;
+import com.redhat.thermostat.common.cli.CompletionInfo;
+import com.redhat.thermostat.common.cli.DependencyServices;
+import com.redhat.thermostat.common.config.ClientPreferences;
+import com.redhat.thermostat.shared.config.CommonPaths;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+public class DbUrlFinder implements CompletionFinder {
+
+    private DependencyServices dependencyServices;
+    private CommonPaths paths;
+    private ClientPreferences prefs;
+
+    public DbUrlFinder(DependencyServices dependencyServices) {
+        this.dependencyServices = dependencyServices;
+    }
+
+    /* Testing only */
+    void setPaths(CommonPaths paths) {
+        this.paths = paths;
+    }
+
+    /* Testing only */
+    void setPrefs(ClientPreferences prefs) {
+        this.prefs = prefs;
+    }
+
+    @Override
+    public List<CompletionInfo> findCompletions() {
+        if (!dependencyServices.hasService(CommonPaths.class)) {
+            return Collections.emptyList();
+        }
+
+        CommonPaths paths = dependencyServices.getService(CommonPaths.class);
+        if (!Objects.equals(this.paths, paths)) {
+            this.paths = paths;
+            this.prefs = new ClientPreferences(paths);
+        }
+
+        String dbUrl = prefs.getConnectionUrl();
+        if (dbUrl == null) {
+            dbUrl = "";
+        }
+        return Collections.singletonList(new CompletionInfo(dbUrl));
+    }
+
+}
--- a/launcher/src/main/java/com/redhat/thermostat/launcher/internal/TabCompletion.java	Mon Apr 25 17:13:31 2016 -0400
+++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/TabCompletion.java	Tue Apr 26 10:27:02 2016 -0400
@@ -154,11 +154,7 @@
                 TreeCompleter.Node command = getCommandByName(info.getName());
 
                 for (Option option : (Collection<Option>) info.getOptions().getOptions()) {
-                    if (option.getLongOpt().equals(Arguments.DB_URL_ARGUMENT)) {
-                        setupCompletion(command, option, new DbUrlCompleter(prefs));
-                    } else {
-                        setupDefaultCompletion(command, option);
-                    }
+                    setupDefaultCompletion(command, option);
                 }
 
                 if (info.needsFileTabCompletions()) {
--- a/launcher/src/test/java/com/redhat/thermostat/launcher/internal/ActivatorTest.java	Mon Apr 25 17:13:31 2016 -0400
+++ b/launcher/src/test/java/com/redhat/thermostat/launcher/internal/ActivatorTest.java	Tue Apr 26 10:27:02 2016 -0400
@@ -155,12 +155,12 @@
 
         assertCommandIsRegistered(context, "help", HelpCommand.class);
 
-        verify(mockTracker, times(5)).open();
+        verify(mockTracker, times(6)).open();
 
         Action action = actionCaptor.getValue();
         assertNotNull(action);
         activator.stop(context);
-        verify(mockTracker, times(5)).close();
+        verify(mockTracker, times(6)).close();
     }
     
     @Test
@@ -194,6 +194,11 @@
         };
         whenNew(MultipleServiceTracker.class).withParameterTypes(BundleContext.class, Class[].class, Action.class).withArguments(eq(context),
                 eq(agentIdCompleterDeps), actionCaptor.capture()).thenReturn(unusedTracker);
+        Class<?>[] dbUrlCompleterDeps = new Class[] {
+                CommonPaths.class
+        };
+        whenNew(MultipleServiceTracker.class).withParameterTypes(BundleContext.class, Class[].class, Action.class).withArguments(eq(context),
+                eq(dbUrlCompleterDeps), actionCaptor.capture()).thenReturn(unusedTracker);
         Class<?>[] pingCompleterDeps = new Class[] {
                 AgentInfoDAO.class
         };
@@ -277,6 +282,11 @@
         };
         whenNew(MultipleServiceTracker.class).withParameterTypes(BundleContext.class, Class[].class, Action.class).withArguments(eq(context),
                 eq(agentIdCompleterDeps), actionCaptor.capture()).thenReturn(unusedTracker);
+        Class<?>[] dbUrlCompleterDeps = new Class[] {
+                CommonPaths.class
+        };
+        whenNew(MultipleServiceTracker.class).withParameterTypes(BundleContext.class, Class[].class, Action.class).withArguments(eq(context),
+                eq(dbUrlCompleterDeps), actionCaptor.capture()).thenReturn(unusedTracker);
         Class<?>[] pingCompleterDeps = new Class[] {
                 AgentInfoDAO.class
         };
@@ -347,6 +357,11 @@
         };
         whenNew(MultipleServiceTracker.class).withParameterTypes(BundleContext.class, Class[].class, Action.class).withArguments(eq(context),
                 eq(agentIdCompleterDeps), unusedCaptor.capture()).thenReturn(unusedTracker);
+        Class<?>[] dbUrlCompleterDeps = new Class[] {
+                CommonPaths.class
+        };
+        whenNew(MultipleServiceTracker.class).withParameterTypes(BundleContext.class, Class[].class, Action.class).withArguments(eq(context),
+                eq(dbUrlCompleterDeps), unusedCaptor.capture()).thenReturn(unusedTracker);
         Class<?>[] pingCompleterDeps = new Class[] {
                 AgentInfoDAO.class
         };
@@ -390,6 +405,11 @@
         };
         whenNew(MultipleServiceTracker.class).withParameterTypes(BundleContext.class, Class[].class, Action.class).withArguments(eq(context),
                 eq(agentIdCompleterDeps), unusedCaptor.capture()).thenReturn(unusedTracker);
+        Class<?>[] dbUrlCompleterDeps = new Class[] {
+                CommonPaths.class
+        };
+        whenNew(MultipleServiceTracker.class).withParameterTypes(BundleContext.class, Class[].class, Action.class).withArguments(eq(context),
+                eq(dbUrlCompleterDeps), unusedCaptor.capture()).thenReturn(unusedTracker);
         Class<?>[] pingCompleterDeps = new Class[] {
                 AgentInfoDAO.class
         };
@@ -440,6 +460,11 @@
         Class<?>[] agentIdCompleterDeps = new Class[] {
                 AgentInfoDAO.class
         };
+        Class<?>[] dbUrlCompleterDeps = new Class[] {
+                CommonPaths.class
+        };
+        whenNew(MultipleServiceTracker.class).withParameterTypes(BundleContext.class, Class[].class, Action.class).withArguments(eq(context),
+                eq(dbUrlCompleterDeps), unusedCaptor.capture()).thenReturn(unusedTracker);
         whenNew(MultipleServiceTracker.class).withParameterTypes(BundleContext.class, Class[].class, Action.class).withArguments(eq(context),
                 eq(agentIdCompleterDeps), agentCaptor.capture()).thenReturn(unusedTracker);
         Class<?>[] pingCompleterDeps = new Class[] {
@@ -494,6 +519,11 @@
         };
         whenNew(MultipleServiceTracker.class).withParameterTypes(BundleContext.class, Class[].class, Action.class).withArguments(eq(context),
                 eq(agentIdCompleterDeps), unusedCaptor.capture()).thenReturn(unusedTracker);
+        Class<?>[] dbUrlCompleterDeps = new Class[] {
+                CommonPaths.class
+        };
+        whenNew(MultipleServiceTracker.class).withParameterTypes(BundleContext.class, Class[].class, Action.class).withArguments(eq(context),
+                eq(dbUrlCompleterDeps), unusedCaptor.capture()).thenReturn(unusedTracker);
         Class<?>[] pingCompleterDeps = new Class[] {
                 AgentInfoDAO.class
         };
@@ -515,6 +545,63 @@
         assertTrue(context.isServiceRegistered(CompleterService.class.getName(), PingCommandCompleterService.class));
     }
 
+    @Test
+    public void testDbUrlCompleterServiceAvailability() throws Exception {
+        StubBundleContext context = new StubBundleContext();
+        MultipleServiceTracker unusedTracker = mock(MultipleServiceTracker.class);
+        ArgumentCaptor<Action> unusedCaptor = ArgumentCaptor.forClass(Action.class);
+        ArgumentCaptor<Action> dbCaptor = ArgumentCaptor.forClass(Action.class);
+        Class<?>[] launcherDeps = new Class[] {
+                Keyring.class,
+                CommonPaths.class,
+                SSLConfiguration.class,
+        };
+        whenNew(MultipleServiceTracker.class).withParameterTypes(BundleContext.class, Class[].class, Action.class).withArguments(eq(context),
+                eq(launcherDeps), unusedCaptor.capture()).thenReturn(unusedTracker);
+
+        Class<?>[] shellDeps = new Class[] {
+                CommonPaths.class,
+                ConfigurationInfoSource.class,
+        };
+        whenNew(MultipleServiceTracker.class).withParameterTypes(BundleContext.class, Class[].class, Action.class).withArguments(eq(context),
+                eq(shellDeps), unusedCaptor.capture()).thenReturn(unusedTracker);
+        Class<?>[] vmIdCompleterDeps = new Class[] {
+                VmInfoDAO.class,
+                AgentInfoDAO.class
+        };
+        whenNew(MultipleServiceTracker.class).withParameterTypes(BundleContext.class, Class[].class, Action.class).withArguments(eq(context),
+                eq(vmIdCompleterDeps), unusedCaptor.capture()).thenReturn(unusedTracker);
+        Class<?>[] agentIdCompleterDeps = new Class[] {
+                AgentInfoDAO.class
+        };
+        whenNew(MultipleServiceTracker.class).withParameterTypes(BundleContext.class, Class[].class, Action.class).withArguments(eq(context),
+                eq(agentIdCompleterDeps), unusedCaptor.capture()).thenReturn(unusedTracker);
+        Class<?>[] dbUrlCompleterDeps = new Class[] {
+                CommonPaths.class
+        };
+        whenNew(MultipleServiceTracker.class).withParameterTypes(BundleContext.class, Class[].class, Action.class).withArguments(eq(context),
+                eq(dbUrlCompleterDeps), dbCaptor.capture()).thenReturn(unusedTracker);
+        Class<?>[] pingCompleterDeps = new Class[] {
+                AgentInfoDAO.class
+        };
+        whenNew(MultipleServiceTracker.class).withParameterTypes(BundleContext.class, Class[].class, Action.class).withArguments(eq(context),
+                eq(pingCompleterDeps), unusedCaptor.capture()).thenReturn(unusedTracker);
+
+        Activator activator = new Activator();
+        activator.start(context);
+
+        Action action = dbCaptor.getValue();
+
+        Map<String, Object> services = new HashMap<>();
+        action.dependenciesAvailable(services);
+
+        assertTrue(context.isServiceRegistered(CompleterService.class.getName(), AgentIdCompleterService.class));
+
+        action.dependenciesUnavailable();
+
+        assertTrue(context.isServiceRegistered(CompleterService.class.getName(), AgentIdCompleterService.class));
+    }
+
     private Path createStubThermostatHome() throws Exception {
         Path tempDir = Files.createTempDirectory("test");
         tempDir.toFile().deleteOnExit();
--- a/launcher/src/test/java/com/redhat/thermostat/launcher/internal/DbUrlCompleterTest.java	Mon Apr 25 17:13:31 2016 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * Copyright 2012-2016 Red Hat, Inc.
- *
- * This file is part of Thermostat.
- *
- * Thermostat is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2, or (at your
- * option) any later version.
- *
- * Thermostat is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Thermostat; see the file COPYING.  If not see
- * <http://www.gnu.org/licenses/>.
- *
- * Linking this code with other modules is making a combined work
- * based on this code.  Thus, the terms and conditions of the GNU
- * General Public License cover the whole combination.
- *
- * As a special exception, the copyright holders of this code give
- * you permission to link this code with independent modules to
- * produce an executable, regardless of the license terms of these
- * independent modules, and to copy and distribute the resulting
- * executable under terms of your choice, provided that you also
- * meet, for each linked independent module, the terms and conditions
- * of the license of that module.  An independent module is a module
- * which is not derived from or based on this code.  If you modify
- * this code, you may extend this exception to your version of the
- * library, but you are not obligated to do so.  If you do not wish
- * to do so, delete this exception statement from your version.
- */
-
-package com.redhat.thermostat.launcher.internal;
-
-import static junit.framework.Assert.assertEquals;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.util.LinkedList;
-import java.util.List;
-
-import com.redhat.thermostat.common.config.ClientPreferences;
-import org.junit.Test;
-
-public class DbUrlCompleterTest {
-
-    @Test
-    public void testDbUrlCompleter() {
-        ClientPreferences prefs = mock(ClientPreferences.class);
-        DbUrlCompleter dbUrlCompleter = new DbUrlCompleter(prefs);
-
-        String partialUrl = "https://ip.addr";
-        String fullUrl = partialUrl + "ess.example.com:25813/thermostat/storage";
-        when(prefs.getConnectionUrl()).thenReturn(fullUrl);
-
-        List<CharSequence> candidates = new LinkedList<>();
-        dbUrlCompleter.complete(partialUrl, partialUrl.length(), candidates);
-
-        assertEquals(1, candidates.size());
-        assertEquals(fullUrl, candidates.get(0).toString().trim());
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/launcher/src/test/java/com/redhat/thermostat/launcher/internal/DbUrlFinderTest.java	Tue Apr 26 10:27:02 2016 -0400
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2012-2016 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.launcher.internal;
+
+import com.redhat.thermostat.common.cli.CompletionInfo;
+import com.redhat.thermostat.common.cli.DependencyServices;
+import com.redhat.thermostat.common.config.ClientPreferences;
+import com.redhat.thermostat.shared.config.CommonPaths;
+import org.junit.Test;
+
+import java.util.List;
+
+import static junit.framework.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class DbUrlFinderTest {
+
+    @Test
+    public void testDbUrlCompleter() {
+        DependencyServices dependencyServices = mock(DependencyServices.class);
+        CommonPaths paths = mock(CommonPaths.class);
+        ClientPreferences prefs = mock(ClientPreferences.class);
+        when(dependencyServices.hasService(CommonPaths.class)).thenReturn(true);
+        when(dependencyServices.getService(CommonPaths.class)).thenReturn(paths);
+        DbUrlFinder dbUrlFinder = new DbUrlFinder(dependencyServices);
+        dbUrlFinder.setPaths(paths);
+        dbUrlFinder.setPrefs(prefs);
+
+        String partialUrl = "https://ip.addr";
+        String fullUrl = partialUrl + "ess.example.com:25813/thermostat/storage";
+        when(prefs.getConnectionUrl()).thenReturn(fullUrl);
+
+        List<CompletionInfo> completions = dbUrlFinder.findCompletions();
+
+        assertEquals(1, completions.size());
+        assertEquals(fullUrl, completions.get(0).getCompletionWithUserVisibleText().trim());
+    }
+}
--- a/launcher/src/test/java/com/redhat/thermostat/launcher/internal/ShellCommandTest.java	Mon Apr 25 17:13:31 2016 -0400
+++ b/launcher/src/test/java/com/redhat/thermostat/launcher/internal/ShellCommandTest.java	Tue Apr 26 10:27:02 2016 -0400
@@ -50,6 +50,7 @@
 import java.util.Collection;
 import java.util.EnumSet;
 
+import com.redhat.thermostat.shared.config.CommonPaths;
 import org.apache.commons.cli.Option;
 import org.apache.commons.cli.Options;
 import org.junit.After;
@@ -396,27 +397,6 @@
     }
 
     @Test
-    public void testDbUrlOptionCompletes() throws CommandException {
-        ServiceReference ref = mock(ServiceReference.class);
-        when(bundleContext.getServiceReference(Launcher.class.getName())).thenReturn(ref);
-        Launcher launcher = mock(Launcher.class);
-        when(bundleContext.getService(ref)).thenReturn(launcher);
-
-        TestCommandContextFactory ctxFactory = new TestCommandContextFactory(bundleContext);
-        ctxFactory.setInput("validate --dbUrl \t\nexit\n");
-        Arguments args = new SimpleArguments();
-        CommandContext ctx = ctxFactory.createContext(args);
-        cmd.run(ctx);
-
-        String usefulOutput = getOutputWithoutIntro(ctxFactory);
-        String tabOutput = getTabOutput(usefulOutput);
-        assertTrue(tabOutput.length() == 0);
-        assertEquals(PROMPT + "validate --dbUrl http://127.0.0.1:mockStorage ", usefulOutput.split("\n")[0]);
-        assertEquals(PROMPT + "exit", usefulOutput.split("\n")[1]);
-        assertEquals("", ctxFactory.getError());
-    }
-
-    @Test
     public void testFullOptionDoesNotTabComplete() throws CommandException {
         ServiceReference ref = mock(ServiceReference.class);
         when(bundleContext.getServiceReference(Launcher.class.getName())).thenReturn(ref);