Home | History | Annotate | Download | only in bytecode
      1 package com.xtremelabs.robolectric.bytecode;
      2 
      3 import javassist.ClassPool;
      4 import javassist.CtClass;
      5 import org.junit.Before;
      6 import org.junit.Test;
      7 
      8 import static org.junit.Assert.*;
      9 import static org.mockito.Matchers.any;
     10 import static org.mockito.Matchers.anyObject;
     11 import static org.mockito.Matchers.eq;
     12 import static org.mockito.Mockito.*;
     13 
     14 public class AndroidTranslatorUnitTest {
     15     private ClassPool classPool;
     16     private AndroidTranslator androidTranslator;
     17 
     18     @Before public void setUp() throws Exception {
     19         classPool = new ClassPool(true);
     20         androidTranslator = new AndroidTranslator(null, null);
     21     }
     22 
     23     @Test
     24     public void whenMethodReturnsObject_shouldGenerateMethodBody() throws Exception {
     25         CtClass ctClass = classPool.get("java.lang.String");
     26         String methodBody = androidTranslator.generateMethodBody(
     27                 ctClass, ctClass.getDeclaredMethod("substring", new CtClass[]{CtClass.intType}),
     28                 ctClass, Type.OBJECT, false, false);
     29         assertEquals("if (!com.xtremelabs.robolectric.bytecode.RobolectricInternals.shouldCallDirectly(this)) {\n" +
     30                 "Object x = com.xtremelabs.robolectric.bytecode.RobolectricInternals.methodInvoked(\n" +
     31                 "  java.lang.String.class, \"substring\", this, new String[] {\"int\"}, new Object[] {com.xtremelabs.robolectric.bytecode.RobolectricInternals.autobox($1)});\n" +
     32                 "if (x != null) return ((java.lang.String) x);\n" +
     33                 "return null;\n" +
     34                 "}\n", methodBody);
     35     }
     36 
     37     @Test
     38     public void whenMethodReturnsPrimitive_shouldGenerateMethodBody() throws Exception {
     39         CtClass ctClass = classPool.get("java.lang.String");
     40         String methodBody = androidTranslator.generateMethodBody(
     41                 ctClass, ctClass.getDeclaredMethod("length"),
     42                 ctClass, Type.OBJECT, false, false);
     43         assertEquals("if (!com.xtremelabs.robolectric.bytecode.RobolectricInternals.shouldCallDirectly(this)) {\n" +
     44                 "Object x = com.xtremelabs.robolectric.bytecode.RobolectricInternals.methodInvoked(\n" +
     45                 "  java.lang.String.class, \"length\", this, new String[0], new Object[0]);\n" +
     46                 "if (x != null) return ((java.lang.String) x);\n" +
     47                 "return null;\n" +
     48                 "}\n", methodBody);
     49     }
     50 
     51     @Test
     52     public void whenMethodReturnsVoid_shouldGenerateMethodBody() throws Exception {
     53         CtClass ctClass = classPool.get("java.lang.Object");
     54         String methodBody = androidTranslator.generateMethodBody(
     55                 ctClass, ctClass.getDeclaredMethod("wait"),
     56                 ctClass, Type.VOID, false, false);
     57         assertEquals("if (!com.xtremelabs.robolectric.bytecode.RobolectricInternals.shouldCallDirectly(this)) {\n" +
     58                 "com.xtremelabs.robolectric.bytecode.RobolectricInternals.methodInvoked(\n" +
     59                 "  java.lang.Object.class, \"wait\", this, new String[] {\"long\"}, new Object[] {com.xtremelabs.robolectric.bytecode.RobolectricInternals.autobox($1)});\n" +
     60                 "return;\n" +
     61                 "}\n", methodBody);
     62     }
     63 
     64     @Test
     65     public void whenMethodIsStatic_shouldGenerateMethodBody() throws Exception {
     66         CtClass ctClass = classPool.get("java.lang.String");
     67         String methodBody = androidTranslator.generateMethodBody(
     68                 ctClass, ctClass.getDeclaredMethod("valueOf", new CtClass[]{CtClass.intType}),
     69                 ctClass, Type.OBJECT, true, false);
     70         assertEquals("if (!com.xtremelabs.robolectric.bytecode.RobolectricInternals.shouldCallDirectly(java.lang.String.class)) {\n" +
     71                 "Object x = com.xtremelabs.robolectric.bytecode.RobolectricInternals.methodInvoked(\n" +
     72                 "  java.lang.String.class, \"valueOf\", null, new String[] {\"int\"}, new Object[] {com.xtremelabs.robolectric.bytecode.RobolectricInternals.autobox($1)});\n" +
     73                 "if (x != null) return ((java.lang.String) x);\n" +
     74                 "return null;\n" +
     75                 "}\n", methodBody);
     76     }
     77 
     78     @Test
     79     public void shouldGenerateParameterList() throws Exception {
     80         assertEquals(androidTranslator.makeParameterReplacementList(0), "");
     81         assertEquals(androidTranslator.makeParameterReplacementList(1), "$1");
     82         assertEquals(androidTranslator.makeParameterReplacementList(2), "$1, $2");
     83     }
     84 
     85     @Test
     86     public void shouldGenerateMethodBodyForEquals() throws Exception {
     87         CtClass ctClass = classPool.get("java.lang.Object");
     88         String methodBody = androidTranslator.generateMethodBody(
     89                 ctClass, ctClass.getDeclaredMethod("equals", new CtClass[]{ctClass}),
     90                 ctClass, Type.BOOLEAN, false, true);
     91         assertEquals("if (!com.xtremelabs.robolectric.bytecode.RobolectricInternals.shouldCallDirectly(this)) {\n" +
     92                 "Object x = com.xtremelabs.robolectric.bytecode.RobolectricInternals.methodInvoked(\n" +
     93                 "  java.lang.Object.class, \"equals\", this, new String[] {\"java.lang.Object\"}, new Object[] {com.xtremelabs.robolectric.bytecode.RobolectricInternals.autobox($1)});\n" +
     94                 "if (x != null) return ((java.lang.Boolean) x).booleanValue();\n" +
     95                 "return super.equals($1);}\n", methodBody);
     96     }
     97 
     98     @Test
     99     public void shouldInstrumentDefaultRequestDirector() throws Exception {
    100         assertTrue(androidTranslator.shouldInstrument(classPool.makeClass("org.apache.http.impl.client.DefaultRequestDirector")));
    101     }
    102 
    103     @Test
    104     public void shouldInstrumentGoogleMapsClasses() throws Exception {
    105         assertTrue(androidTranslator.shouldInstrument(classPool.makeClass("com.google.android.maps.SomeMapsClass")));
    106     }
    107 
    108     @Test
    109     public void shouldNotInstrumentCoreJdkClasses() throws Exception {
    110         assertFalse(androidTranslator.shouldInstrument(classPool.get("java.lang.Object")));
    111         assertFalse(androidTranslator.shouldInstrument(classPool.get("java.lang.String")));
    112     }
    113 
    114     @Test
    115     public void shouldInstumentAndroidCoreClasses() throws Exception {
    116         assertTrue(androidTranslator.shouldInstrument(classPool.makeClass("android.content.Intent")));
    117         assertTrue(androidTranslator.shouldInstrument(classPool.makeClass("android.and.now.for.something.completely.different")));
    118 
    119     }
    120 
    121     @Test
    122     public void shouldNotInstrumentLocalBroadcastManager() throws Exception {
    123         assertFalse(androidTranslator.shouldInstrument(classPool.makeClass("android.support.v4.content.LocalBroadcastManager")));
    124     }
    125 
    126     @Test
    127     public void shouldAddCustomShadowClass() throws Exception {
    128         androidTranslator.addCustomShadowClass("my.custom.Klazz");
    129         assertTrue(androidTranslator.shouldInstrument(classPool.makeClass("my.custom.Klazz")));
    130     }
    131 
    132     @Test
    133     public void testOnLoadWithNonInstrumentedClass() throws Exception {
    134         ClassHandler handler = mock(ClassHandler.class);
    135         ClassCache cache = mock(ClassCache.class);
    136 
    137         AndroidTranslator translator = new AndroidTranslator(handler, cache);
    138 
    139         translator.onLoad(classPool, "java.lang.Object");
    140         verify(cache).isWriting();
    141         verifyNoMoreInteractions(cache);
    142         verifyZeroInteractions(handler);
    143     }
    144 
    145     @Test(expected = IllegalStateException.class)
    146     public void shouldThrowIllegalStateIfClassCacheIsWriting() throws Exception {
    147         ClassCache cache = mock(ClassCache.class);
    148         when(cache.isWriting()).thenReturn(true);
    149         new AndroidTranslator(null, cache).onLoad(classPool, "java.lang.Object");
    150     }
    151 }
    152