From 303650c9cdb7cec88e7ec20747b161d9fff10719 Mon Sep 17 00:00:00 2001 From: Matthew Williams Date: Fri, 17 Apr 2015 18:22:51 -0700 Subject: Add full backup criteria to android manifest BUG: 20010079 Api change: ApplicationInfo now has a fullBackupContent int where -1 is (off) 0 is (on) and >0 indicates an xml resource that should be parsed in order for a developer to indicate exactly which files they want to include/exclude from the backup set. dd: https://docs.google.com/document/d/1dnNctwhWOI-_qtZ7I3iNRtrbShmERj2GFTzwV4xXtOk/edit#heading=h.wcfw1q2pbmae Change-Id: I90273dc0aef5e9a3230c6b074a45e8f5409ed5ce --- .../src/android/app/backup/FullBackupTest.java | 258 +++++++++++++++++++++ 1 file changed, 258 insertions(+) create mode 100644 core/tests/coretests/src/android/app/backup/FullBackupTest.java (limited to 'core/tests/coretests/src') diff --git a/core/tests/coretests/src/android/app/backup/FullBackupTest.java b/core/tests/coretests/src/android/app/backup/FullBackupTest.java new file mode 100644 index 0000000..8c9c63c --- /dev/null +++ b/core/tests/coretests/src/android/app/backup/FullBackupTest.java @@ -0,0 +1,258 @@ +/* + * Copyright (C) 2015 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.app.backup; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.test.AndroidTestCase; +import android.util.ArrayMap; +import android.util.ArraySet; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlPullParserFactory; + +import java.io.File; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class FullBackupTest extends AndroidTestCase { + private XmlPullParserFactory mFactory; + private XmlPullParser mXpp; + private Context mContext; + + Map> includeMap; + Set excludesSet; + + @Override + public void setUp() throws Exception { + mFactory = XmlPullParserFactory.newInstance(); + mXpp = mFactory.newPullParser(); + mContext = getContext(); + + includeMap = new ArrayMap(); + excludesSet = new ArraySet(); + } + + public void testparseBackupSchemeFromXml_onlyInclude() throws Exception { + mXpp.setInput(new StringReader( + "" + + "" + + "")); + + FullBackup.BackupScheme bs = FullBackup.getBackupSchemeForTest(mContext); + bs.parseBackupSchemeFromXmlLocked(mXpp, excludesSet, includeMap); + + assertEquals("Excluding files when there was no tag.", 0, excludesSet.size()); + assertEquals("Unexpected number of s", 1, includeMap.size()); + + Set fileDomainIncludes = includeMap.get(FullBackup.DATA_TREE_TOKEN); + assertEquals("Didn't find expected file domain include.", 1, fileDomainIncludes.size()); + assertEquals("Invalid path parsed for ", + new File(mContext.getFilesDir(), "onlyInclude.txt").getCanonicalPath(), + fileDomainIncludes.iterator().next()); + } + + public void testparseBackupSchemeFromXml_onlyExclude() throws Exception { + mXpp.setInput(new StringReader( + "" + + "" + + "")); + + FullBackup.BackupScheme bs = FullBackup.getBackupSchemeForTest(mContext); + bs.parseBackupSchemeFromXmlLocked(mXpp, excludesSet, includeMap); + + assertEquals("Including files when there was no tag.", 0, includeMap.size()); + assertEquals("Unexpected number of s", 1, excludesSet.size()); + assertEquals("Invalid path parsed for ", + new File(mContext.getFilesDir(), "onlyExclude.txt").getCanonicalPath(), + excludesSet.iterator().next()); + } + + public void testparseBackupSchemeFromXml_includeAndExclude() throws Exception { + mXpp.setInput(new StringReader( + "" + + "" + + "" + + "")); + + FullBackup.BackupScheme bs = FullBackup.getBackupSchemeForTest(mContext); + bs.parseBackupSchemeFromXmlLocked(mXpp, excludesSet, includeMap); + + Set fileDomainIncludes = includeMap.get(FullBackup.DATA_TREE_TOKEN); + assertEquals("Didn't find expected file domain include.", 1, fileDomainIncludes.size()); + assertEquals("Invalid path parsed for ", + new File(mContext.getFilesDir(), "include.txt").getCanonicalPath(), + fileDomainIncludes.iterator().next()); + + assertEquals("Unexpected number of s", 1, excludesSet.size()); + assertEquals("Invalid path parsed for ", + new File(mContext.getFilesDir(), "exclude.txt").getCanonicalPath(), + excludesSet.iterator().next()); + } + + public void testparseBackupSchemeFromXml_lotsOfIncludesAndExcludes() throws Exception { + mXpp.setInput(new StringReader( + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "")); + + + FullBackup.BackupScheme bs = FullBackup.getBackupSchemeForTest(mContext); + bs.parseBackupSchemeFromXmlLocked(mXpp, excludesSet, includeMap); + + Set fileDomainIncludes = includeMap.get(FullBackup.DATA_TREE_TOKEN); + assertEquals("Didn't find expected file domain include.", 1, fileDomainIncludes.size()); + assertEquals("Invalid path parsed for ", + new File(mContext.getFilesDir(), "include1.txt").getCanonicalPath(), + fileDomainIncludes.iterator().next()); + + Set databaseDomainIncludes = includeMap.get(FullBackup.DATABASE_TREE_TOKEN); + assertEquals("Didn't find expected database domain include.", + 2, databaseDomainIncludes.size()); // two expected here because of "-journal" file + assertTrue("Invalid path parsed for ", + databaseDomainIncludes.contains( + new File(mContext.getDatabasePath("foo").getParentFile(), "include2.txt") + .getCanonicalPath())); + assertTrue("Invalid path parsed for ", + databaseDomainIncludes.contains( + new File( + mContext.getDatabasePath("foo").getParentFile(), + "include2.txt-journal") + .getCanonicalPath())); + + Set sharedPrefDomainIncludes = includeMap.get(FullBackup.SHAREDPREFS_TREE_TOKEN); + assertEquals("Didn't find expected sharedpref domain include.", + 1, sharedPrefDomainIncludes.size()); + assertEquals("Invalid path parsed for ", + new File(mContext.getSharedPrefsFile("foo").getParentFile(), "include3.txt") + .getCanonicalPath(), + sharedPrefDomainIncludes.iterator().next()); + + + assertEquals("Unexpected number of s", 4, excludesSet.size()); + // Sets are annoying to iterate over b/c order isn't enforced - convert to an array and + // sort lexicographically. + List arrayedSet = new ArrayList(excludesSet); + Collections.sort(arrayedSet); + + assertEquals("Invalid path parsed for ", + new File(mContext.getDatabasePath("foo").getParentFile(), "exclude2.txt") + .getCanonicalPath(), + arrayedSet.get(0)); + assertEquals("Invalid path parsed for ", + new File(mContext.getDatabasePath("foo").getParentFile(), "exclude2.txt-journal") + .getCanonicalPath(), + arrayedSet.get(1)); + assertEquals("Invalid path parsed for ", + new File(mContext.getFilesDir(), "exclude1.txt").getCanonicalPath(), + arrayedSet.get(2)); + assertEquals("Invalid path parsed for ", + new File(mContext.getSharedPrefsFile("foo").getParentFile(), "exclude3.txt") + .getCanonicalPath(), + arrayedSet.get(3)); + } + + public void testParseBackupSchemeFromXml_invalidXmlFails() throws Exception { + // Invalid root tag. + mXpp.setInput(new StringReader( + "" + + "" + + "" )); + + try { + FullBackup.BackupScheme bs = FullBackup.getBackupSchemeForTest(mContext); + bs.parseBackupSchemeFromXmlLocked(mXpp, excludesSet, includeMap); + fail("Invalid root xml tag should throw an XmlPullParserException"); + } catch (XmlPullParserException expected) {} + + // Invalid exclude tag. + mXpp.setInput(new StringReader( + "" + + "" + + "t" )); + try { + FullBackup.BackupScheme bs = FullBackup.getBackupSchemeForTest(mContext); + bs.parseBackupSchemeFromXmlLocked(mXpp, excludesSet, includeMap); + fail("Misspelled xml exclude tag should throw an XmlPullParserException"); + } catch (XmlPullParserException expected) {} + + // Just for good measure - invalid include tag. + mXpp.setInput(new StringReader( + "" + + "" + + "t" )); + try { + FullBackup.BackupScheme bs = FullBackup.getBackupSchemeForTest(mContext); + bs.parseBackupSchemeFromXmlLocked(mXpp, excludesSet, includeMap); + fail("Misspelled xml exclude tag should throw an XmlPullParserException"); + } catch (XmlPullParserException expected) {} + + } + + public void testInvalidPath_doesNotBackup() throws Exception { + mXpp.setInput(new StringReader( + "" + + "" + // Invalid use of ".." dir. + "" )); + + FullBackup.BackupScheme bs = FullBackup.getBackupSchemeForTest(mContext); + bs.parseBackupSchemeFromXmlLocked(mXpp, excludesSet, includeMap); + + assertEquals("Didn't throw away invalid \"..\" path.", 0, includeMap.size()); + + Set fileDomainIncludes = includeMap.get(FullBackup.DATA_TREE_TOKEN); + assertNull("Didn't throw away invalid \"..\" path.", fileDomainIncludes); + } + public void testDoubleDotInPath_isIgnored() throws Exception { + mXpp.setInput(new StringReader( + "" + + "" + // Invalid use of ".." dir. + "" )); + + FullBackup.BackupScheme bs = FullBackup.getBackupSchemeForTest(mContext); + bs.parseBackupSchemeFromXmlLocked(mXpp, excludesSet, includeMap); + + assertEquals("Didn't throw away invalid \"..\" path.", 0, includeMap.size()); + + Set fileDomainIncludes = includeMap.get(FullBackup.DATA_TREE_TOKEN); + assertNull("Didn't throw away invalid \"..\" path.", fileDomainIncludes); + } + + public void testDoubleSlashInPath_isIgnored() throws Exception { + mXpp.setInput(new StringReader( + "" + + "" + // Invalid use of "//" + "" )); + + FullBackup.BackupScheme bs = FullBackup.getBackupSchemeForTest(mContext); + bs.parseBackupSchemeFromXmlLocked(mXpp, excludesSet, includeMap); + + assertEquals("Didn't throw away invalid path containing \"//\".", 0, excludesSet.size()); + } +} -- cgit v1.1