1fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren/*
2fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren * Copyright (C) 2013 The Android Open Source Project
3fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren *
4fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren * Licensed under the Apache License, Version 2.0 (the "License");
5fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren * you may not use this file except in compliance with the License.
6fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren * You may obtain a copy of the License at
7fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren *
8fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren *      http://www.apache.org/licenses/LICENSE-2.0
9fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren *
10fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren * Unless required by applicable law or agreed to in writing, software
11fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren * distributed under the License is distributed on an "AS IS" BASIS,
12fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren * See the License for the specific language governing permissions and
14fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren * limitations under the License.
15fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren */
16fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren
17fd5f566db84722f9cf54085d8a378e9398ef260dChris Wrenpackage android.app.backup;
18fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren
19fd5f566db84722f9cf54085d8a378e9398ef260dChris Wrenimport android.app.backup.BackupDataInput;
20fd5f566db84722f9cf54085d8a378e9398ef260dChris Wrenimport android.app.backup.BackupDataOutput;
21fd5f566db84722f9cf54085d8a378e9398ef260dChris Wrenimport android.content.res.AssetFileDescriptor;
22fd5f566db84722f9cf54085d8a378e9398ef260dChris Wrenimport android.content.res.AssetManager;
23fd5f566db84722f9cf54085d8a378e9398ef260dChris Wrenimport android.os.Bundle;
24fd5f566db84722f9cf54085d8a378e9398ef260dChris Wrenimport android.os.Environment;
25fd5f566db84722f9cf54085d8a378e9398ef260dChris Wrenimport android.os.ParcelFileDescriptor;
26bdbde55592792efe350acd6a46733f439f6a3f3dAurimas Liutikasimport android.support.test.filters.LargeTest;
27fd5f566db84722f9cf54085d8a378e9398ef260dChris Wrenimport android.test.AndroidTestCase;
28fd5f566db84722f9cf54085d8a378e9398ef260dChris Wrenimport android.test.InstrumentationTestCase;
29fd5f566db84722f9cf54085d8a378e9398ef260dChris Wrenimport android.util.Base64;
30fd5f566db84722f9cf54085d8a378e9398ef260dChris Wrenimport android.util.Log;
31fd5f566db84722f9cf54085d8a378e9398ef260dChris Wrenimport org.json.JSONObject;
32fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren
33fd5f566db84722f9cf54085d8a378e9398ef260dChris Wrenimport java.io.BufferedReader;
34fd5f566db84722f9cf54085d8a378e9398ef260dChris Wrenimport java.io.File;
35fd5f566db84722f9cf54085d8a378e9398ef260dChris Wrenimport java.io.FileInputStream;
36fd5f566db84722f9cf54085d8a378e9398ef260dChris Wrenimport java.io.FileNotFoundException;
37fd5f566db84722f9cf54085d8a378e9398ef260dChris Wrenimport java.io.FileOutputStream;
38fd5f566db84722f9cf54085d8a378e9398ef260dChris Wrenimport java.io.FileReader;
39fd5f566db84722f9cf54085d8a378e9398ef260dChris Wrenimport java.io.IOException;
40fd5f566db84722f9cf54085d8a378e9398ef260dChris Wrenimport java.io.InputStream;
41fd5f566db84722f9cf54085d8a378e9398ef260dChris Wrenimport java.io.InputStreamReader;
42fd5f566db84722f9cf54085d8a378e9398ef260dChris Wrenimport java.lang.Exception;
43fd5f566db84722f9cf54085d8a378e9398ef260dChris Wrenimport java.nio.ByteBuffer;
44fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren
45bdbde55592792efe350acd6a46733f439f6a3f3dAurimas Liutikas@LargeTest
46fd5f566db84722f9cf54085d8a378e9398ef260dChris Wrenpublic class BackupDataTest extends AndroidTestCase {
47fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    private static final String KEY1 = "key1";
48fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    private static final String KEY2 = "key2a";
49fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    private static final String KEY3 = "key3bc";
50fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    private static final String KEY4 = "key4dad";  // variable key lengths to test padding
51fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    private static final String[] KEYS = {KEY1, KEY2, KEY3, KEY4};
52fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren
53fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    private static final String DATA1 = "abcdef";
54fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    private static final String DATA2 = "abcdefg";
55fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    private static final String DATA3 = "abcdefgh";
56fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    private static final String DATA4 = "abcdeffhi"; //variable data lengths to test padding
57fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    private static final String[] DATA = {DATA1, DATA2, DATA3, DATA4};
58fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    private static final String TAG = "BackupDataTest";
59fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren
60fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    private File mFile;
61fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    private ParcelFileDescriptor mDataFile;
62fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    private File mDirectory;
63fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    private Bundle mStatusBundle;
64fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    private AssetManager mAssets;
65fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren
66fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    @Override
67fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    protected void setUp() throws Exception {
68fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        super.setUp();
69fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        mDirectory = new File(Environment.getExternalStorageDirectory(), "test_data");
70fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        mDirectory.mkdirs();
71fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        mAssets = mContext.getAssets();
72fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    }
73fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren
74fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    @Override
75fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    protected void tearDown() throws Exception {
76fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        super.tearDown();
77fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        if (mDataFile != null) {
78fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren            mDataFile.close();
79fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        }
80fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    }
81fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren
82fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    public void testSingle() throws IOException {
83fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        mFile = new File(mDirectory, "backup_mixed_sinlge.dat");
84fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        openForWriting();
85fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        BackupDataOutput bdo = new BackupDataOutput(mDataFile.getFileDescriptor());
86fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren
87fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        writeEntity(bdo, KEY1, DATA1.getBytes());
88fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren
89fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        mDataFile.close();
90fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        openForReading();
91fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren
92fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        BackupDataInput bdi = new BackupDataInput(mDataFile.getFileDescriptor());
93fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        int count = 0;
94fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        while (bdi.readNextHeader()) {
95fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren            readAndVerifyEntity(bdi, KEY1, DATA1.getBytes());
96fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren            count++;
97fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        }
98fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        assertEquals("only one entity in this stream", 1, count);
99fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    }
100fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren
101fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    public void testMultiple() throws IOException {
102fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        mFile = new File(mDirectory, "backup_multiple_test.dat");
103fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        openForWriting();
104fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        BackupDataOutput bdo = new BackupDataOutput(mDataFile.getFileDescriptor());
105fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren
106fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        for(int i = 0; i < KEYS.length; i++) {
107fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren            writeEntity(bdo, KEYS[i], DATA[i].getBytes());
108fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        }
109fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren
110fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        mDataFile.close();
111fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        openForReading();
112fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren
113fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        BackupDataInput bdi = new BackupDataInput(mDataFile.getFileDescriptor());
114fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        int count = 0;
115fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        while (bdi.readNextHeader()) {
116fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren            readAndVerifyEntity(bdi, KEYS[count], DATA[count].getBytes());
117fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren            count++;
118fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        }
119fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        assertEquals("four entities in this stream", KEYS.length, count);
120fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    }
121fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren
122fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    public void testDelete() throws IOException {
123fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        mFile = new File(mDirectory, "backup_delete_test.dat");
124fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        openForWriting();
125fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        BackupDataOutput bdo = new BackupDataOutput(mDataFile.getFileDescriptor());
126fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren
127fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        for(int i = 0; i < KEYS.length; i++) {
128fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren            deleteEntity(bdo, KEYS[i]);
129fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        }
130fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren
131fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        mDataFile.close();
132fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        openForReading();
133fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren
134fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        BackupDataInput bdi = new BackupDataInput(mDataFile.getFileDescriptor());
135fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        int count = 0;
136fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        while (bdi.readNextHeader()) {
137fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren            readAndVerifyDeletedEntity(bdi, KEYS[count]);
138fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren            count++;
139fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        }
140fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        assertEquals("four deletes in this stream", KEYS.length, count);
141fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    }
142fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren
143fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    public void testMixed() throws IOException {
144fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        mFile = new File(mDirectory, "backup_mixed_test.dat");
145fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        openForWriting();
146fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren
147fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        BackupDataOutput bdo = new BackupDataOutput(mDataFile.getFileDescriptor());
148fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren
149fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        int i = 0;
150fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        deleteEntity(bdo, KEYS[i]); i++;
151fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        writeEntity(bdo, KEYS[i], DATA[i].getBytes()); i++;
152fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        writeEntity(bdo, KEYS[i], DATA[i].getBytes()); i++;
153fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        deleteEntity(bdo, KEYS[i]); i++;
154fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren
155fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        mDataFile.close();
156fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        openForReading();
157fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren
158fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        BackupDataInput bdi = new BackupDataInput(mDataFile.getFileDescriptor());
159fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        int out = 0;
160fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        assertTrue(bdi.readNextHeader());
161fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        readAndVerifyDeletedEntity(bdi, KEYS[out]); out++;
162fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        assertTrue(bdi.readNextHeader());
163fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        readAndVerifyEntity(bdi, KEYS[out], DATA[out].getBytes()); out++;
164fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        assertTrue(bdi.readNextHeader());
165fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        readAndVerifyEntity(bdi, KEYS[out], DATA[out].getBytes()); out++;
166fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        assertTrue(bdi.readNextHeader());
167fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        readAndVerifyDeletedEntity(bdi, KEYS[out]); out++;
168fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        assertFalse("four items in this stream",
169fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren                bdi.readNextHeader());
170fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    }
171fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren
172fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    public void testReadMockData() throws IOException {
173fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        copyAssetToFile("backup_mock.dat", "backup_read_mock_test.dat");
174fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren
175fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        openForReading();
176fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        BackupDataInput bdi = new BackupDataInput(mDataFile.getFileDescriptor());
177fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        BufferedReader truth = new BufferedReader(new InputStreamReader(
178fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren                mAssets.openFd("backup_mock.gld").createInputStream()));
179fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        while( bdi.readNextHeader()) {
180fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren            String[] expected = truth.readLine().split(":");
181fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren            byte[] expectedBytes = null;
182fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren            if (expected.length > 1) {
183fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren                expectedBytes = Base64.decode(expected[1], Base64.DEFAULT);
184fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren            }
185fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren            String key = bdi.getKey();
186fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren            int dataSize = bdi.getDataSize();
187fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren
188fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren            assertEquals("wrong key", expected[0], key);
189fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren            assertEquals("wrong length for key " + key,
190fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren                    (expectedBytes == null ? -1: expectedBytes.length), dataSize);
191fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren            if (dataSize != -1) {
192fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren                byte[] buffer = new byte[dataSize];
193fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren                bdi.readEntityData(buffer, 0, dataSize);
194fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren                assertEquals("wrong data for key " + key, expected[1],
195fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren                        Base64.encodeToString(buffer, 0, dataSize, Base64.NO_WRAP));
196fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren            }
197fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        }
198fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        assertNull("there are unused entries in the golden file", truth.readLine());
199fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    }
200fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren
201fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    public void testReadRealData() throws IOException {
202fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        copyAssetToFile("backup_real.dat", "backup_read_real_test.dat");
203fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren
204fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        openForReading();
205fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        BackupDataInput bdi = new BackupDataInput(mDataFile.getFileDescriptor());
206fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        BufferedReader truth = new BufferedReader(new InputStreamReader(
207fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren                mAssets.openFd("backup_real.gld").createInputStream()));
208fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren
209fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        while(bdi.readNextHeader()) {
210fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren            String[] expected = truth.readLine().split(":");
211fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren            byte[] expectedBytes = null;
212fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren            if (expected.length > 1) {
213fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren                expectedBytes = Base64.decode(expected[1], Base64.DEFAULT);
214fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren            }
215fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren            String key = bdi.getKey();
216fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren            int dataSize = bdi.getDataSize();
217fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren
218fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren            assertEquals("wrong key", expected[0], key);
219fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren            assertEquals("wrong length for key " + key,
220fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren                    (expectedBytes == null ? -1: expectedBytes.length), dataSize);
221fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren            if (dataSize != -1) {
222fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren                byte[] buffer = new byte[dataSize];
223fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren                bdi.readEntityData(buffer, 0, dataSize);
224fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren                assertEquals("wrong data for key " + key, expected[1],
225fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren                        Base64.encodeToString(buffer, 0, dataSize, Base64.NO_WRAP));
226fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren            }
227fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        }
228fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        assertNull("there are unused entries in the golden file", truth.readLine());
229fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    }
230fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren
231fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    private void copyAssetToFile(String source, String destination) throws IOException {
232fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        mFile = new File(mDirectory, destination);
233fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        openForWriting();
234fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        FileInputStream fileInputStream = mAssets.openFd(source).createInputStream();
235fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        FileOutputStream fileOutputStream = new FileOutputStream(mDataFile.getFileDescriptor());
236fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        byte[] copybuffer = new byte[1024];
237fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        int numBytes = fileInputStream.read(copybuffer);
238fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        fileOutputStream.write(copybuffer, 0, numBytes);
239fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        fileOutputStream.close();
240fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    }
241fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren
242fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    private void openForWriting() throws FileNotFoundException {
243fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        mDataFile = ParcelFileDescriptor.open(mFile,
244fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren                ParcelFileDescriptor.MODE_WRITE_ONLY |
245fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren                        ParcelFileDescriptor.MODE_CREATE |
246fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren                        ParcelFileDescriptor.MODE_TRUNCATE);  // Make an empty file if necessary
247fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    }
248fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren
249fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    private void openForReading() throws FileNotFoundException {
250fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        mDataFile = ParcelFileDescriptor.open(mFile,
251fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren                ParcelFileDescriptor.MODE_READ_ONLY |
252fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren                        ParcelFileDescriptor.MODE_CREATE);  // Make an empty file if necessary
253fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    }
254fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren
255fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    private void writeEntity(BackupDataOutput bdo, String key, byte[] data) throws IOException {
256fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        int status = bdo.writeEntityHeader(key, data.length);
257fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        // documentation says "number of bytes written" but that's not what we get:
258fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        assertEquals(0, status);
259fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren
260fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        status = bdo.writeEntityData(data, data.length);
261fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        // documentation says "number of bytes written" but that's not what we get:
262fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        assertEquals(0, status);
263fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    }
264fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren
265fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    private void deleteEntity(BackupDataOutput bdo, String key) throws IOException {
266fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        int status = bdo.writeEntityHeader(key, -1);
267fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        // documentation says "number of bytes written" but that's not what we get:
268fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        assertEquals(0, status);
269fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    }
270fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren
271fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    private void readAndVerifyEntity(BackupDataInput bdi, String expectedKey, byte[] expectedData)
272fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren            throws IOException {
273fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        assertEquals("Key mismatch",
274fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren                expectedKey, bdi.getKey());
275fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        assertEquals("data size mismatch",
276fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren                expectedData.length, bdi.getDataSize());
277fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        byte[] data = new byte[bdi.getDataSize()];
278fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        bdi.readEntityData(data, 0, bdi.getDataSize());
279fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        assertEquals("payload size is wrong",
280fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren                expectedData.length, data.length);
281fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        for (int i = 0; i < data.length; i++) {
282fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren            assertEquals("payload mismatch",
283fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren                    expectedData[i], data[i]);
284fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        }
285fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    }
286fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    private void readAndVerifyDeletedEntity(BackupDataInput bdi, String expectedKey)
287fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren            throws IOException {
288fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        assertEquals("Key mismatch",
289fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren                expectedKey, bdi.getKey());
290fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren        assertEquals("deletion mis-reported",
291fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren                -1, bdi.getDataSize());
292fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren    }
293fd5f566db84722f9cf54085d8a378e9398ef260dChris Wren}
294