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