Added test classes for DB*-classes

This commit is contained in:
daniel oeh 2013-08-14 14:38:24 +02:00
parent b0fdb2e8f1
commit c0066b9d64
8 changed files with 844 additions and 330 deletions

View File

@ -10,330 +10,363 @@ import de.danoeh.antennapod.util.EpisodeFilter;
/** /**
* Data Object for a whole feed * Data Object for a whole feed
* *
* @author daniel * @author daniel
*
*/ */
public class Feed extends FeedFile { public class Feed extends FeedFile {
public static final int FEEDFILETYPE_FEED = 0; public static final int FEEDFILETYPE_FEED = 0;
public static final String TYPE_RSS2 = "rss"; public static final String TYPE_RSS2 = "rss";
public static final String TYPE_RSS091 = "rss"; public static final String TYPE_RSS091 = "rss";
public static final String TYPE_ATOM1 = "atom"; public static final String TYPE_ATOM1 = "atom";
private String title; private String title;
/** Contains 'id'-element in Atom feed. */ /**
private String feedIdentifier; * Contains 'id'-element in Atom feed.
/** Link to the website. */ */
private String link; private String feedIdentifier;
private String description; /**
private String language; * Link to the website.
/** Name of the author */ */
private String author; private String link;
private FeedImage image; private String description;
private List<FeedItem> items; private String language;
/** Date of last refresh. */ /**
private Date lastUpdate; * Name of the author
private String paymentLink; */
/** Feed type, for example RSS 2 or Atom */ private String author;
private String type; private FeedImage image;
private List<FeedItem> items;
/**
* Date of last refresh.
*/
private Date lastUpdate;
private String paymentLink;
/**
* Feed type, for example RSS 2 or Atom
*/
private String type;
public Feed(Date lastUpdate) { /**
super(); * This constructor is used for restoring a feed from the database.
items = Collections.synchronizedList(new ArrayList<FeedItem>()); */
this.lastUpdate = lastUpdate; public Feed(long id, Date lastUpdate, String title, String link, String description, String paymentLink,
} String author, String language, String type, String feedIdentifier, FeedImage image, String fileUrl,
String downloadUrl, boolean downloaded) {
super(fileUrl, downloadUrl, downloaded);
this.id = id;
this.title = title;
this.lastUpdate = lastUpdate;
this.link = link;
this.description = description;
this.paymentLink = paymentLink;
this.author = author;
this.language = language;
this.type = type;
this.feedIdentifier = feedIdentifier;
this.image = image;
/** items = new ArrayList<FeedItem>();
* This constructor is used for requesting a feed download. It should NOT be
* used if the title of the feed is already known.
* */
public Feed(String url, Date lastUpdate) {
this(lastUpdate);
this.download_url = url;
}
/**
* This constructor is used for requesting a feed download. It should be
* used if the title of the feed is already known.
* */
public Feed(String url, Date lastUpdate, String title) {
this(url, lastUpdate);
this.title = title;
}
/**
* Returns the number of FeedItems where 'read' is false. If the 'display
* only episodes' - preference is set to true, this method will only count
* items with episodes.
* */
public int getNumOfNewItems() {
int count = 0;
for (FeedItem item : items) {
if (item.getState() == FeedItem.State.NEW) {
if (!UserPreferences.isDisplayOnlyEpisodes()
|| item.getMedia() != null) {
count++;
}
}
}
return count;
}
/**
* Returns the number of FeedItems where the media started to play but
* wasn't finished yet.
* */
public int getNumOfStartedItems() {
int count = 0;
for (FeedItem item : items) {
FeedItem.State state = item.getState();
if (state == FeedItem.State.IN_PROGRESS
|| state == FeedItem.State.PLAYING) {
count++;
}
}
return count;
}
/**
* Returns true if at least one item in the itemlist is unread.
*
* @param enableEpisodeFilter
* true if this method should only count items with episodes if
* the 'display only episodes' - preference is set to true by the
* user.
*/
public boolean hasNewItems(boolean enableEpisodeFilter) {
for (FeedItem item : items) {
if (item.getState() == FeedItem.State.NEW) {
if (!(enableEpisodeFilter && UserPreferences
.isDisplayOnlyEpisodes()) || item.getMedia() != null) {
return true;
}
}
}
return false;
}
/**
* Returns the number of FeedItems.
*
* @param enableEpisodeFilter
* true if this method should only count items with episodes if
* the 'display only episodes' - preference is set to true by the
* user.
* */
public int getNumOfItems(boolean enableEpisodeFilter) {
if (enableEpisodeFilter && UserPreferences.isDisplayOnlyEpisodes()) {
return EpisodeFilter.countItemsWithEpisodes(items);
} else {
return items.size();
}
}
/**
* Returns the item at the specified index.
*
* @param enableEpisodeFilter
* true if this method should ignore items without episdodes if
* the episodes filter has been enabled by the user.
*/
public FeedItem getItemAtIndex(boolean enableEpisodeFilter, int position) {
if (enableEpisodeFilter && UserPreferences.isDisplayOnlyEpisodes()) {
return EpisodeFilter.accessEpisodeByIndex(items, position);
} else {
return items.get(position);
}
}
/**
* Returns the value that uniquely identifies this Feed. If the
* feedIdentifier attribute is not null, it will be returned. Else it will
* try to return the title. If the title is not given, it will use the link
* of the feed.
* */
public String getIdentifyingValue() {
if (feedIdentifier != null && !feedIdentifier.isEmpty()) {
return feedIdentifier;
} else if (title != null && !title.isEmpty()) {
return title;
} else {
return link;
}
}
@Override
public String getHumanReadableIdentifier() {
if (title != null) {
return title;
} else {
return download_url;
}
} }
public void updateFromOther(Feed other) { /**
super.updateFromOther(other); * This constructor can be used when parsing feed data. Only the 'lastUpdate' and 'items' field are initialized.
if (other.title != null) { */
title = other.title; public Feed() {
} super();
if (other.feedIdentifier != null) { items = new ArrayList<FeedItem>();
feedIdentifier = other.feedIdentifier; lastUpdate = new Date();
} }
if (other.link != null) {
link = other.link;
}
if (other.description != null) {
description = other.description;
}
if (other.language != null) {
language = other.language;
}
if (other.author != null) {
author = other.author;
}
if (other.paymentLink != null) {
paymentLink = other.paymentLink;
}
}
public boolean compareWithOther(Feed other) { /**
if (super.compareWithOther(other)) { * This constructor is used for requesting a feed download (it must not be used for anything else!). It should NOT be
return true; * used if the title of the feed is already known.
} */
if (!title.equals(other.title)) { public Feed(String url, Date lastUpdate) {
return true; super(null, url, false);
} this.lastUpdate = lastUpdate;
if (other.feedIdentifier != null) { }
if (feedIdentifier == null
|| !feedIdentifier.equals(other.feedIdentifier)) {
return true;
}
}
if (other.link != null) {
if (link == null || !link.equals(other.link)) {
return true;
}
}
if (other.description != null) {
if (description == null || !description.equals(other.description)) {
return true;
}
}
if (other.language != null) {
if (language == null || !language.equals(other.language)) {
return true;
}
}
if (other.author != null) {
if (author == null || !author.equals(other.author)) {
return true;
}
}
if (other.paymentLink != null) {
if (paymentLink == null || !paymentLink.equals(other.paymentLink)) {
return true;
}
}
return false;
}
@Override /**
public int getTypeAsInt() { * This constructor is used for requesting a feed download (it must not be used for anything else!). It should be
return FEEDFILETYPE_FEED; * used if the title of the feed is already known.
} */
public Feed(String url, Date lastUpdate, String title) {
this(url, lastUpdate);
this.title = title;
}
public String getTitle() { /**
return title; * Returns the number of FeedItems where 'read' is false. If the 'display
} * only episodes' - preference is set to true, this method will only count
* items with episodes.
*/
public int getNumOfNewItems() {
int count = 0;
for (FeedItem item : items) {
if (item.getState() == FeedItem.State.NEW) {
if (!UserPreferences.isDisplayOnlyEpisodes()
|| item.getMedia() != null) {
count++;
}
}
}
return count;
}
public void setTitle(String title) { /**
this.title = title; * Returns the number of FeedItems where the media started to play but
} * wasn't finished yet.
*/
public int getNumOfStartedItems() {
int count = 0;
public String getLink() { for (FeedItem item : items) {
return link; FeedItem.State state = item.getState();
} if (state == FeedItem.State.IN_PROGRESS
|| state == FeedItem.State.PLAYING) {
count++;
}
}
return count;
}
public void setLink(String link) { /**
this.link = link; * Returns true if at least one item in the itemlist is unread.
} *
* @param enableEpisodeFilter true if this method should only count items with episodes if
* the 'display only episodes' - preference is set to true by the
* user.
*/
public boolean hasNewItems(boolean enableEpisodeFilter) {
for (FeedItem item : items) {
if (item.getState() == FeedItem.State.NEW) {
if (!(enableEpisodeFilter && UserPreferences
.isDisplayOnlyEpisodes()) || item.getMedia() != null) {
return true;
}
}
}
return false;
}
public String getDescription() { /**
return description; * Returns the number of FeedItems.
} *
* @param enableEpisodeFilter true if this method should only count items with episodes if
* the 'display only episodes' - preference is set to true by the
* user.
*/
public int getNumOfItems(boolean enableEpisodeFilter) {
if (enableEpisodeFilter && UserPreferences.isDisplayOnlyEpisodes()) {
return EpisodeFilter.countItemsWithEpisodes(items);
} else {
return items.size();
}
}
public void setDescription(String description) { /**
this.description = description; * Returns the item at the specified index.
} *
* @param enableEpisodeFilter true if this method should ignore items without episdodes if
* the episodes filter has been enabled by the user.
*/
public FeedItem getItemAtIndex(boolean enableEpisodeFilter, int position) {
if (enableEpisodeFilter && UserPreferences.isDisplayOnlyEpisodes()) {
return EpisodeFilter.accessEpisodeByIndex(items, position);
} else {
return items.get(position);
}
}
public FeedImage getImage() { /**
return image; * Returns the value that uniquely identifies this Feed. If the
} * feedIdentifier attribute is not null, it will be returned. Else it will
* try to return the title. If the title is not given, it will use the link
* of the feed.
*/
public String getIdentifyingValue() {
if (feedIdentifier != null && !feedIdentifier.isEmpty()) {
return feedIdentifier;
} else if (title != null && !title.isEmpty()) {
return title;
} else {
return link;
}
}
public void setImage(FeedImage image) { @Override
this.image = image; public String getHumanReadableIdentifier() {
} if (title != null) {
return title;
} else {
return download_url;
}
}
public List<FeedItem> getItems() { public void updateFromOther(Feed other) {
return items; super.updateFromOther(other);
} if (other.title != null) {
title = other.title;
}
if (other.feedIdentifier != null) {
feedIdentifier = other.feedIdentifier;
}
if (other.link != null) {
link = other.link;
}
if (other.description != null) {
description = other.description;
}
if (other.language != null) {
language = other.language;
}
if (other.author != null) {
author = other.author;
}
if (other.paymentLink != null) {
paymentLink = other.paymentLink;
}
}
public void setItems(List<FeedItem> list) { public boolean compareWithOther(Feed other) {
this.items = Collections.synchronizedList(list); if (super.compareWithOther(other)) {
} return true;
}
if (!title.equals(other.title)) {
return true;
}
if (other.feedIdentifier != null) {
if (feedIdentifier == null
|| !feedIdentifier.equals(other.feedIdentifier)) {
return true;
}
}
if (other.link != null) {
if (link == null || !link.equals(other.link)) {
return true;
}
}
if (other.description != null) {
if (description == null || !description.equals(other.description)) {
return true;
}
}
if (other.language != null) {
if (language == null || !language.equals(other.language)) {
return true;
}
}
if (other.author != null) {
if (author == null || !author.equals(other.author)) {
return true;
}
}
if (other.paymentLink != null) {
if (paymentLink == null || !paymentLink.equals(other.paymentLink)) {
return true;
}
}
return false;
}
/** Returns an array that contains all the feeditems of this feed. */ @Override
public FeedItem[] getItemsArray() { public int getTypeAsInt() {
return items.toArray(new FeedItem[items.size()]); return FEEDFILETYPE_FEED;
} }
public Date getLastUpdate() { public String getTitle() {
return lastUpdate; return title;
} }
public void setLastUpdate(Date lastUpdate) { public void setTitle(String title) {
this.lastUpdate = lastUpdate; this.title = title;
} }
public String getFeedIdentifier() { public String getLink() {
return feedIdentifier; return link;
} }
public void setFeedIdentifier(String feedIdentifier) { public void setLink(String link) {
this.feedIdentifier = feedIdentifier; this.link = link;
} }
public String getPaymentLink() { public String getDescription() {
return paymentLink; return description;
} }
public void setPaymentLink(String paymentLink) { public void setDescription(String description) {
this.paymentLink = paymentLink; this.description = description;
} }
public String getLanguage() { public FeedImage getImage() {
return language; return image;
} }
public void setLanguage(String language) { public void setImage(FeedImage image) {
this.language = language; this.image = image;
} }
public String getAuthor() { public List<FeedItem> getItems() {
return author; return items;
} }
public void setAuthor(String author) { public void setItems(List<FeedItem> list) {
this.author = author; this.items = list;
} }
public String getType() { /**
return type; * Returns an array that contains all the feeditems of this feed.
} */
public FeedItem[] getItemsArray() {
return items.toArray(new FeedItem[items.size()]);
}
public void setType(String type) { public Date getLastUpdate() {
this.type = type; return lastUpdate;
} }
public void setLastUpdate(Date lastUpdate) {
this.lastUpdate = lastUpdate;
}
public String getFeedIdentifier() {
return feedIdentifier;
}
public void setFeedIdentifier(String feedIdentifier) {
this.feedIdentifier = feedIdentifier;
}
public String getPaymentLink() {
return paymentLink;
}
public void setPaymentLink(String paymentLink) {
this.paymentLink = paymentLink;
}
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
} }

View File

@ -291,30 +291,32 @@ public final class DBReader {
Cursor cursor) { Cursor cursor) {
Date lastUpdate = new Date( Date lastUpdate = new Date(
cursor.getLong(PodDBAdapter.KEY_LAST_UPDATE_INDEX)); cursor.getLong(PodDBAdapter.KEY_LAST_UPDATE_INDEX));
Feed feed = new Feed(lastUpdate);
feed.setId(cursor.getLong(PodDBAdapter.KEY_ID_INDEX)); final FeedImage image;
feed.setTitle(cursor.getString(PodDBAdapter.KEY_TITLE_INDEX));
feed.setLink(cursor.getString(PodDBAdapter.KEY_LINK_INDEX));
feed.setDescription(cursor
.getString(PodDBAdapter.KEY_DESCRIPTION_INDEX));
feed.setPaymentLink(cursor
.getString(PodDBAdapter.KEY_PAYMENT_LINK_INDEX));
feed.setAuthor(cursor.getString(PodDBAdapter.KEY_AUTHOR_INDEX));
feed.setLanguage(cursor.getString(PodDBAdapter.KEY_LANGUAGE_INDEX));
feed.setType(cursor.getString(PodDBAdapter.KEY_TYPE_INDEX));
feed.setFeedIdentifier(cursor
.getString(PodDBAdapter.KEY_FEED_IDENTIFIER_INDEX));
long imageIndex = cursor.getLong(PodDBAdapter.KEY_IMAGE_INDEX); long imageIndex = cursor.getLong(PodDBAdapter.KEY_IMAGE_INDEX);
if (imageIndex != 0) { if (imageIndex != 0) {
feed.setImage(getFeedImage(adapter, imageIndex)); image = getFeedImage(adapter, imageIndex);
feed.getImage().setFeed(feed); } else {
image = null;
} }
feed.setFile_url(cursor.getString(PodDBAdapter.KEY_FILE_URL_INDEX)); Feed feed = new Feed(cursor.getLong(PodDBAdapter.KEY_ID_INDEX),
feed.setDownload_url(cursor lastUpdate,
.getString(PodDBAdapter.KEY_DOWNLOAD_URL_INDEX)); cursor.getString(PodDBAdapter.KEY_TITLE_INDEX),
feed.setDownloaded(cursor.getInt(PodDBAdapter.KEY_DOWNLOADED_INDEX) > 0); cursor.getString(PodDBAdapter.KEY_LINK_INDEX),
cursor.getString(PodDBAdapter.KEY_DESCRIPTION_INDEX),
cursor.getString(PodDBAdapter.KEY_PAYMENT_LINK_INDEX),
cursor.getString(PodDBAdapter.KEY_AUTHOR_INDEX),
cursor.getString(PodDBAdapter.KEY_LANGUAGE_INDEX),
cursor.getString(PodDBAdapter.KEY_TYPE_INDEX),
cursor.getString(PodDBAdapter.KEY_FEED_IDENTIFIER_INDEX),
image,
cursor.getString(PodDBAdapter.KEY_FILE_URL_INDEX),
cursor.getString(PodDBAdapter.KEY_DOWNLOAD_URL_INDEX),
cursor.getInt(PodDBAdapter.KEY_DOWNLOADED_INDEX) > 0);
if (image != null) {
image.setFeed(feed);
}
return feed; return feed;
} }
@ -592,6 +594,7 @@ public final class DBReader {
} else { } else {
Log.e(TAG, "getFeed could not find feed with id " + feedId); Log.e(TAG, "getFeed could not find feed with id " + feedId);
} }
feedCursor.close();
adapter.close(); adapter.close();
return feed; return feed;
} }

View File

@ -131,8 +131,6 @@ public class DBWriter {
editor.commit(); editor.commit();
} }
PodDBAdapter adapter = new PodDBAdapter(context);
adapter.open();
// delete image file // delete image file
if (feed.getImage() != null) { if (feed.getImage() != null) {
if (feed.getImage().isDownloaded() if (feed.getImage().isDownloaded()
@ -163,6 +161,8 @@ public class DBWriter {
requester.cancelDownload(context, item.getMedia()); requester.cancelDownload(context, item.getMedia());
} }
} }
PodDBAdapter adapter = new PodDBAdapter(context);
adapter.open();
if (queueWasModified) { if (queueWasModified) {
adapter.setQueue(queue); adapter.setQueue(queue);
} }

View File

@ -30,7 +30,7 @@ import de.danoeh.antennapod.service.download.DownloadStatus;
public class PodDBAdapter { public class PodDBAdapter {
private static final String TAG = "PodDBAdapter"; private static final String TAG = "PodDBAdapter";
private static final int DATABASE_VERSION = 9; private static final int DATABASE_VERSION = 9;
private static final String DATABASE_NAME = "Antennapod.db"; public static final String DATABASE_NAME = "Antennapod.db";
/** /**
* Maximum number of arguments for IN-operator. * Maximum number of arguments for IN-operator.
@ -629,14 +629,12 @@ public class PodDBAdapter {
* @return The cursor of the query * @return The cursor of the query
*/ */
public final Cursor getAllFeedsCursor() { public final Cursor getAllFeedsCursor() {
open();
Cursor c = db.query(TABLE_NAME_FEEDS, null, null, null, null, null, Cursor c = db.query(TABLE_NAME_FEEDS, null, null, null, null, null,
KEY_TITLE + " ASC"); KEY_TITLE + " ASC");
return c; return c;
} }
public final Cursor getExpiredFeedsCursor(long expirationTime) { public final Cursor getExpiredFeedsCursor(long expirationTime) {
open();
Cursor c = db.query(TABLE_NAME_FEEDS, null, "?<?", new String[]{ Cursor c = db.query(TABLE_NAME_FEEDS, null, "?<?", new String[]{
KEY_LASTUPDATE, String.valueOf(System.currentTimeMillis() - expirationTime)}, null, null, KEY_LASTUPDATE, String.valueOf(System.currentTimeMillis() - expirationTime)}, null, null,
null); null);
@ -654,7 +652,6 @@ public class PodDBAdapter {
} }
public final Cursor getAllItemsOfFeedCursor(final long feedId) { public final Cursor getAllItemsOfFeedCursor(final long feedId) {
open();
Cursor c = db.query(TABLE_NAME_FEED_ITEMS, SEL_FI_SMALL, KEY_FEED Cursor c = db.query(TABLE_NAME_FEED_ITEMS, SEL_FI_SMALL, KEY_FEED
+ "=?", new String[]{String.valueOf(feedId)}, null, null, + "=?", new String[]{String.valueOf(feedId)}, null, null,
null); null);
@ -665,7 +662,6 @@ public class PodDBAdapter {
* Return a cursor with the SEL_FI_EXTRA selection of a single feeditem. * Return a cursor with the SEL_FI_EXTRA selection of a single feeditem.
*/ */
public final Cursor getExtraInformationOfItem(final FeedItem item) { public final Cursor getExtraInformationOfItem(final FeedItem item) {
open();
Cursor c = db Cursor c = db
.query(TABLE_NAME_FEED_ITEMS, SEL_FI_EXTRA, KEY_ID + "=?", .query(TABLE_NAME_FEED_ITEMS, SEL_FI_EXTRA, KEY_ID + "=?",
new String[]{String.valueOf(item.getId())}, null, new String[]{String.valueOf(item.getId())}, null,
@ -680,7 +676,6 @@ public class PodDBAdapter {
* @return The cursor of the query * @return The cursor of the query
*/ */
public final Cursor getFeedMediaOfItemCursor(final FeedItem item) { public final Cursor getFeedMediaOfItemCursor(final FeedItem item) {
open();
Cursor c = db.query(TABLE_NAME_FEED_MEDIA, null, KEY_ID + "=?", Cursor c = db.query(TABLE_NAME_FEED_MEDIA, null, KEY_ID + "=?",
new String[]{String.valueOf(item.getMedia().getId())}, null, new String[]{String.valueOf(item.getMedia().getId())}, null,
null, null); null, null);
@ -694,14 +689,12 @@ public class PodDBAdapter {
* @return The cursor of the query * @return The cursor of the query
*/ */
public final Cursor getImageOfFeedCursor(final long id) { public final Cursor getImageOfFeedCursor(final long id) {
open();
Cursor c = db.query(TABLE_NAME_FEED_IMAGES, null, KEY_ID + "=?", Cursor c = db.query(TABLE_NAME_FEED_IMAGES, null, KEY_ID + "=?",
new String[]{String.valueOf(id)}, null, null, null); new String[]{String.valueOf(id)}, null, null, null);
return c; return c;
} }
public final Cursor getSimpleChaptersOfFeedItemCursor(final FeedItem item) { public final Cursor getSimpleChaptersOfFeedItemCursor(final FeedItem item) {
open();
Cursor c = db.query(TABLE_NAME_SIMPLECHAPTERS, null, KEY_FEEDITEM Cursor c = db.query(TABLE_NAME_SIMPLECHAPTERS, null, KEY_FEEDITEM
+ "=?", new String[]{String.valueOf(item.getId())}, null, + "=?", new String[]{String.valueOf(item.getId())}, null,
null, null); null, null);
@ -709,7 +702,6 @@ public class PodDBAdapter {
} }
public final Cursor getDownloadLogCursor(final int limit) { public final Cursor getDownloadLogCursor(final int limit) {
open();
Cursor c = db.query(TABLE_NAME_DOWNLOAD_LOG, null, null, null, null, Cursor c = db.query(TABLE_NAME_DOWNLOAD_LOG, null, null, null, null,
null, KEY_COMPLETION_DATE + " DESC LIMIT " + limit); null, KEY_COMPLETION_DATE + " DESC LIMIT " + limit);
return c; return c;
@ -720,7 +712,6 @@ public class PodDBAdapter {
* cursor uses the SEL_FI_SMALL selection. * cursor uses the SEL_FI_SMALL selection.
*/ */
public final Cursor getQueueCursor() { public final Cursor getQueueCursor() {
open();
Object[] args = (Object[]) new String[]{ Object[] args = (Object[]) new String[]{
SEL_FI_SMALL_STR + "," + TABLE_NAME_QUEUE + "." + KEY_ID, SEL_FI_SMALL_STR + "," + TABLE_NAME_QUEUE + "." + KEY_ID,
TABLE_NAME_FEED_ITEMS, TABLE_NAME_QUEUE, TABLE_NAME_FEED_ITEMS, TABLE_NAME_QUEUE,
@ -740,7 +731,6 @@ public class PodDBAdapter {
} }
public Cursor getQueueIDCursor() { public Cursor getQueueIDCursor() {
open();
Cursor c = db.query(TABLE_NAME_QUEUE, new String[]{KEY_FEEDITEM}, null, null, null, null, KEY_ID + " ASC", null); Cursor c = db.query(TABLE_NAME_QUEUE, new String[]{KEY_FEEDITEM}, null, null, null, null, KEY_ID + " ASC", null);
return c; return c;
} }
@ -750,14 +740,12 @@ public class PodDBAdapter {
* The returned cursor uses the SEL_FI_SMALL selection. * The returned cursor uses the SEL_FI_SMALL selection.
*/ */
public final Cursor getUnreadItemsCursor() { public final Cursor getUnreadItemsCursor() {
open();
Cursor c = db.query(TABLE_NAME_FEED_ITEMS, SEL_FI_SMALL, KEY_READ Cursor c = db.query(TABLE_NAME_FEED_ITEMS, SEL_FI_SMALL, KEY_READ
+ "=0", null, null, null, KEY_PUBDATE + " DESC"); + "=0", null, null, null, KEY_PUBDATE + " DESC");
return c; return c;
} }
public final Cursor getUnreadItemIdsCursor() { public final Cursor getUnreadItemIdsCursor() {
open();
Cursor c = db.query(TABLE_NAME_FEED_ITEMS, new String[]{KEY_ID}, Cursor c = db.query(TABLE_NAME_FEED_ITEMS, new String[]{KEY_ID},
KEY_READ + "=0", null, null, null, KEY_PUBDATE + " DESC"); KEY_READ + "=0", null, null, null, KEY_PUBDATE + " DESC");
return c; return c;
@ -765,7 +753,6 @@ public class PodDBAdapter {
} }
public Cursor getDownloadedItemsCursor() { public Cursor getDownloadedItemsCursor() {
open();
final String query = "SELECT " + SEL_FI_SMALL_STR + " FROM " + TABLE_NAME_FEED_ITEMS final String query = "SELECT " + SEL_FI_SMALL_STR + " FROM " + TABLE_NAME_FEED_ITEMS
+ " INNER JOIN " + TABLE_NAME_FEED_MEDIA + " ON " + " INNER JOIN " + TABLE_NAME_FEED_MEDIA + " ON "
+ TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "=" + TABLE_NAME_FEED_ITEMS + "." + KEY_ID + "="
@ -787,7 +774,6 @@ public class PodDBAdapter {
if (limit < 0) { if (limit < 0) {
throw new IllegalArgumentException("Limit must be >= 0"); throw new IllegalArgumentException("Limit must be >= 0");
} }
open();
Cursor c = db.query(TABLE_NAME_FEED_MEDIA, null, Cursor c = db.query(TABLE_NAME_FEED_MEDIA, null,
KEY_PLAYBACK_COMPLETION_DATE + " > 0", null, null, KEY_PLAYBACK_COMPLETION_DATE + " > 0", null, null,
null, KEY_PLAYBACK_COMPLETION_DATE + " DESC LIMIT " + limit); null, KEY_PLAYBACK_COMPLETION_DATE + " DESC LIMIT " + limit);
@ -849,7 +835,6 @@ public class PodDBAdapter {
} }
public final Cursor getFeedCursor(final long id) { public final Cursor getFeedCursor(final long id) {
open();
Cursor c = db.query(TABLE_NAME_FEEDS, null, KEY_ID + "=" + id, null, Cursor c = db.query(TABLE_NAME_FEEDS, null, KEY_ID + "=" + id, null,
null, null, null); null, null, null);
return c; return c;
@ -862,7 +847,6 @@ public class PodDBAdapter {
+ IN_OPERATOR_MAXIMUM); + IN_OPERATOR_MAXIMUM);
} }
open();
return db.query(TABLE_NAME_FEED_ITEMS, SEL_FI_SMALL, KEY_ID + " IN " return db.query(TABLE_NAME_FEED_ITEMS, SEL_FI_SMALL, KEY_ID + " IN "
+ buildInOperator(ids.length), ids, null, null, null); + buildInOperator(ids.length), ids, null, null, null);

View File

@ -13,5 +13,6 @@ public class AntennaPodTestRunner extends InstrumentationTestRunner {
@Override @Override
public TestSuite getAllTests() { public TestSuite getAllTests() {
return new TestSuiteBuilder(AntennaPodTestRunner.class).includeAllPackagesUnderHere().build(); return new TestSuiteBuilder(AntennaPodTestRunner.class).includeAllPackagesUnderHere().build();
//return new TestSuiteBuilder(AntennaPodTestRunner.class).includeAllPackagesUnderHere().excludePackages("instrumentationTest.de.test.antennapod.syndication.handler").build();
} }
} }

View File

@ -0,0 +1,11 @@
package instrumentationTest.de.test.antennapod.storage;
import android.test.InstrumentationTestCase;
/**
* Test class for DBReader
*/
public class DBReaderTest extends InstrumentationTestCase {
}

View File

@ -0,0 +1,9 @@
package instrumentationTest.de.test.antennapod.storage;
import android.test.InstrumentationTestCase;
/**
* Test class for DBTasks
*/
public class DBTasksTest extends InstrumentationTestCase {
}

View File

@ -0,0 +1,473 @@
package instrumentationTest.de.test.antennapod.storage;
import android.content.Context;
import android.database.Cursor;
import android.test.InstrumentationTestCase;
import de.danoeh.antennapod.feed.Feed;
import de.danoeh.antennapod.feed.FeedImage;
import de.danoeh.antennapod.feed.FeedItem;
import de.danoeh.antennapod.feed.FeedMedia;
import de.danoeh.antennapod.storage.DBReader;
import de.danoeh.antennapod.storage.DBWriter;
import de.danoeh.antennapod.storage.PodDBAdapter;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* Test class for DBWriter
*/
public class DBWriterTest extends InstrumentationTestCase {
private static final String TEST_FOLDER = "testDBWriter";
@Override
protected void tearDown() throws Exception {
super.tearDown();
final Context context = getInstrumentation().getTargetContext();
context.deleteDatabase(PodDBAdapter.DATABASE_NAME);
File testDir = context.getExternalFilesDir(TEST_FOLDER);
assertNotNull(testDir);
for (File f : testDir.listFiles()) {
f.delete();
}
}
@Override
protected void setUp() throws Exception {
super.setUp();
final Context context = getInstrumentation().getTargetContext();
context.deleteDatabase(PodDBAdapter.DATABASE_NAME);
// make sure database is created
PodDBAdapter adapter = new PodDBAdapter(context);
adapter.open();
adapter.close();
}
public void testDeleteFeedMediaOfItemFileExists() throws IOException, ExecutionException, InterruptedException {
File dest = new File(getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER), "testFile");
assertTrue(dest.createNewFile());
Feed feed = new Feed("url", new Date(), "title");
List<FeedItem> items = new ArrayList<FeedItem>();
feed.setItems(items);
FeedItem item = new FeedItem();
item.setTitle("title");
item.setPubDate(new Date());
item.setFeed(feed);
FeedMedia media = new FeedMedia(0, item, 1, 1, 1, "mime_type", dest.getAbsolutePath(), "download_url", true, null);
item.setMedia(media);
items.add(item);
PodDBAdapter adapter = new PodDBAdapter(getInstrumentation().getTargetContext());
adapter.open();
adapter.setCompleteFeed(feed);
adapter.close();
assertTrue(media.getId() != 0);
assertTrue(item.getId() != 0);
DBWriter.deleteFeedMediaOfItem(getInstrumentation().getTargetContext(), media.getId()).get();
media = DBReader.getFeedMedia(getInstrumentation().getTargetContext(), media.getId());
assertNotNull(media);
assertFalse(dest.exists());
assertFalse(media.isDownloaded());
assertNull(media.getFile_url());
}
public void testDeleteFeedMediaOfItemFileDoesNotExists() throws IOException, ExecutionException, InterruptedException {
File dest = new File(getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER), "testFile");
Feed feed = new Feed("url", new Date(), "title");
List<FeedItem> items = new ArrayList<FeedItem>();
feed.setItems(items);
FeedItem item = new FeedItem();
item.setTitle("title");
item.setPubDate(new Date());
item.setFeed(feed);
FeedMedia media = new FeedMedia(0, item, 1, 1, 1, "mime_type", dest.getAbsolutePath(), "download_url", false, null);
item.setMedia(media);
items.add(item);
PodDBAdapter adapter = new PodDBAdapter(getInstrumentation().getTargetContext());
adapter.open();
adapter.setCompleteFeed(feed);
adapter.close();
assertTrue(media.getId() != 0);
assertTrue(item.getId() != 0);
DBWriter.deleteFeedMediaOfItem(getInstrumentation().getTargetContext(), media.getId()).get();
media = DBReader.getFeedMedia(getInstrumentation().getTargetContext(), media.getId());
assertNotNull(media);
assertFalse(dest.exists());
assertFalse(media.isDownloaded());
assertNull(media.getFile_url());
}
public void testDeleteFeed() throws IOException, ExecutionException, InterruptedException, TimeoutException {
File destFolder = getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER);
assertNotNull(destFolder);
Feed feed = new Feed ("url", new Date(), "title");
feed.setItems(new ArrayList<FeedItem>());
// create Feed image
File imgFile = new File(destFolder, "image");
assertTrue(imgFile.createNewFile());
FeedImage image = new FeedImage(0, "image", imgFile.getAbsolutePath(), "url", true);
image.setFeed(feed);
feed.setImage(image);
List<File> itemFiles = new ArrayList<File>();
// create items with downloaded media files
for (int i = 0; i < 10; i++) {
FeedItem item = new FeedItem();
item.setTitle("Item " + i);
item.setPubDate(new Date(System.currentTimeMillis()));
item.setFeed(feed);
feed.getItems().add(item);
File enc = new File(destFolder, "file " + i);
assertTrue(enc.createNewFile());
itemFiles.add(enc);
FeedMedia media = new FeedMedia(0, item, 1, 1, 1, "mime_type", enc.getAbsolutePath(), "download_url", true, null);
item.setMedia(media);
}
PodDBAdapter adapter = new PodDBAdapter(getInstrumentation().getContext());
adapter.open();
adapter.setCompleteFeed(feed);
adapter.close();
assertTrue(feed.getId() != 0);
assertTrue(feed.getImage().getId() != 0);
for (FeedItem item : feed.getItems()) {
assertTrue(item.getId() != 0);
assertTrue(item.getMedia().getId() != 0);
}
DBWriter.deleteFeed(getInstrumentation().getTargetContext(), feed.getId()).get(5, TimeUnit.SECONDS);
// check if files still exist
assertFalse(imgFile.exists());
for (File f : itemFiles) {
assertFalse(f.exists());
}
adapter = new PodDBAdapter(getInstrumentation().getContext());
adapter.open();
Cursor c = adapter.getFeedCursor(feed.getId());
assertTrue(c.getCount() == 0);
c.close();
c = adapter.getImageOfFeedCursor(image.getId());
assertTrue(c.getCount() == 0);
c.close();
for (FeedItem item : feed.getItems()) {
c = adapter.getFeedItemCursor(String.valueOf(item.getId()));
assertTrue(c.getCount() == 0);
c.close();
c = adapter.getSingleFeedMediaCursor(item.getMedia().getId());
assertTrue(c.getCount() == 0);
c.close();
}
}
public void testDeleteFeedNoImage() throws ExecutionException, InterruptedException, IOException, TimeoutException {
File destFolder = getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER);
assertNotNull(destFolder);
Feed feed = new Feed ("url", new Date(), "title");
feed.setItems(new ArrayList<FeedItem>());
feed.setImage(null);
List<File> itemFiles = new ArrayList<File>();
// create items with downloaded media files
for (int i = 0; i < 10; i++) {
FeedItem item = new FeedItem();
item.setTitle("Item " + i);
item.setPubDate(new Date(System.currentTimeMillis()));
item.setFeed(feed);
feed.getItems().add(item);
File enc = new File(destFolder, "file " + i);
assertTrue(enc.createNewFile());
itemFiles.add(enc);
FeedMedia media = new FeedMedia(0, item, 1, 1, 1, "mime_type", enc.getAbsolutePath(), "download_url", true, null);
item.setMedia(media);
}
PodDBAdapter adapter = new PodDBAdapter(getInstrumentation().getContext());
adapter.open();
adapter.setCompleteFeed(feed);
adapter.close();
assertTrue(feed.getId() != 0);
for (FeedItem item : feed.getItems()) {
assertTrue(item.getId() != 0);
assertTrue(item.getMedia().getId() != 0);
}
DBWriter.deleteFeed(getInstrumentation().getTargetContext(), feed.getId()).get(5, TimeUnit.SECONDS);
// check if files still exist
for (File f : itemFiles) {
assertFalse(f.exists());
}
adapter = new PodDBAdapter(getInstrumentation().getContext());
adapter.open();
Cursor c = adapter.getFeedCursor(feed.getId());
assertTrue(c.getCount() == 0);
c.close();
for (FeedItem item : feed.getItems()) {
c = adapter.getFeedItemCursor(String.valueOf(item.getId()));
assertTrue(c.getCount() == 0);
c.close();
c = adapter.getSingleFeedMediaCursor(item.getMedia().getId());
assertTrue(c.getCount() == 0);
c.close();
}
}
public void testDeleteFeedNoItems() throws IOException, ExecutionException, InterruptedException, TimeoutException {
File destFolder = getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER);
assertNotNull(destFolder);
Feed feed = new Feed ("url", new Date(), "title");
feed.setItems(null);
// create Feed image
File imgFile = new File(destFolder, "image");
assertTrue(imgFile.createNewFile());
FeedImage image = new FeedImage(0, "image", imgFile.getAbsolutePath(), "url", true);
image.setFeed(feed);
feed.setImage(image);
PodDBAdapter adapter = new PodDBAdapter(getInstrumentation().getContext());
adapter.open();
adapter.setCompleteFeed(feed);
adapter.close();
assertTrue(feed.getId() != 0);
assertTrue(feed.getImage().getId() != 0);
DBWriter.deleteFeed(getInstrumentation().getTargetContext(), feed.getId()).get(5, TimeUnit.SECONDS);
// check if files still exist
assertFalse(imgFile.exists());
adapter = new PodDBAdapter(getInstrumentation().getContext());
adapter.open();
Cursor c = adapter.getFeedCursor(feed.getId());
assertTrue(c.getCount() == 0);
c.close();
c = adapter.getImageOfFeedCursor(image.getId());
assertTrue(c.getCount() == 0);
c.close();
}
public void testDeleteFeedNoFeedMedia() throws IOException, ExecutionException, InterruptedException, TimeoutException {
File destFolder = getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER);
assertNotNull(destFolder);
Feed feed = new Feed ("url", new Date(), "title");
feed.setItems(new ArrayList<FeedItem>());
// create Feed image
File imgFile = new File(destFolder, "image");
assertTrue(imgFile.createNewFile());
FeedImage image = new FeedImage(0, "image", imgFile.getAbsolutePath(), "url", true);
image.setFeed(feed);
feed.setImage(image);
// create items
for (int i = 0; i < 10; i++) {
FeedItem item = new FeedItem();
item.setTitle("Item " + i);
item.setPubDate(new Date(System.currentTimeMillis()));
item.setFeed(feed);
feed.getItems().add(item);
}
PodDBAdapter adapter = new PodDBAdapter(getInstrumentation().getContext());
adapter.open();
adapter.setCompleteFeed(feed);
adapter.close();
assertTrue(feed.getId() != 0);
assertTrue(feed.getImage().getId() != 0);
for (FeedItem item : feed.getItems()) {
assertTrue(item.getId() != 0);
}
DBWriter.deleteFeed(getInstrumentation().getTargetContext(), feed.getId()).get(5, TimeUnit.SECONDS);
// check if files still exist
assertFalse(imgFile.exists());
adapter = new PodDBAdapter(getInstrumentation().getContext());
adapter.open();
Cursor c = adapter.getFeedCursor(feed.getId());
assertTrue(c.getCount() == 0);
c.close();
c = adapter.getImageOfFeedCursor(image.getId());
assertTrue(c.getCount() == 0);
c.close();
for (FeedItem item : feed.getItems()) {
c = adapter.getFeedItemCursor(String.valueOf(item.getId()));
assertTrue(c.getCount() == 0);
c.close();
}
}
public void testDeleteFeedWithQueueItems() throws ExecutionException, InterruptedException, TimeoutException {
File destFolder = getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER);
assertNotNull(destFolder);
Feed feed = new Feed ("url", new Date(), "title");
feed.setItems(new ArrayList<FeedItem>());
// create Feed image
File imgFile = new File(destFolder, "image");
FeedImage image = new FeedImage(0, "image", imgFile.getAbsolutePath(), "url", true);
image.setFeed(feed);
feed.setImage(image);
List<File> itemFiles = new ArrayList<File>();
// create items with downloaded media files
for (int i = 0; i < 10; i++) {
FeedItem item = new FeedItem();
item.setTitle("Item " + i);
item.setPubDate(new Date(System.currentTimeMillis()));
item.setFeed(feed);
feed.getItems().add(item);
File enc = new File(destFolder, "file " + i);
itemFiles.add(enc);
FeedMedia media = new FeedMedia(0, item, 1, 1, 1, "mime_type", enc.getAbsolutePath(), "download_url", false, null);
item.setMedia(media);
}
PodDBAdapter adapter = new PodDBAdapter(getInstrumentation().getContext());
adapter.open();
adapter.setCompleteFeed(feed);
adapter.close();
assertTrue(feed.getId() != 0);
assertTrue(feed.getImage().getId() != 0);
for (FeedItem item : feed.getItems()) {
assertTrue(item.getId() != 0);
assertTrue(item.getMedia().getId() != 0);
}
List<FeedItem> queue = new ArrayList<FeedItem>();
queue.addAll(feed.getItems());
adapter.open();
adapter.setQueue(queue);
Cursor queueCursor = adapter.getQueueIDCursor();
assertTrue(queueCursor.getCount() == queue.size());
queueCursor.close();
adapter.close();
DBWriter.deleteFeed(getInstrumentation().getTargetContext(), feed.getId()).get(5, TimeUnit.SECONDS);
adapter.open();
Cursor c = adapter.getFeedCursor(feed.getId());
assertTrue(c.getCount() == 0);
c.close();
c = adapter.getImageOfFeedCursor(image.getId());
assertTrue(c.getCount() == 0);
c.close();
for (FeedItem item : feed.getItems()) {
c = adapter.getFeedItemCursor(String.valueOf(item.getId()));
assertTrue(c.getCount() == 0);
c.close();
c = adapter.getSingleFeedMediaCursor(item.getMedia().getId());
assertTrue(c.getCount() == 0);
c.close();
}
c = adapter.getQueueCursor();
assertTrue(c.getCount() == 0);
c.close();
adapter.close();
}
public void testDeleteFeedNoDownloadedFiles() throws ExecutionException, InterruptedException, TimeoutException {
File destFolder = getInstrumentation().getTargetContext().getExternalFilesDir(TEST_FOLDER);
assertNotNull(destFolder);
Feed feed = new Feed ("url", new Date(), "title");
feed.setItems(new ArrayList<FeedItem>());
// create Feed image
File imgFile = new File(destFolder, "image");
FeedImage image = new FeedImage(0, "image", imgFile.getAbsolutePath(), "url", true);
image.setFeed(feed);
feed.setImage(image);
List<File> itemFiles = new ArrayList<File>();
// create items with downloaded media files
for (int i = 0; i < 10; i++) {
FeedItem item = new FeedItem();
item.setTitle("Item " + i);
item.setPubDate(new Date(System.currentTimeMillis()));
item.setFeed(feed);
feed.getItems().add(item);
File enc = new File(destFolder, "file " + i);
itemFiles.add(enc);
FeedMedia media = new FeedMedia(0, item, 1, 1, 1, "mime_type", enc.getAbsolutePath(), "download_url", false, null);
item.setMedia(media);
}
PodDBAdapter adapter = new PodDBAdapter(getInstrumentation().getContext());
adapter.open();
adapter.setCompleteFeed(feed);
adapter.close();
assertTrue(feed.getId() != 0);
assertTrue(feed.getImage().getId() != 0);
for (FeedItem item : feed.getItems()) {
assertTrue(item.getId() != 0);
assertTrue(item.getMedia().getId() != 0);
}
DBWriter.deleteFeed(getInstrumentation().getTargetContext(), feed.getId()).get(5, TimeUnit.SECONDS);
adapter = new PodDBAdapter(getInstrumentation().getContext());
adapter.open();
Cursor c = adapter.getFeedCursor(feed.getId());
assertTrue(c.getCount() == 0);
c.close();
c = adapter.getImageOfFeedCursor(image.getId());
assertTrue(c.getCount() == 0);
c.close();
for (FeedItem item : feed.getItems()) {
c = adapter.getFeedItemCursor(String.valueOf(item.getId()));
assertTrue(c.getCount() == 0);
c.close();
c = adapter.getSingleFeedMediaCursor(item.getMedia().getId());
assertTrue(c.getCount() == 0);
c.close();
}
}
}