1 /* 2 * Copyright (C) 2016 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 17 package com.android.retaildemo; 18 19 import android.app.DownloadManager; 20 import android.app.ProgressDialog; 21 import android.content.BroadcastReceiver; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.content.IntentFilter; 25 import android.database.Cursor; 26 import android.database.MatrixCursor; 27 import android.net.ConnectivityManager; 28 import android.net.NetworkInfo; 29 import android.net.Uri; 30 import android.os.Build; 31 import android.os.Environment; 32 import android.os.Handler; 33 import android.os.Looper; 34 import android.support.test.filters.SmallTest; 35 import android.support.test.runner.AndroidJUnit4; 36 37 import com.android.retaildemo.DemoPlayer; 38 import com.android.retaildemo.DownloadVideoTask; 39 import com.android.retaildemo.DownloadVideoTask.ResultListener; 40 41 import org.junit.After; 42 import org.junit.Before; 43 import org.junit.Test; 44 import org.junit.runner.RunWith; 45 import org.mockito.ArgumentCaptor; 46 import org.mockito.Mock; 47 import org.mockito.Mockito; 48 import org.mockito.MockitoAnnotations; 49 50 import java.io.File; 51 import java.lang.reflect.Field; 52 import java.net.HttpURLConnection; 53 54 import static android.support.test.InstrumentationRegistry.getTargetContext; 55 56 import static org.junit.Assert.assertEquals; 57 import static org.mockito.Matchers.any; 58 import static org.mockito.Matchers.anyLong; 59 import static org.mockito.Mockito.times; 60 import static org.mockito.Mockito.verify; 61 import static org.mockito.Mockito.verifyNoMoreInteractions; 62 import static org.mockito.Mockito.verifyZeroInteractions; 63 import static org.mockito.Mockito.when; 64 65 @RunWith(AndroidJUnit4.class) 66 @SmallTest 67 public class DownloadVideoTaskTest { 68 69 private static final String TEST_URL = "https://example.com/demo.mp4"; 70 private static final long TEST_DOWNLOAD_ID = 1000; 71 72 private @Mock Context mContext; 73 private @Mock DownloadManager mDownloadManager; 74 private @Mock ResultListener mResultListener; 75 private @Mock ConnectivityManager mConnectivityManager; 76 private @Mock ProgressDialog mProgressDialog; 77 private @Mock HttpURLConnection mConnection; 78 79 private String mDownloadPath; 80 private File mPreloadedVideo; 81 82 @Before setUp()83 public void setUp() throws Exception { 84 MockitoAnnotations.initMocks(this); 85 86 final String videoFileName = getTargetContext().getString( 87 R.string.retail_demo_video_file_name); 88 mDownloadPath = getTargetContext().getObbDir().getPath() + File.separator 89 + videoFileName; 90 clearIfFileExists(mDownloadPath); 91 mPreloadedVideo = new File(Environment.getDataPreloadsDemoDirectory(), videoFileName); 92 setNetworkConnected(true); 93 } 94 95 @After tearDown()96 public void tearDown() throws Exception { 97 clearIfFileExists(mDownloadPath); 98 } 99 clearIfFileExists(String path)100 private void clearIfFileExists(String path) { 101 final File file = new File(path); 102 if (file.exists()) { 103 file.delete(); 104 } 105 } 106 107 @Test testDownloadVideo()108 public void testDownloadVideo() throws Exception { 109 final DownloadVideoTask task = new DownloadVideoTask(mContext, 110 mDownloadPath, mPreloadedVideo, mResultListener, new TestInjector(mContext)); 111 when(mDownloadManager.enqueue(any(DownloadManager.Request.class))) 112 .thenReturn(TEST_DOWNLOAD_ID); 113 114 task.run(); 115 116 final ArgumentCaptor<BroadcastReceiver> downloadReceiver = 117 verifyIfDownloadCompleteReceiverRegistered(); 118 119 verify(mProgressDialog, times(1)).show(); 120 121 final Cursor cursor = createCursor(DownloadManager.STATUS_SUCCESSFUL, mDownloadPath); 122 when(mDownloadManager.query(any(DownloadManager.Query.class))).thenReturn(cursor); 123 124 final Intent downloadCompleteIntent = new Intent(DownloadManager.ACTION_DOWNLOAD_COMPLETE) 125 .putExtra(DownloadManager.EXTRA_DOWNLOAD_ID, TEST_DOWNLOAD_ID); 126 downloadReceiver.getValue().onReceive(mContext, downloadCompleteIntent); 127 128 verify(mContext).unregisterReceiver(downloadReceiver.getValue()); 129 130 verify(mResultListener, times(1)).onFileDownloaded(mDownloadPath); 131 verifyNoMoreInteractions(mResultListener); 132 133 verify(mProgressDialog, times(1)).dismiss(); 134 } 135 136 @Test testDownloadVideo_noNetwork()137 public void testDownloadVideo_noNetwork() throws Exception { 138 setNetworkConnected(false); 139 final DownloadVideoTask task = new DownloadVideoTask(mContext, 140 mDownloadPath, mPreloadedVideo, mResultListener, new TestInjector(mContext)); 141 142 task.run(); 143 144 verify(mResultListener, times(1)).onError(); 145 // Verify that broadcast receivers are registered for ACTION_DOWNLOAD_COMPLETE and 146 // ConnectivityManager.CONNECTIVITY_ACTION. 147 final ArgumentCaptor<BroadcastReceiver> broadcastReceiver = 148 ArgumentCaptor.forClass(BroadcastReceiver.class); 149 final ArgumentCaptor<IntentFilter> intentFilter = 150 ArgumentCaptor.forClass(IntentFilter.class); 151 verify(mContext, times(2)).registerReceiver( 152 broadcastReceiver.capture(), intentFilter.capture()); 153 final BroadcastReceiver downloadReceiver = broadcastReceiver.getAllValues().get(0); 154 assertEquals(intentFilter.getAllValues().get(0).getAction(0), 155 DownloadManager.ACTION_DOWNLOAD_COMPLETE); 156 assertEquals(intentFilter.getAllValues().get(1).getAction(0), 157 ConnectivityManager.CONNECTIVITY_ACTION); 158 final BroadcastReceiver networkReceiver = broadcastReceiver.getAllValues().get(1); 159 160 when(mDownloadManager.enqueue(any(DownloadManager.Request.class))) 161 .thenReturn(TEST_DOWNLOAD_ID); 162 setNetworkConnected(true); 163 164 networkReceiver.onReceive(mContext, 165 new Intent(ConnectivityManager.CONNECTIVITY_ACTION)); 166 167 final Cursor cursor = createCursor(DownloadManager.STATUS_SUCCESSFUL, mDownloadPath); 168 when(mDownloadManager.query(any(DownloadManager.Query.class))).thenReturn(cursor); 169 170 final Intent downloadCompleteIntent = new Intent(DownloadManager.ACTION_DOWNLOAD_COMPLETE) 171 .putExtra(DownloadManager.EXTRA_DOWNLOAD_ID, TEST_DOWNLOAD_ID); 172 downloadReceiver.onReceive(mContext, downloadCompleteIntent); 173 174 verify(mContext).unregisterReceiver(downloadReceiver); 175 verify(mContext).unregisterReceiver(networkReceiver); 176 177 verify(mResultListener).onFileDownloaded(mDownloadPath); 178 verifyNoMoreInteractions(mResultListener); 179 180 verify(mProgressDialog).dismiss(); 181 } 182 183 @Test testDownloadVideo_downloadFailed()184 public void testDownloadVideo_downloadFailed() throws Exception { 185 final DownloadVideoTask task = new DownloadVideoTask(mContext, 186 mDownloadPath, mPreloadedVideo, mResultListener, new TestInjector(mContext)); 187 when(mDownloadManager.enqueue(any(DownloadManager.Request.class))) 188 .thenReturn(TEST_DOWNLOAD_ID); 189 190 task.run(); 191 192 final ArgumentCaptor<BroadcastReceiver> downloadReceiver = 193 verifyIfDownloadCompleteReceiverRegistered(); 194 195 verify(mProgressDialog, times(1)).show(); 196 197 final Cursor cursor = createCursor(DownloadManager.STATUS_FAILED, mDownloadPath); 198 when(mDownloadManager.query(any(DownloadManager.Query.class))).thenReturn(cursor); 199 200 final Intent downloadCompleteIntent = new Intent(DownloadManager.ACTION_DOWNLOAD_COMPLETE) 201 .putExtra(DownloadManager.EXTRA_DOWNLOAD_ID, TEST_DOWNLOAD_ID); 202 downloadReceiver.getValue().onReceive(mContext, downloadCompleteIntent); 203 204 verify(mContext).unregisterReceiver(downloadReceiver.getValue()); 205 206 verify(mResultListener, times(1)).onError(); 207 verifyNoMoreInteractions(mResultListener); 208 209 verify(mProgressDialog, times(1)).dismiss(); 210 } 211 212 @Test testDownloadUpdatedVideo()213 public void testDownloadUpdatedVideo() throws Exception { 214 new File(mDownloadPath).createNewFile(); 215 216 final TestInjector injector = new TestInjector(mContext); 217 final DownloadVideoTask task = new DownloadVideoTask(mContext, 218 mDownloadPath, mPreloadedVideo, mResultListener, injector); 219 final Handler handler = injector.getHandler(task); 220 221 when(mConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_OK); 222 handler.handleMessage(handler.obtainMessage(DownloadVideoTask.MSG_CHECK_FOR_UPDATE)); 223 224 verify(mConnection).setIfModifiedSince(anyLong()); 225 verify(mDownloadManager).enqueue(any(DownloadManager.Request.class)); 226 } 227 228 @Test testDownloadUpdatedVideo_notModified()229 public void testDownloadUpdatedVideo_notModified() throws Exception { 230 new File(mDownloadPath).createNewFile(); 231 232 final TestInjector injector = new TestInjector(mContext); 233 final DownloadVideoTask task = new DownloadVideoTask(mContext, 234 mDownloadPath, mPreloadedVideo, mResultListener, injector); 235 final Handler handler = injector.getHandler(task); 236 237 when(mConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_NOT_MODIFIED); 238 handler.handleMessage(handler.obtainMessage(DownloadVideoTask.MSG_CHECK_FOR_UPDATE)); 239 240 verify(mConnection).setIfModifiedSince(anyLong()); 241 verifyZeroInteractions(mDownloadManager); 242 } 243 verifyIfDownloadCompleteReceiverRegistered()244 private ArgumentCaptor<BroadcastReceiver> verifyIfDownloadCompleteReceiverRegistered() { 245 final ArgumentCaptor<BroadcastReceiver> broadcastReceiver = 246 ArgumentCaptor.forClass(BroadcastReceiver.class); 247 final ArgumentCaptor<IntentFilter> intentFilter = 248 ArgumentCaptor.forClass(IntentFilter.class); 249 verify(mContext).registerReceiver( 250 broadcastReceiver.capture(), intentFilter.capture()); 251 assertEquals(intentFilter.getValue().getAction(0), 252 DownloadManager.ACTION_DOWNLOAD_COMPLETE); 253 return broadcastReceiver; 254 } 255 createCursor(int status, String filePath)256 private Cursor createCursor(int status, String filePath) { 257 final MatrixCursor cursor = new MatrixCursor(new String[] { 258 DownloadManager.COLUMN_STATUS, 259 DownloadManager.COLUMN_LOCAL_URI 260 }); 261 cursor.addRow(new Object[] { 262 status, 263 Uri.fromFile(new File(filePath)) 264 }); 265 return cursor; 266 } 267 setNetworkConnected(boolean connected)268 private void setNetworkConnected(boolean connected) { 269 NetworkInfo networkInfo = Mockito.mock(NetworkInfo.class); 270 when(networkInfo.isConnected()).thenReturn(connected); 271 when(mConnectivityManager.getActiveNetworkInfo()).thenReturn(networkInfo); 272 } 273 274 private class TestInjector extends DownloadVideoTask.Injector { TestInjector(Context context)275 TestInjector(Context context) { 276 super(context); 277 } 278 279 @Override getDownloadManager()280 DownloadManager getDownloadManager() { 281 return mDownloadManager; 282 } 283 284 @Override getDownloadUrl()285 String getDownloadUrl() { 286 return TEST_URL; 287 } 288 289 @Override getConnectivityManager()290 ConnectivityManager getConnectivityManager() { 291 return mConnectivityManager; 292 } 293 294 @Override getHandler(DownloadVideoTask task)295 Handler getHandler(DownloadVideoTask task) { 296 return task.new ThreadHandler(Looper.getMainLooper()); 297 } 298 299 @Override getProgressDialog()300 ProgressDialog getProgressDialog() { 301 return mProgressDialog; 302 } 303 304 @Override openConnection(String downloadUri)305 HttpURLConnection openConnection(String downloadUri) { 306 return mConnection; 307 } 308 } 309 }