PageRenderTime 30ms CodeModel.GetById 2ms app.highlight 22ms RepoModel.GetById 2ms app.codeStats 0ms

/interpreter/tags/at2dist220411/test/edu/vub/at/objects/natives/LexicalRootTest.java

http://ambienttalk.googlecode.com/
Java | 185 lines | 96 code | 29 blank | 60 comment | 0 complexity | ccfa33221712d8c0a078184d07622fec MD5 | raw file
  1package edu.vub.at.objects.natives;
  2
  3import edu.vub.at.AmbientTalkTest;
  4import edu.vub.at.eval.Evaluator;
  5import edu.vub.at.exceptions.InterpreterException;
  6import edu.vub.at.exceptions.XImportConflict;
  7import edu.vub.at.objects.natives.grammar.AGBegin;
  8import edu.vub.at.objects.natives.grammar.AGImport;
  9import edu.vub.at.objects.natives.grammar.AGSelf;
 10import edu.vub.at.objects.natives.grammar.AGSymbol;
 11
 12/**
 13 * @author tvcutsem
 14 *
 15 * The unit test LexicalRootTest tests globally visible methods in the lexical root.
 16 * 
 17 * TODO: finish me
 18 */
 19public class LexicalRootTest extends AmbientTalkTest {
 20
 21	public static void main(String[] args) {
 22		junit.swingui.TestRunner.run(LexicalRootTest.class);
 23	}
 24	
 25	//private OBJLexicalRoot root_ = (OBJLexicalRoot) OBJLexicalRoot.getGlobalLexicalScope().lexicalParent_;
 26	
 27	public void testLexicalRootFields() {
 28		evalAndCompareTo("nil", Evaluator.getNil());
 29		evalAndCompareTo("true", NATBoolean._TRUE_);
 30		evalAndCompareTo("false", NATBoolean._FALSE_);
 31		evalAndCompareTo("/", Evaluator.getLobbyNamespace());
 32	}
 33
 34	private NATObject trait_;
 35	
 36	public static final AGSymbol atX_ = AGSymbol.jAlloc("x");
 37	public static final AGSymbol atM_ = AGSymbol.jAlloc("m");
 38	public static final AGSymbol atN_ = AGSymbol.jAlloc("n");
 39	
 40	/**
 41	 * Initialize the trait used for testing import:
 42	 * 
 43	 * def parent := object: { def n() { nil }; def m() { nil } }
 44	 * def trait := extend: parent with: {
 45	 *   def x := 0;
 46	 *   def m() { self }
 47	 * }
 48	 */
 49	public void setUp() throws Exception {
 50		super.setUp();
 51		NATObject parent = new NATObject();
 52		parent.meta_addMethod(new NATMethod(atN_, NATTable.EMPTY, new AGBegin(NATTable.of(Evaluator.getNil())), NATTable.EMPTY));
 53		parent.meta_addMethod(new NATMethod(atM_, NATTable.EMPTY, new AGBegin(NATTable.of(Evaluator.getNil())), NATTable.EMPTY));
 54		trait_ = new NATObject(parent, Evaluator.getGlobalLexicalScope(), NATObject._IS_A_);
 55		trait_.meta_defineField(atX_, NATNumber.ZERO);
 56		trait_.meta_addMethod(new NATMethod(atM_,
 57				                            NATTable.EMPTY,
 58				                            new AGBegin(NATTable.of(AGSelf._INSTANCE_)), NATTable.EMPTY));
 59	}
 60	
 61	/**
 62	 * Tests whether a basic import of fields and methods from a
 63	 * 'trait' object into a 'host' object works properly.
 64	 */
 65	public void testBasicImport() throws InterpreterException {
 66		// def host := object: { def test() { x } }
 67		NATObject host = new NATObject();
 68		AGSymbol atTest = AGSymbol.jAlloc("test");
 69		// test method accesses 'x' unqualified
 70		host.meta_addMethod(new NATMethod(atTest, NATTable.EMPTY,
 71				                  new AGBegin(NATTable.of(atX_)), NATTable.EMPTY));
 72		
 73		// < import trait > . eval(ctx[lex=host;self=host])
 74		new AGImport(trait_, NATTable.EMPTY, NATTable.EMPTY).meta_eval(new NATContext(host, host));
 75		
 76		// check whether host contains the appropriate fields and methods of the traits
 77		assertTrue(host.meta_respondsTo(atX_).asNativeBoolean().javaValue);
 78		assertTrue(host.meta_respondsTo(atM_).asNativeBoolean().javaValue);
 79		
 80		// check whether the methods and fields of the parents of traits are also present
 81		assertTrue(host.meta_respondsTo(atN_).asNativeBoolean().javaValue);
 82		
 83		// ensure that 'self' is correctly late bound to host when invoking m()
 84		assertEquals(host, host.impl_invoke(host, atM_, NATTable.EMPTY));
 85		// when invoking m() directly on the trait, self should be bound to the trait
 86		assertEquals(trait_, trait_.impl_invoke(trait_, atM_, NATTable.EMPTY));
 87		
 88		// when someone delegates m() to host, the trait's self should be bound to the original delegator
 89		NATObject delegator = new NATObject();
 90		assertEquals(delegator, host.impl_invoke(delegator, atM_, NATTable.EMPTY));
 91		
 92		// ensure that when invoking test() on host, it can access x unqualified
 93		assertEquals(NATNumber.ZERO, host.impl_invoke(host, atTest, NATTable.EMPTY));
 94		
 95		// when assigning x in host, trait's x field should not be modified
 96		host.impl_invoke(host, atX_.asAssignmentSymbol(), NATTable.of(NATNumber.ONE));
 97		assertEquals(NATNumber.ZERO, trait_.impl_invokeAccessor(trait_, atX_, NATTable.EMPTY));
 98		
 99		// host's primitive methods should be left untouched, i.e.
100		// host != trait and host == host
101		assertTrue(host.impl_invoke(host, NATNil._EQL_NAME_, NATTable.of(host)).asNativeBoolean().javaValue);
102		assertFalse(host.impl_invoke(host, NATNil._EQL_NAME_, NATTable.of(trait_)).asNativeBoolean().javaValue);
103	}
104	
105	/**
106	 * Tests whether conflicts are successfully detected.
107	 */
108	public void testConflictingImport() throws InterpreterException {
109		NATObject host = new NATObject();
110		
111		// host defines x itself, so import should fail
112		host.meta_defineField(atX_, NATNumber.ONE);
113		
114		try {
115			// < import trait > . eval(ctx[lex=host;self=host])
116			new AGImport(trait_, NATTable.EMPTY, NATTable.EMPTY).meta_eval(new NATContext(host, host));
117			fail("Expected an XImportConflict exception");
118		} catch (XImportConflict e) {
119			assertEquals(atX_, e.getConflictingNames().base_at(NATNumber.ONE));
120		}
121	}
122	
123	/**
124	 * Tests whether traits can be transitively imported into objects.
125	 */
126	public void testTransitiveImport() throws InterpreterException {
127		NATObject hostA = new NATObject();
128		NATObject hostB = new NATObject();
129		// < import trait > . eval(ctx[lex=hostA;self=hostA])
130		new AGImport(trait_, NATTable.EMPTY, NATTable.EMPTY).meta_eval(new NATContext(hostA, hostA));
131		// < import trait > . eval(ctx[lex=hostB;self=hostB])
132		new AGImport(trait_, NATTable.EMPTY, NATTable.EMPTY).meta_eval(new NATContext(hostB, hostB));
133		
134		// check whether m() can be invoked from hostB and that self equals hostB
135		assertEquals(hostB, hostB.impl_invoke(hostB, atM_, NATTable.EMPTY));
136	}
137	
138	/**
139	 * Tests whether aliasing works properly.
140	 */
141	public void testImportAndAliasing() throws InterpreterException {
142		NATObject host = new NATObject();
143		AGSymbol foo = AGSymbol.jAlloc("foo");
144		NATTable alias = NATTable.of(NATTable.of(atM_, foo)); // [[m,foo]]
145		// < import trait alias m := foo > . eval(ctx[lex=host;self=host])
146		new AGImport(trait_, alias, NATTable.EMPTY).meta_eval(new NATContext(host, host));
147		
148		// check whether m() can be invoked as foo()
149		assertTrue(host.meta_respondsTo(foo).asNativeBoolean().javaValue);
150		assertEquals(host, host.impl_invoke(host, foo, NATTable.EMPTY));
151	}
152	
153	/**
154	 * Tests whether exclusion works properly.
155	 */
156	public void testImportAndExclusion() throws InterpreterException {
157		NATObject host = new NATObject();
158		NATTable exclude = NATTable.of(atN_);
159		// < import trait exclude n > . eval(ctx[lex=host;self=host])
160		new AGImport(trait_, NATTable.EMPTY, exclude).meta_eval(new NATContext(host, host));
161		
162		// check whether m is present and n is not present
163		assertTrue(host.meta_respondsTo(atM_).asNativeBoolean().javaValue);
164		assertFalse(host.meta_respondsTo(atN_).asNativeBoolean().javaValue);
165	}
166	
167	/**
168	 * Tests whether aliasing and exclusion work properly together.
169	 */
170	public void testImportAndAliasingAndExclusion() throws InterpreterException {
171		NATObject host = new NATObject();
172		AGSymbol foo = AGSymbol.jAlloc("foo");
173		NATTable alias = NATTable.of(NATTable.of(atM_, foo)); // [[m,foo]]
174		NATTable exclude = NATTable.of(atN_);
175		// < import trait alias m := foo exclude n> . eval(ctx[lex=host;self=host])
176		new AGImport(trait_, alias, exclude).meta_eval(new NATContext(host, host));
177		
178		// check whether m() can be invoked as foo()
179		assertTrue(host.meta_respondsTo(foo).asNativeBoolean().javaValue);
180		assertEquals(host, host.impl_invoke(host, foo, NATTable.EMPTY));
181		
182		// check whether n is not present
183		assertFalse(host.meta_respondsTo(atN_).asNativeBoolean().javaValue);
184	}
185}