/* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.tradefed.build; import com.android.tradefed.util.FileUtil; import com.android.tradefed.util.StreamUtil; import junit.framework.TestCase; import org.easymock.EasyMock; import org.easymock.IAnswer; import java.io.File; import java.io.FileInputStream; import java.io.IOException; /** * Unit tests for {@link FileDownloadCache}. */ public class FileDownloadCacheTest extends TestCase { private static final String REMOTE_PATH = "foo/path"; private static final String DOWNLOADED_CONTENTS = "downloaded contents"; private IFileDownloader mMockDownloader; private File mCacheDir; private FileDownloadCache mCache; @Override protected void setUp() throws Exception { super.setUp(); mMockDownloader = EasyMock.createMock(IFileDownloader.class); mCacheDir = FileUtil.createTempDir("unittest"); mCache = new FileDownloadCache(mCacheDir); } @Override protected void tearDown() throws Exception { mCache.empty(); FileUtil.recursiveDelete(mCacheDir); super.tearDown(); } /** * Test basic case for {@link FileDownloadCache#fetchRemoteFile(IFileDownloader, String)}. */ public void testFetchRemoteFile() throws Exception { setDownloadExpections(); EasyMock.replay(mMockDownloader); assertFetchRemoteFile(); EasyMock.verify(mMockDownloader); } /** * Test {@link FileDownloadCache#fetchRemoteFile(IFileDownloader, String)} when file can be * retrieved from cache. */ public void testFetchRemoteFile_cacheHit() throws Exception { setDownloadExpections(); EasyMock.replay(mMockDownloader); assertFetchRemoteFile(); // now retrieve file again assertFetchRemoteFile(); // verify only one download call occurred EasyMock.verify(mMockDownloader); } /** * Test {@link FileDownloadCache#fetchRemoteFile(IFileDownloader, String)} when cache grows * larger than max */ public void testFetchRemoteFile_cacheSizeExceeded() throws Exception { final String remotePath2 = "anotherpath"; // set cache size to be small mCache.setMaxCacheSize(DOWNLOADED_CONTENTS.length() + 1); setDownloadExpections(remotePath2); setDownloadExpections(); EasyMock.replay(mMockDownloader); assertFetchRemoteFile(remotePath2); // now retrieve another file, which will exceed size of cache assertFetchRemoteFile(); assertNotNull(mCache.getCachedFile(REMOTE_PATH)); assertNull(mCache.getCachedFile(remotePath2)); EasyMock.verify(mMockDownloader); } /** * Test {@link FileDownloadCache#fetchRemoteFile(IFileDownloader, String)} when download fails */ public void testFetchRemoteFile_downloadFailed() throws Exception { mMockDownloader.downloadFile(EasyMock.eq(REMOTE_PATH), (File)EasyMock.anyObject()); EasyMock.expectLastCall().andThrow(new BuildRetrievalError("download error")); EasyMock.replay(mMockDownloader); try { mCache.fetchRemoteFile(mMockDownloader, REMOTE_PATH); fail("BuildRetrievalError not thrown"); } catch (BuildRetrievalError e) { // expected } assertNull(mCache.getCachedFile(REMOTE_PATH)); EasyMock.verify(mMockDownloader); } /** * Test {@link FileDownloadCache#fetchRemoteFile(IFileDownloader, String)} when * copy of a cached file fails */ public void testFetchRemoteFile_copyFailed() throws Exception { // perform successful download setDownloadExpections(REMOTE_PATH); EasyMock.replay(mMockDownloader); assertFetchRemoteFile(REMOTE_PATH); // now be sneaky and delete the cachedFile, so copy will fail // TODO: add ability to mock FileUtil.copyFile File cachedFile = mCache.getCachedFile(REMOTE_PATH); assertNotNull(cachedFile); cachedFile.delete(); try { mCache.fetchRemoteFile(mMockDownloader, REMOTE_PATH); fail("BuildRetrievalError not thrown"); } catch (BuildRetrievalError e) { // expected } // file should be removed from cache assertNull(mCache.getCachedFile(REMOTE_PATH)); EasyMock.verify(mMockDownloader); } /** * Perform one fetchRemoteFile call and verify contents for default remote path */ private void assertFetchRemoteFile() throws BuildRetrievalError, IOException { assertFetchRemoteFile(REMOTE_PATH); } /** * Perform one fetchRemoteFile call and verify contents */ private void assertFetchRemoteFile(String remotePath) throws BuildRetrievalError, IOException { // test downloading file not in cache File fileCopy = mCache.fetchRemoteFile(mMockDownloader, remotePath); try { assertNotNull(mCache.getCachedFile(remotePath)); String contents = StreamUtil.getStringFromStream(new FileInputStream(fileCopy)); assertEquals(DOWNLOADED_CONTENTS, contents); } finally { fileCopy.delete(); } } /** * Set EasyMock expectations for a downloadFile call for default remote path */ private void setDownloadExpections() throws BuildRetrievalError { setDownloadExpections(REMOTE_PATH); } /** * Set EasyMock expectations for a downloadFile call */ @SuppressWarnings("unchecked") private void setDownloadExpections(String remotePath) throws BuildRetrievalError { IAnswer downloadAnswer = new IAnswer() { @Override public Object answer() throws Throwable { File fileArg = (File) EasyMock.getCurrentArguments()[1]; FileUtil.writeToFile("downloaded contents", fileArg); return null; } }; mMockDownloader.downloadFile(EasyMock.eq(remotePath), (File)EasyMock.anyObject()); EasyMock.expectLastCall().andAnswer(downloadAnswer); } }