diff options
author | Neal Nguyen <tommyn@google.com> | 2010-10-10 17:50:52 -0700 |
---|---|---|
committer | Neal Nguyen <tommyn@google.com> | 2010-11-01 18:21:21 -0700 |
commit | 5dda76a72e8bb4630fb5fd38a42e7bceb5b9c954 (patch) | |
tree | 06738629d29d441c48db454be38ab1bfef3f1bf6 /core | |
parent | bd06f02d02e07ca15e420ee9e50e35253646ba64 (diff) | |
download | frameworks_base-5dda76a72e8bb4630fb5fd38a42e7bceb5b9c954.zip frameworks_base-5dda76a72e8bb4630fb5fd38a42e7bceb5b9c954.tar.gz frameworks_base-5dda76a72e8bb4630fb5fd38a42e7bceb5b9c954.tar.bz2 |
Adding some StorageManager integration test infrastructure and some basic tests.
More interesting tests to come in the form of host-based tests.
Change-Id: Ifdedf7ef26ed9889871c902af20164df0498cf07
Diffstat (limited to 'core')
-rw-r--r-- | core/tests/coretests/res/raw/obb_enc_file100_orig1.obb | bin | 0 -> 275008 bytes | |||
-rw-r--r-- | core/tests/coretests/res/raw/obb_enc_file100_orig3.obb | bin | 0 -> 298560 bytes | |||
-rw-r--r-- | core/tests/coretests/res/raw/obb_file1.obb | bin | 0 -> 275008 bytes | |||
-rw-r--r-- | core/tests/coretests/res/raw/obb_file2.obb | bin | 0 -> 266816 bytes | |||
-rw-r--r-- | core/tests/coretests/res/raw/obb_file2_nosign.obb | bin | 0 -> 266752 bytes | |||
-rw-r--r-- | core/tests/coretests/res/raw/obb_file3.obb | bin | 0 -> 298560 bytes | |||
-rw-r--r-- | core/tests/coretests/res/raw/obb_file3_bad_packagename.obb | bin | 0 -> 298576 bytes | |||
-rw-r--r-- | core/tests/coretests/src/android/os/storage/StorageManagerBaseTest.java | 644 | ||||
-rw-r--r-- | core/tests/coretests/src/android/os/storage/StorageManagerIntegrationTest.java | 244 |
9 files changed, 888 insertions, 0 deletions
diff --git a/core/tests/coretests/res/raw/obb_enc_file100_orig1.obb b/core/tests/coretests/res/raw/obb_enc_file100_orig1.obb Binary files differnew file mode 100644 index 0000000..373b8e4 --- /dev/null +++ b/core/tests/coretests/res/raw/obb_enc_file100_orig1.obb diff --git a/core/tests/coretests/res/raw/obb_enc_file100_orig3.obb b/core/tests/coretests/res/raw/obb_enc_file100_orig3.obb Binary files differnew file mode 100644 index 0000000..aa531d8 --- /dev/null +++ b/core/tests/coretests/res/raw/obb_enc_file100_orig3.obb diff --git a/core/tests/coretests/res/raw/obb_file1.obb b/core/tests/coretests/res/raw/obb_file1.obb Binary files differnew file mode 100644 index 0000000..e71a680 --- /dev/null +++ b/core/tests/coretests/res/raw/obb_file1.obb diff --git a/core/tests/coretests/res/raw/obb_file2.obb b/core/tests/coretests/res/raw/obb_file2.obb Binary files differnew file mode 100644 index 0000000..1c397df --- /dev/null +++ b/core/tests/coretests/res/raw/obb_file2.obb diff --git a/core/tests/coretests/res/raw/obb_file2_nosign.obb b/core/tests/coretests/res/raw/obb_file2_nosign.obb Binary files differnew file mode 100644 index 0000000..8292361 --- /dev/null +++ b/core/tests/coretests/res/raw/obb_file2_nosign.obb diff --git a/core/tests/coretests/res/raw/obb_file3.obb b/core/tests/coretests/res/raw/obb_file3.obb Binary files differnew file mode 100644 index 0000000..7f97a88 --- /dev/null +++ b/core/tests/coretests/res/raw/obb_file3.obb diff --git a/core/tests/coretests/res/raw/obb_file3_bad_packagename.obb b/core/tests/coretests/res/raw/obb_file3_bad_packagename.obb Binary files differnew file mode 100644 index 0000000..baa714a --- /dev/null +++ b/core/tests/coretests/res/raw/obb_file3_bad_packagename.obb diff --git a/core/tests/coretests/src/android/os/storage/StorageManagerBaseTest.java b/core/tests/coretests/src/android/os/storage/StorageManagerBaseTest.java new file mode 100644 index 0000000..90cb9a5 --- /dev/null +++ b/core/tests/coretests/src/android/os/storage/StorageManagerBaseTest.java @@ -0,0 +1,644 @@ +/* + * Copyright (C) 2010 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.os.storage; + +import android.content.Context; +import android.content.res.Resources; +import android.content.res.Resources.NotFoundException; +import android.os.Environment; +import android.os.SystemClock; +import android.test.InstrumentationTestCase; +import android.util.Log; +import android.os.Environment; +import android.os.FileUtils; +import android.os.storage.OnObbStateChangeListener; +import android.os.storage.StorageManager; + +import java.io.BufferedReader; +import java.io.DataInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.InputStream; +import java.io.IOException; +import java.io.StringReader; + +public class StorageManagerBaseTest extends InstrumentationTestCase { + + protected Context mContext = null; + protected StorageManager mSm = null; + private static String LOG_TAG = "StorageManagerBaseTest"; + protected static final long MAX_WAIT_TIME = 120*1000; + protected static final long WAIT_TIME_INCR = 5*1000; + protected static String OBB_FILE_1 = "obb_file1.obb"; + protected static String OBB_FILE_1_CONTENTS_1 = "OneToOneThousandInts.bin"; + protected static String OBB_FILE_2 = "obb_file2.obb"; + protected static String OBB_FILE_3 = "obb_file3.obb"; + protected static String OBB_FILE_1_PASSWORD = "password1"; + protected static String OBB_FILE_1_ENCRYPTED = "obb_enc_file100_orig1.obb"; + protected static String OBB_FILE_2_UNSIGNED = "obb_file2_nosign.obb"; + protected static String OBB_FILE_3_PASSWORD = "password3"; + protected static String OBB_FILE_3_ENCRYPTED = "obb_enc_file100_orig3.obb"; + protected static String OBB_FILE_3_BAD_PACKAGENAME = "obb_file3_bad_packagename.obb"; + + protected static boolean FORCE = true; + protected static boolean DONT_FORCE = false; + + private static final String SAMPLE1_TEXT = "This is sample text.\n\nTesting 1 2 3."; + + private static final String SAMPLE2_TEXT = + "We the people of the United States, in order to form a more perfect union,\n" + + "establish justice, insure domestic tranquility, provide for the common\n" + + "defense, promote the general welfare, and secure the blessings of liberty\n" + + "to ourselves and our posterity, do ordain and establish this Constitution\n" + + "for the United States of America.\n\n"; + + class MountingObbThread extends Thread { + boolean mStop = false; + volatile boolean mFileOpenOnObb = false; + private String mObbFilePath = null; + private String mPathToContentsFile = null; + private String mOfficialObbFilePath = null; + + /** + * Constructor + * + * @param obbFilePath path to the OBB image file + * @param pathToContentsFile path to a file on the mounted OBB volume to open after the OBB + * has been mounted + */ + public MountingObbThread (String obbFilePath, String pathToContentsFile) { + assertTrue("obbFilePath cannot be null!", obbFilePath != null); + mObbFilePath = obbFilePath; + assertTrue("path to contents file cannot be null!", pathToContentsFile != null); + mPathToContentsFile = pathToContentsFile; + } + + /** + * Runs the thread + * + * Mounts OBB_FILE_1, and tries to open a file on the mounted OBB (specified in the + * constructor). Once it's open, it waits until someone calls its doStop(), after which it + * closes the opened file. + */ + public void run() { + // the official OBB file path and the mount-request file path should be the same, but + // let's distinguish the two as they may make for some interesting tests later + mOfficialObbFilePath = mountObb(mObbFilePath); + assertEquals("Expected and actual OBB file paths differ!", mObbFilePath, + mOfficialObbFilePath); + + // open a file on OBB 1... + DataInputStream inputFile = openFileOnMountedObb(mOfficialObbFilePath, + mPathToContentsFile); + assertTrue("Failed to open file!", inputFile != null); + + synchronized (this) { + mFileOpenOnObb = true; + notifyAll(); + } + + while (!mStop) { + try { + Thread.sleep(WAIT_TIME_INCR); + } catch (InterruptedException e) { + // nothing special to be done for interruptions + } + } + try { + inputFile.close(); + } catch (IOException e) { + fail("Failed to close file on OBB due to error: " + e.toString()); + } + } + + /** + * Tells whether a file has yet been successfully opened on the OBB or not + * + * @return true if the specified file on the OBB was opened; false otherwise + */ + public boolean isFileOpenOnObb() { + return mFileOpenOnObb; + } + + /** + * Returns the official path of the OBB file that was mounted + * + * This is not the mount path, but the normalized path to the actual OBB file + * + * @return a {@link String} representation of the path to the OBB file that was mounted + */ + public String officialObbFilePath() { + return mOfficialObbFilePath; + } + + /** + * Requests the thread to stop running + * + * Closes the opened file and returns + */ + public void doStop() { + mStop = true; + } + } + + public class ObbListener extends OnObbStateChangeListener { + private String LOG_TAG = "StorageManagerBaseTest.ObbListener"; + + String mOfficialPath = null; + boolean mDone = false; + int mState = -1; + + /** + * {@inheritDoc} + */ + @Override + public void onObbStateChange(String path, int state) { + Log.i(LOG_TAG, "Storage state changing to: " + state); + + synchronized (this) { + Log.i(LOG_TAG, "OfficialPath is now: " + path); + mState = state; + mOfficialPath = path; + mDone = true; + notifyAll(); + } + } + + /** + * Tells whether we are done or not (system told us the OBB has changed state) + * + * @return true if the system has told us this OBB's state has changed, false otherwise + */ + public boolean isDone() { + return mDone; + } + + /** + * The last state of the OBB, according to the system + * + * @return A {@link String} representation of the state of the OBB + */ + public int state() { + return mState; + } + + /** + * The normalized, official path to the OBB file (according to the system) + * + * @return A {@link String} representation of the official path to the OBB file + */ + public String officialPath() { + return mOfficialPath; + } + } + + /** + * {@inheritDoc} + */ + @Override + public void setUp() throws Exception { + mContext = getInstrumentation().getContext(); + mSm = (StorageManager)mContext.getSystemService(android.content.Context.STORAGE_SERVICE); + + } + + /** + * Helper to copy a raw resource file to an actual specified file + * + * @param rawResId The raw resource ID of the OBB resource file + * @param outFile A File representing the file we want to copy the OBB to + * @throws NotFoundException If the resource file could not be found + */ + private void copyRawToFile(int rawResId, File outFile) throws NotFoundException { + Resources res = mContext.getResources(); + InputStream is = null; + try { + is = res.openRawResource(rawResId); + } catch (NotFoundException e) { + Log.i(LOG_TAG, "Failed to load resource with id: " + rawResId); + throw e; + } + FileUtils.setPermissions(outFile.getPath(), FileUtils.S_IRWXU | FileUtils.S_IRWXG + | FileUtils.S_IRWXO, -1, -1); + assertTrue(FileUtils.copyToFile(is, outFile)); + FileUtils.setPermissions(outFile.getPath(), FileUtils.S_IRWXU | FileUtils.S_IRWXG + | FileUtils.S_IRWXO, -1, -1); + } + + /** + * Creates an OBB file (with the given name), into the app's standard files directory + * + * @param name The name of the OBB file we want to create/write to + * @param rawResId The raw resource ID of the OBB file in the package + * @return A {@link File} representing the file to write to + */ + protected File createObbFile(String name, int rawResId) { + File outFile = null; + try { + final File filesDir = mContext.getFilesDir(); + outFile = new File(filesDir, name); + copyRawToFile(rawResId, outFile); + } catch (NotFoundException e) { + if (outFile != null) { + outFile.delete(); + } + } + return outFile; + } + + /** + * Mounts an OBB file and opens a file located on it + * + * @param obbPath Path to OBB image + * @param fileName The full name and path to the file on the OBB to open once the OBB is mounted + * @return The {@link DataInputStream} representing the opened file, if successful in opening + * the file, or null of unsuccessful. + */ + protected DataInputStream openFileOnMountedObb(String obbPath, String fileName) { + + // get mSm obb mount path + assertTrue("Cannot open file when OBB is not mounted!", mSm.isObbMounted(obbPath)); + + String path = mSm.getMountedObbPath(obbPath); + assertTrue("Path should not be null!", path != null); + + File inFile = new File(path, fileName); + DataInputStream inStream = null; + try { + inStream = new DataInputStream(new FileInputStream(inFile)); + Log.i(LOG_TAG, "Opened file: " + fileName + " for read at path: " + path); + } catch (FileNotFoundException e) { + Log.e(LOG_TAG, e.toString()); + return null; + } catch (SecurityException e) { + Log.e(LOG_TAG, e.toString()); + return null; + } + return inStream; + } + + /** + * Mounts an OBB file + * + * @param obbFilePath The full path to the OBB file to mount + * @param key (optional) The key to use to unencrypt the OBB; pass null for no encryption + * @param expectedState The expected state resulting from trying to mount the OBB + * @return A {@link String} representing the normalized path to OBB file that was mounted + */ + protected String mountObb(String obbFilePath, String key, int expectedState) { + return doMountObb(obbFilePath, key, expectedState); + } + + /** + * Mounts an OBB file with default options (no encryption, mounting succeeds) + * + * @param obbFilePath The full path to the OBB file to mount + * @return A {@link String} representing the normalized path to OBB file that was mounted + */ + protected String mountObb(String obbFilePath) { + return doMountObb(obbFilePath, null, OnObbStateChangeListener.MOUNTED); + } + + /** + * Synchronously waits for an OBB listener to be signaled of a state change, but does not throw + * + * @param obbListener The listener for the OBB file + * @return true if the listener was signaled of a state change by the system, else returns + * false if we time out. + */ + protected boolean doWaitForObbStateChange(ObbListener obbListener) { + synchronized(obbListener) { + long waitTimeMillis = 0; + while (!obbListener.isDone()) { + try { + Log.i(LOG_TAG, "Waiting for listener..."); + obbListener.wait(WAIT_TIME_INCR); + Log.i(LOG_TAG, "Awoke from waiting for listener..."); + waitTimeMillis += WAIT_TIME_INCR; + if (waitTimeMillis > MAX_WAIT_TIME) { + fail("Timed out waiting for OBB state to change!"); + } + } catch (InterruptedException e) { + Log.i(LOG_TAG, e.toString()); + } + } + return obbListener.isDone(); + } + } + + /** + * Synchronously waits for an OBB listener to be signaled of a state change + * + * @param obbListener The listener for the OBB file + * @return true if the listener was signaled of a state change by the system; else a fail() + * is triggered if we timed out + */ + protected String doMountObb_noThrow(String obbFilePath, String key, int expectedState) { + Log.i(LOG_TAG, "doMountObb() on " + obbFilePath + " using key: " + key); + assertTrue ("Null path was passed in for OBB file!", obbFilePath != null); + assertTrue ("Null path was passed in for OBB file!", obbFilePath != null); + + ObbListener obbListener = new ObbListener(); + boolean success = mSm.mountObb(obbFilePath, key, obbListener); + success &= obbFilePath.equals(doWaitForObbStateChange(obbListener)); + success &= (expectedState == obbListener.state()); + + if (OnObbStateChangeListener.MOUNTED == expectedState) { + success &= obbFilePath.equals(obbListener.officialPath()); + success &= mSm.isObbMounted(obbListener.officialPath()); + } else { + success &= !mSm.isObbMounted(obbListener.officialPath()); + } + + if (success) { + return obbListener.officialPath(); + } else { + return null; + } + } + + /** + * Mounts an OBB file without throwing and synchronously waits for it to finish mounting + * + * @param obbFilePath The full path to the OBB file to mount + * @param key (optional) The key to use to unencrypt the OBB; pass null for no encryption + * @param expectedState The expected state resulting from trying to mount the OBB + * @return A {@link String} representing the actual normalized path to OBB file that was + * mounted, or null if the mounting failed + */ + protected String doMountObb(String obbFilePath, String key, int expectedState) { + Log.i(LOG_TAG, "doMountObb() on " + obbFilePath + " using key: " + key); + assertTrue ("Null path was passed in for OBB file!", obbFilePath != null); + + ObbListener obbListener = new ObbListener(); + assertTrue("mountObb call failed", mSm.mountObb(obbFilePath, key, obbListener)); + assertTrue("Failed to get OBB mount status change for file: " + obbFilePath, + doWaitForObbStateChange(obbListener)); + assertEquals("OBB mount state not what was expected!", expectedState, obbListener.state()); + + if (OnObbStateChangeListener.MOUNTED == expectedState) { + assertEquals(obbFilePath, obbListener.officialPath()); + assertTrue("Obb should be mounted, but SM reports it is not!", + mSm.isObbMounted(obbListener.officialPath())); + } else if (OnObbStateChangeListener.UNMOUNTED == expectedState) { + assertFalse("Obb should not be mounted, but SM reports it is!", + mSm.isObbMounted(obbListener.officialPath())); + } + + assertEquals("Mount state is not what was expected!", expectedState, obbListener.state()); + return obbListener.officialPath(); + } + + /** + * Unmounts an OBB file without throwing, and synchronously waits for it to finish unmounting + * + * @param obbFilePath The full path to the OBB file to mount + * @param force true if we shuold force the unmount, false otherwise + * @return true if the unmount was successful, false otherwise + */ + protected boolean unmountObb_noThrow(String obbFilePath, boolean force) { + Log.i(LOG_TAG, "doUnmountObb_noThrow() on " + obbFilePath); + assertTrue ("Null path was passed in for OBB file!", obbFilePath != null); + boolean success = true; + + ObbListener obbListener = new ObbListener(); + assertTrue("unmountObb call failed", mSm.unmountObb(obbFilePath, force, obbListener)); + + boolean stateChanged = doWaitForObbStateChange(obbListener); + if (force) { + success &= stateChanged; + success &= (OnObbStateChangeListener.UNMOUNTED == obbListener.state()); + success &= !mSm.isObbMounted(obbFilePath); + } + return success; + } + + /** + * Unmounts an OBB file and synchronously waits for it to finish unmounting + * + * @param obbFilePath The full path to the OBB file to mount + * @param force true if we shuold force the unmount, false otherwise + */ + protected void unmountObb(String obbFilePath, boolean force) { + Log.i(LOG_TAG, "doUnmountObb() on " + obbFilePath); + assertTrue ("Null path was passed in for OBB file!", obbFilePath != null); + + ObbListener obbListener = new ObbListener(); + assertTrue("unmountObb call failed", mSm.unmountObb(obbFilePath, force, obbListener)); + + boolean stateChanged = doWaitForObbStateChange(obbListener); + if (force) { + assertTrue("Timed out waiting to unmount OBB file " + obbFilePath, stateChanged); + assertEquals("OBB failed to unmount", OnObbStateChangeListener.UNMOUNTED, + obbListener.state()); + assertFalse("Obb should NOT be mounted, but SM reports it is!", mSm.isObbMounted( + obbFilePath)); + } + } + + /** + * Helper to validate the contents of an "int" file in an OBB. + * + * The format of the files are sequential int's, in the range of: [start..end) + * + * @param path The full path to the file (path to OBB) + * @param filename The filename containing the ints to validate + * @param start The first int expected to be found in the file + * @param end The last int + 1 expected to be found in the file + */ + protected void doValidateIntContents(String path, String filename, int start, int end) { + File inFile = new File(path, filename); + DataInputStream inStream = null; + Log.i(LOG_TAG, "Validating file " + filename + " at " + path); + try { + inStream = new DataInputStream(new FileInputStream(inFile)); + + for (int i = start; i < end; ++i) { + if (inStream.readInt() != i) { + fail("Unexpected value read in OBB file"); + } + } + if (inStream != null) { + inStream.close(); + } + Log.i(LOG_TAG, "Successfully validated file " + filename); + } catch (FileNotFoundException e) { + fail("File " + inFile + " not found: " + e.toString()); + } catch (IOException e) { + fail("IOError with file " + inFile + ":" + e.toString()); + } + } + + /** + * Helper to validate the contents of a text file in an OBB + * + * @param path The full path to the file (path to OBB) + * @param filename The filename containing the ints to validate + * @param contents A {@link String} containing the expected contents of the file + */ + protected void doValidateTextContents(String path, String filename, String contents) { + File inFile = new File(path, filename); + BufferedReader fileReader = null; + BufferedReader textReader = null; + Log.i(LOG_TAG, "Validating file " + filename + " at " + path); + try { + fileReader = new BufferedReader(new FileReader(inFile)); + textReader = new BufferedReader(new StringReader(contents)); + String actual = null; + String expected = null; + while ((actual = fileReader.readLine()) != null) { + expected = textReader.readLine(); + if (!actual.equals(expected)) { + fail("File " + filename + " in OBB " + path + " does not match expected value"); + } + } + fileReader.close(); + textReader.close(); + Log.i(LOG_TAG, "File " + filename + " successfully verified."); + } catch (IOException e) { + fail("IOError with file " + inFile + ":" + e.toString()); + } + } + + /** + * Helper to validate the contents of a "long" file on our OBBs + * + * The format of the files are sequential 0's of type long + * + * @param path The full path to the file (path to OBB) + * @param filename The filename containing the ints to validate + * @param size The number of zero's expected in the file + * @param checkContents If true, the contents of the file are actually verified; if false, + * we simply verify that the file can be opened + */ + protected void doValidateZeroLongFile(String path, String filename, long size, + boolean checkContents) { + File inFile = new File(path, filename); + DataInputStream inStream = null; + Log.i(LOG_TAG, "Validating file " + filename + " at " + path); + try { + inStream = new DataInputStream(new FileInputStream(inFile)); + + if (checkContents) { + for (long i = 0; i < size; ++i) { + if (inStream.readLong() != 0) { + fail("Unexpected value read in OBB file" + filename); + } + } + } + + if (inStream != null) { + inStream.close(); + } + Log.i(LOG_TAG, "File " + filename + " successfully verified for " + size + " zeros"); + } catch (IOException e) { + fail("IOError with file " + inFile + ":" + e.toString()); + } + } + + /** + * Helper to synchronously wait until we can get a path for a given OBB file + * + * @param filePath The full normalized path to the OBB file + * @return The mounted path of the OBB, used to access contents in it + */ + protected String doWaitForPath(String filePath) { + String path = null; + + long waitTimeMillis = 0; + assertTrue("OBB " + filePath + " is not currently mounted!", mSm.isObbMounted(filePath)); + while (path == null) { + try { + Thread.sleep(WAIT_TIME_INCR); + waitTimeMillis += WAIT_TIME_INCR; + if (waitTimeMillis > MAX_WAIT_TIME) { + fail("Timed out waiting to get path of OBB file " + filePath); + } + } catch (InterruptedException e) { + // do nothing + } + path = mSm.getMountedObbPath(filePath); + } + Log.i(LOG_TAG, "Got OBB path: " + path); + return path; + } + + /** + * Verifies the pre-defined contents of our first OBB (OBB_FILE_1) + * + * The OBB contains 4 files and no subdirectories + * + * @param filePath The normalized path to the already-mounted OBB file + */ + protected void verifyObb1Contents(String filePath) { + String path = null; + path = doWaitForPath(filePath); + + // Validate contents of 2 files in this obb + doValidateIntContents(path, "OneToOneThousandInts.bin", 0, 1000); + doValidateIntContents(path, "SevenHundredInts.bin", 0, 700); + doValidateZeroLongFile(path, "FiveLongs.bin", 5, true); + } + + /** + * Verifies the pre-defined contents of our second OBB (OBB_FILE_2) + * + * The OBB contains 2 files and no subdirectories + * + * @param filePath The normalized path to the already-mounted OBB file + */ + protected void verifyObb2Contents(String filename) { + String path = null; + path = doWaitForPath(filename); + + // Validate contents of file + doValidateTextContents(path, "sample.txt", SAMPLE1_TEXT); + doValidateTextContents(path, "sample2.txt", SAMPLE2_TEXT); + } + + /** + * Verifies the pre-defined contents of our third OBB (OBB_FILE_3) + * + * The OBB contains nested files and subdirectories + * + * @param filePath The normalized path to the already-mounted OBB file + */ + protected void verifyObb3Contents(String filename) { + String path = null; + path = doWaitForPath(filename); + + // Validate contents of file + doValidateIntContents(path, "OneToOneThousandInts.bin", 0, 1000); + doValidateZeroLongFile(path, "TwoHundredLongs", 200, true); + + // validate subdirectory 1 + doValidateZeroLongFile(path + File.separator + "subdir1", "FiftyLongs", 50, true); + + // validate subdirectory subdir2/ + doValidateIntContents(path + File.separator + "subdir2", "OneToOneThousandInts", 0, 1000); + + // validate subdirectory subdir2/subdir2a/ + doValidateZeroLongFile(path + File.separator + "subdir2" + File.separator + "subdir2a", + "TwoHundredLongs", 200, true); + + // validate subdirectory subdir2/subdir2a/subdir2a1/ + doValidateIntContents(path + File.separator + "subdir2" + File.separator + "subdir2a" + + File.separator + "subdir2a1", "OneToOneThousandInts", 0, 1000); + } +}
\ No newline at end of file diff --git a/core/tests/coretests/src/android/os/storage/StorageManagerIntegrationTest.java b/core/tests/coretests/src/android/os/storage/StorageManagerIntegrationTest.java new file mode 100644 index 0000000..71772d9 --- /dev/null +++ b/core/tests/coretests/src/android/os/storage/StorageManagerIntegrationTest.java @@ -0,0 +1,244 @@ +/* + * Copyright (C) 2010 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.os.storage; + +import android.content.Context; +import android.os.Environment; +import android.test.InstrumentationTestCase; +import android.test.suitebuilder.annotation.LargeTest; +import android.util.Log; + +import com.android.frameworks.coretests.R; + +import java.io.DataInputStream; +import java.io.IOException; +import java.io.File; +import java.io.FileInputStream; + +import junit.framework.AssertionFailedError; + +public class StorageManagerIntegrationTest extends StorageManagerBaseTest { + + private static String LOG_TAG = "StorageManagerBaseTest.StorageManagerIntegrationTest"; + protected File mFile = null; + + /** + * {@inheritDoc} + */ + @Override + public void setUp() throws Exception { + super.setUp(); + mContext = getInstrumentation().getContext(); + mFile = null; + } + + /** + * {@inheritDoc} + */ + @Override + protected void tearDown() throws Exception { + if (mFile != null) { + mFile.delete(); + mFile = null; + } + super.tearDown(); + } + + /** + * Tests mounting a single OBB file and verifies its contents. + */ + @LargeTest + public void testMountSingleObb() { + mFile = createObbFile(OBB_FILE_1, R.raw.obb_file1); + String filePath = mFile.getAbsolutePath(); + mountObb(filePath); + verifyObb1Contents(filePath); + unmountObb(filePath, DONT_FORCE); + } + + /** + * Tests mounting several OBB files and verifies its contents. + */ + @LargeTest + public void testMountMultipleObb() { + File file1 = null; + File file2 = null; + File file3 = null; + try { + file1 = createObbFile(OBB_FILE_1, R.raw.obb_file1); + String filePath1 = file1.getAbsolutePath(); + mountObb(filePath1); + verifyObb1Contents(filePath1); + + file2 = createObbFile(OBB_FILE_2, R.raw.obb_file2); + String filePath2 = file2.getAbsolutePath(); + mountObb(filePath2); + verifyObb2Contents(filePath2); + + file3 = createObbFile(OBB_FILE_3, R.raw.obb_file3); + String filePath3 = file3.getAbsolutePath(); + mountObb(filePath3); + verifyObb3Contents(filePath3); + + unmountObb(filePath1, DONT_FORCE); + unmountObb(filePath2, DONT_FORCE); + unmountObb(filePath3, DONT_FORCE); + } finally { + if (file1 != null) { + file1.delete(); + } + if (file2 != null) { + file2.delete(); + } + if (file3 != null) { + file3.delete(); + } + } + } + + /** + * Tests mounting a single encrypted OBB file and verifies its contents. + */ + @LargeTest + public void testMountSingleEncryptedObb() { + mFile = createObbFile(OBB_FILE_3_ENCRYPTED, R.raw.obb_enc_file100_orig3); + String filePath = mFile.getAbsolutePath(); + mountObb(filePath, OBB_FILE_3_PASSWORD, OnObbStateChangeListener.MOUNTED); + verifyObb3Contents(filePath); + unmountObb(filePath, DONT_FORCE); + } + + /** + * Tests mounting a single encrypted OBB file using an invalid password. + */ + @LargeTest + public void testMountSingleEncryptedObbInvalidPassword() { + mFile = createObbFile("bad password@$%#@^*(!&)", R.raw.obb_enc_file100_orig3); + String filePath = mFile.getAbsolutePath(); + mountObb(filePath, OBB_FILE_3_PASSWORD, OnObbStateChangeListener.ERROR_COULD_NOT_MOUNT); + unmountObb(filePath, DONT_FORCE); + } + + /** + * Tests simultaneously mounting 2 encrypted OBBs with different keys and verifies contents. + */ + @LargeTest + public void testMountTwoEncryptedObb() { + File file3 = null; + File file1 = null; + try { + file3 = createObbFile(OBB_FILE_3_ENCRYPTED, R.raw.obb_enc_file100_orig3); + String filePath3 = file3.getAbsolutePath(); + mountObb(filePath3, OBB_FILE_3_PASSWORD, OnObbStateChangeListener.MOUNTED); + verifyObb3Contents(filePath3); + + file1 = createObbFile(OBB_FILE_1_ENCRYPTED, R.raw.obb_enc_file100_orig1); + String filePath1 = file1.getAbsolutePath(); + mountObb(filePath1, OBB_FILE_1_PASSWORD, OnObbStateChangeListener.MOUNTED); + verifyObb1Contents(filePath1); + + unmountObb(filePath3, DONT_FORCE); + unmountObb(filePath1, DONT_FORCE); + } finally { + if (file3 != null) { + file3.delete(); + } + if (file1 != null) { + file1.delete(); + } + } + } + + /** + * Tests that we can not force unmount when a file is currently open on the OBB. + */ + @LargeTest + public void testUnmount_DontForce() { + mFile = createObbFile(OBB_FILE_1, R.raw.obb_file1); + String obbFilePath = mFile.getAbsolutePath(); + + MountingObbThread mountingThread = new MountingObbThread(obbFilePath, + OBB_FILE_1_CONTENTS_1); + + try { + mountingThread.start(); + + long waitTime = 0; + while (!mountingThread.isFileOpenOnObb()) { + synchronized (mountingThread) { + Log.i(LOG_TAG, "Waiting for file to be opened on OBB..."); + mountingThread.wait(WAIT_TIME_INCR); + waitTime += WAIT_TIME_INCR; + if (waitTime > MAX_WAIT_TIME) { + fail("Timed out waiting for file file to be opened on OBB!"); + } + } + } + + unmountObb(obbFilePath, DONT_FORCE); + + // verify still mounted + assertTrue("mounted path should not be null!", obbFilePath != null); + assertTrue("mounted path should still be mounted!", mSm.isObbMounted(obbFilePath)); + + // close the opened file + mountingThread.doStop(); + + // try unmounting again (should succeed this time) + unmountObb(obbFilePath, DONT_FORCE); + assertFalse("mounted path should no longer be mounted!", + mSm.isObbMounted(obbFilePath)); + } catch (InterruptedException e) { + fail("Timed out waiting for file on OBB to be opened..."); + } + } + + /** + * Tests mounting a single OBB that isn't signed. + */ + @LargeTest + public void testMountUnsignedObb() { + mFile = createObbFile(OBB_FILE_2_UNSIGNED, R.raw.obb_file2_nosign); + String filePath = mFile.getAbsolutePath(); + mountObb(filePath, OBB_FILE_2_UNSIGNED, OnObbStateChangeListener.ERROR_INTERNAL); + } + + /** + * Tests mounting a single OBB that is signed with a different package. + */ + @LargeTest + public void testMountBadPackageNameObb() { + mFile = createObbFile(OBB_FILE_3_BAD_PACKAGENAME, R.raw.obb_file3_bad_packagename); + String filePath = mFile.getAbsolutePath(); + mountObb(filePath, OBB_FILE_3_BAD_PACKAGENAME, + OnObbStateChangeListener.ERROR_PERMISSION_DENIED); + } + + /** + * Tests remounting a single OBB that has already been mounted. + */ + @LargeTest + public void testRemountObb() { + mFile = createObbFile(OBB_FILE_1, R.raw.obb_file1); + String filePath = mFile.getAbsolutePath(); + mountObb(filePath); + verifyObb1Contents(filePath); + mountObb(filePath, null, OnObbStateChangeListener.ERROR_ALREADY_MOUNTED); + verifyObb1Contents(filePath); + unmountObb(filePath, DONT_FORCE); + } +}
\ No newline at end of file |