All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.xtext.junit4.AbstractXtextTests Maven / Gradle / Ivy

There is a newer version: 2.4.3
Show newest version
/*******************************************************************************
 * Copyright (c) 2008-2010 itemis AG (http://www.itemis.eu) and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *******************************************************************************/
package org.eclipse.xtext.junit4;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource.Diagnostic;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.xtext.Constants;
import org.eclipse.xtext.IGrammarAccess;
import org.eclipse.xtext.ISetup;
import org.eclipse.xtext.conversion.IValueConverterService;
import org.eclipse.xtext.diagnostics.ExceptionDiagnostic;
import org.eclipse.xtext.formatting.INodeModelFormatter;
import org.eclipse.xtext.junit4.GlobalRegistries.GlobalStateMemento;
import org.eclipse.xtext.junit4.serializer.SerializerTester;
import org.eclipse.xtext.junit4.util.ResourceLoadHelper;
import org.eclipse.xtext.linking.ILinkingService;
import org.eclipse.xtext.linking.lazy.LazyLinkingResource;
import org.eclipse.xtext.nodemodel.ICompositeNode;
import org.eclipse.xtext.nodemodel.impl.InvariantChecker;
import org.eclipse.xtext.parser.IAstFactory;
import org.eclipse.xtext.parser.IParseResult;
import org.eclipse.xtext.parser.IParser;
import org.eclipse.xtext.parsetree.reconstr.IParseTreeConstructor;
import org.eclipse.xtext.resource.IResourceFactory;
import org.eclipse.xtext.resource.XtextResource;
import org.eclipse.xtext.resource.XtextResourceSet;
import org.eclipse.xtext.scoping.IScopeProvider;
import org.eclipse.xtext.serializer.ISerializer;
import org.eclipse.xtext.util.CancelIndicator;
import org.eclipse.xtext.util.StringInputStream;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;

import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.Provider;
import com.google.inject.TypeLiteral;
import com.google.inject.name.Names;

/**
 * @author Sven Efftinge - Initial contribution and API
 * @since 2.3
 */
public abstract class AbstractXtextTests extends Assert implements ResourceLoadHelper {

	private Injector injector;
	private boolean canCreateInjector;
	private boolean isSerializerTestDisabled = false;
	private GlobalStateMemento globalStateMemento;
	
	static {
		GlobalRegistries.initializeDefaults();
	}

	@Before
	public void setUp() throws Exception {
		canCreateInjector = true;
		isSerializerTestDisabled = false;
		globalStateMemento = GlobalRegistries.makeCopyOfGlobalState();
	}

	@After
	public void tearDown() throws Exception {
		injector = null;
		isSerializerTestDisabled = false;
		globalStateMemento.restoreGlobalState();
	}

	public String serialize(EObject obj) {
		return getSerializer().serialize(obj);
	}

	/**
	 * call this to set the language class to be used in the current test.
	 */
	protected void with(Module ... modules) throws Exception {
		assertTrue("super.setUp() has to be called before any injector is instantiated", canCreateInjector);
		setInjector(Guice.createInjector(modules));
	}

	protected void with(Class setupClazz) throws Exception {
		assertTrue("super.setUp() has to be called before any injector is instantiated", canCreateInjector);
		ISetup instance = setupClazz.newInstance();
		setInjector(instance.createInjectorAndDoEMFRegistration());
	}

	public void with(ISetup setup) throws Exception {
		assertTrue("super.setUp() has to be called before any injector is instantiated", canCreateInjector);
		setInjector(setup.createInjectorAndDoEMFRegistration());
	}
	
	protected void setInjector(Injector injector) {
		this.injector = injector;
	}
	
	final public Injector getInjector() {
		if (injector==null)
			throw new IllegalStateException("No injector set. Did you forget to call something like 'with(new YourStadaloneSetup())'?");
		return injector;
	}

	public T get(Class clazz) {
		if (injector == null)
			injector = Guice.createInjector();
		return injector.getInstance(clazz);
	}

	public T get(Key key) {
		if (injector == null)
			injector = Guice.createInjector();
		return injector.getInstance(key);
	}
	
	public void injectMembers(Object object) {
		if (injector == null)
			injector = Guice.createInjector();
		injector.injectMembers(object);
	}

	protected IParser getParser() {
		return getInjector().getInstance(IParser.class);
	}

