package org.robolectric.shadows;

import android.os.Binder;
import android.os.Parcel;
import android.os.RemoteException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.TestRunners;

import static junit.framework.Assert.assertTrue;
import static org.assertj.core.api.Assertions.assertThat;

@RunWith(TestRunners.MultiApiWithDefaults.class)
public class ShadowBinderTest {
  @Test
  public void transactCallsOnTransact() throws Exception {
    TestBinder testBinder = new TestBinder();
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    data.writeString("Hello Robolectric");
    assertTrue(testBinder.transact(2, data, reply, 3));
    assertThat(testBinder.code).isEqualTo(2);
    assertThat(testBinder.data).isSameAs(data);
    assertThat(testBinder.reply).isSameAs(reply);
    assertThat(testBinder.flags).isEqualTo(3);
    assertThat(reply.readString()).isEqualTo("Hello Robolectric");
  }

  static class TestBinder extends Binder {
    int code;
    Parcel data;
    Parcel reply;
    int flags;

    @Override
    protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
      this.code = code;
      this.data = data;
      this.reply = reply;
      this.flags = flags;
      String string = data.readString();
      reply.writeString(string);
      return true;
    }
  }

  @Test
  public void testSetCallingUid() {
    ShadowBinder.setCallingUid(37);
    assertThat(Binder.getCallingUid()).isEqualTo(37);
  }

  @Test
  public void testSetCallingPid() {
    ShadowBinder.setCallingPid(25);
    assertThat(Binder.getCallingPid()).isEqualTo(25);
  }

  @Test
  public void testGetCallingUidShouldUseProcessUidByDefault() {
    assertThat(Binder.getCallingUid()).isEqualTo(android.os.Process.myUid());
  }

  @Test
  public void testGetCallingPidShouldUseProcessPidByDefault() {
    assertThat(Binder.getCallingPid()).isEqualTo(android.os.Process.myPid());
  }

  @Test
  public void testResetUpdatesCallingUidAndPid() {
    ShadowBinder.setCallingPid(48);
    ShadowBinder.setCallingUid(49);
    ShadowBinder.reset();
    assertThat(Binder.getCallingPid()).isEqualTo(android.os.Process.myPid());
    assertThat(Binder.getCallingUid()).isEqualTo(android.os.Process.myUid());
  }
}

@@ -256,16 +256,59 @@
 rtTrue;%0A
+import static junit.framework.Assert.fail;%0A
 import s
@@ -357,16 +357,16 @@
 rtThat;%0A
-
 %0A@RunWit
@@ -913,16 +913,43 @@
 lTo(3);%0A
+    reply.readException();%0A
     asse
@@ -1377,24 +1377,56 @@
 adString();%0A
+      reply.writeNoException();%0A
       reply.
@@ -1446,16 +1446,16 @@
 tring);%0A
-
       re
@@ -1472,24 +1472,712 @@
 %0A    %7D%0A  %7D%0A%0A
+  @Test%0A  public void transactCallsOnTransact() throws Exception %7B%0A    TestThrowingBinder testThrowingBinder = new TestThrowingBinder();%0A    Parcel data = Parcel.obtain();%0A    Parcel reply = Parcel.obtain();%0A    testThrowingBinder.transact(2, data, reply, 3);%0A    try %7B%0A      reply.readException();%0A      fail();  // Expect thrown%0A    %7D catch (SecurityException e) %7B%0A      assertThat(e.getMessage).isEqualTo(%22Halt! Who goes there?%22);%0A    %7D%0A  %7D%0A%0A  static class TestThrowingBinder extends Binder %7B%0A%0A    @Override%0A    protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException %7B%0A      throw new SecurityException(%22Halt! Who goes there?%22);%0A    %7D%0A  %7D%0A%0A
   @Test%0A  pu

Test parceling of exceptions across Binder