Mercurial > hg > release > thermostat-0.11
changeset 1108:c6ad4123876e
Handle unknown extensions
Reviewed-by: jerboaa
Review-thread: http://icedtea.classpath.org/pipermail/thermostat/2013-May/006709.html
author | Omair Majid <omajid@redhat.com> |
---|---|
date | Thu, 23 May 2013 11:12:20 -0400 |
parents | f806af5a02f5 |
children | 83452b440c23 |
files | integration-tests/src/test/java/com/redhat/thermostat/itest/PluginTest.java launcher/src/main/java/com/redhat/thermostat/launcher/internal/CompoundCommandInfoSource.java launcher/src/test/java/com/redhat/thermostat/launcher/internal/CompoundCommandInfoSourceTest.java |
diffstat | 3 files changed, 272 insertions(+), 7 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/integration-tests/src/test/java/com/redhat/thermostat/itest/PluginTest.java Thu May 23 11:12:20 2013 -0400 @@ -0,0 +1,221 @@ +/* + * Copyright 2012, 2013 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.itest; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import expectj.Spawn; + +public class PluginTest extends IntegrationTest { + + private static final String PLUGIN_HOME = getThermostatHome() + File.separator + "plugins"; + + private static NewCommandPlugin newPlugin = new NewCommandPlugin(PLUGIN_HOME + File.separator + "new"); + private static UnknownExtendsPlugin unknownExtension = new UnknownExtendsPlugin(PLUGIN_HOME + File.separator + "unknown"); + + @BeforeClass + public static void setUpOnce() { + newPlugin.install(); + unknownExtension.install(); + } + + @AfterClass + public static void tearDownOnce() { + unknownExtension.uninstall(); + newPlugin.uninstall(); + } + + @Test + public void testHelpIsOkay() throws Exception { + Spawn shell = spawnThermostat("help"); + shell.expectClose(); + + String stdOut = shell.getCurrentStandardOutContents(); + String stdErr = shell.getCurrentStandardErrContents(); + + assertTrue(stdOut.contains("list of commands")); + assertTrue(stdOut.contains("help")); + assertTrue(stdOut.contains("agent")); + assertTrue(stdOut.contains("gui")); + assertTrue(stdOut.contains("ping")); + assertTrue(stdOut.contains("shell")); + + assertTrue(stdOut.contains(newPlugin.command)); + assertTrue(stdOut.contains(newPlugin.description)); + + assertFalse(stdOut.contains(unknownExtension.command)); + + // TODO assertEquals("", stdErr); + } + + /** + * This plugin provides a new command + */ + private static class NewCommandPlugin { + + private final String pluginHome; + private final String command; + private final String description; + + public NewCommandPlugin(String pluginLocation) { + this.pluginHome = pluginLocation; + + this.command = "foo"; + this.description = "foo plugin to foo bar"; + } + + private void install() { + File home = new File(pluginHome); + if (!home.isDirectory() && !home.mkdir()) { + throw new AssertionError("could not create directory: " + pluginHome); + } + + String pluginContents = "" + + "<?xml version=\"1.0\"?>\n" + + "<plugin xmlns=\"http://icedtea.classpath.org/thermostat/plugins/v1.0\"\n" + + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" + + " xsi:schemaLocation=\"http://icedtea.classpath.org/thermostat/plugins/v1.0 thermost-plugin.xsd\">\n" + + " <commands>" + + " <command>" + + " <name>" + command + "</name>" + + " <description>" + description + "</description>" + + " <options>" + + " <option>" + + " <long>aaaaa</long>" + + " <short>a</short>" + + " </option>" + + " </options>" + + " <bundles>" + + " <bundle>bar</bundle>" + + " </bundles>" + + " <dependencies>" + + " <dependency>foo</dependency>" + + " </dependencies>" + + " </command>" + + " </commands>" + + "</plugin>"; + + try (FileWriter writer = new FileWriter(pluginHome + File.separator + "thermostat-plugin.xml")) { + writer.write(pluginContents); + } catch (IOException e) { + throw new AssertionError("unable to write plugin configuration", e); + } + + } + + private void uninstall() { + if (!new File(pluginHome).exists()) { + return; + } + if (!new File(pluginHome, "thermostat-plugin.xml").delete()) { + throw new AssertionError("Could not delete plugin file"); + } + if (!new File(pluginHome).delete()) { + throw new AssertionError("Could not delete plugin directory"); + } + } + } + + /** + * This plugin extends an unknown command + */ + private static class UnknownExtendsPlugin { + + private final String pluginHome; + private final String command; + + public UnknownExtendsPlugin(String pluginLocation) { + this.pluginHome = pluginLocation; + + this.command = "unknown-command"; + } + + private void install() { + File home = new File(pluginHome); + if (!home.isDirectory() && !home.mkdir()) { + throw new AssertionError("could not create directory: " + pluginHome); + } + + String pluginContents = "" + + "<?xml version=\"1.0\"?>\n" + + "<plugin xmlns=\"http://icedtea.classpath.org/thermostat/plugins/v1.0\"\n" + + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" + + " xsi:schemaLocation=\"http://icedtea.classpath.org/thermostat/plugins/v1.0 thermost-plugin.xsd\">\n" + + " <extensions>" + + " <extension>" + + " <name>" + command + "</name>" + + " <bundles>" + + " <bundle>bar</bundle>" + + " </bundles>" + + " <dependencies>" + + " <dependency>foo</dependency>" + + " </dependencies>" + + " </extension>" + + " </extensions>" + + "</plugin>"; + + try (FileWriter writer = new FileWriter(pluginHome + File.separator + "thermostat-plugin.xml")) { + writer.write(pluginContents); + } catch (IOException e) { + throw new AssertionError("unable to write plugin configuration", e); + } + + } + + private void uninstall() { + if (!new File(pluginHome).exists()) { + return; + } + if (!new File(pluginHome, "thermostat-plugin.xml").delete()) { + throw new AssertionError("Could not delete plugin file"); + } + if (!new File(pluginHome).delete()) { + throw new AssertionError("Could not delete plugin directory"); + } + } + } + +}
--- a/launcher/src/main/java/com/redhat/thermostat/launcher/internal/CompoundCommandInfoSource.java Thu May 23 10:49:35 2013 -0400 +++ b/launcher/src/main/java/com/redhat/thermostat/launcher/internal/CompoundCommandInfoSource.java Thu May 23 11:12:20 2013 -0400 @@ -96,20 +96,28 @@ } private Collection<CommandInfo> mergeAll(Collection<CommandInfo> commandInfos1, Collection<CommandInfo> commandInfos2) { - Map<String, CommandInfo> result = new HashMap<>(); + Map<String, CommandInfo> merged = new HashMap<>(); for (CommandInfo info : commandInfos1) { - result.put(info.getName(), info); + merged.put(info.getName(), info); } for (CommandInfo info : commandInfos2) { String cmdName = info.getName(); - if (!result.containsKey(cmdName)) { - result.put(cmdName, info); + if (!merged.containsKey(cmdName)) { + merged.put(cmdName, info); } else { - result.put(cmdName, merge(result.get(cmdName), info)); + CommandInfo mergedCommand = merge(merged.get(cmdName), info); + merged.put(cmdName, mergedCommand); } } - return result.values(); + List<CommandInfo> result = new ArrayList<>(); + for (CommandInfo mergedCommand : merged.values()) { + if (isComplete(mergedCommand)) { + result.add(mergedCommand); + } + } + + return result; } private CommandInfo merge(CommandInfo info1, CommandInfo info2) { @@ -142,4 +150,13 @@ return result; } + private boolean isComplete(CommandInfo merged) { + if ((merged.getDescription() == null) + || (merged.getOptions() == null)) { + return false; + } + + return true; + } + }
--- a/launcher/src/test/java/com/redhat/thermostat/launcher/internal/CompoundCommandInfoSourceTest.java Thu May 23 10:49:35 2013 -0400 +++ b/launcher/src/test/java/com/redhat/thermostat/launcher/internal/CompoundCommandInfoSourceTest.java Thu May 23 11:12:20 2013 -0400 @@ -133,6 +133,33 @@ public void verifyGetCommandInfosMergesResultsFromBothSources() { CommandInfo cmdInfo11 = mock(CommandInfo.class); when(cmdInfo11.getName()).thenReturn("cmd1"); + when(cmdInfo11.getDescription()).thenReturn("cmd1"); + when(cmdInfo11.getOptions()).thenReturn(new Options()); + + CommandInfo cmdInfo12 = mock(CommandInfo.class); + when(cmdInfo12.getName()).thenReturn("cmd2"); + when(cmdInfo12.getDescription()).thenReturn("cmd2"); + when(cmdInfo12.getOptions()).thenReturn(new Options()); + + when(source1.getCommandInfos()).thenReturn(Arrays.asList(cmdInfo11, cmdInfo12)); + + CommandInfo cmdInfo21 = mock(CommandInfo.class); + when(cmdInfo21.getName()).thenReturn("cmd3"); + when(cmdInfo21.getDescription()).thenReturn("cmd3"); + when(cmdInfo21.getOptions()).thenReturn(new Options()); + CommandInfo cmdInfo22 = mock(CommandInfo.class); + when(cmdInfo22.getName()).thenReturn("cmd2"); + + when(source2.getCommandInfos()).thenReturn(Arrays.asList(cmdInfo21, cmdInfo22)); + + Collection<CommandInfo> results = compoundSource.getCommandInfos(); + assertEquals(3, results.size()); + } + + @Test + public void verifyGetCommandInfosIgnoresIncompleteCommands() { + CommandInfo cmdInfo11 = mock(CommandInfo.class); + when(cmdInfo11.getName()).thenReturn("cmd1"); CommandInfo cmdInfo12 = mock(CommandInfo.class); when(cmdInfo12.getName()).thenReturn("cmd2"); @@ -146,6 +173,6 @@ when(source2.getCommandInfos()).thenReturn(Arrays.asList(cmdInfo21, cmdInfo22)); Collection<CommandInfo> results = compoundSource.getCommandInfos(); - assertEquals(3, results.size()); + assertEquals(0, results.size()); } }