blob: 16307740440a5b308ce6c0f14950807dee08c0ac [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2010 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.internal.tests.contexts.inject;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
import javax.inject.Named;
import junit.framework.AssertionFailedError;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.eclipse.e4.core.contexts.ContextInjectionFactory;
import org.eclipse.e4.core.contexts.EclipseContextFactory;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.di.annotations.Execute;
import org.eclipse.e4.core.di.annotations.Optional;
/**
* Tests for the basic context injection functionality
*/
public class AnnotationsInjectionTest extends TestCase {
public static Test suite() {
return new TestSuite(AnnotationsInjectionTest.class);
}
public AnnotationsInjectionTest() {
super();
}
public AnnotationsInjectionTest(String name) {
super(name);
}
public void testContextSetOneArg() {
class TestData {
// empty
}
class Injected {
int contextSetCalled = 0;
int setMethodCalled = 0;
public TestData value;
@SuppressWarnings("unused")
@Inject
public void settings(IEclipseContext context) {
contextSetCalled++;
}
@SuppressWarnings("unused")
@Inject
public void injectedMethod(@Named("testing123") TestData arg) {
setMethodCalled++;
value = arg;
}
}
IEclipseContext context = EclipseContextFactory.create();
TestData methodValue = new TestData();
context.set("testing123", methodValue);
Injected object = new Injected();
ContextInjectionFactory.inject(object, context);
assertEquals(1, object.setMethodCalled);
assertEquals(1, object.contextSetCalled);
TestData methodValue2 = new TestData();
context.set("testing123", methodValue2);
assertEquals(2, object.setMethodCalled);
assertEquals(methodValue2, object.value);
assertEquals(1, object.contextSetCalled);
}
public void testPostConstruct() {
class TestData {
// empty
}
class Injected {
int postConstructCalled = 0;
int setMethodCalled = 0;
public TestData value;
@SuppressWarnings("unused")
@PostConstruct
public void init() {
postConstructCalled++;
}
@SuppressWarnings("unused")
@Inject
public void setData(TestData arg) {
setMethodCalled++;
value = arg;
}
}
IEclipseContext context = EclipseContextFactory.create();
TestData methodValue = new TestData();
context.set(TestData.class.getName(), methodValue);
Injected object = new Injected();
ContextInjectionFactory.inject(object, context);
assertEquals(1, object.setMethodCalled);
assertEquals(1, object.postConstructCalled);
TestData methodValue2 = new TestData();
context.set(TestData.class.getName(), methodValue2);
assertEquals(2, object.setMethodCalled);
assertEquals(1, object.postConstructCalled);
assertEquals(methodValue2, object.value);
}
/**
* Tests basic context injection
*/
public synchronized void testInjection() {
Integer testInt = new Integer(123);
String testString = new String("abc");
Double testDouble = new Double(1.23);
Float testFloat = new Float(12.3);
Character testChar = new Character('v');
// create context
IEclipseContext context = EclipseContextFactory.create();
context.set(Integer.class.getName(), testInt);
context.set(String.class.getName(), testString);
context.set(Double.class.getName(), testDouble);
context.set(Float.class.getName(), testFloat);
context.set(Character.class.getName(), testChar);
ObjectBasic userObject = new ObjectBasic();
ContextInjectionFactory.inject(userObject, context);
// check field injection
assertEquals(testString, userObject.injectedString);
assertEquals(testInt, userObject.getInt());
assertEquals(context, userObject.context);
// check method injection
assertEquals(1, userObject.setMethodCalled);
assertEquals(1, userObject.setMethodCalled2);
assertEquals(testDouble, userObject.d);
assertEquals(testFloat, userObject.f);
assertEquals(testChar, userObject.c);
// check post processing
assertTrue(userObject.finalized);
}
/**
* Tests that fields are injected before methods.
*/
public void testFieldMethodOrder() {
final AssertionFailedError[] error = new AssertionFailedError[1];
class TestData {
// empty
}
class Injected {
@Inject @Named("valueField")
Object injectedField;
Object methodValue;
@SuppressWarnings("unused")
@Inject
public void injectedMethod(@Optional @Named("valueMethod") Object arg) {
try {
assertTrue(injectedField != null);
} catch (AssertionFailedError e) {
error[0] = e;
}
methodValue = arg;
}
}
IEclipseContext context = EclipseContextFactory.create();
TestData fieldValue = new TestData();
TestData methodValue = new TestData();
context.set("valueField", fieldValue);
context.set("valueMethod", 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("valueMethod");
if (error[0] != null)
throw error[0];
assertEquals(fieldValue, object.injectedField);
assertNull(object.methodValue);
context.dispose();
if (error[0] != null)
throw error[0];
}
public void testOptionalInjection() {
Integer testInt = new Integer(123);
IEclipseContext context = EclipseContextFactory.create();
context.set(Integer.class.getName(), testInt);
OptionalAnnotations userObject = new OptionalAnnotations();
ContextInjectionFactory.inject(userObject, context);
assertEquals(0, userObject.methodOptionalCalled);
assertEquals(1, userObject.methodRequiredCalled);
assertEquals(testInt, userObject.i);
assertNull(userObject.s);
assertNull(userObject.d);
assertNull(userObject.f);
// add optional services
String testString = new String("abc");
Double testDouble = new Double(1.23);
Float testFloat = new Float(12.3);
context.set(String.class.getName(), testString);
context.set(Double.class.getName(), testDouble);
context.set(Float.class.getName(), testFloat);
assertEquals(1, userObject.methodOptionalCalled);
assertEquals(2, userObject.methodRequiredCalled);
assertEquals(testInt, userObject.i);
assertEquals(testString, userObject.s);
assertEquals(testDouble, userObject.d);
assertEquals(testFloat, userObject.f);
}
public void testOptionalInvoke() {
class TestObject {
public int called = 0;
@SuppressWarnings("unused")
@Execute
public String something(@Optional String param) {
called++;
return param;
}
}
IEclipseContext context = EclipseContextFactory.create();
Object notAnObject = new Object();
TestObject testObject = new TestObject();
context.set(String.class.getName(), testObject);
Object result = ContextInjectionFactory.invoke(testObject, Execute.class, context, notAnObject);
assertNull(result);
assertEquals(1, testObject.called);
String string = "sample";
context.set(String.class.getName(), string);
result = ContextInjectionFactory.invoke(testObject, Execute.class, context, notAnObject);
assertEquals(string, result);
assertEquals(2, testObject.called);
}
/**
* Tests that a class with multiple inherited post-construct / pre-destroy methods.
*/
public void testInheritedSpecialMethods() {
IEclipseContext context = EclipseContextFactory.create();
context.set(Integer.class.getName(), new Integer(123));
context.set(String.class.getName(), new String("abc"));
context.set(Float.class.getName(), new Float(12.3));
ObjectSubClass userObject = new ObjectSubClass();
ContextInjectionFactory.inject(userObject, context);
assertEquals(1, userObject.superPostConstructCount);
assertEquals(1, userObject.subPostConstructCount);
assertEquals(0, userObject.superPreDestroyCount);
assertEquals(0, userObject.subPreDestroyCount);
assertEquals(0, userObject.overriddenPreDestroyCount);
context.set(Float.class.getName(), new Float(45.6));
assertEquals(1, userObject.superPostConstructCount);
assertEquals(1, userObject.subPostConstructCount);
assertEquals(0, userObject.superPreDestroyCount);
assertEquals(0, userObject.subPreDestroyCount);
assertEquals(0, userObject.overriddenPreDestroyCount);
context.dispose();
assertEquals(1, userObject.superPreDestroyCount);
assertEquals(1, userObject.subPreDestroyCount);
assertEquals(1, userObject.overriddenPreDestroyCount);
}
public void testInvoke() {
class TestData {
public String value;
public TestData(String tmp) {
value = tmp;
}
}
class Injected {
public String myString;
public Injected() {
// placeholder
}
@SuppressWarnings("unused")
@Execute
public String something(@Named("testing123") TestData data) {
myString = data.value;
return "true";
}
}
IEclipseContext context = EclipseContextFactory.create();
TestData methodValue = new TestData("abc");
context.set("testing123", methodValue);
Injected object = new Injected();
assertNull(object.myString);
assertEquals("true", ContextInjectionFactory.invoke(object, Execute.class, context, null));
assertEquals("abc", object.myString);
}
public void testPreDestroy() {
class TestData {
// empty
}
class Injected {
int preDestoryCalled = 0;
public TestData value;
@Inject
public TestData directFieldInjection;
@SuppressWarnings("unused")
@PreDestroy
public void aboutToClose() {
preDestoryCalled++;
assertNotNull(value);
assertNotNull(directFieldInjection);
}
@SuppressWarnings("unused")
@Inject
public void setData(TestData arg) {
value = arg;
}
}
IEclipseContext context = EclipseContextFactory.create();
TestData methodValue = new TestData();
context.set(TestData.class.getName(), methodValue);
Injected object = new Injected();
ContextInjectionFactory.inject(object, context);
assertNotNull(object.value);
assertNotNull(object.directFieldInjection);
context.dispose();
assertEquals(1, object.preDestoryCalled);
assertNotNull(object.value);
assertNotNull(object.directFieldInjection);
}
}