Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright (C) 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.os.cts;
     18 
     19 import android.app.ActivityManager;
     20 import android.content.ComponentName;
     21 import android.content.Context;
     22 import android.content.Intent;
     23 import android.content.ServiceConnection;
     24 import android.os.IBinder;
     25 import android.os.ParcelFileDescriptor;
     26 import android.os.RemoteException;
     27 import android.os.SystemClock;
     28 import android.test.AndroidTestCase;
     29 
     30 import com.google.common.util.concurrent.AbstractFuture;
     31 
     32 import junit.framework.ComparisonFailure;
     33 
     34 import java.util.concurrent.ExecutionException;
     35 import java.util.concurrent.TimeUnit;
     36 import java.util.concurrent.TimeoutException;
     37 
     38 /**
     39  * Test various cross-process {@link ParcelFileDescriptor} interactions.
     40  */
     41 public class ParcelFileDescriptorProcessTest extends AndroidTestCase {
     42 
     43     private Intent redIntent;
     44     private Intent blueIntent;
     45     private PeerConnection redConn;
     46     private PeerConnection blueConn;
     47     private IParcelFileDescriptorPeer red;
     48     private IParcelFileDescriptorPeer blue;
     49 
     50     public static class PeerConnection extends AbstractFuture<IParcelFileDescriptorPeer>
     51             implements ServiceConnection {
     52         @Override
     53         public void onServiceConnected(ComponentName name, IBinder service) {
     54             set(IParcelFileDescriptorPeer.Stub.asInterface(service));
     55         }
     56 
     57         @Override
     58         public void onServiceDisconnected(ComponentName name) {
     59         }
     60 
     61         @Override
     62         public IParcelFileDescriptorPeer get() throws InterruptedException, ExecutionException {
     63             try {
     64                 return get(5, TimeUnit.SECONDS);
     65             } catch (TimeoutException e) {
     66                 throw new RuntimeException(e);
     67             }
     68         }
     69     }
     70 
     71     private static void assertContains(String expected, String actual) {
     72         if (actual.contains(expected)) return;
     73         throw new ComparisonFailure("", expected, actual);
     74     }
     75 
     76     private static void crash(IParcelFileDescriptorPeer peer) {
     77         try {
     78             peer.crash();
     79         } catch (RemoteException e) {
     80         }
     81         SystemClock.sleep(500);
     82     }
     83 
     84     @Override
     85     protected void setUp() throws Exception {
     86         super.setUp();
     87         final Context context = getContext();
     88 
     89         // Bring up both remote processes and wire them to each other
     90         redIntent = new Intent();
     91         redIntent.setComponent(new ComponentName(
     92                 "android.os.cts", "android.os.cts.ParcelFileDescriptorPeer$Red"));
     93         blueIntent = new Intent();
     94         blueIntent.setComponent(new ComponentName(
     95                 "android.os.cts", "android.os.cts.ParcelFileDescriptorPeer$Blue"));
     96         redConn = new PeerConnection();
     97         blueConn = new PeerConnection();
     98         context.startService(redIntent);
     99         context.startService(blueIntent);
    100         getContext().bindService(redIntent, redConn, 0);
    101         getContext().bindService(blueIntent, blueConn, 0);
    102         red = redConn.get();
    103         blue = blueConn.get();
    104         red.setPeer(blue);
    105         blue.setPeer(red);
    106     }
    107 
    108     @Override
    109     protected void tearDown() throws Exception {
    110         super.tearDown();
    111 
    112         final Context context = getContext();
    113         context.unbindService(redConn);
    114         context.unbindService(blueConn);
    115         context.stopService(redIntent);
    116         context.stopService(blueIntent);
    117 
    118         final ActivityManager am = (ActivityManager) mContext.getSystemService(
    119                 Context.ACTIVITY_SERVICE);
    120         am.killBackgroundProcesses(context.getPackageName());
    121     }
    122 
    123     public void testPullPipeNormal() throws Exception {
    124         // red <-- blue
    125         red.setupReadPipe();
    126         blue.doGet();
    127 
    128         blue.write(1);
    129         assertEquals(1, red.read());
    130 
    131         blue.close();
    132         assertEquals(-1, red.read());
    133         assertEquals(null, red.checkError());
    134     }
    135 
    136     public void testPushPipeNormal() throws Exception {
    137         // red --> blue
    138         red.setupWritePipe();
    139         red.doSet();
    140 
    141         red.write(2);
    142         assertEquals(2, blue.read());
    143 
    144         red.close();
    145         assertEquals(-1, blue.read());
    146         assertEquals(null, blue.checkError());
    147     }
    148 
    149     public void testPipeWriterError() throws Exception {
    150         // red --> blue
    151         red.setupWritePipe();
    152         red.doSet();
    153 
    154         red.write(3);
    155         red.closeWithError("OMG MUFFINS");
    156 
    157         // even though closed we should still drain pipe
    158         assertEquals(3, blue.read());
    159         assertEquals(-1, blue.read());
    160         assertContains("OMG MUFFINS", blue.checkError());
    161     }
    162 
    163     public void testPipeWriterCrash() throws Exception {
    164         // red --> blue
    165         red.setupWritePipe();
    166         blue.doGet();
    167 
    168         red.write(4);
    169         crash(red);
    170 
    171         // even though dead we should still drain pipe
    172         assertEquals(4, blue.read());
    173         assertEquals(-1, blue.read());
    174         assertContains("Remote side is dead", blue.checkError());
    175     }
    176 
    177     public void testSocketCrash() throws Exception {
    178         // red <--> blue
    179         red.setupSocket();
    180         blue.doGet();
    181 
    182         red.write(5);
    183         blue.write(6);
    184 
    185         assertEquals(5, blue.read());
    186         crash(blue);
    187         assertEquals(6, red.read());
    188         assertEquals(-1, red.read());
    189         assertContains("Remote side is dead", red.checkError());
    190     }
    191 
    192     public void testFileNormal() throws Exception {
    193         red.setupFile();
    194         blue.doGet();
    195 
    196         blue.write(7);
    197         blue.close();
    198 
    199         // make sure red heard us finish
    200         assertEquals("null", red.checkListener());
    201     }
    202 
    203     public void testFileError() throws Exception {
    204         red.setupFile();
    205         blue.doGet();
    206 
    207         blue.write(8);
    208         blue.closeWithError("OMG BANANAS");
    209 
    210         // make sure red heard us error
    211         assertContains("OMG BANANAS", red.checkListener());
    212     }
    213 
    214     public void testFileCrash() throws Exception {
    215         red.setupFile();
    216         blue.doGet();
    217 
    218         blue.write(9);
    219         crash(blue);
    220 
    221         // make sure red heard us die
    222         assertContains("Remote side is dead", red.checkListener());
    223     }
    224 
    225     public void testFileDetach() throws Exception {
    226         red.setupFile();
    227         blue.doGet();
    228         blue.detachFd();
    229 
    230         // make sure red heard us detach
    231         assertContains("DETACHED", red.checkListener());
    232     }
    233 
    234     public void testFileLeak() throws Exception {
    235         red.setupFile();
    236         blue.doGet();
    237         blue.leak();
    238 
    239         // make sure red heard us get leaked
    240         assertContains("leaked", red.checkListener());
    241     }
    242 
    243     public void testSocketErrorAfterClose() throws Exception {
    244         // red <--> blue
    245         red.setupSocket();
    246         blue.doGet();
    247 
    248         // both sides throw their hands in the air
    249         blue.closeWithError("BLUE RAWR");
    250         red.closeWithError("RED RAWR");
    251 
    252         // red noticed the blue error, but after that the comm pipe was dead so
    253         // blue had no way of seeing the red error.
    254         assertContains("BLUE RAWR", red.checkError());
    255         assertNull(blue.checkError());
    256     }
    257 
    258     public void testSocketDeathBeforeClose() throws Exception {
    259         // red <--> blue
    260         red.setupSocket();
    261         blue.doGet();
    262 
    263         crash(blue);
    264         assertContains("Remote side is dead", red.checkError());
    265         red.close();
    266     }
    267 
    268     public void testSocketDeathAfterClose() throws Exception {
    269         // red <--> blue
    270         red.setupSocket();
    271         blue.doGet();
    272 
    273         crash(blue);
    274         red.close();
    275         assertContains("Remote side is dead", red.checkError());
    276     }
    277 
    278     public void testSocketMultipleCheck() throws Exception {
    279         // red <--> blue
    280         red.setupSocket();
    281         blue.doGet();
    282 
    283         // allow checking before closed
    284         assertNull(blue.checkError());
    285         assertNull(blue.checkError());
    286         assertNull(blue.checkError());
    287 
    288         // and verify we actually see it
    289         red.closeWithError("RAWR RED");
    290         assertContains("RAWR RED", blue.checkError());
    291     }
    292 
    293     public void testSocketGiantError() throws Exception {
    294         // red <--> blue
    295         red.setupSocket();
    296         blue.doGet();
    297 
    298         final StringBuilder builder = new StringBuilder();
    299         for (int i = 0; i < 1024; i++) {
    300             builder.append(i).append(",");
    301         }
    302         final String msg = builder.toString();
    303         red.closeWithError(msg);
    304 
    305         // we should at least see the first 512 chars
    306         assertContains(msg.substring(0, 512), blue.checkError());
    307     }
    308 }
    309