package cgeo.geocaching.storage;
import cgeo.CGeoTestCase;
import cgeo.geocaching.SearchResult;
import cgeo.geocaching.connector.gc.GCConnector;
import cgeo.geocaching.connector.gc.Tile;
import cgeo.geocaching.enumerations.CacheType;
import cgeo.geocaching.enumerations.LoadFlags;
import cgeo.geocaching.enumerations.LoadFlags.SaveFlag;
import cgeo.geocaching.list.StoredList;
import cgeo.geocaching.location.Geopoint;
import cgeo.geocaching.location.Viewport;
import cgeo.geocaching.log.LogEntry;
import cgeo.geocaching.models.Geocache;
import cgeo.geocaching.models.Trackable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import static org.assertj.core.api.Java6Assertions.assertThat;
public class DataStoreTest extends CGeoTestCase {
static final String ARTIFICIAL_GEOCODE = "TEST";
public static void testStoredLists() {
int listId1 = StoredList.STANDARD_LIST_ID;
int listId2 = StoredList.STANDARD_LIST_ID;
// create caches
final Geocache cache1 = new Geocache();
cache1.setGeocode("Cache 1");
final Geocache cache2 = new Geocache();
cache2.setGeocode("Cache 2");
assertThat(cache2).isNotNull();
try {
// create lists
listId1 = DataStore.createList("DataStore Test");
assertThat(listId1).isGreaterThan(StoredList.STANDARD_LIST_ID);
listId2 = DataStore.createList("DataStoreTest");
assertThat(listId2).isGreaterThan(StoredList.STANDARD_LIST_ID);
assertThat(DataStore.getLists().size()).isGreaterThanOrEqualTo(2);
cache1.setDetailed(true);
cache1.getLists().add(listId1);
cache2.setDetailed(true);
cache2.getLists().add(listId1);
// save caches to DB (cache1=listId1, cache2=listId1)
DataStore.saveCache(cache1, LoadFlags.SAVE_ALL);
DataStore.saveCache(cache2, LoadFlags.SAVE_ALL);
assertThat(DataStore.getAllCachesCount()).isGreaterThanOrEqualTo(2);
// move list (cache1=listId1, cache2=listId1)
assertThat(DataStore.renameList(listId1, "DataStore Test (renamed)")).isEqualTo(1);
// get list
final StoredList list1 = DataStore.getList(listId1);
assertThat(list1).isNotNull();
assertThat(list1.title).isEqualTo("DataStore Test (renamed)");
// move to list (cache1=listId2, cache2=listId2)
DataStore.moveToList(Collections.singletonList(cache1), listId1, listId2);
assertThat(DataStore.getAllStoredCachesCount(CacheType.ALL, listId2)).isEqualTo(1);
// remove list (cache1=listId2, cache2=listId2)
assertThat(DataStore.removeList(listId1)).isTrue();
// mark dropped (cache1=1, cache2=0)
DataStore.markDropped(Collections.singletonList(cache2));
// mark stored (cache1=1, cache2=listId2)
DataStore.moveToList(Collections.singletonList(cache2), listId1, listId2);
assertThat(DataStore.getAllStoredCachesCount(CacheType.ALL, listId2)).isEqualTo(2);
// drop stored (cache1=0, cache2=0)
DataStore.removeList(listId2);
} finally {
// remove caches
final Set<String> geocodes = new HashSet<>();
geocodes.add(cache1.getGeocode());
geocodes.add(cache2.getGeocode());
DataStore.removeCaches(geocodes, LoadFlags.REMOVE_ALL);
// remove list
DataStore.removeList(listId1);
DataStore.removeList(listId2);
}
}
// Check that queries don't throw an exception (see issue #1429).
public static void testLoadWaypoints() {
final Viewport viewport = new Viewport(new Geopoint(-1, -2), new Geopoint(3, 4));
DataStore.loadWaypoints(viewport, false, false, CacheType.ALL);
DataStore.loadWaypoints(viewport, false, true, CacheType.ALL);
DataStore.loadWaypoints(viewport, true, false, CacheType.ALL);
DataStore.loadWaypoints(viewport, true, true, CacheType.ALL);
DataStore.loadWaypoints(viewport, false, false, CacheType.TRADITIONAL);
DataStore.loadWaypoints(viewport, false, true, CacheType.TRADITIONAL);
DataStore.loadWaypoints(viewport, true, false, CacheType.TRADITIONAL);
DataStore.loadWaypoints(viewport, true, true, CacheType.TRADITIONAL);
}
// Check that saving a cache and trackable without logs works (see #2199)
public static void testSaveWithoutLogs() {
// create cache and trackable
final Geocache cache = new Geocache();
cache.setGeocode(ARTIFICIAL_GEOCODE);
cache.setDetailed(true);
final Trackable trackable = new Trackable();
trackable.setLogs(null);
final List<Trackable> inventory = new ArrayList<>();
inventory.add(trackable);
cache.setInventory(inventory);
try {
DataStore.saveCache(cache, EnumSet.of(SaveFlag.DB));
final Geocache loadedCache = DataStore.loadCache(ARTIFICIAL_GEOCODE, LoadFlags.LOAD_ALL_DB_ONLY);
assert loadedCache != null;
assertThat(loadedCache).isNotNull();
assertThat(loadedCache).overridingErrorMessage("Cache was not saved.").isNotNull();
assertThat(loadedCache.getInventory()).hasSize(1);
} finally {
DataStore.removeCache(ARTIFICIAL_GEOCODE, LoadFlags.REMOVE_ALL);
}
}
// Check that loading a cache by case insensitive geo code works correctly (see #3139)
public static void testGeocodeCaseInsensitive() {
final String upperCase = ARTIFICIAL_GEOCODE;
final String lowerCase = StringUtils.lowerCase(upperCase);
assertThat(upperCase.equals(lowerCase)).isFalse();
// create cache and trackable
final Geocache cache = new Geocache();
cache.setGeocode(upperCase);
cache.setDetailed(true);
try {
final Geocache oldCache = DataStore.loadCache(upperCase, LoadFlags.LOAD_ALL_DB_ONLY);
assertThat(oldCache).as("Old cache").isNull();
DataStore.saveCache(cache, EnumSet.of(SaveFlag.DB));
final Geocache cacheWithOriginalCode = DataStore.loadCache(upperCase, LoadFlags.LOAD_ALL_DB_ONLY);
assertThat(cacheWithOriginalCode).overridingErrorMessage("Cache was not saved correctly!").isNotNull();
final Geocache cacheLowerCase = DataStore.loadCache(lowerCase, LoadFlags.LOAD_ALL_DB_ONLY);
assertThat(cacheLowerCase).overridingErrorMessage("Could not find cache by case insensitive geocode").isNotNull();
} finally {
DataStore.removeCache(upperCase, LoadFlags.REMOVE_ALL);
}
}
// Loading logs for an empty geocode should return an empty list, not null!
public static void testLoadLogsFromEmptyGeocode() {
final List<LogEntry> logs = DataStore.loadLogs("");
assertThat(logs).as("Logs for empty geocode").isNotNull();
assertThat(logs).as("Logs for empty geocode").isEmpty();
}
public static void testLoadCacheHistory() {
int sumCaches = 0;
int allCaches = 0;
for (final CacheType cacheType : CacheType.values()) {
final SearchResult historyOfType = DataStore.getHistoryOfCaches(cacheType);
assertThat(historyOfType).isNotNull();
if (cacheType != CacheType.ALL) {
sumCaches += historyOfType.getCount();
} else {
allCaches = historyOfType.getCount();
}
}
// check that sum of types equals 'all'
assertThat(allCaches).isEqualTo(sumCaches);
// check that two different routines behave the same
assertThat(sumCaches).isEqualTo(DataStore.getAllHistoryCachesCount());
}
public static void testCachedMissing() {
// Tile to test
final Tile tile = new Tile(new Geopoint("N49 44.0 E8 37.0"), 14);
final Set<Tile> tiles = new HashSet<>();
tiles.add(tile);
// set up geocaches to fill into cacheCache
final Geocache main = new Geocache();
main.setGeocode("GC12345");
main.setCoords(new Geopoint("N49 44.0 E8 37.0"));
final Geocache inTileLowZoom = new Geocache();
inTileLowZoom.setGeocode("GC12346");
inTileLowZoom.setCoords(new Geopoint("N49 44.001 E8 37.001"), Tile.ZOOMLEVEL_MIN_PERSONALIZED - 5);
final Geocache outTile = new Geocache();
outTile.setGeocode("GC12347");
outTile.setCoords(new Geopoint(tile.getViewport().getLatitudeMin() - 0.1, tile.getViewport().getLongitudeMin() - 0.1));
final Geocache otherConnector = new Geocache();
otherConnector.setGeocode("OC0001");
otherConnector.setCoords(new Geopoint("N49 44.0 E8 37.0"));
final Geocache inTileHighZoom = new Geocache();
inTileHighZoom.setGeocode("GC12348");
inTileHighZoom.setCoords(new Geopoint("N49 44.001 E8 37.001"), Tile.ZOOMLEVEL_MIN_PERSONALIZED + 1);
// put in cache
DataStore.saveCache(main, EnumSet.of(SaveFlag.CACHE));
DataStore.saveCache(inTileLowZoom, EnumSet.of(SaveFlag.CACHE));
DataStore.saveCache(inTileHighZoom, EnumSet.of(SaveFlag.CACHE));
DataStore.saveCache(outTile, EnumSet.of(SaveFlag.CACHE));
DataStore.saveCache(otherConnector, EnumSet.of(SaveFlag.CACHE));
final SearchResult search = new SearchResult(main);
final Set<String> filteredGeoCodes = DataStore.getCachedMissingFromSearch(search, tiles, GCConnector.getInstance(), Tile.ZOOMLEVEL_MIN_PERSONALIZED - 1);
assertThat(filteredGeoCodes).contains(inTileLowZoom.getGeocode());
assertThat(filteredGeoCodes).doesNotContain(inTileHighZoom.getGeocode(), otherConnector.getGeocode(), outTile.getGeocode(), main.getGeocode());
}
}