	protected ILinkingService getLinkingService() {
		return getInjector().getInstance(ILinkingService.class);
	}

	protected IAstFactory getASTFactory() {
		return getInjector().getInstance(IAstFactory.class);
	}

	protected IGrammarAccess getGrammarAccess() {
		return getInjector().getInstance(IGrammarAccess.class);
	}

	protected IParseTreeConstructor getParseTreeConstructor() {
		return getInjector().getInstance(IParseTreeConstructor.class);
	}

	protected IResourceFactory getResourceFactory()  {
		return getInjector().getInstance(IResourceFactory.class);
	}

	protected IValueConverterService getValueConverterService() {
		return getInjector().getInstance(IValueConverterService.class);
	}

	protected ISerializer getSerializer() {
		return getInjector().getInstance(ISerializer.class);
	}
	
	protected INodeModelFormatter getNodeModelFormatter() {
		return getInjector().getInstance(INodeModelFormatter.class);
	}

	protected IScopeProvider getScopeProvider() {
		return getInjector().getInstance(IScopeProvider.class);
	}
	
	protected InvariantChecker getInvariantChecker(){
		return getInjector().getInstance(InvariantChecker.class);
	}

	protected InputStream getAsStream(String model) {
		return new StringInputStream(model);
	}
	
	// parse methods

	public EObject getModel(String model) throws Exception {
		return getModel(getAsStream(model));
	}
	
	public final EObject getModel(InputStream model) throws Exception {
		XtextResource resource = getResource(model);
		return getModel(resource);
	}
	
	public static final int EXPECT_ERRORS = -2;
	public static final int UNKNOWN_EXPECTATION = Integer.MIN_VALUE;

	public final EObject getModelAndExpect(String model, int errors) throws Exception {
		return getModelAndExpect(getAsStream(model), errors);
	}
	
	public final EObject getModelAndExpect(InputStream model, int errors) throws Exception {
		XtextResource resource = getResourceAndExpect(model, errors);
		return getModel(resource);
	}

	protected EObject getModel(XtextResource resource) {
		return resource.getParseResult().getRootASTElement();
	}

	protected final XtextResource getResourceFromString(String model) throws Exception {
		return getResource(getAsStream(model));
	}
	
	protected final XtextResource getResourceFromStringAndExpect(String model, int errors) throws Exception {
		return getResourceAndExpect(getAsStream(model), errors);
	}

	public final XtextResource getResource(InputStream in) throws Exception {
		return getResource(in, URI.createURI("mytestmodel."+getCurrentFileExtension()));
	}
	
	protected String getCurrentFileExtension() {
		String instance = getInjector().getInstance(Key.get(String.class,Names.named(Constants.FILE_EXTENSIONS)));
		if (instance.indexOf(',')==-1)
			return instance;
		return instance.split(",")[0];
	}
	
