Home | History | Annotate | Download | only in build
      1 /*
      2  * Copyright (C) 2011 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 package com.android.tradefed.build;
     17 
     18 import static org.junit.Assert.*;
     19 
     20 import com.android.tradefed.util.FileUtil;
     21 import com.android.tradefed.util.StreamUtil;
     22 
     23 import org.easymock.EasyMock;
     24 import org.easymock.IAnswer;
     25 import org.easymock.IExpectationSetters;
     26 import org.junit.After;
     27 import org.junit.Before;
     28 import org.junit.Test;
     29 import org.junit.runner.RunWith;
     30 import org.junit.runners.JUnit4;
     31 
     32 import java.io.File;
     33 import java.io.FileInputStream;
     34 import java.io.IOException;
     35 
     36 /** Unit tests for {@link FileDownloadCache}. */
     37 @RunWith(JUnit4.class)
     38 public class FileDownloadCacheTest {
     39 
     40     private static final String REMOTE_PATH = "foo/path";
     41     private static final String DOWNLOADED_CONTENTS = "downloaded contents";
     42 
     43     private IFileDownloader mMockDownloader;
     44 
     45     private File mCacheDir;
     46     private FileDownloadCache mCache;
     47     private boolean mFailCopy = false;
     48 
     49     @Before
     50     public void setUp() throws Exception {
     51         mMockDownloader = EasyMock.createMock(IFileDownloader.class);
     52         mCacheDir = FileUtil.createTempDir("unittest");
     53         mCache = new FileDownloadCache(mCacheDir);
     54     }
     55 
     56     @After
     57     public void tearDown() throws Exception {
     58         mCache.empty();
     59         FileUtil.recursiveDelete(mCacheDir);
     60     }
     61 
     62     /** Test basic case for {@link FileDownloadCache#fetchRemoteFile(IFileDownloader, String)}. */
     63     @Test
     64     public void testFetchRemoteFile() throws Exception {
     65         setDownloadExpections();
     66         EasyMock.replay(mMockDownloader);
     67         assertFetchRemoteFile();
     68         EasyMock.verify(mMockDownloader);
     69     }
     70 
     71     /**
     72      * Test {@link FileDownloadCache#fetchRemoteFile(IFileDownloader, String)} when file can be
     73      * retrieved from cache.
     74      */
     75     @Test
     76     public void testFetchRemoteFile_cacheHit() throws Exception {
     77         setDownloadExpections();
     78         EasyMock.replay(mMockDownloader);
     79         assertFetchRemoteFile();
     80         // now retrieve file again
     81         assertFetchRemoteFile();
     82         // verify only one download call occurred
     83         EasyMock.verify(mMockDownloader);
     84     }
     85 
     86     /**
     87      * Test {@link FileDownloadCache#fetchRemoteFile(IFileDownloader, String)} when cache grows
     88      * larger than max
     89      */
     90     @Test
     91     public void testFetchRemoteFile_cacheSizeExceeded() throws Exception {
     92         final String remotePath2 = "anotherpath";
     93         // set cache size to be small
     94         mCache.setMaxCacheSize(DOWNLOADED_CONTENTS.length() + 1);
     95         setDownloadExpections(remotePath2);
     96         setDownloadExpections();
     97         EasyMock.replay(mMockDownloader);
     98         assertFetchRemoteFile(remotePath2);
     99         // now retrieve another file, which will exceed size of cache
    100         assertFetchRemoteFile();
    101         assertNotNull(mCache.getCachedFile(REMOTE_PATH));
    102         assertNull(mCache.getCachedFile(remotePath2));
    103         EasyMock.verify(mMockDownloader);
    104     }
    105 
    106     /**
    107      * Test {@link FileDownloadCache#fetchRemoteFile(IFileDownloader, String)} when download fails
    108      */
    109     @Test
    110     public void testFetchRemoteFile_downloadFailed() throws Exception {
    111         mMockDownloader.downloadFile(EasyMock.eq(REMOTE_PATH),
    112                 (File)EasyMock.anyObject());
    113         EasyMock.expectLastCall().andThrow(new BuildRetrievalError("download error"));
    114         EasyMock.replay(mMockDownloader);
    115         try {
    116             mCache.fetchRemoteFile(mMockDownloader, REMOTE_PATH);
    117             fail("BuildRetrievalError not thrown");
    118         } catch (BuildRetrievalError e) {
    119             // expected
    120         }
    121         assertNull(mCache.getCachedFile(REMOTE_PATH));
    122         EasyMock.verify(mMockDownloader);
    123     }
    124 
    125     /**
    126      * Test {@link FileDownloadCache#fetchRemoteFile(IFileDownloader, String)} when download fails
    127      * with RuntimeException.
    128      */
    129     @Test
    130     public void testFetchRemoteFile_downloadFailed_Runtime() throws Exception {
    131         mMockDownloader.downloadFile(EasyMock.eq(REMOTE_PATH), (File) EasyMock.anyObject());
    132         EasyMock.expectLastCall().andThrow(new RuntimeException("download error"));
    133         EasyMock.replay(mMockDownloader);
    134         try {
    135             mCache.fetchRemoteFile(mMockDownloader, REMOTE_PATH);
    136             fail("RuntimeException not thrown");
    137         } catch (RuntimeException e) {
    138             // expected
    139         }
    140         assertNull(mCache.getCachedFile(REMOTE_PATH));
    141         EasyMock.verify(mMockDownloader);
    142     }
    143 
    144     /**
    145      * Test {@link FileDownloadCache#fetchRemoteFile(IFileDownloader, String)} when copy of a cached
    146      * file is missing
    147      */
    148     @Test
    149     public void testFetchRemoteFile_cacheMissing() throws Exception {
    150         // perform successful download
    151         setDownloadExpections(REMOTE_PATH).times(2);
    152         EasyMock.replay(mMockDownloader);
    153         assertFetchRemoteFile(REMOTE_PATH);
    154         // now be sneaky and delete the cachedFile, so copy will fail
    155         File cachedFile = mCache.getCachedFile(REMOTE_PATH);
    156         assertNotNull(cachedFile);
    157         cachedFile.delete();
    158         File file = null;
    159         try {
    160             file = mCache.fetchRemoteFile(mMockDownloader, REMOTE_PATH);
    161             // file should have been updated in cache.
    162             assertNotNull(file);
    163             assertNotNull(mCache.getCachedFile(REMOTE_PATH));
    164             EasyMock.verify(mMockDownloader);
    165         } finally {
    166             FileUtil.deleteFile(file);
    167         }
    168     }
    169 
    170     /**
    171      * Test {@link FileDownloadCache#fetchRemoteFile(IFileDownloader, String)} when copy of a cached
    172      * file fails
    173      */
    174     @Test
    175     public void testFetchRemoteFile_copyFailed() throws Exception {
    176         mCache =
    177                 new FileDownloadCache(mCacheDir) {
    178                     @Override
    179                     File copyFile(String remotePath, File cachedFile) throws BuildRetrievalError {
    180                         if (mFailCopy) {
    181                             FileUtil.deleteFile(cachedFile);
    182                         }
    183                         return super.copyFile(remotePath, cachedFile);
    184                     }
    185                 };
    186         // perform successful download
    187         setDownloadExpections(REMOTE_PATH);
    188         EasyMock.replay(mMockDownloader);
    189         assertFetchRemoteFile(REMOTE_PATH);
    190         mFailCopy = true;
    191         try {
    192             mCache.fetchRemoteFile(mMockDownloader, REMOTE_PATH);
    193             fail("BuildRetrievalError not thrown");
    194         } catch (BuildRetrievalError e) {
    195             // expected
    196         }
    197         // file should be removed from cache
    198         assertNull(mCache.getCachedFile(REMOTE_PATH));
    199         EasyMock.verify(mMockDownloader);
    200     }
    201 
    202     /**
    203      * Perform one fetchRemoteFile call and verify contents for default remote path
    204      */
    205     private void assertFetchRemoteFile() throws BuildRetrievalError, IOException {
    206         assertFetchRemoteFile(REMOTE_PATH);
    207     }
    208 
    209     /**
    210      * Perform one fetchRemoteFile call and verify contents
    211      */
    212     private void assertFetchRemoteFile(String remotePath) throws BuildRetrievalError, IOException {
    213         // test downloading file not in cache
    214         File fileCopy = mCache.fetchRemoteFile(mMockDownloader, remotePath);
    215         try {
    216             assertNotNull(mCache.getCachedFile(remotePath));
    217             String contents = StreamUtil.getStringFromStream(new FileInputStream(fileCopy));
    218             assertEquals(DOWNLOADED_CONTENTS, contents);
    219         } finally {
    220             fileCopy.delete();
    221         }
    222     }
    223 
    224     /**
    225      * Set EasyMock expectations for a downloadFile call for default remote path
    226      */
    227     private void setDownloadExpections() throws BuildRetrievalError {
    228         setDownloadExpections(REMOTE_PATH);
    229     }
    230 
    231     /** Set EasyMock expectations for a downloadFile call */
    232     private IExpectationSetters<Object> setDownloadExpections(String remotePath)
    233             throws BuildRetrievalError {
    234         IAnswer<Object> downloadAnswer = new IAnswer<Object>() {
    235             @Override
    236             public Object answer() throws Throwable {
    237                 File fileArg =  (File) EasyMock.getCurrentArguments()[1];
    238                 FileUtil.writeToFile("downloaded contents", fileArg);
    239                 return null;
    240             }
    241         };
    242         mMockDownloader.downloadFile(EasyMock.eq(remotePath),
    243                 EasyMock.<File>anyObject());
    244         return EasyMock.expectLastCall().andAnswer(downloadAnswer);
    245     }
    246 }
    247