/* * Copyright 2017 ThoughtWorks, Inc. * * Licensed 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 com.thoughtworks.go.config.registry; import java.io.File; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import com.thoughtworks.go.config.BuildTask; import com.thoughtworks.go.domain.Task; import com.thoughtworks.go.plugins.PluginExtensions; import com.thoughtworks.go.plugins.PluginTestUtil; import com.thoughtworks.go.plugins.presentation.PluggableViewModelFactory; import com.thoughtworks.go.presentation.TaskViewModel; import com.thoughtworks.go.util.DataStructureUtils; import org.jdom2.Element; import org.jdom2.Namespace; import org.junit.Before; import org.junit.Test; import org.osgi.framework.BundleContext; import static com.thoughtworks.go.util.DataStructureUtils.m; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.StringContains.containsString; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; public class ConfigElementImplementationRegistryTest { private PluginExtensions pluginExtns; @Before public void setUp() { pluginExtns = mock(PluginExtensions.class); List<ConfigurationExtension> configTags = new ArrayList<>(); when(pluginExtns.configTagImplementations()).thenReturn(configTags); } @Test public void shouldProvideTheNamespaceUriAndTheLocation() throws MalformedURLException { ConfigElementImplementationRegistry registry = new ConfigElementImplementationRegistry(pluginExtns); URL resource = new File("file:///tmp/foo").toURI().toURL(); URL resource1 = new File("file:///tmp/bar").toURI().toURL(); registry.xsdFor(PluginTestUtil.bundleCtxWithHeaders(m(PluginNamespace.XSD_NAMESPACE_PREFIX, "uri-1", PluginNamespace.XSD_NAMESPACE_URI, "uri1")), resource); registry.xsdFor(PluginTestUtil.bundleCtxWithHeaders(m(PluginNamespace.XSD_NAMESPACE_PREFIX, "uri-2", PluginNamespace.XSD_NAMESPACE_URI, "uri2")), resource); registry.xsdFor(PluginTestUtil.bundleCtxWithHeaders(m(PluginNamespace.XSD_NAMESPACE_PREFIX, "uri-3", PluginNamespace.XSD_NAMESPACE_URI, "uri3")), resource1); assertThat(registry.xsds(), containsString(String.format("uri1 %s", resource.toString()))); assertThat(registry.xsds(), containsString(String.format("uri2 %s", resource.toString()))); assertThat(registry.xsds(), containsString(String.format("uri3 %s", resource1.toString()))); } @Test public void shouldAddPluginNamespaceToPassedInElement() throws MalformedURLException { ConfigElementImplementationRegistry registry = new ConfigElementImplementationRegistry(pluginExtns); registry.xsdFor(PluginTestUtil.bundleCtxWithHeaders(m(PluginNamespace.XSD_NAMESPACE_PREFIX, "something", PluginNamespace.XSD_NAMESPACE_URI, "uri")), new File("file:///tmp/foo").toURI().toURL()); registry.xsdFor(PluginTestUtil.bundleCtxWithHeaders(m(PluginNamespace.XSD_NAMESPACE_PREFIX, "second", PluginNamespace.XSD_NAMESPACE_URI, "uri-1")), new File("file:///tmp/foo1").toURI().toURL()); Element foo = new Element("foo"); registry.registerNamespacesInto(foo); assertThat(foo.getNamespace("something"), is(Namespace.getNamespace("something", "uri"))); assertThat(foo.getNamespace("second"), is(Namespace.getNamespace("second", "uri-1"))); } private static final class TestTaskConfigTypeExtension<T extends Task> implements ConfigTypeExtension<Task> { private Class<T> implType; private PluggableViewModelFactory<T> factory; private TestTaskConfigTypeExtension(Class<T> implType, PluggableViewModelFactory<T> factory) { this.implType = implType; this.factory = factory; } public Class<Task> getType() { return Task.class; } public Class<? extends Task> getImplementation() { return implType; } public PluggableViewModelFactory<? extends Task> getFactory() { return factory; } } @Test public void shouldCreateTaskViewModelForPlugins() throws MalformedURLException { BundleContext execCtx = PluginTestUtil.bundleCtxWithHeaders(DataStructureUtils.m(PluginNamespace.XSD_NAMESPACE_PREFIX, "exec", PluginNamespace.XSD_NAMESPACE_URI, "uri-exec")); PluggableViewModelFactory<PluginExec> factory = mock(PluggableViewModelFactory.class); ConfigTypeExtension exec = new TestTaskConfigTypeExtension<>(PluginExec.class, factory); PluginExec execInstance = new PluginExec(); TaskViewModel stubbedViewModel = new TaskViewModel(execInstance, "my/view"); when(factory.viewModelFor(execInstance, "new")).thenReturn(stubbedViewModel); ConfigurationExtension execTask = new ConfigurationExtension<>( new PluginNamespace(execCtx, new URL("file:///exec")), exec); when(pluginExtns.configTagImplementations()).thenReturn(Arrays.asList(execTask)); ConfigElementImplementationRegistry registry = new ConfigElementImplementationRegistry(pluginExtns); assertThat(registry.getViewModelFor(execInstance, "new"), is(stubbedViewModel)); } @Test public void shouldNotThrowUpIfPluginHasNotRegisteredViewTemplates() throws Exception { BundleContext execCtx = PluginTestUtil.bundleCtxWithHeaders(DataStructureUtils.m(PluginNamespace.XSD_NAMESPACE_PREFIX, "exec", PluginNamespace.XSD_NAMESPACE_URI, "uri-exec")); ConfigTypeExtension exec = new TestTaskConfigTypeExtension<>(PluginExec.class, PluggableViewModelFactory.DOES_NOT_APPLY); PluginExec execInstance = new PluginExec(); ConfigurationExtension execTask = new ConfigurationExtension<>( new PluginNamespace(execCtx, new URL("file:///exec")), exec); when(pluginExtns.configTagImplementations()).thenReturn(Arrays.asList(execTask)); ConfigElementImplementationRegistry registry = new ConfigElementImplementationRegistry(pluginExtns); try { registry.getViewModelFor(execInstance, "new"); fail("Should not have a view model when the plugin factory does not exist"); } catch (Exception e) { assertThat(e.getMessage(), is(String.format("This component does not support rendering '%s' for action 'new'", execInstance))); } } @Test public void registerAllConfigTagImplementationsProvidedByPlugins() throws MalformedURLException { BundleContext execCtx = PluginTestUtil.bundleCtxWithHeaders(DataStructureUtils.m(PluginNamespace.XSD_NAMESPACE_PREFIX, "exec", PluginNamespace.XSD_NAMESPACE_URI, "uri-exec")); PluggableViewModelFactory<PluginExec> factory = mock(PluggableViewModelFactory.class); ConfigTypeExtension exec = new TestTaskConfigTypeExtension<>(PluginExec.class, factory); ConfigurationExtension execTag = new ConfigurationExtension<>( new PluginNamespace(execCtx, new URL("file:///exec")), exec); BundleContext antCtx = PluginTestUtil.bundleCtxWithHeaders(DataStructureUtils.m(PluginNamespace.XSD_NAMESPACE_PREFIX, "ant", PluginNamespace.XSD_NAMESPACE_URI, "uri-ant")); ConfigTypeExtension ant = new TestTaskConfigTypeExtension<>(PluginAnt.class, mock(PluggableViewModelFactory.class)); ConfigurationExtension antTag = new ConfigurationExtension<>( new PluginNamespace(antCtx, new URL("file:///ant")), ant); when(pluginExtns.configTagImplementations()).thenReturn(Arrays.asList(execTag, antTag)); ConfigElementImplementationRegistry registry = new ConfigElementImplementationRegistry(pluginExtns); assertThat(registry.xsds(), containsString("uri-exec file:/exec")); assertThat(registry.xsds(), containsString("uri-ant file:/ant")); List<Class<? extends Task>> implementationTypes = registry.implementersOf(Task.class); assertThat(implementationTypes.contains(PluginExec.class), is(true)); assertThat(implementationTypes.contains(PluginAnt.class), is(true)); Element mock = mock(Element.class); registry.registerNamespacesInto(mock); verify(mock).addNamespaceDeclaration(Namespace.getNamespace("exec", "uri-exec")); verify(mock).addNamespaceDeclaration(Namespace.getNamespace("ant", "uri-ant")); } class PluginAnt extends BuildTask { @Override public String getTaskType() { return "build"; } public String getTypeForDisplay() { return null; } @Override public String command() { return null; } @Override public String arguments() { return null; } } class PluginExec extends BuildTask { @Override public String getTaskType() { return "build"; } public String getTypeForDisplay() { return null; } @Override public String command() { return null; } @Override public String arguments() { return null; } } }