1 /* 2 * Copyright 2022 Google LLC 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 package com.google.android.libraries.mobiledatadownload.file; 17 18 import static com.google.android.libraries.mobiledatadownload.file.common.testing.StreamUtils.makeArrayOfBytesContent; 19 import static com.google.common.truth.Truth.assertThat; 20 import static org.mockito.ArgumentMatchers.any; 21 import static org.mockito.Mockito.doThrow; 22 import static org.mockito.Mockito.mock; 23 import static org.mockito.Mockito.times; 24 import static org.mockito.Mockito.verify; 25 import static org.mockito.Mockito.when; 26 27 import android.net.Uri; 28 import com.google.android.libraries.mobiledatadownload.file.common.testing.BufferingMonitor; 29 import com.google.android.libraries.mobiledatadownload.file.spi.Monitor; 30 import java.io.ByteArrayInputStream; 31 import java.io.IOException; 32 import java.io.InputStream; 33 import java.util.Arrays; 34 import org.junit.Test; 35 import org.junit.runner.RunWith; 36 import org.robolectric.RobolectricTestRunner; 37 38 /** Test {@link com.google.android.libraries.mobiledatadownload.file.MonitorInputStream}. */ 39 @RunWith(RobolectricTestRunner.class) 40 public class MonitorInputStreamTest { 41 42 private static final byte[] TEST_CONTENT = makeArrayOfBytesContent(); 43 44 @Test monitorRead_shouldSeeAllBytes()45 public void monitorRead_shouldSeeAllBytes() throws Exception { 46 BufferingMonitor buffer = new BufferingMonitor(); 47 Uri uri = Uri.parse("foo:"); 48 InputStream in = new ByteArrayInputStream(TEST_CONTENT); 49 MonitorInputStream stream = MonitorInputStream.newInstance(Arrays.asList(buffer), uri, in); 50 51 stream.read(); 52 stream.read(new byte[5]); 53 stream.read(); 54 stream.read(new byte[10], 5, 3); 55 56 assertThat(buffer.bytesRead()).isEqualTo(Arrays.copyOf(TEST_CONTENT, 10)); 57 } 58 59 @Test monitorRead_withNullInputMonitor_shouldReturnNull()60 public void monitorRead_withNullInputMonitor_shouldReturnNull() throws Exception { 61 Monitor mockMonitor = mock(Monitor.class); 62 when(mockMonitor.monitorRead(any())).thenReturn(null); 63 Uri uri = Uri.parse("foo:"); 64 InputStream in = new ByteArrayInputStream(TEST_CONTENT); 65 66 assertThat(MonitorInputStream.newInstance(Arrays.asList(mockMonitor), uri, in)).isNull(); 67 } 68 69 @Test monitorRead_shouldCallClose()70 public void monitorRead_shouldCallClose() throws Exception { 71 Monitor mockMonitor = mock(Monitor.class); 72 Monitor.InputMonitor mockInputMonitor = mock(Monitor.InputMonitor.class); 73 when(mockMonitor.monitorRead(any())).thenReturn(mockInputMonitor); 74 Uri uri = Uri.parse("foo:"); 75 InputStream in = new ByteArrayInputStream(TEST_CONTENT); 76 try (MonitorInputStream stream = 77 MonitorInputStream.newInstance(Arrays.asList(mockMonitor), uri, in)) { 78 stream.read(new byte[TEST_CONTENT.length]); 79 } 80 verify(mockInputMonitor, times(1)).close(); 81 } 82 83 @Test monitorReadWithMonitorCloseException_shouldCallClose()84 public void monitorReadWithMonitorCloseException_shouldCallClose() throws Exception { 85 Monitor mockMonitor = mock(Monitor.class); 86 Monitor.InputMonitor mockInputMonitor = mock(Monitor.InputMonitor.class); 87 when(mockMonitor.monitorRead(any())).thenReturn(mockInputMonitor); 88 doThrow(new RuntimeException("Unchecked")).when(mockInputMonitor).close(); 89 Uri uri = Uri.parse("foo:"); 90 FakeInputStream fakeIn = new FakeInputStream(); 91 try (MonitorInputStream stream = 92 MonitorInputStream.newInstance(Arrays.asList(mockMonitor), uri, fakeIn)) { 93 stream.read(new byte[TEST_CONTENT.length]); 94 } 95 verify(mockInputMonitor, times(1)).close(); 96 assertThat(fakeIn.bytesRead).isEqualTo(TEST_CONTENT.length); 97 assertThat(fakeIn.closed).isTrue(); 98 } 99 100 private static class FakeInputStream extends InputStream { 101 private boolean closed = true; 102 private int bytesRead = 0; 103 104 @Override read()105 public int read() throws IOException { 106 bytesRead += 1; 107 return 0; 108 } 109 110 @Override close()111 public void close() throws IOException { 112 closed = true; 113 } 114 } 115 } 116