blob: 9849b7f8355cac051a09c67cd689cb81b0862e26 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2013 David Green and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* David Green - initial API and implementation
*******************************************************************************/
package org.eclipse.mylyn.wikitext.util;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.mylyn.internal.wikitext.MockMarkupLanguage;
import org.eclipse.mylyn.internal.wikitext.MockMarkupLanguageProvider;
import org.eclipse.mylyn.wikitext.parser.MarkupParser;
import org.eclipse.mylyn.wikitext.parser.markup.MarkupLanguage;
import org.eclipse.mylyn.wikitext.parser.markup.MarkupLanguageProvider;
import org.eclipse.mylyn.wikitext.util.ServiceLocator;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import com.google.common.base.Charsets;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableSet;
/**
* Tests for {@link ServiceLocator}
*
* @author David Green
*/
public class ServiceLocatorTest {
static class TestMarkupLanguage extends MarkupLanguage {
public TestMarkupLanguage(String name) {
setName(name);
}
@Override
public void processContent(MarkupParser parser, String markupContent, boolean asDocument) {
throw new IllegalStateException();
}
}
@Rule
public ExpectedException thrown = ExpectedException.none();
private ServiceLocator locator;
@Before
public void setUp() {
ServiceLocator.setImplementation(null);
locator = ServiceLocator.getInstance(ServiceLocatorTest.class.getClassLoader());
}
@Test
public void testKnownLanguageMetaInf() {
setupServiceLocatorWithMockMarkupLanguage(true);
assertKnownMarkupLanguage();
}
@Test
public void testKnownLanguageServices() {
setupServiceLocatorWithMockMarkupLanguage(false);
assertKnownMarkupLanguage();
}
@Test
public void testKnownLanguageProviderMetaInf() {
setupServiceLocatorWithMockMarkupLanguageProvider(true);
assertKnownMarkupLanguage();
}
@Test
public void testKnownLanguageProviderServices() {
setupServiceLocatorWithMockMarkupLanguageProvider(false);
assertKnownMarkupLanguage();
}
@Test
public void testLoadClassNotFound() throws MalformedURLException {
final URL url = new URL("file://example");
final AtomicBoolean wasThrown = new AtomicBoolean();
locator = new ServiceLocator(ServiceLocatorTest.class.getClassLoader()) {
@Override
protected Class<?> loadClass(ResourceDescriptor resource, String className) throws ClassNotFoundException {
wasThrown.set(true);
throw new ClassNotFoundException(className);
}
@Override
protected List<ResourceDescriptor> discoverServiceResources() {
return Collections.singletonList(new ResourceDescriptor(url));
}
@Override
protected List<String> readServiceClassNames(URL url) {
return Collections.singletonList("test.TestLanguage");
}
@Override
void logFailure(String className, Exception e) {
}
};
Set<MarkupLanguage> languages = locator.getAllMarkupLanguages();
assertTrue(wasThrown.get());
assertNotNull(languages);
assertTrue(languages.isEmpty());
}
protected void assertKnownMarkupLanguage() {
MarkupLanguage markupLanguage = locator.getMarkupLanguage(MockMarkupLanguage.class.getSimpleName());
assertNotNull(markupLanguage);
assertEquals(new MockMarkupLanguage().getName(), markupLanguage.getName());
}
protected void setupServiceLocatorWithMockMarkupLanguage(boolean metaInf) {
try {
ClassLoader classLoader = mock(ClassLoader.class);
Collection<URL> resources = Collections
.singletonList(new URL("file:" + MockMarkupLanguage.class.getName()));
Enumeration<Object> empty = Collections.enumeration(Collections.emptyList());
doReturn(empty).when(classLoader).getResources(any(String.class));
doReturn(metaInf ? Collections.enumeration(resources) : empty).when(classLoader)
.getResources(eq("META-INF/services/" + MarkupLanguage.class.getName()));
doReturn(!metaInf ? Collections.enumeration(resources) : empty).when(classLoader)
.getResources(eq("services/" + MarkupLanguage.class.getName()));
doReturn(MockMarkupLanguage.class).when(classLoader).loadClass(MockMarkupLanguage.class.getName());
locator = new ServiceLocator(classLoader) {
@Override
protected List<String> readServiceClassNames(URL url) {
return super.readServiceClassNames(
new ByteArrayInputStream(MockMarkupLanguage.class.getName().getBytes(Charsets.UTF_8)));
}
};
} catch (Exception e) {
throw Throwables.propagate(e);
}
}
protected void setupServiceLocatorWithMockMarkupLanguageProvider(boolean metaInf) {
try {
ClassLoader classLoader = mock(ClassLoader.class);
Collection<URL> resources = Collections
.singletonList(new URL("file:" + MockMarkupLanguageProvider.class.getName()));
Enumeration<Object> empty = Collections.enumeration(Collections.emptyList());
doReturn(empty).when(classLoader).getResources(any(String.class));
doReturn(metaInf ? Collections.enumeration(resources) : empty).when(classLoader)
.getResources(eq("META-INF/services/" + MarkupLanguageProvider.class.getName()));
doReturn(!metaInf ? Collections.enumeration(resources) : empty).when(classLoader)
.getResources(eq("services/" + MarkupLanguageProvider.class.getName()));
doReturn(MockMarkupLanguageProvider.class).when(classLoader)
.loadClass(MockMarkupLanguageProvider.class.getName());
locator = new ServiceLocator(classLoader) {
@Override
protected List<String> readServiceClassNames(URL url) {
return super.readServiceClassNames(new ByteArrayInputStream(
MockMarkupLanguageProvider.class.getName().getBytes(Charsets.UTF_8)));
}
};
} catch (Exception e) {
throw Throwables.propagate(e);
}
}
@Test
public void testUnknownLanguage() {
setupServiceLocatorWithMockMarkupLanguage(true);
thrown.expect(IllegalArgumentException.class);
locator.getMarkupLanguage("No Such Language asdlkfjal;sjdf");
}
@Test
public void testFQN() {
MarkupLanguage markupLanguage = locator.getMarkupLanguage(MockMarkupLanguage.class.getName());
assertNotNull(markupLanguage);
assertEquals(MockMarkupLanguage.class, markupLanguage.getClass());
}
@Test
public void getMarkupLanguageNull() {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Must provide a languageName");
locator.getMarkupLanguage(null);
}
@Test
public void getMarkupLanguageUnknown() {
setupServiceLocatorWithMockMarkupLanguage(true);
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage(
"Cannot load markup language 'UnknownLanguage'. Known markup languages are 'MockMarkupLanguage'");
locator.getMarkupLanguage("UnknownLanguage");
}
@Test
public void readServicesFileNone() {
List<String> names = locator.readServiceClassNames(createInput(""));
assertNotNull(names);
assertTrue(names.isEmpty());
}
@Test
public void readServicesFileCommentsAndEmptyLinesOnly() {
List<String> names = locator.readServiceClassNames(createInput("#" + Object.class.getName() + "\n\n\n\n#last"));
assertNotNull(names);
assertTrue(names.isEmpty());
}
@Test
public void readServicesFile() {
List<String> names = locator.readServiceClassNames(
createInput(Object.class.getName() + "\n" + String.class.getName() + " # trailing comment"));
assertNotNull(names);
assertEquals(2, names.size());
assertEquals(Object.class.getName(), names.get(0));
assertEquals(String.class.getName(), names.get(1));
}
@Test
public void getClasspathServiceResourceNames() {
List<String> names = locator.getClasspathServiceResourceNames();
assertNotNull(names);
assertTrue(names.contains("META-INF/services/" + MarkupLanguage.class.getName()));
assertTrue(names.contains("services/" + MarkupLanguage.class.getName()));
}
@Test
public void getAllMarkupLanguagesFiltersDuplicates() {
final MarkupLanguage language1 = new TestMarkupLanguage("Language 1");
final MarkupLanguage language1b = new MarkupLanguage() {
{
setName("Language 1");
}
@Override
public void processContent(MarkupParser parser, String markupContent, boolean asDocument) {
throw new IllegalStateException();
}
};
final MarkupLanguage language2 = new TestMarkupLanguage("Language 3");
final MarkupLanguage language2b = new TestMarkupLanguage("Language 3");
ServiceLocator locator = new ServiceLocator(ServiceLocatorTest.class.getClassLoader()) {
@Override
void loadMarkupLanguages(MarkupLanguageVisitor visitor) {
visitor.accept(language1);
visitor.accept(language1b);
visitor.accept(language2);
visitor.accept(language2b);
}
};
Set<MarkupLanguage> markupLanguages = locator.getAllMarkupLanguages();
assertEquals(3, markupLanguages.size());
assertTrue(markupLanguages.containsAll(ImmutableSet.of(language1, language1b)));
assertTrue(markupLanguages.contains(language2) || markupLanguages.contains(language2b));
}
private InputStream createInput(String content) {
return new ByteArrayInputStream(content.getBytes(Charsets.UTF_8));
}
}