blob: 6b5ffc75248088dd3a67350cdf568e750ed8e1c2 [file] [log] [blame]
/*
* 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 static org.junit.Assert.*;
import com.android.tradefed.util.FileUtil;
import com.android.tradefed.util.StreamUtil;
import org.easymock.EasyMock;
import org.easymock.IAnswer;
import org.easymock.IExpectationSetters;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
/** Unit tests for {@link FileDownloadCache}. */
@RunWith(JUnit4.class)
public class FileDownloadCacheTest {
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;
private boolean mFailCopy = false;
@Before
public void setUp() throws Exception {
mMockDownloader = EasyMock.createMock(IFileDownloader.class);
mCacheDir = FileUtil.createTempDir("unittest");
mCache = new FileDownloadCache(mCacheDir);
}
@After
public void tearDown() throws Exception {
mCache.empty();
FileUtil.recursiveDelete(mCacheDir);
}
/** Test basic case for {@link FileDownloadCache#fetchRemoteFile(IFileDownloader, String)}. */
@Test
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.
*/
@Test
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
*/
@Test
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
*/
@Test
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 download fails
* with RuntimeException.
*/
@Test
public void testFetchRemoteFile_downloadFailed_Runtime() throws Exception {
mMockDownloader.downloadFile(EasyMock.eq(REMOTE_PATH), (File) EasyMock.anyObject());
EasyMock.expectLastCall().andThrow(new RuntimeException("download error"));
EasyMock.replay(mMockDownloader);
try {
mCache.fetchRemoteFile(mMockDownloader, REMOTE_PATH);
fail("RuntimeException not thrown");
} catch (RuntimeException e) {
// expected
}
assertNull(mCache.getCachedFile(REMOTE_PATH));
EasyMock.verify(mMockDownloader);
}
/**
* Test {@link FileDownloadCache#fetchRemoteFile(IFileDownloader, String)} when copy of a cached
* file is missing
*/
@Test
public void testFetchRemoteFile_cacheMissing() throws Exception {
// perform successful download
setDownloadExpections(REMOTE_PATH).times(2);
EasyMock.replay(mMockDownloader);
assertFetchRemoteFile(REMOTE_PATH);
// now be sneaky and delete the cachedFile, so copy will fail
File cachedFile = mCache.getCachedFile(REMOTE_PATH);
assertNotNull(cachedFile);
cachedFile.delete();
File file = null;
try {
file = mCache.fetchRemoteFile(mMockDownloader, REMOTE_PATH);
// file should have been updated in cache.
assertNotNull(file);
assertNotNull(mCache.getCachedFile(REMOTE_PATH));
EasyMock.verify(mMockDownloader);
} finally {
FileUtil.deleteFile(file);
}
}
/**
* Test {@link FileDownloadCache#fetchRemoteFile(IFileDownloader, String)} when copy of a cached
* file fails
*/
@Test
public void testFetchRemoteFile_copyFailed() throws Exception {
mCache =
new FileDownloadCache(mCacheDir) {
@Override
File copyFile(String remotePath, File cachedFile) throws BuildRetrievalError {
if (mFailCopy) {
FileUtil.deleteFile(cachedFile);
}
return super.copyFile(remotePath, cachedFile);
}
};
// perform successful download
setDownloadExpections(REMOTE_PATH);
EasyMock.replay(mMockDownloader);
assertFetchRemoteFile(REMOTE_PATH);
mFailCopy = true;
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 */
private IExpectationSetters<Object> setDownloadExpections(String remotePath)
throws BuildRetrievalError {
IAnswer<Object> downloadAnswer = new IAnswer<Object>() {
@Override
public Object answer() throws Throwable {
File fileArg = (File) EasyMock.getCurrentArguments()[1];
FileUtil.writeToFile("downloaded contents", fileArg);
return null;
}
};
mMockDownloader.downloadFile(EasyMock.eq(remotePath),
EasyMock.<File>anyObject());
return EasyMock.expectLastCall().andAnswer(downloadAnswer);
}
}