1/* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17package com.android.server.backup.utils; 18 19import static com.google.common.truth.Truth.assertThat; 20 21import static org.junit.Assert.fail; 22import static org.mockito.Mockito.never; 23import static org.mockito.Mockito.verify; 24import static org.mockito.Mockito.verifyZeroInteractions; 25 26import android.os.ParcelFileDescriptor; 27import android.platform.test.annotations.Presubmit; 28import android.support.test.filters.SmallTest; 29import android.support.test.runner.AndroidJUnit4; 30 31import org.junit.After; 32import org.junit.Before; 33import org.junit.Test; 34import org.junit.runner.RunWith; 35import org.mockito.Mock; 36import org.mockito.MockitoAnnotations; 37 38import java.io.ByteArrayOutputStream; 39import java.io.DataOutputStream; 40import java.io.EOFException; 41import java.io.File; 42import java.io.FileOutputStream; 43import java.io.IOException; 44import java.io.OutputStream; 45import java.util.Random; 46 47@SmallTest 48@Presubmit 49@RunWith(AndroidJUnit4.class) 50public class FullBackupUtilsTest { 51 @Mock private ParcelFileDescriptor mParcelFileDescriptorMock; 52 @Mock private OutputStream mOutputStreamMock; 53 private File mTemporaryFile; 54 private ByteArrayOutputStream mByteArrayOutputStream; 55 private ParcelFileDescriptor mTemporaryFileDescriptor; 56 57 @Before 58 public void setUp() throws Exception { 59 MockitoAnnotations.initMocks(this); 60 61 mTemporaryFile = File.createTempFile("backup-data", ".txt"); 62 mByteArrayOutputStream = new ByteArrayOutputStream(); 63 } 64 65 @After 66 public void tearDown() throws Exception { 67 if (mTemporaryFileDescriptor != null) { 68 mTemporaryFileDescriptor.close(); 69 } 70 if (mTemporaryFile != null) { 71 mTemporaryFile.delete(); 72 } 73 } 74 75 @Test 76 public void routeSocketDataToOutput_inPipeIsNull_throwsNPE() throws Exception { 77 try { 78 FullBackupUtils.routeSocketDataToOutput(null, mOutputStreamMock); 79 fail(); 80 } catch (NullPointerException expected) { 81 } 82 } 83 84 @Test 85 public void routeSocketDataToOutput_outNull_throwsNPE() throws Exception { 86 try { 87 FullBackupUtils.routeSocketDataToOutput(mParcelFileDescriptorMock, null); 88 fail(); 89 } catch (NullPointerException expected) { 90 } 91 } 92 93 @Test 94 public void routeSocketDataToOutput_emptyInput_throwsEOFException() throws Exception { 95 DataOutputStream outputStream = new DataOutputStream(new FileOutputStream(mTemporaryFile)); 96 outputStream.close(); 97 98 mTemporaryFileDescriptor = ParcelFileDescriptor.open(mTemporaryFile, 99 ParcelFileDescriptor.MODE_READ_ONLY); 100 101 try { 102 FullBackupUtils.routeSocketDataToOutput(mTemporaryFileDescriptor, 103 mOutputStreamMock); 104 fail(); 105 } catch (EOFException expected) { 106 } 107 108 verifyZeroInteractions(mOutputStreamMock); 109 assertThat(mTemporaryFileDescriptor.getFileDescriptor().valid()).isTrue(); 110 } 111 112 @Test 113 public void routeSocketDataToOutput_incompleteChunkSizeInput_throwsEOFException() 114 throws Exception { 115 DataOutputStream outputStream = new DataOutputStream(new FileOutputStream(mTemporaryFile)); 116 outputStream.writeByte(100); 117 outputStream.close(); 118 119 mTemporaryFileDescriptor = ParcelFileDescriptor.open(mTemporaryFile, 120 ParcelFileDescriptor.MODE_READ_ONLY); 121 122 try { 123 FullBackupUtils.routeSocketDataToOutput(mTemporaryFileDescriptor, 124 mOutputStreamMock); 125 fail(); 126 } catch (EOFException expected) { 127 } 128 129 verifyZeroInteractions(mOutputStreamMock); 130 assertThat(mTemporaryFileDescriptor.getFileDescriptor().valid()).isTrue(); 131 } 132 133 @Test 134 public void routeSocketDataToOutput_validEmptyInput_doesNotWriteAnything() throws Exception { 135 DataOutputStream outputStream = new DataOutputStream(new FileOutputStream(mTemporaryFile)); 136 outputStream.writeInt(0); 137 outputStream.close(); 138 139 mTemporaryFileDescriptor = ParcelFileDescriptor.open(mTemporaryFile, 140 ParcelFileDescriptor.MODE_READ_ONLY); 141 142 FullBackupUtils.routeSocketDataToOutput(mTemporaryFileDescriptor, mOutputStreamMock); 143 144 verifyZeroInteractions(mOutputStreamMock); 145 assertThat(mTemporaryFileDescriptor.getFileDescriptor().valid()).isTrue(); 146 } 147 148 @Test 149 public void routeSocketDataToOutput_notEnoughData_throwsEOFException() throws Exception { 150 byte[] data = createFakeDataArray(100); 151 DataOutputStream outputStream = new DataOutputStream(new FileOutputStream(mTemporaryFile)); 152 outputStream.writeInt(data.length + 1); 153 outputStream.write(data); 154 outputStream.close(); 155 156 mTemporaryFileDescriptor = ParcelFileDescriptor.open(mTemporaryFile, 157 ParcelFileDescriptor.MODE_READ_ONLY); 158 159 try { 160 FullBackupUtils.routeSocketDataToOutput(mTemporaryFileDescriptor, 161 mByteArrayOutputStream); 162 fail(); 163 } catch (EOFException expected) { 164 } 165 166 verify(mOutputStreamMock, never()).close(); 167 assertThat(mTemporaryFileDescriptor.getFileDescriptor().valid()).isTrue(); 168 } 169 170 @Test 171 public void routeSocketDataToOutput_oneSmallChunk_writesOutputCorrectly() throws Exception { 172 byte[] data = createFakeDataArray(100); 173 DataOutputStream outputStream = new DataOutputStream(new FileOutputStream(mTemporaryFile)); 174 outputStream.writeInt(data.length); 175 outputStream.write(data); 176 outputStream.writeInt(0); 177 outputStream.close(); 178 179 mTemporaryFileDescriptor = ParcelFileDescriptor.open(mTemporaryFile, 180 ParcelFileDescriptor.MODE_READ_ONLY); 181 182 FullBackupUtils.routeSocketDataToOutput(mTemporaryFileDescriptor, 183 mByteArrayOutputStream); 184 185 assertThat(mByteArrayOutputStream.toByteArray()).isEqualTo(data); 186 verify(mOutputStreamMock, never()).close(); 187 assertThat(mTemporaryFileDescriptor.getFileDescriptor().valid()).isTrue(); 188 } 189 190 @Test 191 public void routeSocketDataToOutput_oneLargeChunk_writesOutputCorrectly() throws Exception { 192 byte[] data = createFakeDataArray(128000); 193 DataOutputStream outputStream = new DataOutputStream(new FileOutputStream(mTemporaryFile)); 194 outputStream.writeInt(data.length); 195 outputStream.write(data); 196 outputStream.writeInt(0); 197 outputStream.close(); 198 199 mTemporaryFileDescriptor = ParcelFileDescriptor.open(mTemporaryFile, 200 ParcelFileDescriptor.MODE_READ_ONLY); 201 202 FullBackupUtils.routeSocketDataToOutput(mTemporaryFileDescriptor, 203 mByteArrayOutputStream); 204 205 assertThat(mByteArrayOutputStream.toByteArray()).isEqualTo(data); 206 verify(mOutputStreamMock, never()).close(); 207 assertThat(mTemporaryFileDescriptor.getFileDescriptor().valid()).isTrue(); 208 } 209 210 @Test 211 public void routeSocketDataToOutput_twoSmallChunks_writesOutputCorrectly() throws Exception { 212 byte[] data = createFakeDataArray(200); 213 int chunk1Length = 97; 214 int chunk2Length = data.length - chunk1Length; 215 216 DataOutputStream outputStream = new DataOutputStream(new FileOutputStream(mTemporaryFile)); 217 outputStream.writeInt(chunk1Length); 218 outputStream.write(data, 0, chunk1Length); 219 outputStream.writeInt(chunk2Length); 220 outputStream.write(data, chunk1Length, chunk2Length); 221 outputStream.writeInt(0); 222 outputStream.close(); 223 224 mTemporaryFileDescriptor = ParcelFileDescriptor.open(mTemporaryFile, 225 ParcelFileDescriptor.MODE_READ_ONLY); 226 227 FullBackupUtils.routeSocketDataToOutput(mTemporaryFileDescriptor, 228 mByteArrayOutputStream); 229 230 assertThat(mByteArrayOutputStream.toByteArray()).isEqualTo(data); 231 verify(mOutputStreamMock, never()).close(); 232 assertThat(mTemporaryFileDescriptor.getFileDescriptor().valid()).isTrue(); 233 } 234 235 @Test 236 public void routeSocketDataToOutput_twoLargeChunks_writesOutputCorrectly() throws Exception { 237 byte[] data = createFakeDataArray(256000); 238 int chunk1Length = 127313; 239 int chunk2Length = data.length - chunk1Length; 240 241 DataOutputStream outputStream = new DataOutputStream(new FileOutputStream(mTemporaryFile)); 242 outputStream.writeInt(chunk1Length); 243 outputStream.write(data, 0, chunk1Length); 244 outputStream.writeInt(chunk2Length); 245 outputStream.write(data, chunk1Length, chunk2Length); 246 outputStream.writeInt(0); 247 outputStream.close(); 248 249 mTemporaryFileDescriptor = ParcelFileDescriptor.open(mTemporaryFile, 250 ParcelFileDescriptor.MODE_READ_ONLY); 251 252 FullBackupUtils.routeSocketDataToOutput(mTemporaryFileDescriptor, 253 mByteArrayOutputStream); 254 255 assertThat(mByteArrayOutputStream.toByteArray()).isEqualTo(data); 256 verify(mOutputStreamMock, never()).close(); 257 assertThat(mTemporaryFileDescriptor.getFileDescriptor().valid()).isTrue(); 258 } 259 260 private static byte[] createFakeDataArray(int length) { 261 byte[] data = new byte[length]; 262 new Random(3742).nextBytes(data); 263 return data; 264 } 265} 266