blob: c00828f8ba3a8d6d72dd450107a5edce9a755bcc [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009 IBM Corporation 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
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.e4.core.services.internal.context;
import junit.framework.AssertionFailedError;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.eclipse.e4.core.services.IDisposable;
import org.eclipse.e4.core.services.annotations.In;
import org.eclipse.e4.core.services.annotations.PostConstruct;
import org.eclipse.e4.core.services.context.EclipseContextFactory;
import org.eclipse.e4.core.services.context.IEclipseContext;
import org.eclipse.e4.core.services.context.spi.ContextInjectionFactory;
/**
* Tests for the basic context injection functionality
*/
public class ContextInjectionTest extends TestCase {
public static Test suite() {
return new TestSuite(ContextInjectionTest.class);
}
public ContextInjectionTest() {
super();
}
public ContextInjectionTest(String name) {
super(name);
}
public void testContextSetOneArg() {
class Injected {
int contextSetCalled = 0;
int setMethodCalled = 0;
@SuppressWarnings("unused")
public void contextSet(IEclipseContext context) {
contextSetCalled++;
}
@SuppressWarnings("unused")
@In
public void setInjectedMethod(Object arg) {
setMethodCalled++;
}
}
IEclipseContext context = EclipseContextFactory.create();
Object methodValue = new Object();
context.set("injectedMethod", methodValue);
Injected object = new Injected();
ContextInjectionFactory.inject(object, context);
assertEquals(1, object.setMethodCalled);
assertEquals(1, object.contextSetCalled);
context.set("injectedMethod", "AnotherValue");
assertEquals(2, object.setMethodCalled);
assertEquals(1, object.contextSetCalled);
}
public void testContextSetZeroArgs() {
class Injected {
int contextSetCalled = 0;
int setMethodCalled = 0;
@SuppressWarnings("unused")
public void contextSet() {
contextSetCalled++;
}
@SuppressWarnings("unused")
@In
public void setInjectedMethod(Object arg) {
setMethodCalled++;
}
}
IEclipseContext context = EclipseContextFactory.create();
Object methodValue = new Object();
context.set("injectedMethod", methodValue);
Injected object = new Injected();
ContextInjectionFactory.inject(object, context);
assertEquals(1, object.setMethodCalled);
assertEquals(1, object.contextSetCalled);
context.set("injectedMethod", "AnotherValue");
assertEquals(2, object.setMethodCalled);
assertEquals(1, object.contextSetCalled);
}
/**
* Tests that fields are injected before methods.
*/
public void testFieldMethodOrder() {
final AssertionFailedError[] error = new AssertionFailedError[1];
class Injected {
@In
Object injectedField;
Object methodValue;
@SuppressWarnings("unused")
@In
public void setInjectedMethod(Object arg) {
try {
assertTrue(injectedField != null);
} catch (AssertionFailedError e) {
error[0] = e;
}
methodValue = arg;
}
}
IEclipseContext context = EclipseContextFactory.create();
Object fieldValue = new Object();
Object methodValue = new Object();
context.set("injectedField", fieldValue);
context.set("injectedMethod", methodValue);
Injected object = new Injected();
ContextInjectionFactory.inject(object, context);
if (error[0] != null)
throw error[0];
assertEquals(fieldValue, object.injectedField);
assertEquals(methodValue, object.methodValue);
// removing method value, the field should still have value
context.remove("injectedMethod");
if (error[0] != null)
throw error[0];
assertEquals(fieldValue, object.injectedField);
assertNull(object.methodValue);
((IDisposable) context).dispose();
if (error[0] != null)
throw error[0];
}
/**
* Tests that a class with multiple post-construct methods has post-construct methods invoked at
* the correct time.
*/
public void testInheritedPostConstruct() {
IEclipseContext context = EclipseContextFactory.create();
context.set("OverriddenMethod", new Object());
context.set("StringViaMethod", "");
context.set("ObjectViaMethod", new Object());
ObjectSubClass userObject = new ObjectSubClass();
ContextInjectionFactory.inject(userObject, context);
assertEquals(1, userObject.superPostConstructCount);
assertEquals(1, userObject.subPostConstructCount);
context.set("OverriddenMethod", new Object());
assertEquals(1, userObject.superPostConstructCount);
assertEquals(1, userObject.subPostConstructCount);
}
/**
* Tests that a class with multiple pre-destroy methods has those methods invoked at the correct
* time.
*/
public void testInheritedPreDestroy() {
IEclipseContext context = EclipseContextFactory.create();
context.set("OverriddenMethod", new Object());
context.set("StringViaMethod", "");
context.set("ObjectViaMethod", new Object());
ObjectSubClass userObject = new ObjectSubClass();
ContextInjectionFactory.inject(userObject, context);
assertEquals(0, userObject.superPreDestroyCount);
assertEquals(0, userObject.subPreDestroyCount);
context.set("OverriddenMethod", new Object());
assertEquals(0, userObject.superPreDestroyCount);
assertEquals(0, userObject.subPreDestroyCount);
((IDisposable) context).dispose();
assertEquals(1, userObject.superPreDestroyCount);
assertEquals(1, userObject.subPreDestroyCount);
}
/**
* Tests that a class with a @PreDestroy method that is overridden by a subclass.
*/
public void testOverriddenPreDestroy() {
IEclipseContext context = EclipseContextFactory.create();
context.set("OverriddenMethod", new Object());
context.set("StringViaMethod", "");
context.set("ObjectViaMethod", new Object());
ObjectSubClass userObject = new ObjectSubClass();
ContextInjectionFactory.inject(userObject, context);
assertEquals(0, userObject.overriddenPreDestroyCount);
context.set("OverriddenMethod", new Object());
assertEquals(0, userObject.overriddenPreDestroyCount);
((IDisposable) context).dispose();
assertEquals(1, userObject.overriddenPreDestroyCount);
}
/**
* Tests basic context injection
*/
public synchronized void testInjection() {
Integer testInt = new Integer(123);
String testString = new String("abc");
Boolean testBoolean = new Boolean(true);
String testStringViaMethod = new String("abcd");
Object testObjectViaMethod = new Object();
// create context
IEclipseContext context = EclipseContextFactory.create();
// elements to be populated via fields
context.set("Integer", testInt);
context.set("string", testString); // this checks capitalization as well
context.set("Boolean", testBoolean);
// elements to be populated via methods
context.set("StringViaMethod", testStringViaMethod);
context.set("objectViaMethod", testObjectViaMethod); // this checks capitalization as well
ObjectBasic userObject = new ObjectBasic();
ContextInjectionFactory.inject(userObject, context);
// check field injection
assertEquals(testString, userObject.getString());
assertEquals(testInt, userObject.getInteger());
assertEquals(context, userObject.getContext());
// check method injection
assertEquals(1, userObject.setStringCalled);
assertEquals(1, userObject.setObjectCalled);
assertEquals(testStringViaMethod, userObject.getStringViaMethod());
assertEquals(testObjectViaMethod, userObject.getObjectViaMethod());
// check post processing
assertTrue(userObject.isFinalized());
}
/**
* Tests injection into classes with inheritance
*/
public synchronized void testInjectionAndInheritance() {
Integer testInt = new Integer(123);
String testString = new String("abc");
String testStringViaMethod = new String("abcd");
Object testObjectViaMethod = new Object();
// create context
IEclipseContext context = EclipseContextFactory.create();
// elements to be populated via fields
context.set("Integer", testInt);
context.set("string", testString); // this checks capitalization as well
// elements to be populated via methods
context.set("StringViaMethod", testStringViaMethod);
context.set("objectViaMethod", testObjectViaMethod); // this checks capitalization as well
context.set("OverriddenMethod", new Object());
ObjectSubClass userObject = new ObjectSubClass();
ContextInjectionFactory.inject(userObject, context);
// check inherited portion
assertEquals(testString, userObject.getString());
assertEquals(context, userObject.getContext());
assertEquals(testStringViaMethod, userObject.getStringViaMethod());
assertEquals(1, userObject.setStringCalled);
// check declared portion
assertEquals(testInt, userObject.getInteger());
assertEquals(testObjectViaMethod, userObject.getObjectViaMethod());
assertEquals(1, userObject.setObjectCalled);
// check post processing
assertEquals(1, userObject.getFinalizedCalled());
}
/**
* Tests injection of objects from parent context
*/
public synchronized void testInjectionFromParent() {
Integer testInt = new Integer(123);
String testStringViaMethod = new String("abcd");
Object testObjectViaMethod = new Object();
// create parent context
IEclipseContext parentContext = EclipseContextFactory.create();
parentContext.set("Integer", testInt);
parentContext.set("StringViaMethod", testStringViaMethod);
// create child context
IEclipseContext context = EclipseContextFactory.create(parentContext, null);
context.set("objectViaMethod", testObjectViaMethod); // this checks capitalization as well
context.set("string", "foo"); // not important for this test
ObjectBasic userObject = new ObjectBasic();
ContextInjectionFactory.inject(userObject, context);
assertEquals(testInt, userObject.getInteger());
assertEquals(context, userObject.getContext());
assertEquals(testStringViaMethod, userObject.getStringViaMethod());
assertEquals(testObjectViaMethod, userObject.getObjectViaMethod());
assertEquals(1, userObject.setStringCalled);
assertEquals(1, userObject.setObjectCalled);
// check post processing
assertTrue(userObject.isFinalized());
}
public void testOptionalInjection() {
Integer testInt = new Integer(123);
String testString = new String("abc");
Boolean testBoolean = new Boolean(true);
String testStringViaMethod = new String("abcd");
Object testObjectViaMethod = new Object();
// create context
IEclipseContext context = EclipseContextFactory.create();
// elements to be populated via fields
context.set("Integer", testInt);
context.set("string", testString); // this checks capitalization as well
context.set("Boolean", testBoolean);
// elements to be populated via methods
context.set("StringViaMethod", testStringViaMethod);
context.set("objectViaMethod", testObjectViaMethod); // this checks capitalization as well
ObjectWithAnnotations userObject = new ObjectWithAnnotations();
ContextInjectionFactory.inject(userObject, context);
// check field injection
assertEquals(testString, userObject.getString());
assertEquals(testInt, userObject.getInteger());
assertEquals(context, userObject.getContext());
// check method injection
assertEquals(1, userObject.setStringCalled);
assertEquals(1, userObject.setObjectCalled);
assertEquals(testStringViaMethod, userObject.getStringViaMethod());
assertEquals(testObjectViaMethod, userObject.getObjectViaMethod());
// check that no extra injections are done
assertNull(userObject.diMissing);
assertNull(userObject.myMissing);
assertEquals(0, userObject.setMissingCalled);
// check incompatible types
assertNull(userObject.diBoolean);
assertNull(userObject.myBoolean);
assertEquals(0, userObject.setBooleanCalled);
// check incompatible types
assertNull(userObject.diBoolean);
assertNull(userObject.myBoolean);
assertEquals(0, userObject.setBooleanCalled);
// check post processing
assertTrue(userObject.isFinalized());
}
/**
* Tests that a setter overridden from a superclass is only invoked once.
*/
public void testOverriddenSetter() {
IEclipseContext context = EclipseContextFactory.create();
context.set("OverriddenMethod", new Object());
context.set("StringViaMethod", "");
context.set("ObjectViaMethod", new Object());
ObjectSubClass userObject = new ObjectSubClass();
ContextInjectionFactory.inject(userObject, context);
assertEquals(1, userObject.getOverriddenCount());
context.set("OverriddenMethod", new Object());
assertEquals(2, userObject.getOverriddenCount());
}
public void testPostConstruct() {
class Injected {
int postConstructCalled = 0;
int setMethodCalled = 0;
@SuppressWarnings("unused")
@PostConstruct
public void init() {
postConstructCalled++;
}
@SuppressWarnings("unused")
@In
public void setInjectedMethod(Object arg) {
setMethodCalled++;
}
}
IEclipseContext context = EclipseContextFactory.create();
Object methodValue = new Object();
context.set("injectedMethod", methodValue);
Injected object = new Injected();
ContextInjectionFactory.inject(object, context);
assertEquals(1, object.setMethodCalled);
assertEquals(1, object.postConstructCalled);
context.set("injectedMethod", "AnotherValue");
assertEquals(2, object.setMethodCalled);
assertEquals(1, object.postConstructCalled);
}
/**
* Tests that post-construct methods are always called after all setters have been called
*/
public void testPostConstructAfterSetters() {
IEclipseContext context = EclipseContextFactory.create();
context.set("OverriddenMethod", new Object());
context.set("StringViaMethod", "");
context.set("ObjectViaMethod", new Object());
ObjectSubClass userObject = new ObjectSubClass();
ContextInjectionFactory.inject(userObject, context);
assertEquals(1, userObject.postConstructSetObjectCalled);
assertEquals(1, userObject.postConstructSetStringCalled);
assertEquals(1, userObject.postConstructSetOverriddenCalled);
}
}