Files
frameworks_base/test-runner/src/android/test/RenamingDelegatingContext.java
Paul Duffin 20af1df63f Modify android.test.runner to use new mock APIs
Previous change added some new public APIs to allow the
android.test.runner classes to be built against the public API stubs
rather than the internal classes. This change updates the
android.test.runner classes to use that new API.

This in turn is preparation for building an android.test.legacy library
that can be safely statically included in APKs.

Bug: 30188076
Test: make checkbuild
Change-Id: I302626abb7e048ef0c3169e9a5209b85f2f87d34
2018-01-09 14:38:43 +00:00

258 lines
9.0 KiB
Java

/*
* Copyright (C) 2007 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 android.test;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.ContentProvider;
import android.database.DatabaseErrorHandler;
import android.database.sqlite.SQLiteDatabase;
import android.test.mock.MockContentProvider;
import android.util.Log;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.attribute.PosixFilePermissions;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Set;
/**
* This is a class which delegates to the given context, but performs database
* and file operations with a renamed database/file name (prefixes default
* names with a given prefix).
*
* @deprecated New tests should be written using the
* <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
*/
@Deprecated
public class RenamingDelegatingContext extends ContextWrapper {
private Context mFileContext;
private String mFilePrefix = null;
private File mCacheDir;
private final Object mSync = new Object();
private Set<String> mDatabaseNames = new HashSet<>();
private Set<String> mFileNames = new HashSet<>();
public static <T extends ContentProvider> T providerWithRenamedContext(
Class<T> contentProvider, Context c, String filePrefix)
throws IllegalAccessException, InstantiationException {
return providerWithRenamedContext(contentProvider, c, filePrefix, false);
}
public static <T extends ContentProvider> T providerWithRenamedContext(
Class<T> contentProvider, Context c, String filePrefix,
boolean allowAccessToExistingFilesAndDbs)
throws IllegalAccessException, InstantiationException {
Class<T> mProviderClass = contentProvider;
T mProvider = mProviderClass.newInstance();
RenamingDelegatingContext mContext = new RenamingDelegatingContext(c, filePrefix);
if (allowAccessToExistingFilesAndDbs) {
mContext.makeExistingFilesAndDbsAccessible();
}
MockContentProvider.attachInfoForTesting(mProvider, mContext, null);
return mProvider;
}
/**
* Makes accessible all files and databases whose names match the filePrefix that was passed to
* the constructor. Normally only files and databases that were created through this context are
* accessible.
*/
public void makeExistingFilesAndDbsAccessible() {
String[] databaseList = mFileContext.databaseList();
for (String diskName : databaseList) {
if (shouldDiskNameBeVisible(diskName)) {
mDatabaseNames.add(publicNameFromDiskName(diskName));
}
}
String[] fileList = mFileContext.fileList();
for (String diskName : fileList) {
if (shouldDiskNameBeVisible(diskName)) {
mFileNames.add(publicNameFromDiskName(diskName));
}
}
}
/**
* Returns if the given diskName starts with the given prefix or not.
* @param diskName name of the database/file.
*/
boolean shouldDiskNameBeVisible(String diskName) {
return diskName.startsWith(mFilePrefix);
}
/**
* Returns the public name (everything following the prefix) of the given diskName.
* @param diskName name of the database/file.
*/
String publicNameFromDiskName(String diskName) {
if (!shouldDiskNameBeVisible(diskName)) {
throw new IllegalArgumentException("disk file should not be visible: " + diskName);
}
return diskName.substring(mFilePrefix.length(), diskName.length());
}
/**
* @param context : the context that will be delegated.
* @param filePrefix : a prefix with which database and file names will be
* prefixed.
*/
public RenamingDelegatingContext(Context context, String filePrefix) {
super(context);
mFileContext = context;
mFilePrefix = filePrefix;
}
/**
* @param context : the context that will be delegated.
* @param fileContext : the context that file and db methods will be delegated to
* @param filePrefix : a prefix with which database and file names will be
* prefixed.
*/
public RenamingDelegatingContext(Context context, Context fileContext, String filePrefix) {
super(context);
mFileContext = fileContext;
mFilePrefix = filePrefix;
}
public String getDatabasePrefix() {
return mFilePrefix;
}
private String renamedFileName(String name) {
return mFilePrefix + name;
}
@Override
public SQLiteDatabase openOrCreateDatabase(String name,
int mode, SQLiteDatabase.CursorFactory factory) {
final String internalName = renamedFileName(name);
if (!mDatabaseNames.contains(name)) {
mDatabaseNames.add(name);
mFileContext.deleteDatabase(internalName);
}
return mFileContext.openOrCreateDatabase(internalName, mode, factory);
}
@Override
public SQLiteDatabase openOrCreateDatabase(String name,
int mode, SQLiteDatabase.CursorFactory factory, DatabaseErrorHandler errorHandler) {
final String internalName = renamedFileName(name);
if (!mDatabaseNames.contains(name)) {
mDatabaseNames.add(name);
mFileContext.deleteDatabase(internalName);
}
return mFileContext.openOrCreateDatabase(internalName, mode, factory, errorHandler);
}
@Override
public boolean deleteDatabase(String name) {
if (mDatabaseNames.contains(name)) {
mDatabaseNames.remove(name);
return mFileContext.deleteDatabase(renamedFileName(name));
} else {
return false;
}
}
@Override
public File getDatabasePath(String name) {
return mFileContext.getDatabasePath(renamedFileName(name));
}
@Override
public String[] databaseList() {
return mDatabaseNames.toArray(new String[]{});
}
@Override
public FileInputStream openFileInput(String name)
throws FileNotFoundException {
final String internalName = renamedFileName(name);
if (mFileNames.contains(name)) {
return mFileContext.openFileInput(internalName);
} else {
throw new FileNotFoundException(internalName);
}
}
@Override
public FileOutputStream openFileOutput(String name, int mode)
throws FileNotFoundException {
mFileNames.add(name);
return mFileContext.openFileOutput(renamedFileName(name), mode);
}
@Override
public File getFileStreamPath(String name) {
return mFileContext.getFileStreamPath(renamedFileName(name));
}
@Override
public boolean deleteFile(String name) {
if (mFileNames.contains(name)) {
mFileNames.remove(name);
return mFileContext.deleteFile(renamedFileName(name));
} else {
return false;
}
}
@Override
public String[] fileList() {
return mFileNames.toArray(new String[]{});
}
/**
* In order to support calls to getCacheDir(), we create a temp cache dir (inside the real
* one) and return it instead. This code is basically getCacheDir(), except it uses the real
* cache dir as the parent directory and creates a test cache dir inside that.
*/
@Override
public File getCacheDir() {
synchronized (mSync) {
if (mCacheDir == null) {
mCacheDir = new File(mFileContext.getCacheDir(), renamedFileName("cache"));
}
if (!mCacheDir.exists()) {
if(!mCacheDir.mkdirs()) {
Log.w("RenamingDelegatingContext", "Unable to create cache directory");
return null;
}
try {
// Give the directory all possible permissions.
Files.setPosixFilePermissions(mCacheDir.toPath(),
EnumSet.allOf(PosixFilePermission.class));
} catch (IOException e) {
Log.e("RenamingDelegatingContext",
"Could not set permissions of test cacheDir", e);
}
}
}
return mCacheDir;
}
}