Home | History | Annotate | Download | only in mtp
      1 /*
      2  * Copyright (C) 2015 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 com.android.mtp;
     18 
     19 import android.os.ParcelFileDescriptor;
     20 import android.os.storage.StorageManager;
     21 import android.system.ErrnoException;
     22 import android.system.Os;
     23 import android.test.AndroidTestCase;
     24 import android.test.suitebuilder.annotation.MediumTest;
     25 
     26 import libcore.io.IoUtils;
     27 
     28 import java.io.File;
     29 import java.io.FileNotFoundException;
     30 import java.io.IOException;
     31 import java.util.Arrays;
     32 
     33 @MediumTest
     34 public class AppFuseTest extends AndroidTestCase {
     35     public void testMount() throws ErrnoException, IOException {
     36         final StorageManager storageManager = getContext().getSystemService(StorageManager.class);
     37         final AppFuse appFuse = new AppFuse("test", new TestCallback());
     38         appFuse.mount(storageManager);
     39         final File file = appFuse.getMountPoint();
     40         assertTrue(file.isDirectory());
     41         assertEquals(1, Os.stat(file.getPath()).st_ino);
     42         appFuse.close();
     43         assertTrue(1 != Os.stat(file.getPath()).st_ino);
     44     }
     45 
     46     public void testOpenFile() throws IOException {
     47         final StorageManager storageManager = getContext().getSystemService(StorageManager.class);
     48         final int INODE = 10;
     49         final AppFuse appFuse = new AppFuse(
     50                 "test",
     51                 new TestCallback() {
     52                     @Override
     53                     public long getFileSize(int inode) throws FileNotFoundException {
     54                         if (INODE == inode) {
     55                             return 1024;
     56                         }
     57                         throw new FileNotFoundException();
     58                     }
     59                 });
     60         appFuse.mount(storageManager);
     61         final ParcelFileDescriptor fd = appFuse.openFile(
     62                 INODE, ParcelFileDescriptor.MODE_READ_ONLY);
     63         fd.close();
     64         appFuse.close();
     65     }
     66 
     67     public void testOpenFile_fileNotFound() throws IOException {
     68         final StorageManager storageManager = getContext().getSystemService(StorageManager.class);
     69         final int INODE = 10;
     70         final AppFuse appFuse = new AppFuse("test", new TestCallback());
     71         appFuse.mount(storageManager);
     72         try {
     73             appFuse.openFile(INODE, ParcelFileDescriptor.MODE_READ_ONLY);
     74             fail();
     75         } catch (FileNotFoundException exp) {}
     76         appFuse.close();
     77     }
     78 
     79     public void testOpenFile_illegalMode() throws IOException {
     80         final StorageManager storageManager = getContext().getSystemService(StorageManager.class);
     81         final int INODE = 10;
     82         final AppFuse appFuse = new AppFuse("test", new TestCallback());
     83         appFuse.mount(storageManager);
     84         try {
     85             appFuse.openFile(INODE, ParcelFileDescriptor.MODE_READ_WRITE);
     86             fail();
     87         } catch (IllegalArgumentException exp) {}
     88         appFuse.close();
     89     }
     90 
     91     public void testReadFile() throws IOException {
     92         final StorageManager storageManager = getContext().getSystemService(StorageManager.class);
     93         final int fileInode = 10;
     94         final byte[] fileBytes = new byte[] { 'a', 'b', 'c', 'd', 'e' };
     95         final AppFuse appFuse = new AppFuse(
     96                 "test",
     97                 new TestCallback() {
     98                     @Override
     99                     public long getFileSize(int inode) throws FileNotFoundException {
    100                         if (inode == fileInode) {
    101                             return fileBytes.length;
    102                         }
    103                         return super.getFileSize(inode);
    104                     }
    105 
    106                     @Override
    107                     public long readObjectBytes(int inode, long offset, long size, byte[] bytes)
    108                             throws IOException {
    109                         if (inode == fileInode) {
    110                             int i = 0;
    111                             while (i < size && i + offset < fileBytes.length)  {
    112                                 bytes[i] = fileBytes[(int) (i + offset)];
    113                                 i++;
    114                             }
    115                             return i;
    116                         }
    117                         return super.readObjectBytes(inode, offset, size, bytes);
    118                     }
    119                 });
    120         appFuse.mount(storageManager);
    121         final ParcelFileDescriptor fd = appFuse.openFile(
    122                 fileInode, ParcelFileDescriptor.MODE_READ_ONLY);
    123         try (final ParcelFileDescriptor.AutoCloseInputStream stream =
    124                 new ParcelFileDescriptor.AutoCloseInputStream(fd)) {
    125             final byte[] buffer = new byte[1024];
    126             final int size = stream.read(buffer, 0, buffer.length);
    127             assertEquals(5, size);
    128         }
    129         appFuse.close();
    130     }
    131 
    132     public void testWriteFile() throws IOException {
    133         final StorageManager storageManager = getContext().getSystemService(StorageManager.class);
    134         final int INODE = 10;
    135         final byte[] resultBytes = new byte[5];
    136         final AppFuse appFuse = new AppFuse(
    137                 "test",
    138                 new TestCallback() {
    139                     @Override
    140                     public long getFileSize(int inode) throws FileNotFoundException {
    141                         if (inode != INODE) {
    142                             throw new FileNotFoundException();
    143                         }
    144                         return resultBytes.length;
    145                     }
    146 
    147                     @Override
    148                     public int writeObjectBytes(
    149                             long fileHandle, int inode, long offset, int size, byte[] bytes) {
    150                         for (int i = 0; i < size; i++) {
    151                             resultBytes[(int)(offset + i)] = bytes[i];
    152                         }
    153                         return size;
    154                     }
    155                 });
    156         appFuse.mount(storageManager);
    157         final ParcelFileDescriptor fd = appFuse.openFile(
    158                 INODE, ParcelFileDescriptor.MODE_WRITE_ONLY | ParcelFileDescriptor.MODE_TRUNCATE);
    159         try (final ParcelFileDescriptor.AutoCloseOutputStream stream =
    160                 new ParcelFileDescriptor.AutoCloseOutputStream(fd)) {
    161             stream.write('a');
    162             stream.write('b');
    163             stream.write('c');
    164             stream.write('d');
    165             stream.write('e');
    166         }
    167         final byte[] BYTES = new byte[] { 'a', 'b', 'c', 'd', 'e' };
    168         assertTrue(Arrays.equals(BYTES, resultBytes));
    169         appFuse.close();
    170     }
    171 
    172     public void testWriteFile_writeError() throws IOException {
    173         final StorageManager storageManager = getContext().getSystemService(StorageManager.class);
    174         final int INODE = 10;
    175         final AppFuse appFuse = new AppFuse(
    176                 "test",
    177                 new TestCallback() {
    178                     @Override
    179                     public long getFileSize(int inode) throws FileNotFoundException {
    180                         if (inode != INODE) {
    181                             throw new FileNotFoundException();
    182                         }
    183                         return 5;
    184                     }
    185                 });
    186         appFuse.mount(storageManager);
    187         final ParcelFileDescriptor fd = appFuse.openFile(
    188                 INODE, ParcelFileDescriptor.MODE_WRITE_ONLY | ParcelFileDescriptor.MODE_TRUNCATE);
    189         try (final ParcelFileDescriptor.AutoCloseOutputStream stream =
    190                 new ParcelFileDescriptor.AutoCloseOutputStream(fd)) {
    191             stream.write('a');
    192             fail();
    193         } catch (IOException e) {
    194         }
    195         appFuse.close();
    196     }
    197 
    198     public void testWriteFile_flushError() throws IOException {
    199         final StorageManager storageManager = getContext().getSystemService(StorageManager.class);
    200         final int INODE = 10;
    201         final AppFuse appFuse = new AppFuse(
    202                 "test",
    203                 new TestCallback() {
    204                     @Override
    205                     public long getFileSize(int inode) throws FileNotFoundException {
    206                         if (inode != INODE) {
    207                             throw new FileNotFoundException();
    208                         }
    209                         return 5;
    210                     }
    211 
    212                     @Override
    213                     public int writeObjectBytes(
    214                             long fileHandle, int inode, long offset, int size, byte[] bytes) {
    215                         return size;
    216                     }
    217 
    218                     @Override
    219                     public void flushFileHandle(long fileHandle) throws IOException {
    220                         throw new IOException();
    221                     }
    222                 });
    223         appFuse.mount(storageManager);
    224         final ParcelFileDescriptor fd = appFuse.openFile(
    225                 INODE, ParcelFileDescriptor.MODE_WRITE_ONLY | ParcelFileDescriptor.MODE_TRUNCATE);
    226         try (final ParcelFileDescriptor.AutoCloseOutputStream stream =
    227                 new ParcelFileDescriptor.AutoCloseOutputStream(fd)) {
    228             stream.write('a');
    229             try {
    230                 IoUtils.close(fd.getFileDescriptor());
    231                 fail();
    232             } catch (IOException e) {
    233             }
    234         }
    235         appFuse.close();
    236     }
    237 
    238     private static class TestCallback implements AppFuse.Callback {
    239         @Override
    240         public long getFileSize(int inode) throws FileNotFoundException {
    241             throw new FileNotFoundException();
    242         }
    243 
    244         @Override
    245         public long readObjectBytes(int inode, long offset, long size, byte[] bytes)
    246                 throws IOException {
    247             throw new IOException();
    248         }
    249 
    250         @Override
    251         public int writeObjectBytes(long fileHandle, int inode, long offset, int size, byte[] bytes)
    252                 throws IOException {
    253             throw new IOException();
    254         }
    255 
    256         @Override
    257         public void flushFileHandle(long fileHandle) throws IOException {}
    258 
    259         @Override
    260         public void closeFileHandle(long fileHandle) {}
    261     }
    262 }
    263