	public final XtextResource getResourceFor(InputStream stream) {
		try {
			return getResourceAndExpect(stream, AbstractXtextTests.UNKNOWN_EXPECTATION);
		} catch (RuntimeException e) {
			throw e;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	
	public final XtextResource getResourceAndExpect(InputStream in, int errors) throws Exception {
		return getResourceAndExpect(in, URI.createURI("mytestmodel."+getCurrentFileExtension()), errors);
	}

	public final XtextResource getResource(InputStream in, URI uri) throws Exception {
		return getResourceAndExpect(in, uri, 0);
	}
	
	public final XtextResource getResource(String contents, String uri) throws Exception {
		return getResource(getAsStream(contents), URI.createURI(uri));
	}
	
	public final XtextResource getResourceAndExpect(InputStream in, URI uri, int expectedErrors) throws Exception {
		XtextResource resource = doGetResource(in, uri);
		checkNodeModel(resource);
		if (expectedErrors != UNKNOWN_EXPECTATION) {
			if (expectedErrors == EXPECT_ERRORS)
				assertFalse(resource.getErrors().toString(), resource.getErrors().isEmpty());
			else
				assertEquals(resource.getErrors().toString(), expectedErrors, resource.getErrors().size());
		}
		for(Diagnostic d: resource.getErrors()) {
			if (d instanceof ExceptionDiagnostic)
				fail(d.getMessage());
		}

		for(Diagnostic d: resource.getWarnings())
			System.out.println("Resource Warning: "+d);
				
		if (expectedErrors == 0 && resource.getContents().size() > 0 && shouldTestSerializer(resource)) {
			SerializerTester tester = get(SerializerTester.class);
			EObject obj = resource.getContents().get(0);
			tester.assertSerializeWithNodeModel(obj);
			tester.assertSerializeWithoutNodeModel(obj);
		}

		return resource;
	}

	protected void checkNodeModel(XtextResource resource) {
		IParseResult parseResult = resource.getParseResult();
		if(parseResult != null)
			getInvariantChecker().checkInvariant(parseResult.getRootNode());
	}

	protected boolean shouldTestSerializer(XtextResource resource) {
		return !isSerializerTestDisabled && !("org.eclipse.xtext.Xtext".equals(resource.getLanguageName()) 
				// TODO: fix serializer issues in refactoring tests
				|| "org.eclipse.xtext.ui.tests.refactoring.RefactoringTestLanguage".equals(resource.getLanguageName()));
	}
	
	protected void disableSerializerTest() {
		isSerializerTestDisabled = true;
	}

	protected XtextResource doGetResource(InputStream in, URI uri) throws Exception {
		XtextResourceSet rs = get(XtextResourceSet.class);
		rs.setClasspathURIContext(getClass());
		XtextResource resource = (XtextResource) getResourceFactory().createResource(uri);
		rs.getResources().add(resource);
		resource.load(in, null);
		if (resource instanceof LazyLinkingResource) {
			((LazyLinkingResource) resource).resolveLazyCrossReferences(CancelIndicator.NullImpl);
		} else {
			EcoreUtil.resolveAll(resource);
		}
		return resource;
	}

	protected final ICompositeNode getRootNode(InputStream model) throws Exception {
		XtextResource resource = getResource(model);
		return getRootNode(resource);
	}
	
	protected final ICompositeNode getRootNodeAndExpect(InputStream model, int errors) throws Exception {
		XtextResource resource = getResourceAndExpect(model, errors);
		return getRootNode(resource);
	}

	protected final ICompositeNode getRootNode(XtextResource resource) {
		return resource.getParseResult().getRootNode();
	}

	protected final IParseResult getParseResult(String model) throws Exception {
		return getResourceFromString(model).getParseResult();
	}
	
	protected final IParseResult getParseResultAndExpect(String model, int errors) throws Exception {
		return getResourceFromStringAndExpect(model, errors).getParseResult();
	}
	
	protected final ICompositeNode getRootNode(String model) throws Exception {
		return getRootNode(getAsStream(model));
	}
	
	protected final ICompositeNode getRootNodeAndExpect(String model, int errors) throws Exception {
		return getRootNodeAndExpect(getAsStream(model), errors);
	}
	
	protected String readFileIntoString(String filePath) throws IOException {
		ClassLoader classLoader = getClass().getClassLoader();
		URL url = classLoader.getResource(filePath);
		if (url == null) {
			fail("Could not read resource: '" + filePath + "'. Is your file system case sensitive?");
		} else {
			String canonicalPath = new File(new File(url.getPath()).getCanonicalPath()).toURI().getPath();
			if(!canonicalPath.endsWith(filePath))
				throw new RuntimeException(filePath + " -> " + canonicalPath + ":\n" +
						"The file does not exist exactly as it was named.\n" +
						"The test is likely to cause trouble on the build server.\n" +
						"Is your filesystem case insensitive? Please verify the spelling.");

			InputStream resourceAsStream = classLoader.getResourceAsStream(filePath);
			try {
				if (resourceAsStream == null) {
					fail("Could not read resource: '" + filePath + "'. Is your file system case sensitive?");
				} else {
						byte[] buffer = new byte[2048];
						int bytesRead = 0;
						StringBuffer b = new StringBuffer();
						do {
							bytesRead = resourceAsStream.read(buffer);
							if (bytesRead != -1)
								b.append(new String(buffer, 0, bytesRead));
						} while (bytesRead != -1);
						String model = b.toString();
						return model;
				}
			} finally {
				if (resourceAsStream != null)
					resourceAsStream.close();
			}
		}
		throw new IllegalStateException("May not happen, but helps to suppress false positives in eclipse' control flow analysis.");
	}

	public static final class Keys {
		private static final TypeLiteral> resourceSetLiteral = new TypeLiteral>(){
		};

		public static final Key> RESOURCE_SET_KEY = Key.get(resourceSetLiteral);
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy