Skip to content
Snippets Groups Projects
Commit 691444d8 authored by My Name's avatar My Name Committed by Cherrypicker Worker
Browse files

Add BluetoothOppSendFileInfoTest

Test: atest BluetoothInstrumentionTests
Bug: 237467631
Tag: #refactor
Change-Id: I8f25a113cb700fe545a525d7cf76753b751a27a4
(cherry picked from commit 8d86ccba)
Merged-In: I8f25a113cb700fe545a525d7cf76753b751a27a4
parent 23bef9ea
No related branches found
No related tags found
No related merge requests found
......@@ -22,6 +22,7 @@ import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
......@@ -34,6 +35,7 @@ import com.android.obex.HeaderSet;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
/**
* Proxy class for method calls to help with unit testing
......@@ -132,6 +134,23 @@ public class BluetoothMethodProxy {
return contentResolver.openFileDescriptor(uri, mode);
}
/**
* Proxies {@link ContentResolver#openAssetFileDescriptor(Uri, String)}.
*/
public AssetFileDescriptor contentResolverOpenAssetFileDescriptor(
ContentResolver contentResolver, final Uri uri, final String mode)
throws FileNotFoundException {
return contentResolver.openAssetFileDescriptor(uri, mode);
}
/**
* Proxies {@link ContentResolver#openInputStream(Uri)}.
*/
public InputStream contentResolverOpenInputStream(ContentResolver contentResolver,
final Uri uri) throws FileNotFoundException {
return contentResolver.openInputStream(uri);
}
/**
* Proxies {@link Context#sendBroadcast(Intent)}.
*/
......
......@@ -42,6 +42,7 @@ import android.provider.OpenableColumns;
import android.util.EventLog;
import android.util.Log;
import com.android.bluetooth.BluetoothMethodProxy;
import com.android.bluetooth.R;
import java.io.File;
......@@ -119,9 +120,10 @@ public class BluetoothOppSendFileInfo {
contentType = contentResolver.getType(uri);
Cursor metadataCursor;
try {
metadataCursor = contentResolver.query(uri, new String[]{
OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE
}, null, null, null);
metadataCursor = BluetoothMethodProxy.getInstance().contentResolverQuery(
contentResolver, uri, new String[]{
OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE
}, null, null, null);
} catch (SQLiteException e) {
// some content providers don't support the DISPLAY_NAME or SIZE columns
metadataCursor = null;
......@@ -180,7 +182,8 @@ public class BluetoothOppSendFileInfo {
// right size in _OpenableColumns.SIZE
// As a second source of getting the correct file length,
// get a file descriptor and get the stat length
AssetFileDescriptor fd = contentResolver.openAssetFileDescriptor(uri, "r");
AssetFileDescriptor fd = BluetoothMethodProxy.getInstance()
.contentResolverOpenAssetFileDescriptor(contentResolver, uri, "r");
long statLength = fd.getLength();
if (length != statLength && statLength > 0) {
Log.e(TAG, "Content provider length is wrong (" + Long.toString(length)
......@@ -200,7 +203,8 @@ public class BluetoothOppSendFileInfo {
length = getStreamSize(is);
Log.w(TAG, "File length not provided. Length from stream = " + length);
// Reset the stream
fd = contentResolver.openAssetFileDescriptor(uri, "r");
fd = BluetoothMethodProxy.getInstance()
.contentResolverOpenAssetFileDescriptor(contentResolver, uri, "r");
is = fd.createInputStream();
}
} catch (IOException e) {
......@@ -219,14 +223,16 @@ public class BluetoothOppSendFileInfo {
if (is == null) {
try {
is = (FileInputStream) contentResolver.openInputStream(uri);
is = (FileInputStream) BluetoothMethodProxy.getInstance()
.contentResolverOpenInputStream(contentResolver, uri);
// If the database doesn't contain the file size, get the size
// by reading through the entire stream
if (length == 0) {
length = getStreamSize(is);
// Reset the stream
is = (FileInputStream) contentResolver.openInputStream(uri);
is = (FileInputStream) BluetoothMethodProxy.getInstance()
.contentResolverOpenInputStream(contentResolver, uri);
}
} catch (FileNotFoundException e) {
return SEND_FILE_INFO_ERROR;
......
/*
* Copyright 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.bluetooth.opp;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.database.MatrixCursor;
import android.net.Uri;
import android.provider.OpenableColumns;
import android.util.Log;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import com.android.bluetooth.BluetoothMethodProxy;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.io.FileInputStream;
import java.io.IOException;
@RunWith(AndroidJUnit4.class)
public class BluetoothOppSendFileInfoTest {
Context mContext;
MatrixCursor mCursor;
@Mock
BluetoothMethodProxy mCallProxy;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
BluetoothMethodProxy.setInstanceForTesting(mCallProxy);
}
@After
public void tearDown() {
BluetoothMethodProxy.setInstanceForTesting(null);
}
@Test
public void createInstance_withFileInputStream() {
String fileName = "abc.txt";
String type = "text/plain";
long length = 10000;
FileInputStream inputStream = mock(FileInputStream.class);
int status = BluetoothShare.STATUS_SUCCESS;
BluetoothOppSendFileInfo info =
new BluetoothOppSendFileInfo(fileName, type, length, inputStream, status);
assertThat(info.mStatus).isEqualTo(status);
assertThat(info.mFileName).isEqualTo(fileName);
assertThat(info.mLength).isEqualTo(length);
assertThat(info.mInputStream).isEqualTo(inputStream);
assertThat(info.mMimetype).isEqualTo(type);
}
@Test
public void createInstance_withoutFileInputStream() {
String type = "text/plain";
long length = 10000;
int status = BluetoothShare.STATUS_SUCCESS;
String data = "Testing is boring";
BluetoothOppSendFileInfo info =
new BluetoothOppSendFileInfo(data, type, length, status);
assertThat(info.mStatus).isEqualTo(status);
assertThat(info.mData).isEqualTo(data);
assertThat(info.mLength).isEqualTo(length);
assertThat(info.mMimetype).isEqualTo(type);
}
@Test
public void generateFileInfo_withUnsupportedScheme_returnsSendFileInfoError() {
String type = "text/plain";
Uri uri = Uri.parse("https://www.google.com");
BluetoothOppSendFileInfo info = BluetoothOppSendFileInfo.generateFileInfo(mContext, uri,
type, true);
assertThat(info).isEqualTo(BluetoothOppSendFileInfo.SEND_FILE_INFO_ERROR);
}
@Test
public void generateFileInfo_withForbiddenExternalUri_returnsSendFileInfoError() {
String type = "text/plain";
Uri uri = Uri.parse("content://com.android.bluetooth.map.MmsFileProvider:8080");
BluetoothOppSendFileInfo info = BluetoothOppSendFileInfo.generateFileInfo(mContext, uri,
type, true);
assertThat(info).isEqualTo(BluetoothOppSendFileInfo.SEND_FILE_INFO_ERROR);
}
@Test
public void generateFileInfo_withoutPermissionForAccessingUri_returnsSendFileInfoError() {
String type = "text/plain";
Uri uri = Uri.parse("content:///hello/world");
doThrow(new SecurityException()).when(mCallProxy).contentResolverQuery(
any(), eq(uri), any(), any(), any(),
any());
BluetoothOppSendFileInfo info = BluetoothOppSendFileInfo.generateFileInfo(mContext, uri,
type, true);
assertThat(info).isEqualTo(BluetoothOppSendFileInfo.SEND_FILE_INFO_ERROR);
}
@Test
public void generateFileInfo_withUncorrectableMismatch_returnsSendFileInfoError()
throws IOException {
String type = "text/plain";
Uri uri = Uri.parse("content:///hello/world");
long fileLength = 0;
String fileName = "coolName.txt";
AssetFileDescriptor fd = mock(AssetFileDescriptor.class);
FileInputStream fs = mock(FileInputStream.class);
mCursor = new MatrixCursor(new String[]{
OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE
});
mCursor.addRow(new Object[]{fileName, fileLength});
doReturn(mCursor).when(mCallProxy).contentResolverQuery(
any(), eq(uri), any(), any(), any(),
any());
doReturn(fd).when(mCallProxy).contentResolverOpenAssetFileDescriptor(
any(), eq(uri), any());
doReturn(0L).when(fd).getLength();
doThrow(new IOException()).when(fd).createInputStream();
doReturn(fs).when(mCallProxy).contentResolverOpenInputStream(any(), eq(uri));
doReturn(0, -1).when(fs).read(any(), anyInt(), anyInt());
BluetoothOppSendFileInfo info = BluetoothOppSendFileInfo.generateFileInfo(mContext, uri,
type, true);
assertThat(info).isEqualTo(BluetoothOppSendFileInfo.SEND_FILE_INFO_ERROR);
}
@Test
public void generateFileInfo_withCorrectableMismatch_returnInfoWithCorrectLength()
throws IOException {
String type = "text/plain";
Uri uri = Uri.parse("content:///hello/world");
long fileLength = 0;
long correctFileLength = 1000;
String fileName = "coolName.txt";
AssetFileDescriptor fd = mock(AssetFileDescriptor.class);
FileInputStream fs = mock(FileInputStream.class);
mCursor = new MatrixCursor(new String[]{
OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE
});
mCursor.addRow(new Object[]{fileName, fileLength});
doReturn(mCursor).when(mCallProxy).contentResolverQuery(
any(), eq(uri), any(), any(), any(),
any());
doReturn(fd).when(mCallProxy).contentResolverOpenAssetFileDescriptor(
any(), eq(uri), any());
doReturn(0L).when(fd).getLength();
doReturn(fs).when(fd).createInputStream();
// the real size will be returned in getStreamSize(fs)
doReturn((int) correctFileLength, -1).when(fs).read(any(), anyInt(), anyInt());
BluetoothOppSendFileInfo info = BluetoothOppSendFileInfo.generateFileInfo(mContext, uri,
type, true);
assertThat(info.mInputStream).isEqualTo(fs);
assertThat(info.mFileName).isEqualTo(fileName);
assertThat(info.mLength).isEqualTo(correctFileLength);
assertThat(info.mStatus).isEqualTo(0);
}
@Test
public void generateFileInfo_withFileUriNotInExternalStorageDir_returnFileErrorInfo() {
String type = "text/plain";
Uri uri = Uri.parse("file:///obviously/not/in/external/storage");
BluetoothOppSendFileInfo info = BluetoothOppSendFileInfo.generateFileInfo(mContext, uri,
type, true);
assertThat(info).isEqualTo(BluetoothOppSendFileInfo.SEND_FILE_INFO_ERROR);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment