PageRenderTime 7ms CodeModel.GetById 2ms app.highlight 3ms RepoModel.GetById 1ms app.codeStats 0ms

/interpreter/tags/at2-build270707/test/edu/vub/at/objects/symbiosis/CoercionTest.java

http://ambienttalk.googlecode.com/
Java | 98 lines | 51 code | 14 blank | 33 comment | 0 complexity | 1f83abc5af4aa50554ec5dceadf2c3ba MD5 | raw file
 1/**
 2 * 
 3 */
 4package edu.vub.at.objects.symbiosis;
 5
 6import edu.vub.at.AmbientTalkTest;
 7import edu.vub.at.exceptions.InterpreterException;
 8import edu.vub.at.objects.ATObject;
 9import edu.vub.at.objects.ATTable;
10import edu.vub.at.objects.base.BaseClosure;
11import edu.vub.at.objects.coercion.Coercer;
12import edu.vub.at.objects.natives.NATNumber;
13import edu.vub.at.objects.natives.NATTable;
14import edu.vub.at.objects.natives.OBJNil;
15import edu.vub.at.objects.natives.grammar.AGSymbol;
16
17/**
18 * Tests the coercion of both objects and native data types to an interface. The use of coercion is required not
19 * only to absorb AmbientTalk objects and use them instead of native types (i.e. passing an object with at and 
20 * atPut methods where a table is expected) but is also used to ensure the proper use of AmbientTalk objects 
21 * which are passed outside their enclosing actor and handed to another Java thread.
22 * 
23 * @author smostinc
24 */
25public class CoercionTest extends AmbientTalkTest {
26
27	public static void main(String[] args) {
28		junit.swingui.TestRunner.run(CoercionTest.class);
29	}
30	
31	/** 
32	 * Tests the coercion of an AmbientTalk object which is to be used as a native table type.
33	 */
34	public void testTypeCoercion() throws InterpreterException {
35		ATObject cubbyhole = evalAndReturn(
36				"def cubbyhole := object: { \n" +
37				"  def content := nil; \n" +
38				"  def at(i) { \n" +
39				"    if: (i = 1) then: { content } else: { `error }; \n" +
40				"  }; \n" +
41				"  def atPut(i, val) { \n" +
42				"    if: (i = 1) then: { content := val } else: { `error }; \n" +
43				"  }; \n" +
44				"} \n");
45		
46		// under normal circumstances the cubbyhole object would be implicitly coerced to a table once it is
47		// passed to a function which expects a table as an argument. Here we explicitly coerce by performing 
48		// such an invocation at the Java level.
49		
50		ATTable coercedCubbyhole = (ATTable)Coercer.coerce(cubbyhole, ATTable.class);
51		ATObject result = coercedCubbyhole.base_at(NATNumber.ONE);
52		
53		assertEquals(OBJNil._INSTANCE_, result);
54	}
55
56	/**
57	 * Tests the coercion of an AmbientTalk object onto a classical Java Interface for symbiotic use.
58	 * Such coercions typically happen when passing an AmbientTalk object to a Java method which expects 
59	 * a given interface. At that point in time the passed AmbientTalk object will be implictly coerced 
60	 * to the requested type. 
61	 */
62	public void testSymbioticCoercion() throws InterpreterException {
63		ATObject listener = evalAndReturn(
64			"def result := `error;" +
65			"def listener := object: { \n" +
66			"  def run() { result := `ok; }; \n" +
67			"}; \n");
68				
69		Runnable coercedListener = (Runnable)Coercer.coerce(listener, Runnable.class);
70		coercedListener.run();
71		
72		ATObject result = evalAndReturn("result");
73		assertEquals(AGSymbol.jAlloc("ok"), result);
74	}
75	
76	/**
77	 * Tests the coercion of an AmbientTalk native type onto a Java Interface corresponding to its base-level 
78	 * interface for symbiotic use. The reason to support this is that coercion ensures that invoking a method
79	 * respects the event loop concurrency properties of AmbientTalk actors. 
80	 * <p>
81	 * Hence, the difference between <closure:lambda>.base_apply([]) and <coercer on:<closure:lambda> >.apply([])
82	 * is that is the latter is called from a separate Java thread, it will schedule a message in the owning
83	 * actor's queue whereas the latter would proceed and thus activate a second thread within the boundaries
84	 * of a single actor.
85	 */
86	public void testSymbioticNativeCoercion() throws InterpreterException {
87		ATObject lambda = evalAndReturn(
88			"def result := `error;" +
89			"def lambda := { result := `ok; }; \n");
90		
91		
92		BaseClosure coercedListener = (BaseClosure)Coercer.coerce(lambda, BaseClosure.class);
93		coercedListener.apply(NATTable.EMPTY);
94		
95		ATObject result = evalAndReturn("result");
96		assertEquals(AGSymbol.jAlloc("ok"), result);
97	}
98}